reviewing-cli-command
SKILL.md
Reviewing CLI Commands
Checklist for reviewing Typer CLI command implementations.
Review Process
- Read the command file
- Check each section below
- Report findings using output format at bottom
Structure
- File in
src/<cli_app>/commands/ - Has
app = typer.Typer()and@app.command() - Command groups use
@app.command()for each subcommand - Registered in
commands/__init__.pywithadd_typer() - Single commands:
add_typer(app)without name - Command groups:
add_typer(app, name="group")
Arguments & Options
- Uses
Annotatedsyntax - Arguments for required positional input
- Options for optional named parameters
- Short flags where appropriate (
-f,-q) - Help text: lowercase, no period, brief
# GOOD:
name: Annotated[str, typer.Argument(help="item name")]
force: Annotated[bool, typer.Option("--force", "-f", help="skip confirmation")] = False
# BAD:
name: str = typer.Argument(..., help="The name of the item.")
Error Handling
- Validates input before processing
- Exit codes: 0=success, 1=error, 2=invalid input
- Errors via
display.error() - Uses
raise typer.Exit(code)after errors - Uses
raise typer.Abort()for cancellation
# GOOD:
if id < 1:
display.error("ID must be positive")
raise typer.Exit(EXIT_INVALID_INPUT)
# BAD:
if id < 1:
print("Error: ID must be positive")
return
Output
- All output through
displaymodule - No
print(),typer.echo(), orconsole.print()
# GOOD:
display.success(f"Added '{task.title}'")
# BAD:
print(f"Added '{task.title}'")
Destructive Actions
- Has
--force/-fflag -
typer.confirm()withdefault=False - Shows "Cancelled" on abort
# GOOD:
if not force:
confirm = typer.confirm(f"Delete '{task.title}'?", default=False)
if not confirm:
display.info("Cancelled")
raise typer.Abort()
# BAD: defaults to Yes
confirm = typer.confirm(f"Delete?", default=True)
Help Text
- Docstring exists
- Imperative mood ("Add a task" not "Adds a task")
- First line < 60 characters
Common Mistakes
| Mistake | Fix |
|---|---|
print() |
display.success/error/warning/info() |
| Wrong exit code | 0=success, 1=error, 2=invalid |
Missing --force on delete |
Add force option with default False |
| Confirmation defaults Yes | default=False in typer.confirm() |
| Old Typer syntax | Annotated[type, typer.Argument()] |
Missing app = typer.Typer() |
Each command file needs its own app |
| Not registered | add_typer(app) in commands/__init__.py |
Review Output Format
## Review: <command_name>
[OK] Uses Annotated syntax
[OK] Has docstring in imperative mood
[X] Missing --force flag on destructive command
[X] Uses print() instead of display module
[!] Help text could be shorter
### Summary
<brief summary of issues found>
### Suggested Fixes
<code suggestions if needed>
Weekly Installs
1
Repository
https-deeplearn…ls-filesGitHub Stars
787
First Seen
11 days ago
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1