CLI Principles
CLI Principles Section 12 Draft

12. Logging and diagnostics

Source 12-logging-and-diagnostics.md

Back to the spec index

Commands are short-lived, so this spec does not copy the twelve-factor “logs as an event stream” idea. The twelve-factor app is written for long-running services whose platform captures stdout and routes it. A command that runs for a moment has no such platform, and in this spec stdout carries data only (section 4). So a CLI does not write structured (JSON) log events to stdout or stderr.

Verbose mode

  • -verbose is a boolean parameter on every CLI. It is off by default. There is no single-letter alias (3a).
  • With -verbose, the CLI writes extra human-readable diagnostic lines to stderr. They explain what it is doing. Examples of useful content:
    • which config files and folders it read or used, and the resolved scope values (env, tenant, organization, project, namespace, see 3a),
    • waiting for a lock, and who holds it (section 7),
    • calls made to a remote system: the method and address, the status, and the time taken,
    • the debug detail of a failure: a stack, or a raw response from a remote system.
  • There is one level, on or off. No -verbose 3, no level names.
  • stdout is unchanged. The result is the same with or without -verbose.
  • Diagnostic lines follow the colour and styling rules of section 4, per stream. They are plain text, not JSON.
  • Diagnostic lines are not a contract. Their wording and order can change at any time, with no notice. Programs read result and error, never the diagnostics.
  • Never print secrets, even in verbose mode. No credential, token, or password. Print names, not values. This includes values from a credential CLI (section 9) and sensitive parameters (3a). A remote call is shown without its authorization header or any secret in the address.

Errors and verbose mode

  • Without -verbose, an error carries only what section 5 defines. Debug detail (a stack, a raw remote response) is not printed.
  • With -verbose, that debug detail is printed as diagnostic lines on stderr.
  • internal errors (section 5) tell the caller to repeat the command with -verbose and to include the requestId when reporting a bug.
  • Output with -output json or yaml and -verbose together: the diagnostic lines come first, and the error object is the last line of stderr, on its own line. A program that needs exactly one object on stderr does not pass -verbose.
  • No diagnostic log file by default. A failure is investigated by repeating the command with -verbose. A CLI may keep a log file, in which case the convention of section 9 applies.

Out of scope: tracing and metrics

  • This spec gives no guidance on tracing or metrics. How a CLI or a team measures or follows commands is up to the implementer.
  • Boundary: anything an implementer adds must not change the specified behaviour. It must not write to stdout, change an exit code or an output shape, put a secret anywhere, or alter the files and folders of section 9.
CLI Principles · draft specificationBuilt from docs/spec/12-logging-and-diagnostics.md