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 Usage — nargs
, choices
, exclusive groups, custom actions, and more black magic 🧙♂️
And after that:
Final Build — a real mini CLI app using all lessons so far