Agent-First CLI Design
If the primary operator of your CLI is already an agent, what does it assume that the model cannot infer?
The agent that uses the CLI is the first customer. If it cannot discover commands, validate inputs, or parse outputs without guessing, the tool is human-grade with agent hopes attached. Agents fail differently than people: they cannot read prose, they hallucinate flags that were never defined, and they cannot ask a colleague what an undocumented option does. Agent-grade CLIs close those gaps by design.
The Six Dimensions
An agent-operable CLI holds six properties. Miss one and the agent degrades to guessing:
- Predictable contracts — every command returns structured output (
--output json), never prose. Prose is unparseable; a contract is not. - Runtime introspection —
schema/--describe/--help --jsonso the agent reads the current interface, not stale docs. - Context discipline — field masking (
--fields id,name) so results fit the window instead of flooding it. - Input hardening — validate aggressively; agents produce malformed input in ways humans never would.
- Dry-run safety —
--dry-runon every mutation so the agent can rehearse before committing a side effect. - Explicit invariants — document what the agent cannot infer from
--helpin a companion contract file.
The Retrofit Order
When upgrading a human-first CLI to agent-grade, this sequence minimises risk and delivers value earliest:
--output jsonon every command — agents can't parse prose. This is the single highest-leverage change.- Validate all inputs aggressively — agents hallucinate differently than humans typo; catch it at the boundary.
schema/--describe/--help --json— runtime discoverability replaces stale documentation.- Field masking (
--fields) — context-window discipline; return only what was asked for. --dry-runon mutations — rehearse before committing side effects.- Document invariants in a companion contract file — what the agent can't infer from
--help. - Expose via MCP / tool protocol — one capability model, many surfaces (see MCP Server Engineering).
One Contract, Not Ten Flags
Raw JSON payloads beat bespoke flags. Ten individual flags are ten hallucination opportunities; one JSON object is one contract:
# fragile — ten independent flags the agent can each get wrong
tool list --name --id --status --created --owner ...
# robust — one structured contract
tool list --params '{"fields": ["id", "name"], "status": "active"}'
The principle generalises: collapse surface area into contracts. Every degree of freedom you expose as a loose flag is a degree of freedom for the agent to hallucinate.
How to Apply
- Pick the one command an agent runs most; add
--output json. - Add aggressive input validation to that command's arguments.
- Add
--help --json(orschema) so the interface is machine-readable. - Add
--fieldsmasking and, for any mutation,--dry-run. - Write the invariants the agent cannot infer into a companion contract file.
- Repeat per command in frequency order; expose the stable set via MCP.
Proof of done: an agent completes the workflow end-to-end from introspection alone — no hard-coded flag knowledge, no prose parsing, no un-rehearsed mutation.
Failure Modes
- Prose output. The agent regex-scrapes results and breaks on the first format change.
- Silent input acceptance. A malformed argument runs instead of erroring, producing a wrong side effect.
- Stale docs as the contract. The
--helptext drifts from behaviour; the agent trusts the text and fails. - Flag sprawl. Each new capability adds flags until the agent cannot reliably assemble a valid invocation.
- Un-rehearsed mutation. No
--dry-run, so the agent's first attempt at a destructive command is also its live one.
Changes my mind: if agents became reliable at parsing arbitrary human prose output and inferring undocumented behaviour, the contract discipline would be optional rather than load-bearing.
Inversion
The human-first instinct is to make the CLI friendly — helpful prose, forgiving inputs, sensible defaults that "just work." For an agent, every one of those is a trap: prose is unparseable, forgiving inputs hide errors, and hidden defaults are undocumented behaviour. Agent-grade design inverts the instinct — be strict, be explicit, be machine-readable, and let a thin human layer add the friendliness on top.
Context
- pairs-with Agentic CLI Checklist — the audit that scores a CLI against these principles before release
- pairs-with MCP Server Engineering — the protocol surface a hardened CLI exposes itself through
- pairs-with AI Harness — the agent side of the same contract; a domain agent carries only the tools it needs
- applies-to AI Toolkit — the CLIs catalogued there for selection are what this page teaches you to build
- depends-on Agent Protocols — the standards a tool speaks once it is exposed
- up Agent Tooling — the engineering hub
Links
- Rewrite your CLI for AI agents — Justin Poehnelt
- Building secure AI agents (MCP)
- CLI development guidelines
- InfoQ — the AI agent CLI
Questions
Which dimension would you relax first under schedule pressure — and what would that cost the first time an agent hallucinates a flag?
- Where does your CLI sit today on "one model, many surfaces" versus parallel logic trees?
- What must always be true for your tool that you have not yet written down?
- If the primary operator is already an agent, what does your contract file assume the model cannot infer?