Output Triple
Every CLI command in The Shift Platform supports three output modes. This pattern ensures that the same command works well for human operators in a terminal, AI agents parsing structured data, and scripts that only care about success or failure.
The Three Modes
Human (default)
Chalk-colored, formatted output designed for terminal readability. This is what you see when you run a command with no flags.
$ shift-cli yp services list
Services (3)
NAME OWNER SYSTEM LANGUAGE
────────────────────────────────────────────────────
auth-service platform core TypeScript
billing-api payments billing TypeScript
email-worker comms messaging Python
JSON (--json)
Structured JSON output for agent and script consumption. All data is emitted as a single JSON object to stdout with no decorative formatting.
$ shift-cli yp services list --json
[
{
"id": "abc12345",
"name": "auth-service",
"owner": "platform",
"system": "core",
"language": "TypeScript"
},
{
"id": "def67890",
"name": "billing-api",
"owner": "payments",
"system": "billing",
"language": "TypeScript"
},
{
"id": "ghi24680",
"name": "email-worker",
"owner": "comms",
"system": "messaging",
"language": "Python"
}
]
Quiet (--quiet)
No stdout output at all. The command communicates purely through its exit code. Useful for conditional logic in shell scripts.
$ shift-cli yp services get auth-service --quiet
$ echo $?
0
$ shift-cli yp services get nonexistent --quiet
$ echo $?
4
The output() Helper
The output() function from @shift/platform-core/output handles mode selection. It accepts the global options and a set of handler functions:
import { output, success, table } from "@shift/platform-core/output";
output(options, {
json: () => services,
quiet: () => {},
human: () => {
success(`Services (${services.length})`);
table(services, [
{ key: "name", label: "NAME" },
{ key: "owner", label: "OWNER" },
{ key: "system", label: "SYSTEM" },
{ key: "language", label: "LANGUAGE" },
]);
},
});
The output() function checks the flags in order:
- If
options.jsonis true and ajsonhandler is provided, it serializes the return value as formatted JSON viajsonOutput(). - If
options.quietis true and aquiethandler is provided, it calls that handler (which typically does nothing). - Otherwise, it calls the
humanhandler.
OutputOptions Interface
interface OutputOptions {
json?: boolean;
quiet?: boolean;
}
These flags come from Commander's global options, propagated via optsWithGlobals():
program
.option("--json", "Output as JSON")
.option("--quiet", "Suppress output, exit code only");
Additional Output Helpers
The @shift/platform-core/output module also exports helpers used within human-mode handlers:
| Helper | Purpose |
|---|---|
success(msg) | Green checkmark + message |
info(msg) | Blue info icon + message |
warn(msg) | Yellow warning icon + message |
error(msg) | Red cross + message |
bold(s) | Bold text |
dim(s) | Dimmed text |
cmd(s) | Cyan text (for command references) |
bullet(msg) | Green bullet point |
header(title) | Section header with spacing |
table(rows, columns) | Aligned table output |
barChart(items) | Horizontal bar chart |
Why This Matters for AI Agents
AI coding agents need to consume CLI output programmatically. The Output Triple pattern means:
- Agents use
--jsonto get structured data they can parse reliably, without scraping formatted terminal output. - Scripts use
--quietcombined with exit codes for conditional control flow (if shift-cli yp services get my-service --quiet; then ...). - Humans get readable output by default, with no extra flags needed.
This eliminates the common problem of agents trying to parse human-formatted output with regex or string manipulation, which breaks whenever formatting changes.