From dh
Reviews CLI apps for exit codes, help/version flags, stdin/stdout/stderr separation, non-interactive operation, signal handling, and argument validation. Activates on argparse, click, typer, commander.js.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dh:code-review-cliThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Stack-specific rules loaded by `dh:code-reviewer` when CLI entrypoints are detected (argparse, click, typer, commander.js, or similar argument parsing libraries).
Stack-specific rules loaded by dh:code-reviewer when CLI entrypoints are detected (argparse, click, typer, commander.js, or similar argument parsing libraries).
0 must be returned only on success — any error condition must produce a non-zero exit code0 after printing an error message is a blocking finding — tools in pipelines cannot detect the failure1 for general errors, 2 for usage/argument errors, 3+ for application-specific codes documented in --helpsys.exit(1) or process.exit(1) must be called on fatal errors, not just printing to stderr# WRONG: exits 0 even on error
def main():
try:
run()
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
# implicit exit 0
# RIGHT: non-zero on error
def main():
try:
run()
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
--help must be present and print usage information, option descriptions, and examples — the auto-generated help from argparse/click/typer is acceptable as a minimum--version must be present and print the version string matching pyproject.toml or package.json--help must exit 0; --version must exit 0stderrstdoutstdout breaks pipe usage — this is a blocking finding for tools that produce structured outputstderr with a non-zero exit codeinput(), readline, inquirer) must have a corresponding flag alternative (--flag value) for use in CI and scriptssys.stdin.isatty() or equivalent and skip interactive prompts in non-TTY mode130 by defaultatexit callbacksNO_COLOR environment variable is set (any non-empty value)sys.stdout.isatty() or equivalent before colorizing output--dry-run flag that shows what would happen without doing it--dry-run output must clearly distinguish what would be changed and what would remain untouched# WRONG: no --dry-run for destructive command
@app.command()
def delete_records(pattern: str):
records = find_records(pattern)
for r in records:
r.delete()
print(f"Deleted {len(records)} records")
# RIGHT: dry-run support
@app.command()
def delete_records(pattern: str, dry_run: bool = typer.Option(False, "--dry-run")):
records = find_records(pattern)
if dry_run:
for r in records:
print(f"Would delete: {r.id}")
print(f"Would delete {len(records)} records (dry run)")
return
for r in records:
r.delete()
print(f"Deleted {len(records)} records")
# WRONG: ANSI always on
print(f"\033[32mSuccess\033[0m")
# RIGHT: conditional color
import sys
USE_COLOR = sys.stdout.isatty() and not os.environ.get("NO_COLOR")
success = "\033[32mSuccess\033[0m" if USE_COLOR else "Success"
print(success)
npx claudepluginhub jamie-bitflight/claude_skills --plugin dhCLI application design: argument conventions, output streams, exit codes, configuration hierarchy, interactive modes, and terminal UX. Invoke whenever task involves any interaction with command-line tools or terminal applications — building, reviewing, debugging, or designing CLI interfaces.
Guides the design, implementation, review, and testing of CLI tools including flags, config precedence, terminal UX, error handling, and documentation.
Designs CLIs for both human users and LLM agents, covering subcommand structure, output streams, exit codes, JSON modes, TTY-aware color, and structured errors. Use when building or refactoring a CLI, adding machine-readable output, or making a tool agent-friendly.