CLI Principles
CLI Principles Section 4 Draft

4. Output

Source 04-output.md

Back to the spec index

  • stdout carries data only. stderr carries the error, warnings, and -verbose diagnostics.
  • Formats for -output: text, json, yaml, md. yaml is encouraged but optional, to keep a CLI simple to implement. json is needed by every CLI, since it is the default when stdout is not a TTY. text is mandatory, since it is the default on a TTY. md is encouraged but optional, and it is cheap to produce, since text is already built from markdown.
    • Summary: json and text mandatory, md and yaml encouraged but optional.
    • A CLI that does not support yaml fails -output yaml with unsupported (exit 12), parameter: -output, and a fix that lists the formats it does support. describe lists the supported formats for each CLI (section 8).
    • There is no separate resource format. A resource is part of the result payload in json or yaml.
    • text: the human rendering. The CLI writes markdown-like structured text and renders it for the terminal (see Colour below).
    • md: raw markdown, written as is.
    • json, yaml: the result / error envelopes.
  • Default format: text when stdout is a TTY, json otherwise. -output always overrides. (Same as clig.dev and Arcjet.)
    • Only stdout decides the default format. Colour is decided per stream (a redirected stderr gets no colour even if stdout is a TTY).
    • Known weakness: the same command can print different things depending on how it runs, and TTY detection can mislead. An agent under a pseudo-terminal (ConPTY on Windows) can look like a human, and a person piping to less gets JSON.
    • Mitigation: agents, scripts, tests, and examples that depend on the shape pass -output json explicitly. Generated skills and describe tell agents to do this (section 8).
    • Rejected for now: JSON always by default, with a user setting to switch humans to text.
  • Success is wrapped: {"result": <payload>}. In json and yaml output, a one-shot command prints exactly one object with a result member on stdout. It is the mirror of {"error": ...} on stderr (section 5). So a caller checks one rule: result means success, error means failure.
    • Warnings. A command that succeeds but has something worth telling the caller returns a warnings list beside result: {"result": ..., "warnings": [{"kind": "deprecated", "message": "..."}]}. Each warning has a short kind and a message, and may carry parameter. The exit code stays 0. In text and md, warnings are shown as lines in the human form on stderr (**Warning:** message). A command with nothing to warn about omits warnings.
    • text and md output are for humans and are not wrapped.
    • Exit code 0 always comes with result. A non-zero exit never has result on stdout (the exception is confirmation_required, which is a result, see section 6).
    • What goes inside result is up to the CLI. The spec does not force one payload shape.
      • A CLI that deals with resources returns the resource in the shape it defines, for example for something just created or updated.
      • A CLI returning plain query results returns a list/array or a bare object.
      • describe states which shape each command returns (section 8).
  • -field (repeatable) limits fields inside result to save agent context. The result wrapper stays.
  • Colour.
    • Every CLI must honour the NO_COLOR environment variable. When it is set and not empty, no colour or other ANSI styling is written, to stdout or stderr. -no-color and TERM=dumb have the same effect.
    • No colour, spinners, or decoration when not a TTY. json and yaml output never has colour.
    • Implicit structured text uses styling instead of marks. When the CLI writes its human rendering (text, which is the default on a TTY) and styling is on, the renderer shows each span like this, and the markdown marks (`, **, *) are not written:
      • bold spans are written in bold (ANSI bold).
      • the other spans, code spans and italics, are shown with colour (a different colour for each kind).
      • plain text is left unstyled.
    • Explicit -output md is raw markdown. No colour, and the marks are included, so the output is valid markdown to paste into a file or a viewer. This holds on a TTY too.