2 min read

Lesson 4: Grouping & Subcommands — Organize Like a Pro

Lesson 4: Grouping & Subcommands — Organize Like a Pro

Your CLI isn’t just a script anymore — it’s a command suite.
This lesson takes you beyond single-command logic and into the world of:

  • ✅ Organized --help output
  • ✅ Input safety with mutually exclusive options
  • ✅ Scalable command families like git add, git commit, git push

🔹 Grouping Arguments — Clean Up Your Help Menu

Use .add_argument_group() to visually separate related options in your help menu — then add a little magic to auto-show help when no input is given.

import argparse
import sys

parser = argparse.ArgumentParser(description="User management CLI")

auth_group = parser.add_argument_group("Authentication Options")
auth_group.add_argument('--username', help="User’s name")
auth_group.add_argument('--password', help="User’s password")

# 🪄 Auto-show help if no arguments were provided
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit(1)

args = parser.parse_args()

Use it when your CLI is meant to guide users
Why it matters: Helpful defaults = fewer support headaches


🔀 Mutually Exclusive Groups — Say “Pick One”

Use .add_mutually_exclusive_group() to prevent users from doing conflicting things.

group = parser.add_mutually_exclusive_group()
group.add_argument('--add', action='store_true', help="Add a user")
group.add_argument('--delete', action='store_true', help="Delete a user")

Now if someone tries:

python app.py --add --delete

They get:

error: argument --delete: not allowed with argument --add

Use it when:

  • --verbose vs --quiet
  • --encrypt vs --public
  • --json vs --csv

Why it matters: Keeps your logic safe and unbreakable


⚙️ Subcommands — Create a Real Command Suite

Now it gets really powerful. You can build commands like:

python taskcli.py add "Feed the dogs"
python taskcli.py done 2

Each one maps to a different subparser:

parser = argparse.ArgumentParser(description="Task CLI")

subparsers = parser.add_subparsers(dest='command', required=True)

add_parser = subparsers.add_parser('add', help='Add a task')
add_parser.add_argument('title', help='Task title')

done_parser = subparsers.add_parser('done', help='Mark task as done')
done_parser.add_argument('task_id', type=int)

args = parser.parse_args()

if args.command == 'add':
    print(f"✅ Task added: {args.title}")
elif args.command == 'done':
    print(f"✅ Task {args.task_id} marked done")

Use it when:

  • You’re building a CLI suite like git, pip, aws, etc.
  • You want separate logic per command
  • You dream of having argparse greatness

🧪 Recap

Feature Use Case Command Style
Argument Group Clean help sections --username, --password
Mutually Exclusive Group Conflict prevention --add XOR --delete
Subcommands Multi-tool CLI taskcli.py add "...", done 3

🔜 Coming Up

Next in Lesson 5:
Advanced Usagenargs, choices, exclusive groups, custom actions, and more black magic 🧙‍♂️

And after that:
Final Build — a real mini CLI app using all lessons so far