Checks one running service: its API, failure handling, limits, and security. This page holds the cards for the cli context. The Service audit page lists every card. Report each check as PASS, FAIL, or N/A with file:line evidence. A FAIL carries the card's severity. Any blockFAIL means request changes. A should-fix or discussFAIL goes in the review but does not block.
Verdict: request changes - change, function - 2 block, 1 should-fix FAIL, 1 PASS, 14 N/A
FAIL [block] chg-expand-contract - src/a.py:42 - renames the column and drops the old one in one migration
FAIL [block] svc-sqli-authn - src/db.py:88 - proven: builds the WHERE clause with an f-string from request.args
FAIL [should-fix] chg-one-concern - src/b.py:7 - a logging rewrite rides along with the bug fix
PASS chg-breaking-change-taxonomy - src/c.py:15 - no signature or return shape changes
N/A: 14 cards, applies_when does not hold
Filters
Concerns Topics
A card appears under each concern or topic it lists, so a group view can repeat a card.
Checklist
CardSeverityConcernsRule
svc-cli-destructive-dry-runshould-fixreliabilitymaintainabilityGive a destructive command a preview flag that changes nothing and a flag that skips the confirmation prompt.
svc-cli-exit-codes-and-streamsshould-fixcorrectnessmaintainabilityExit non-zero when a command fails, and write results to stdout and errors and progress to stderr.
svc-cli-non-interactiveshould-fixmaintainabilityprocessLet the caller turn every prompt off with a flag or an environment variable, so the command never waits on a terminal.
Tool gate: what a linter or CI check could enforce instead of a reviewer.
Cards
svc-cli-destructive-dry-run
should-fixstablereliabilitymaintainability
Applies when: A command-line tool has a command that deletes, overwrites or sends something.
Rule. Give a destructive command a preview flag that changes nothing and a flag that skips the confirmation prompt.
Why. Without a preview, the first run is the real one. Without a bypass, a script cannot run the command at all, so people write wrappers that pipe "yes" into it.
FAIL
func main() {
fmt.Printf("Delete %d backups? [y/N] ", len(old))
var ans string
fmt.Scanln(&ans) // no preview flag, no way to skip the prompt
if ans == "y" {
for _, b := range old {
os.Remove(b)
}
}
}
PASS
dry := flag.Bool("dry-run", false, "list what would be deleted, delete nothing")
yes := flag.Bool("yes", false, "do not ask for confirmation")
flag.Parse()
for _, b := range old {
fmt.Println(b)
}
if *dry {
return
}
if !*yes && !confirm(fmt.Sprintf("Delete %d backups?", len(old))) {
os.Exit(1)
}
for _, b := range old {
if err := os.Remove(b); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
Counterpoint. "A bypass flag invites accidents." The prompt stays the default for people, and the flag has to be typed on purpose. Pair it with svc-cli-non-interactive.
Tool gate: CLI test that runs the command with the preview flag and checks nothing changed.
Command Line Interface Guidelines(unjudged): clig.dev/
svc-cli-exit-codes-and-streams
should-fixstablecorrectnessmaintainability
Applies when: The code ships a command-line tool that scripts or other programs may run.
Rule. Exit non-zero when a command fails, and write results to stdout and errors and progress to stderr.
Why. Scripts branch on the exit code and pipe stdout into the next program. A failure that exits 0 reads as success, and an error line on stdout lands in the next program's input. Add a --json flag for structured results, and keep prompts out of non-terminal runs (see svc-cli-non-interactive).
FAIL
if err := run(); err != nil {
fmt.Println("error:", err) // error goes into the pipe
}
// main returns: exit status 0
Counterpoint. "Some tools use exit codes for non-error results." Documented codes for states such as "differences found" are fine. The rule is that a failure never exits 0.
Tool gate: CLI test that runs a failing command and checks the exit code and that stdout is empty.
Command Line Interface Guidelines(unjudged): clig.dev/
svc-cli-non-interactive
should-fixstablemaintainabilityprocess
Applies when: The code ships a command-line tool that scripts or agents may run.
Rule. Let the caller turn every prompt off with a flag or an environment variable, so the command never waits on a terminal.
Why. A script or an agent has no one to answer a prompt, so the command hangs until a timeout kills it. When stdin is not a terminal, the best behaviour is to fail at once with an error that names the missing flag and shows an example call, so the caller fixes it in one step.
FAIL
env := flag.String("env", "", "target environment")
flag.Parse()
if *env == "" {
fmt.Print("Choose environment: ")
fmt.Scanln(env) // always prompts: no way to turn it off, hangs in CI
}