CLI Principles
CLI Principles Section 1 Draft

1. Scope and principles

Source 01-scope.md

Back to the spec index

  • Audience: local-machine projects and agents that share these CLIs.
  • This is a specification, not an implementation, and it is language agnostic. It describes what a CLI does that a caller can see: parameters, streams, exit codes, output shapes, files and folders. It does not say how a CLI is written. Any language, framework, or library may be used. See section 11.
  • Agents are first-class users, humans second. Output defaults to machine-friendly when stdout is not a TTY.
  • Composable, consistent, discoverable, robust (from clig.dev).

Principle: commands are idempotent

Running the same command again, with the same parameters, leaves the system in the same state as running it once. Every command in every CLI follows this. It is what makes retries, crashes, and agent mistakes safe.

  • Queries have no side effects, so they are idempotent by nature. (The answer can change if the data changes. The command itself changes nothing.)
  • Mutations must be written so a repeat does no further harm:
    • A repeat that finds the work already done succeeds and says so: "status": "unchanged" in the result, and no write happens (6a).
    • create with an -id that exists, and the same content: unchanged. With different content: conflict (exit 6). Either way the state is unchanged.
    • Set, not adjust: set-status -status done, not “move to the next status”. set-count -value 5, not “add 1”. A command that depends on the current state to decide what to do is not allowed, unless it is guarded by -if-version (6a).
    • Prefer IDs chosen by the caller. With an ID the caller supplied, a repeated create is safe (see above). Where the system assigns the ID (for example a remote that creates it), how a repeat is kept safe is up to the CLI. The spec defines no idempotency key and no stored results. If a command cannot be made idempotent, it says so in describe (below).
    • No hidden side effects that pile up: no appended log lines in data, no counters, no “last modified” changes when nothing changed.
  • Retry rules follow from this. An error with retryable: true (section 5) means the same command is safe to run again. A partial failure that cannot be repeated safely says retryable: false and lists what was applied.
  • describe states it. Each command is marked idempotent: true. A command that cannot be idempotent is allowed, with a reason. It is marked idempotent: false, describe carries the written reason, and it needs review before it ships. This should be rare.
  • Conformance check. A check (section 10) runs each mutation twice and verifies the second run reports unchanged and that the data is byte-for-byte the same.
  • Delete of something already gone succeeds with unchanged (exit 0). A repeat is always safe. The cost is that a mistyped ID looks like success, so delete echoes the exact ID it acted on in the result.
CLI Principles · draft specificationBuilt from docs/spec/01-scope.md