CLI For Agents
Build CLIs as one engine with two renderers:
- human mode: readable text or TUI
- agent mode: deterministic JSON or NDJSON
Do not maintain separate doctrine for the two audiences. Keep one command model and one source of truth, then render it differently.
Use When
- designing a new CLI
- reviewing an existing CLI for agent compatibility
- adding commands, flags, or help text
- building watch/status/list commands that must work for both humans and agents
- tightening tests or guardrails around CLI output shape
Core Model
Dual-audience design
- Separate data production from presentation.
- The same command should support both human-readable and machine-readable output.
- Prefer
--json for bounded results and --ndjson for streams or watch modes.
- If a TUI exists, provide a non-TUI path for the same command.
Examples:
# Human
mycli watch --task abc123
# Agent
mycli watch --task abc123 --ndjson --no-tui
Canonical behavior
- The machine-readable mode is not a second implementation.
- Do not let TUI logic become the only place where important state transitions exist.
- The CLI should emit the same underlying facts in both modes.
Stable contract model
- Treat
--json as the stable contract for agents, scripts, and tests.
- Human-formatted output may change as wording, spacing, and styling improve.
- If a command is consumed programmatically, say so explicitly in help:
- script against
--json
- human output may change
Bounded default output
Protect the context window
- Default output must be the minimum useful response, not the maximum available data.
- Pre-sort items so the most important rows appear first.
- Truncate long fields by default.
- Require explicit opt-in such as
--full, --verbose, or --raw for large payloads.
- Preserve critical head and tail context when truncating command output.
Bad:
mycli list
# dumps every row and every field
Good:
mycli list
# top items only, scoped fields only
mycli list --full
# full payload
Progressive disclosure
Prefer graduated retrieval over one-shot dumps:
list or search for routing
summary for bounded orientation
show --section <name> for targeted expansion
show --full only by explicit opt-in
- Discovery responses should stay routing-sized. A good default JSON envelope is:
status
query
count
results
schema_version
next_step when it makes the cheapest follow-up obvious
- Bounded reads should report how resolution happened when the command accepted natural input.
Use fields such as
matched_on or resolved_from so agents know whether they are operating on an exact ID or a search-resolved target.
If a CLI owns rich documents, logs, or traces, build commands around:
summary -> section -> full
This is better for both humans and agents than dumping the entire surface by default.
Structured discoverability
- Root help should group commands by job, not alphabetically.
- Mark likely entry points with hints like
start here.
- Prefer command families that separate:
- discovery
- resolve
- read
- write
- Every command should define:
- short summary: 5-10 words, starts with an action verb
- long description: what it does, when to use it, how it differs from nearby commands
- examples: 3-5 concrete copy-pasteable invocations
- Examples matter more than prose. Agents infer flag shape from examples.
Example layout:
Task Management:
send Send a message to start or continue a task (start here)
watch Subscribe to live updates for a running task
get Retrieve the current state of a task
Discovery:
describe Inspect identity, skills, and capabilities
For repeated external-service, archive, or admin workflows, aim for:
doctor Verify setup, auth, version, and reachability
discover Find top-level resources or containers
resolve Turn names, URLs, or slugs into stable IDs
read Fetch exact objects or bounded lists
write Perform one named mutation with preview or dry-run support
request Raw escape hatch
Metadata quality is routing quality
- Titles, summaries, tags, and identifiers determine what an agent loads next.
- Short descriptions must be specific, not generic boilerplate.
- Result-card summaries and longer detail summaries should be distinct.
- Tags should be deterministic and meaningful, not inferred freeform when routing quality matters.
- Cross-links between related entities or docs should be deliberate, not opportunistic.
If the CLI returns knowledge-like records, every item should have:
- a strong title
- a bounded short summary
- optional deeper summary or section handles
- useful tags or categories
- adjacent links or next-hop identifiers when available
Agent-first interoperability
doctor is first-class
- Durable agent-facing CLIs should expose a
doctor or equivalent command.
doctor --json should verify config, auth source, version, endpoint reachability, and missing setup.
- If offline or fixture mode exists,
doctor --json should report that explicitly instead of failing ambiguously.
- Later tasks should be able to run
tool-name --json doctor first without reading docs.
Non-interactive first
- Every required input must be expressible as a flag, stdin, or positional argument.
- Interactive prompts are fallback only, never the default requirement.
- Respect
NO_COLOR and [APP]_NO_TUI environment variables.
- When stdout is piped, suppress TUI, prompts, spinners, and decorative color.
--json on everything that returns data
- Commands that return data should support
--json.
- Keep machine output bounded too; large structured payloads still need scoping.
- Prefer
--ndjson for streaming or watch commands.
- Never force agents to scrape tables or prose when the command already knows the schema.
- Do not return silent false-positive success payloads for misses. If resolution fails, return a deterministic error shape with retry guidance and, when possible, ranked suggestions.
Pipelines and stdin
- Accept stdin when composition is natural.
- Support
- as stdin where appropriate.
- Let one command feed the next without requiring temp files.
Examples:
mycli search "stalled tasks" --json | mycli rerank --stdin
mycli build --json | mycli deploy --spec-json -
Discover, then resolve, then read
- Discovery commands should return bounded lists with stable handles.
- Resolve commands should convert human input such as names, URLs, slugs, or permalinks into canonical IDs.
- Read commands should accept those stable IDs directly.
- Do not force agents to repeat broad searches when an exact read can follow a resolve step.
- If a command accepts natural-language input directly, let
summary or read auto-resolve obvious first-try matches and expose the resolution mode in machine output.
- Multi-word natural queries should not require brittle quoting if the command intent is retrieval rather than mutation.
Headless authentication
- Agents cannot complete browser auth flows reliably.
- Support headless auth such as env vars, tokens, service accounts, or pre-authenticated config.
- If interactive auth is unavoidable, fail immediately with a clear actionable hint.
- Never hang waiting for a browser login when running in no-TUI or machine-readable mode.
Mutative safety
- Mutating commands should support
--dry-run.
- Commands with confirmations should offer
--yes or --force.
- Default behavior should remain safe for humans.
- Repeat successful operations safely: no-op or explicit
already done beats duplicate side effects.
Error guidance
- Fail fast on invalid flags, missing config, missing auth, or missing prerequisites.
- Print exact next-step commands in errors.
- Emit errors to stderr.
- Return deterministic exit codes:
0 success
1 general failure
2 invalid usage
3 auth or connectivity failure
Example:
Error: database not initialized
Hint: run 'mycli init' to create the local database
Success output
- Successful commands should return machine-useful identifiers and next-hop values.
- Plain text is fine for human mode, but avoid decorative output as the only success signal.
Example:
deployed v1.2.3 to staging
url: https://staging.myapp.com
deploy_id: dep_abc123
duration: 34s
Config and environment
- Prefer standard config locations and explicit environment selection.
- Support named environments like
--env local|staging|prod.
- Let agents switch environments without knowing raw URLs or tokens.
Visual design
- Color should communicate state, not decorate prose.
- Prefer semantic colors:
- accent: headers, landmarks
- command: command names and flags
- pass: success
- warn: warnings or pending
- fail: errors
- muted: metadata
- id: identifiers
- Whitespace and alignment should carry hierarchy more than color.
- When formatting tables with ANSI colors, pad before styling or use a layout engine that handles colored strings safely.
Enforcement inside the CLI
These are the highest-value behaviors to enforce in code, not just document:
- stdout piped or
--json:
- disable TUI, prompts, spinners, and progress animation
- bounded defaults:
- limit rows, truncate long fields, and require
--full or --verbose for expansion
- stable machine mode:
- return one documented
--json schema per command
- deterministic exit codes:
- keep success, usage, auth, and runtime failures separated
- mutative safety:
- require
--yes or --force for dangerous actions
- expose
--dry-run for previewable mutations
- explicit errors:
- always return a
Hint: line with the exact next command when recovery is obvious
Enforcement around the CLI
These should be enforced through tests, quality gates, or CI:
- snapshot or schema tests for
--json output on agent-consumed commands
- tests proving human output can change without breaking
--json
- tests for piped stdout behavior: no TUI, no prompts, no spinner leakage
- tests for bounded default output vs
--full
- tests for summary/section/full retrieval flows where the CLI returns rich documents
- tests for
doctor --json setup and auth reporting
- tests proving the installed command works from outside the source folder
- tests for
discover -> resolve -> read flows using stable IDs
- tests for headless auth failure paths
- tests for deterministic exit codes and
Hint: guidance
- help-text checks: grouped commands, examples present, start-here hints where needed
- regression tests for metadata quality:
- titles
- summaries
- tags
- related links
If drift keeps recurring, add a gate instead of repeating cleanup.
Review checklist
- non-interactive path exists
--json or --ndjson exists where needed
- TUI has a non-TUI equivalent
- help is grouped and example-rich
- outputs are scoped, sorted, and bounded by default
summary -> section -> full exists where the CLI exposes large documents or traces
--json is treated as the stable contract
doctor --json exists for durable CLIs
- command families are separated into discover, resolve, read, and write where the domain needs them
- short summaries are specific, not generic boilerplate
- tags and adjacent links are useful routing metadata when the CLI returns knowledge-like records
- auth works headlessly or fails clearly
- mutative commands have
--dry-run
- confirmations have
--yes or --force
- exit codes are deterministic
- errors include exact next steps
- command shape and shorthand usage are consistent
- success output exposes IDs, URLs, durations, and next useful values
- tests enforce the important invariants above
When reviewing an existing CLI
Check:
- discoverability
- examples
- machine-readable output
- doctor/setup surface
- no-TUI behavior
- stdin and pipeline support
- headless auth
- bounded default output
- discover/resolve/read/write separation
- summary/section/full retrieval shape where relevant
- metadata quality for routing
- mutative safety
- deterministic errors
- consistent flags
- semantic output
- idempotency
- tests or gates covering the contract
Companion skill expectations
If the CLI is meant for repeated use across threads, pair it with a companion skill that records:
- when to use the CLI instead of ad hoc shell or browser work
- which command to run first, usually
doctor, discover, or summary
- how to keep output bounded
- where file downloads or exports land
- which write commands require explicit user approval
The CLI is the executable surface. The companion skill is the routing memory for future agents.
1---2name: cli-for-agents3description: Design or review CLIs so both coding agents and humans can use them reliably: dual-audience output, non-interactive paths, layered help, machine-readable data, predictable flags, safe mutations, and actionable errors. Use when building a CLI, adding commands, writing --help, or when the user mentions agents, terminals, automation-friendly CLIs, JSON output, or headless usage.4---56# CLI For Agents78Build CLIs as one engine with two renderers:9- human mode: readable text or TUI10- agent mode: deterministic JSON or NDJSON1112Do not maintain separate doctrine for the two audiences. Keep one command model and one source of truth, then render it differently.1314## Use When1516- designing a new CLI17- reviewing an existing CLI for agent compatibility18- adding commands, flags, or help text19- building watch/status/list commands that must work for both humans and agents20- tightening tests or guardrails around CLI output shape2122## Core Model2324### Dual-audience design2526- Separate data production from presentation.27- The same command should support both human-readable and machine-readable output.28- Prefer `--json` for bounded results and `--ndjson` for streams or watch modes.29- If a TUI exists, provide a non-TUI path for the same command.3031Examples:3233```bash34# Human35mycli watch --task abc1233637# Agent38mycli watch --task abc123 --ndjson --no-tui39```4041### Canonical behavior4243- The machine-readable mode is not a second implementation.44- Do not let TUI logic become the only place where important state transitions exist.45- The CLI should emit the same underlying facts in both modes.4647### Stable contract model4849- Treat `--json` as the stable contract for agents, scripts, and tests.50- Human-formatted output may change as wording, spacing, and styling improve.51- If a command is consumed programmatically, say so explicitly in help:52 - script against `--json`53 - human output may change5455## Bounded default output5657### Protect the context window5859- Default output must be the minimum useful response, not the maximum available data.60- Pre-sort items so the most important rows appear first.61- Truncate long fields by default.62- Require explicit opt-in such as `--full`, `--verbose`, or `--raw` for large payloads.63- Preserve critical head and tail context when truncating command output.6465Bad:6667```bash68mycli list69# dumps every row and every field70```7172Good:7374```bash75mycli list76# top items only, scoped fields only7778mycli list --full79# full payload80```8182### Progressive disclosure8384Prefer graduated retrieval over one-shot dumps:8586- `list` or `search` for routing87- `summary` for bounded orientation88- `show --section <name>` for targeted expansion89- `show --full` only by explicit opt-in90- Discovery responses should stay routing-sized. A good default JSON envelope is:91 - `status`92 - `query`93 - `count`94 - `results`95 - `schema_version`96 - `next_step` when it makes the cheapest follow-up obvious97- Bounded reads should report how resolution happened when the command accepted natural input.98 Use fields such as `matched_on` or `resolved_from` so agents know whether they are operating on an exact ID or a search-resolved target.99100If a CLI owns rich documents, logs, or traces, build commands around:101102```text103summary -> section -> full104```105106This is better for both humans and agents than dumping the entire surface by default.107108## Structured discoverability109110- Root help should group commands by job, not alphabetically.111- Mark likely entry points with hints like `start here`.112- Prefer command families that separate:113 - discovery114 - resolve115 - read116 - write117- Every command should define:118 - short summary: 5-10 words, starts with an action verb119 - long description: what it does, when to use it, how it differs from nearby commands120 - examples: 3-5 concrete copy-pasteable invocations121- Examples matter more than prose. Agents infer flag shape from examples.122123Example layout:124125```text126Task Management:127 send Send a message to start or continue a task (start here)128 watch Subscribe to live updates for a running task129 get Retrieve the current state of a task130131Discovery:132 describe Inspect identity, skills, and capabilities133```134135For repeated external-service, archive, or admin workflows, aim for:136137```text138doctor Verify setup, auth, version, and reachability139discover Find top-level resources or containers140resolve Turn names, URLs, or slugs into stable IDs141read Fetch exact objects or bounded lists142write Perform one named mutation with preview or dry-run support143request Raw escape hatch144```145146## Metadata quality is routing quality147148- Titles, summaries, tags, and identifiers determine what an agent loads next.149- Short descriptions must be specific, not generic boilerplate.150- Result-card summaries and longer detail summaries should be distinct.151- Tags should be deterministic and meaningful, not inferred freeform when routing quality matters.152- Cross-links between related entities or docs should be deliberate, not opportunistic.153154If the CLI returns knowledge-like records, every item should have:155156- a strong title157- a bounded short summary158- optional deeper summary or section handles159- useful tags or categories160- adjacent links or next-hop identifiers when available161162## Agent-first interoperability163164### `doctor` is first-class165166- Durable agent-facing CLIs should expose a `doctor` or equivalent command.167- `doctor --json` should verify config, auth source, version, endpoint reachability, and missing setup.168- If offline or fixture mode exists, `doctor --json` should report that explicitly instead of failing ambiguously.169- Later tasks should be able to run `tool-name --json doctor` first without reading docs.170171### Non-interactive first172173- Every required input must be expressible as a flag, stdin, or positional argument.174- Interactive prompts are fallback only, never the default requirement.175- Respect `NO_COLOR` and `[APP]_NO_TUI` environment variables.176- When stdout is piped, suppress TUI, prompts, spinners, and decorative color.177178### `--json` on everything that returns data179180- Commands that return data should support `--json`.181- Keep machine output bounded too; large structured payloads still need scoping.182- Prefer `--ndjson` for streaming or watch commands.183- Never force agents to scrape tables or prose when the command already knows the schema.184- Do not return silent false-positive success payloads for misses. If resolution fails, return a deterministic error shape with retry guidance and, when possible, ranked suggestions.185186### Pipelines and stdin187188- Accept stdin when composition is natural.189- Support `-` as stdin where appropriate.190- Let one command feed the next without requiring temp files.191192Examples:193194```bash195mycli search "stalled tasks" --json | mycli rerank --stdin196mycli build --json | mycli deploy --spec-json -197```198199### Discover, then resolve, then read200201- Discovery commands should return bounded lists with stable handles.202- Resolve commands should convert human input such as names, URLs, slugs, or permalinks into canonical IDs.203- Read commands should accept those stable IDs directly.204- Do not force agents to repeat broad searches when an exact read can follow a resolve step.205- If a command accepts natural-language input directly, let `summary` or `read` auto-resolve obvious first-try matches and expose the resolution mode in machine output.206- Multi-word natural queries should not require brittle quoting if the command intent is retrieval rather than mutation.207208## Headless authentication209210- Agents cannot complete browser auth flows reliably.211- Support headless auth such as env vars, tokens, service accounts, or pre-authenticated config.212- If interactive auth is unavoidable, fail immediately with a clear actionable hint.213- Never hang waiting for a browser login when running in no-TUI or machine-readable mode.214215## Mutative safety216217- Mutating commands should support `--dry-run`.218- Commands with confirmations should offer `--yes` or `--force`.219- Default behavior should remain safe for humans.220- Repeat successful operations safely: no-op or explicit `already done` beats duplicate side effects.221222## Error guidance223224- Fail fast on invalid flags, missing config, missing auth, or missing prerequisites.225- Print exact next-step commands in errors.226- Emit errors to stderr.227- Return deterministic exit codes:228 - `0` success229 - `1` general failure230 - `2` invalid usage231 - `3` auth or connectivity failure232233Example:234235```text236Error: database not initialized237Hint: run 'mycli init' to create the local database238```239240## Success output241242- Successful commands should return machine-useful identifiers and next-hop values.243- Plain text is fine for human mode, but avoid decorative output as the only success signal.244245Example:246247```text248deployed v1.2.3 to staging249url: https://staging.myapp.com250deploy_id: dep_abc123251duration: 34s252```253254## Config and environment255256- Prefer standard config locations and explicit environment selection.257- Support named environments like `--env local|staging|prod`.258- Let agents switch environments without knowing raw URLs or tokens.259260## Visual design261262- Color should communicate state, not decorate prose.263- Prefer semantic colors:264 - accent: headers, landmarks265 - command: command names and flags266 - pass: success267 - warn: warnings or pending268 - fail: errors269 - muted: metadata270 - id: identifiers271- Whitespace and alignment should carry hierarchy more than color.272- When formatting tables with ANSI colors, pad before styling or use a layout engine that handles colored strings safely.273274## Enforcement inside the CLI275276These are the highest-value behaviors to enforce in code, not just document:277278- stdout piped or `--json`:279 - disable TUI, prompts, spinners, and progress animation280- bounded defaults:281 - limit rows, truncate long fields, and require `--full` or `--verbose` for expansion282- stable machine mode:283 - return one documented `--json` schema per command284- deterministic exit codes:285 - keep success, usage, auth, and runtime failures separated286- mutative safety:287 - require `--yes` or `--force` for dangerous actions288 - expose `--dry-run` for previewable mutations289- explicit errors:290 - always return a `Hint:` line with the exact next command when recovery is obvious291292## Enforcement around the CLI293294These should be enforced through tests, quality gates, or CI:295296- snapshot or schema tests for `--json` output on agent-consumed commands297- tests proving human output can change without breaking `--json`298- tests for piped stdout behavior: no TUI, no prompts, no spinner leakage299- tests for bounded default output vs `--full`300- tests for summary/section/full retrieval flows where the CLI returns rich documents301- tests for `doctor --json` setup and auth reporting302- tests proving the installed command works from outside the source folder303- tests for `discover -> resolve -> read` flows using stable IDs304- tests for headless auth failure paths305- tests for deterministic exit codes and `Hint:` guidance306- help-text checks: grouped commands, examples present, start-here hints where needed307- regression tests for metadata quality:308 - titles309 - summaries310 - tags311 - related links312313If drift keeps recurring, add a gate instead of repeating cleanup.314315## Review checklist316317- non-interactive path exists318- `--json` or `--ndjson` exists where needed319- TUI has a non-TUI equivalent320- help is grouped and example-rich321- outputs are scoped, sorted, and bounded by default322- `summary -> section -> full` exists where the CLI exposes large documents or traces323- `--json` is treated as the stable contract324- `doctor --json` exists for durable CLIs325- command families are separated into discover, resolve, read, and write where the domain needs them326- short summaries are specific, not generic boilerplate327- tags and adjacent links are useful routing metadata when the CLI returns knowledge-like records328- auth works headlessly or fails clearly329- mutative commands have `--dry-run`330- confirmations have `--yes` or `--force`331- exit codes are deterministic332- errors include exact next steps333- command shape and shorthand usage are consistent334- success output exposes IDs, URLs, durations, and next useful values335- tests enforce the important invariants above336337## When reviewing an existing CLI338339Check:340- discoverability341- examples342- machine-readable output343- doctor/setup surface344- no-TUI behavior345- stdin and pipeline support346- headless auth347- bounded default output348- discover/resolve/read/write separation349- summary/section/full retrieval shape where relevant350- metadata quality for routing351- mutative safety352- deterministic errors353- consistent flags354- semantic output355- idempotency356- tests or gates covering the contract357358## Companion skill expectations359360If the CLI is meant for repeated use across threads, pair it with a companion skill that records:361362- when to use the CLI instead of ad hoc shell or browser work363- which command to run first, usually `doctor`, `discover`, or `summary`364- how to keep output bounded365- where file downloads or exports land366- which write commands require explicit user approval367368The CLI is the executable surface. The companion skill is the routing memory for future agents.