Agent-Friendly CLI Spec v0.1
When building or modifying CLI tools, follow these rules to make them safe and
reliable for AI agents to use.
Overview
A comprehensive design specification for building AI-native CLI tools. It defines
98 rules across three certification levels (Agent-Friendly, Agent-Ready, Agent-Native)
with prioritized requirements (P0/P1/P2). The spec covers structured JSON output,
error handling, input contracts, safety guardrails, exit codes, self-description,
and a feedback loop via a built-in issue system.
When to Use This Skill
- Use when building a new CLI tool that AI agents will invoke
- Use when retrofitting an existing CLI to be agent-friendly
- Use when designing command-line interfaces for automation pipelines
- Use when auditing a CLI tool's compliance with agent-safety standards
Core Philosophy
- Agent-first -- default output is JSON; human-friendly is opt-in via
--human
- Agent is untrusted -- validate all input at the same level as a public API
- Fail-Closed -- when validation logic itself errors, deny by default
- Verifiable -- every rule is written so it can be automatically checked
Layer Model
This spec uses two orthogonal axes:
- Layer answers rollout scope:
core, recommended, ecosystem
- Priority answers severity:
P0, P1, P2
Use layers for migration and certification:
- core -- execution contract: JSON, errors, exit codes, stdout/stderr, safety
- recommended -- better machine UX: self-description, explicit modes, richer schemas
- ecosystem -- agent-native integration:
agent/, skills, issue, inline context
Certification maps to layers:
- Agent-Friendly -- all
core rules pass
- Agent-Ready -- all
core + recommended rules pass
- Agent-Native -- all layers pass
How It Works
Step 1: Output Mode
Default is agent mode (JSON). Explicit flags to switch:
$ mycli list # default = JSON output (agent mode)
$ mycli list --human # human-friendly: colored, tables, formatted
$ mycli list --agent # explicit agent mode (override config if needed)
- Default (no flag) -- JSON to stdout. Agent never needs to add a flag.
- --human -- human-friendly format (colors, tables, progress bars)
- --agent -- explicit JSON mode (useful when env/config overrides default)
Step 2: agent/ Directory Convention
Every CLI tool MUST have an agent/ directory at its project root. This is the
tool's identity and behavior contract for AI agents.
agent/
brief.md # One paragraph: who am I, what can I do
rules/ # Behavior constraints (auto-registered)
trigger.md # When should an agent use this tool
workflow.md # Step-by-step usage flow
writeback.md # How to write feedback back
skills/ # Extended capabilities (auto-registered)
getting-started.md
Step 3: Four Levels of Self-Description
- --brief (business card, injected into agent config)
- Every Command Response (always-on context: data + rules + skills + issue)
- --help (full self-description: brief + commands + rules + skills + issue)
- skills <name> (on-demand deep dive into a specific skill)
Certification Requirements
Each level includes all rules from the previous level.
Priority tag [P0]=agent breaks without it, [P1]=agent works but poorly, [P2]=nice to have.
Level 1: Agent-Friendly (core -- 20 rules)
Goal: CLI is a stable, callable API. Agent can invoke, parse, and handle errors.
Output -- default is JSON, stable schema
[P0] O1: Default output is JSON. No --json flag needed
[P0] O2: JSON MUST pass jq . validation
[P0] O3: JSON schema MUST NOT change within same version
Error -- structured, to stderr, never interactive
[P0] E1: Errors -> {"error":true, "code":"...", "message":"...", "suggestion":"..."} to stderr
[P0] E4: Error has machine-readable code (e.g. MISSING_REQUIRED)
[P0] E5: Error has human-readable message
[P0] E7: On error, NEVER enter interactive mode -- exit immediately
[P0] E8: Error codes are API contracts -- MUST NOT rename across versions
Exit Code -- predictable failure signals
[P0] X3: Parameter/usage errors MUST exit 2
[P0] X9: Failures MUST exit non-zero -- never exit 0 then report error in stdout
Composability -- clean pipe semantics
[P0] C1: stdout is for data ONLY
[P0] C2: logs, progress, warnings go to stderr ONLY
Input -- fail fast on bad input
[P1] I4: Missing required param -> structured error, never interactive prompt
[P1] I5: Type mismatch -> exit 2 + structured error
Safety -- protect against agent mistakes
[P1] S1: Destructive ops require --yes confirmation
[P1] S4: Reject ../../ path traversal, control chars
Guardrails -- runtime input protection
[P1] G1: Unknown flags rejected with exit 2
[P1] G2: Detect API key / token patterns in args, reject execution
[P1] G3: Reject sensitive file paths (*.env, *.key, *.pem)
[P1] G8: Reject shell metacharacters in arguments (; | && $())
Level 2: Agent-Ready (+ recommended -- 59 rules)
Goal: CLI is self-describing, well-named, and pipe-friendly. Agent discovers capabilities and chains commands without trial and error.
Self-Description -- agent discovers what CLI can do
[P1] D1: --help outputs structured JSON with commands[]
[P1] D3: Schema has required fields (help, commands)
[P1] D4: All parameters have type declarations
[P1] D7: Parameters annotated as required/optional
[P1] D9: Every command has a description
[P1] D11: --help outputs JSON with help, rules, skills, commands
[P1] D15: --brief outputs agent/brief.md content
[P1] D16: Default JSON (agent mode), --human for human-friendly
[P2] D2/D5/D6/D8/D10: per-command help, enums, defaults, output schema, version
Input -- unambiguous calling convention
[P1] I1: All flags use --long-name format
[P1] I2: No positional argument ambiguity
[P2] I3/I6/I7: --json-input, boolean --no-X, array params
Error
[P1] E6: Error includes suggestion field
[P2] E2/E3: errors to stderr, error JSON valid
Safety
[P1] S8: --sanitize flag for external input
[P2] S2/S3/S5/S6/S7: default deny, --dry-run, no auto-update, destructive marking
Exit Code
[P1] X1: 0 = success
[P2] X2/X4-X8: 1=general, 10=auth, 11=permission, 20=not-found, 30=conflict
Composability
[P1] C6: No interactive prompts in pipe mode
[P2] C3/C4/C5/C7: pipe-friendly, --quiet, pipe chain, idempotency
Naming -- predictable flag conventions
[P1] N4: Reserved flags (--agent, --human, --brief, --help, --version, --yes, --dry-run, --quiet, --fields)
[P2] N1/N2/N3/N5/N6: consistent naming, kebab-case, max 3 levels, --version semver
Guardrails
[P1] I8/I9: no implicit state, non-interactive auth
[P1] G6/G9: precondition checks, fail-closed
[P2] G4/G5/G7: permission levels, PII redaction, batch limits
Reserved Flags
| Flag |
Semantics |
Notes |
--agent |
JSON output (default) |
Explicit override |
--human |
Human-friendly output |
Colors, tables, formatted |
--brief |
One-paragraph identity |
For sync into agent config |
--help |
Full self-description JSON |
Brief + commands + rules + skills + issue |
--version |
Semver version string |
|
--yes |
Confirm destructive ops |
Required for delete/destroy |
--dry-run |
Preview without executing |
|
--quiet |
Suppress stderr output |
|
--fields |
Filter output fields |
Save tokens |
Level 3: Agent-Native (+ ecosystem -- 19 rules)
Goal: CLI has identity, behavior contract, skill system, and feedback loop. Agent can learn the tool, extend its use, and report problems -- full closed-loop collaboration.
Agent Directory -- tool identity and behavior contract
[P1] D12: agent/brief.md exists
[P1] D13: agent/rules/ has trigger.md, workflow.md, writeback.md
[P1] D17: agent/rules/*.md have YAML frontmatter (name, description)
[P1] D18: agent/skills/*.md have YAML frontmatter (name, description)
[P2] D14: agent/skills/ directory + skills subcommand
Response Structure -- inline context on every call
[P1] R1: Every response includes rules[] (full content from agent/rules/)
[P1] R2: Every response includes skills[] (name + description + command)
[P1] R3: Every response includes issue (feedback guide)
Meta -- project-level integration
[P2] M1: AGENTS.md at project root
[P2] M2: Optional MCP tool schema export
[P2] M3: CHANGELOG.md marks breaking changes
Feedback -- built-in issue system
[P2] F1: issue subcommand (create/list/show)
[P2] F2: Structured submission with version/context/exit_code
[P2] F3: Categories: bug / requirement / suggestion / bad-output
[P2] F4: Issues stored locally, no external service dependency
[P2] F5: issue list / issue show <id> queryable
[P2] F6: Issues have status tracking (open/in-progress/resolved/closed)
[P2] F7: Issue JSON has all required fields (id, type, status, message, created_at, updated_at)
[P2] F8: All issues have status field
Examples
Example 1: JSON Output (Agent Mode)
$ mycli list
{"result": [{"id": 1, "title": "Buy milk", "status": "todo"}], "rules": [...], "skills": [...], "issue": "..."}
Example 2: Structured Error
{
"error": true,
"code": "AUTH_EXPIRED",
"message": "Access token expired 2 hours ago",
"suggestion": "Run 'mycli auth refresh' to get a new token"
}
Example 3: Exit Code Table
0 success 10 auth failed 20 resource not found
1 general error 11 permission denied 30 conflict/precondition
2 param/usage error
Quick Implementation Checklist
Implement by layer -- each phase gets you the next certification level.
Phase 1: Agent-Friendly (core)
- Default output is JSON -- no
--json flag needed
- Error handler:
{ error, code, message, suggestion } to stderr
- Exit codes: 0 success, 2 param error, 1 general
- stdout = data only, stderr = logs only
- Missing param -> structured error (never interactive)
--yes guard on destructive operations
- Guardrails: reject secrets, path traversal, shell metacharacters
Phase 2: Agent-Ready (+ recommended)
8. --help returns structured JSON (help, commands[], rules[], skills[])
9. --brief reads and outputs agent/brief.md content
10. --human flag switches to human-friendly format
11. Reserved flags: --agent, --version, --dry-run, --quiet, --fields
12. Exit codes: 20 not found, 30 conflict, 10 auth, 11 permission
Phase 3: Agent-Native (+ ecosystem)
13. Create agent/ directory: brief.md, rules/trigger.md, rules/workflow.md, rules/writeback.md
14. Every command response appends: rules[] + skills[] + issue
15. skills subcommand: list all / show one with full content
16. issue subcommand for feedback (create/list/show/close/transition)
17. AGENTS.md at project root
Best Practices
- Do: Default to JSON output so agents never need to add flags
- Do: Include
suggestion field in every error response
- Do: Use the three-level certification model for incremental adoption
- Do: Keep
agent/brief.md to one paragraph for token efficiency
- Don't: Enter interactive mode on errors -- always exit immediately
- Don't: Change JSON schema or error codes within the same version
- Don't: Put logs or progress info on stdout -- use stderr only
- Don't: Accept unknown flags silently -- reject with exit code 2
Common Pitfalls
Problem: CLI outputs human-readable text by default, breaking agent parsing
Solution: Make JSON the default output format; add --human flag for human-friendly mode
Problem: Errors reported in stdout with exit code 0
Solution: Always exit non-zero on failure and write structured error JSON to stderr
Problem: CLI prompts for missing input interactively
Solution: Return structured error with suggestion field and exit immediately
Related Skills
@cli-best-practices - General CLI design patterns (this skill focuses specifically on AI agent compatibility)
Additional Resources
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
1---2name: ai-native-cli3description: Design spec with 98 rules for building CLI tools that AI agents can safely use — structured JSON output, error handling, input contracts, safety guardrails, exit codes, and agent self-description. USE WHEN building, retrofitting, or auditing a command-line tool that AI agents or automation pipelines will invoke.4---56# Agent-Friendly CLI Spec v0.178When building or modifying CLI tools, follow these rules to make them safe and9reliable for AI agents to use.1011## Overview1213A comprehensive design specification for building AI-native CLI tools. It defines1498 rules across three certification levels (Agent-Friendly, Agent-Ready, Agent-Native)15with prioritized requirements (P0/P1/P2). The spec covers structured JSON output,16error handling, input contracts, safety guardrails, exit codes, self-description,17and a feedback loop via a built-in issue system.1819## When to Use This Skill2021- Use when building a new CLI tool that AI agents will invoke22- Use when retrofitting an existing CLI to be agent-friendly23- Use when designing command-line interfaces for automation pipelines24- Use when auditing a CLI tool's compliance with agent-safety standards2526## Core Philosophy27281. **Agent-first** -- default output is JSON; human-friendly is opt-in via `--human`292. **Agent is untrusted** -- validate all input at the same level as a public API303. **Fail-Closed** -- when validation logic itself errors, deny by default314. **Verifiable** -- every rule is written so it can be automatically checked3233## Layer Model3435This spec uses two orthogonal axes:3637- **Layer** answers rollout scope: `core`, `recommended`, `ecosystem`38- **Priority** answers severity: `P0`, `P1`, `P2`3940Use layers for migration and certification:4142- **core** -- execution contract: JSON, errors, exit codes, stdout/stderr, safety43- **recommended** -- better machine UX: self-description, explicit modes, richer schemas44- **ecosystem** -- agent-native integration: `agent/`, `skills`, `issue`, inline context4546Certification maps to layers:4748- **Agent-Friendly** -- all `core` rules pass49- **Agent-Ready** -- all `core` + `recommended` rules pass50- **Agent-Native** -- all layers pass5152## How It Works5354### Step 1: Output Mode5556Default is agent mode (JSON). Explicit flags to switch:5758```bash59$ mycli list # default = JSON output (agent mode)60$ mycli list --human # human-friendly: colored, tables, formatted61$ mycli list --agent # explicit agent mode (override config if needed)62```6364- **Default (no flag)** -- JSON to stdout. Agent never needs to add a flag.65- **--human** -- human-friendly format (colors, tables, progress bars)66- **--agent** -- explicit JSON mode (useful when env/config overrides default)6768### Step 2: agent/ Directory Convention6970Every CLI tool MUST have an `agent/` directory at its project root. This is the71tool's identity and behavior contract for AI agents.7273```74agent/75 brief.md # One paragraph: who am I, what can I do76 rules/ # Behavior constraints (auto-registered)77 trigger.md # When should an agent use this tool78 workflow.md # Step-by-step usage flow79 writeback.md # How to write feedback back80 skills/ # Extended capabilities (auto-registered)81 getting-started.md82```8384### Step 3: Four Levels of Self-Description85861. **--brief** (business card, injected into agent config)872. **Every Command Response** (always-on context: data + rules + skills + issue)883. **--help** (full self-description: brief + commands + rules + skills + issue)894. **skills \<name\>** (on-demand deep dive into a specific skill)9091## Certification Requirements9293Each level includes all rules from the previous level.94Priority tag `[P0]`=agent breaks without it, `[P1]`=agent works but poorly, `[P2]`=nice to have.9596### Level 1: Agent-Friendly (core -- 20 rules)9798Goal: CLI is a stable, callable API. Agent can invoke, parse, and handle errors.99100**Output** -- default is JSON, stable schema101- `[P0]` O1: Default output is JSON. No `--json` flag needed102- `[P0]` O2: JSON MUST pass `jq .` validation103- `[P0]` O3: JSON schema MUST NOT change within same version104105**Error** -- structured, to stderr, never interactive106- `[P0]` E1: Errors -> `{"error":true, "code":"...", "message":"...", "suggestion":"..."}` to stderr107- `[P0]` E4: Error has machine-readable `code` (e.g. `MISSING_REQUIRED`)108- `[P0]` E5: Error has human-readable `message`109- `[P0]` E7: On error, NEVER enter interactive mode -- exit immediately110- `[P0]` E8: Error codes are API contracts -- MUST NOT rename across versions111112**Exit Code** -- predictable failure signals113- `[P0]` X3: Parameter/usage errors MUST exit 2114- `[P0]` X9: Failures MUST exit non-zero -- never exit 0 then report error in stdout115116**Composability** -- clean pipe semantics117- `[P0]` C1: stdout is for data ONLY118- `[P0]` C2: logs, progress, warnings go to stderr ONLY119120**Input** -- fail fast on bad input121- `[P1]` I4: Missing required param -> structured error, never interactive prompt122- `[P1]` I5: Type mismatch -> exit 2 + structured error123124**Safety** -- protect against agent mistakes125- `[P1]` S1: Destructive ops require `--yes` confirmation126- `[P1]` S4: Reject `../../` path traversal, control chars127128**Guardrails** -- runtime input protection129- `[P1]` G1: Unknown flags rejected with exit 2130- `[P1]` G2: Detect API key / token patterns in args, reject execution131- `[P1]` G3: Reject sensitive file paths (*.env, *.key, *.pem)132- `[P1]` G8: Reject shell metacharacters in arguments (; | && $())133134### Level 2: Agent-Ready (+ recommended -- 59 rules)135136Goal: CLI is self-describing, well-named, and pipe-friendly. Agent discovers capabilities and chains commands without trial and error.137138**Self-Description** -- agent discovers what CLI can do139- `[P1]` D1: `--help` outputs structured JSON with `commands[]`140- `[P1]` D3: Schema has required fields (help, commands)141- `[P1]` D4: All parameters have type declarations142- `[P1]` D7: Parameters annotated as required/optional143- `[P1]` D9: Every command has a description144- `[P1]` D11: `--help` outputs JSON with help, rules, skills, commands145- `[P1]` D15: `--brief` outputs `agent/brief.md` content146- `[P1]` D16: Default JSON (agent mode), `--human` for human-friendly147- `[P2]` D2/D5/D6/D8/D10: per-command help, enums, defaults, output schema, version148149**Input** -- unambiguous calling convention150- `[P1]` I1: All flags use `--long-name` format151- `[P1]` I2: No positional argument ambiguity152- `[P2]` I3/I6/I7: --json-input, boolean --no-X, array params153154**Error**155- `[P1]` E6: Error includes `suggestion` field156- `[P2]` E2/E3: errors to stderr, error JSON valid157158**Safety**159- `[P1]` S8: `--sanitize` flag for external input160- `[P2]` S2/S3/S5/S6/S7: default deny, --dry-run, no auto-update, destructive marking161162**Exit Code**163- `[P1]` X1: 0 = success164- `[P2]` X2/X4-X8: 1=general, 10=auth, 11=permission, 20=not-found, 30=conflict165166**Composability**167- `[P1]` C6: No interactive prompts in pipe mode168- `[P2]` C3/C4/C5/C7: pipe-friendly, --quiet, pipe chain, idempotency169170**Naming** -- predictable flag conventions171- `[P1]` N4: Reserved flags (--agent, --human, --brief, --help, --version, --yes, --dry-run, --quiet, --fields)172- `[P2]` N1/N2/N3/N5/N6: consistent naming, kebab-case, max 3 levels, --version semver173174**Guardrails**175- `[P1]` I8/I9: no implicit state, non-interactive auth176- `[P1]` G6/G9: precondition checks, fail-closed177- `[P2]` G4/G5/G7: permission levels, PII redaction, batch limits178179#### Reserved Flags180181| Flag | Semantics | Notes |182|------|-----------|-------|183| `--agent` | JSON output (default) | Explicit override |184| `--human` | Human-friendly output | Colors, tables, formatted |185| `--brief` | One-paragraph identity | For sync into agent config |186| `--help` | Full self-description JSON | Brief + commands + rules + skills + issue |187| `--version` | Semver version string | |188| `--yes` | Confirm destructive ops | Required for delete/destroy |189| `--dry-run` | Preview without executing | |190| `--quiet` | Suppress stderr output | |191| `--fields` | Filter output fields | Save tokens |192193### Level 3: Agent-Native (+ ecosystem -- 19 rules)194195Goal: CLI has identity, behavior contract, skill system, and feedback loop. Agent can learn the tool, extend its use, and report problems -- full closed-loop collaboration.196197**Agent Directory** -- tool identity and behavior contract198- `[P1]` D12: `agent/brief.md` exists199- `[P1]` D13: `agent/rules/` has trigger.md, workflow.md, writeback.md200- `[P1]` D17: agent/rules/*.md have YAML frontmatter (name, description)201- `[P1]` D18: agent/skills/*.md have YAML frontmatter (name, description)202- `[P2]` D14: `agent/skills/` directory + `skills` subcommand203204**Response Structure** -- inline context on every call205- `[P1]` R1: Every response includes `rules[]` (full content from agent/rules/)206- `[P1]` R2: Every response includes `skills[]` (name + description + command)207- `[P1]` R3: Every response includes `issue` (feedback guide)208209**Meta** -- project-level integration210- `[P2]` M1: AGENTS.md at project root211- `[P2]` M2: Optional MCP tool schema export212- `[P2]` M3: CHANGELOG.md marks breaking changes213214**Feedback** -- built-in issue system215- `[P2]` F1: `issue` subcommand (create/list/show)216- `[P2]` F2: Structured submission with version/context/exit_code217- `[P2]` F3: Categories: bug / requirement / suggestion / bad-output218- `[P2]` F4: Issues stored locally, no external service dependency219- `[P2]` F5: `issue list` / `issue show <id>` queryable220- `[P2]` F6: Issues have status tracking (open/in-progress/resolved/closed)221- `[P2]` F7: Issue JSON has all required fields (id, type, status, message, created_at, updated_at)222- `[P2]` F8: All issues have status field223224## Examples225226### Example 1: JSON Output (Agent Mode)227228```bash229$ mycli list230{"result": [{"id": 1, "title": "Buy milk", "status": "todo"}], "rules": [...], "skills": [...], "issue": "..."}231```232233### Example 2: Structured Error234235```json236{237 "error": true,238 "code": "AUTH_EXPIRED",239 "message": "Access token expired 2 hours ago",240 "suggestion": "Run 'mycli auth refresh' to get a new token"241}242```243244### Example 3: Exit Code Table245246```2470 success 10 auth failed 20 resource not found2481 general error 11 permission denied 30 conflict/precondition2492 param/usage error250```251252## Quick Implementation Checklist253254Implement by layer -- each phase gets you the next certification level.255256**Phase 1: Agent-Friendly (core)**2571. Default output is JSON -- no `--json` flag needed2582. Error handler: `{ error, code, message, suggestion }` to stderr2593. Exit codes: 0 success, 2 param error, 1 general2604. stdout = data only, stderr = logs only2615. Missing param -> structured error (never interactive)2626. `--yes` guard on destructive operations2637. Guardrails: reject secrets, path traversal, shell metacharacters264265**Phase 2: Agent-Ready (+ recommended)**2668. `--help` returns structured JSON (help, commands[], rules[], skills[])2679. `--brief` reads and outputs `agent/brief.md` content26810. `--human` flag switches to human-friendly format26911. Reserved flags: --agent, --version, --dry-run, --quiet, --fields27012. Exit codes: 20 not found, 30 conflict, 10 auth, 11 permission271272**Phase 3: Agent-Native (+ ecosystem)**27313. Create `agent/` directory: `brief.md`, `rules/trigger.md`, `rules/workflow.md`, `rules/writeback.md`27414. Every command response appends: rules[] + skills[] + issue27515. `skills` subcommand: list all / show one with full content27616. `issue` subcommand for feedback (create/list/show/close/transition)27717. AGENTS.md at project root278279## Best Practices280281- Do: Default to JSON output so agents never need to add flags282- Do: Include `suggestion` field in every error response283- Do: Use the three-level certification model for incremental adoption284- Do: Keep `agent/brief.md` to one paragraph for token efficiency285- Don't: Enter interactive mode on errors -- always exit immediately286- Don't: Change JSON schema or error codes within the same version287- Don't: Put logs or progress info on stdout -- use stderr only288- Don't: Accept unknown flags silently -- reject with exit code 2289290## Common Pitfalls291292- **Problem:** CLI outputs human-readable text by default, breaking agent parsing293 **Solution:** Make JSON the default output format; add `--human` flag for human-friendly mode294295- **Problem:** Errors reported in stdout with exit code 0296 **Solution:** Always exit non-zero on failure and write structured error JSON to stderr297298- **Problem:** CLI prompts for missing input interactively299 **Solution:** Return structured error with suggestion field and exit immediately300301## Related Skills302303- `@cli-best-practices` - General CLI design patterns (this skill focuses specifically on AI agent compatibility)304305## Additional Resources306307- [Agent CLI Spec Repository](https://github.com/ChaosRealmsAI/agent-cli-spec)308309## Limitations310- Use this skill only when the task clearly matches the scope described above.311- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.312- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.