Skip to main content

cli-design

Use when designing or changing a command-line interface, including commands, flags, output streams, structured output, exit status, or the boundary between command adapters and application behavior. Do not use merely to invoke an existing command.

Source facts

Repository
abhinav/home
Last source activity
September 25, 2026 at 21:51
Detected SKILL.md language
English
Stars
13
Forks
6

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
cli-design
description
Use when designing or changing a command-line interface, including commands, flags, output streams, structured output, exit status, or the boundary between command adapters and application behavior. Do not use merely to invoke an existing command.
# Command-line interface design Apply these principles when designing or changing a command-line program. ## Keep commands at the boundary A command is an adapter between command-line syntax and application behavior. It should parse input and produce a typed request, then invoke an application or domain operation and translate the result into the command's output contract. Do not make command implementations a second business-logic layer. Policy, state transitions, and reusable workflows belong in application or domain abstractions. Those abstractions should be testable without parsing command-line arguments. Parser callbacks and framework hooks should not become hidden homes for that behavior. ## Organize commands by responsibility Organize command implementation files around user-facing operations or cohesive operation families. Keep a command's request shape, validation, dispatch, and output translation near one another. Avoid collecting every command, command type, or command service into declaration-kind files. When several commands share behavior, extract an application operation or a focused adapter component rather than a large command utility layer. ## Preserve output contracts Treat standard output and standard error as separate interfaces. Reserve standard output for the result the user requested, especially data intended for pipes, files, or machine consumption. Write diagnostics, progress, and logs to standard error. Structured output modes must not be contaminated by logs or incidental status messages. Keep rendering decisions at the command boundary so application operations do not need to know whether a result will be printed as text, JSON, or another representation. ## Make outcomes interpretable A command result should let the caller determine what happened, what changed, and which action is available next. Design output for the decision it supports, not as an unbounded transcript of the command's internal work. Useful result behavior includes: - quiet success when the requested result already establishes completion - a bounded, stable structure for results consumed mechanically - the violated invariant and affected target when an operation fails - a known recovery action when one exists - a stable retrieval path for details omitted from the primary result - an inspection or dry-run mode before consequential effects - a receipt or postcondition query after a state-changing operation Output suppression belongs at the command boundary. The command should run the complete operation, preserve the full output and true exit status, return the information needed for the next decision, and provide a stable route to any omitted evidence. Do not require callers to truncate a command with `head` or `tail` to obtain a manageable result. Early-closing consumers can terminate the command before completion, discarded output can remove necessary context, and pipelines can hide the command's exit status. ## Test the boundary and the behavior separately Test parser behavior for public syntax, defaults, conflicts, and error messages. Test application behavior through typed requests without going through the parser. Use focused end-to-end tests for contracts that depend on real process streams, exit status, or shell behavior. When output is intentionally bounded, test that the complete operation still runs, the original exit status is preserved, and omitted evidence remains retrievable. For consequential operations, test the preview, receipt, or postcondition behavior promised by the command.
View on GitHub