Groups in practice
Build a Click group with two subcommands that share config through the context object.
- Create a click.group with two subcommands
- Pass shared configuration through the Click context object
- Invoke subcommands via CliRunner for verification
The cleanest way to understand groups is to build one. This lesson constructs a
small notes tool with two subcommands — add and list — that share a
storage dict through the Click context.
The structure
notes
add TEXT -- append a note
list -- show all notesThe shared state is a list of notes. In a real tool it might be a database connection or a loaded config file. Here a plain Python list serves the same purpose.
Building the group
The group initialises the shared list and attaches it to ctx.obj:
import click
@click.group()
@click.pass_context
def notes(ctx):
"""A minimal note-taking tool."""
ctx.ensure_object(dict)
ctx.obj.setdefault("notes", [])The setdefault call means subsequent group invocations within the same
process (as happens in tests) do not reset the list.
The subcommands
Each subcommand retrieves ctx.obj via @click.pass_obj, which passes
ctx.obj directly instead of the full context:
@notes.command()
@click.argument("text")
@click.pass_obj
def add(obj, text):
"""Add a note."""
obj["notes"].append(text)
click.echo(f"Added: {text}")
@notes.command()
@click.pass_obj
def list_notes(obj):
"""List all notes."""
if not obj["notes"]:
click.echo("No notes yet.")
return
for i, note in enumerate(obj["notes"], 1):
click.echo(f"{i}. {note}")Note the function is named list_notes to avoid shadowing Python's built-in
list. Click uses the function name as the subcommand name by default; you can
override it with @notes.command(name="list").
Try it
@click.pass_obj is shorthand for @click.pass_context followed by
ctx.obj access. Use @click.pass_obj when the subcommand only needs the
shared data; use @click.pass_context when it also needs context metadata
like ctx.invoked_subcommand or ctx.parent.
Where to go next
Next: configuration files — the ~/.config/tool/config.toml pattern,
Click's auto_envvar_prefix, and the correct precedence order for settings.