agent-friendly-cli
Agent-Friendly CLI Skill
Two modes: Create (new CLI) and Audit (existing CLI).
Mode: Audit
When given an existing CLI, evaluate it against each requirement below. For each item report: ✅ pass, ❌ fail, or ⚠️ partial — and give a concrete fix for every non-pass.
Present findings as a prioritized list (blockers first, then improvements).
Mode: Create
When asked to build a new CLI, apply all requirements below from the start. Remind the user of the CLI vs. MCP decision before writing code.
CLI vs. MCP Decision
Choose CLI when:
- Fewer than ~15 commands
- Stateless operations
- Agent has shell access
- Token budget matters (MCP adds ambient cost in system prompt)
Choose MCP when:
- 50+ tools behind one server
- Stateful sessions needed
- No shell access for agent
- Multi-agent systems
Requirements
1. Structured Output
--jsonflag outputs machine-readable JSON to stdout- In
--jsonmode: all warnings, progress, and human text go to stderr so stdout stays parseable - In normal (human) mode: output goes to stdout as usual
- Keep output flat over nested — easier to parse reliably
- Consistent field types across all commands: timestamps in ISO 8601, durations in seconds
# Human mode — rich output to stdout
$ mytool list
┌─────┬──────┐
│ ID │ Name │
└─────┴──────┘
# Machine mode — clean JSON to stdout, any warnings to stderr
$ mytool list --json
[{"id":"abc","name":"foo","created_at":"2025-01-01T00:00:00Z"}]
2. Exit Codes
Agents use $? for control flow. Use meaningful codes:
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General failure |
| 2 | Usage error (bad arguments) |
| 3 | Resource not found |
| 4 | Permission denied |
| 5 | Conflict (resource already exists) |
3. Idempotency
- Design commands safe to retry: prefer
ensure/upsertsemantics overcreate - Or support
--if-not-existsto turn conflict into a no-op - If idempotency isn't possible, return exit code
5on conflict so agents can handle it
4. Self-Documenting Help
--helpincludes realistic examples for every command- Required vs. optional flags are clearly marked
--jsonis documented prominently- Use hierarchical
noun verbpattern:tool resource action(e.g.docker container ls, notdocker-container-ls)
5. Composability & Piping
--quiet/-qfor bare output (one item per line, no decoration) — pipe-friendly--output jsonwith optional--fields id,nameto limit response size- Batch operations via
--selectoror repeated args instead of requiring 50 individual calls
6. Dry-Run & No-Prompt Modes
--dry-runproduces structured output showing what would change — nothing is mutated--yes/--forcebypasses all interactive prompts (agents cannot type "y")- Detect non-TTY (
!isatty(stdin)) and either skip prompts automatically or fail fast with a clear message pointing to--yes
7. Actionable Error Messages
Include in structured error output:
error_code/error_type(not just"Error: deployment failed")- The failing input echoed back, so agents can construct a fix
- Suggested next step where applicable
- Whether the error is transient (safe to retry) or permanent (give up)
{
"error": "resource_not_found",
"message": "Project 'staging' does not exist",
"input": {"project": "staging"},
"suggestion": "Run 'mytool project list' to see available projects",
"retryable": false
}
8. Input Hardening
Agents hallucinate in ways humans don't:
- Validate file paths — reject traversals (
../../.ssh) - Reject control characters and shell-special characters in IDs/names
- Validate resource IDs — reject
?,#,%, URL-encoded sequences - Guard against double-encoding (
%2520→%20→)
Checklist (quick reference)
[ ] --json flag outputs to stdout; warnings/progress to stderr only in --json mode
[ ] Meaningful exit codes (0–5 minimum)
[ ] Idempotent operations or clear conflict handling (exit 5)
[ ] --help with realistic examples per command
[ ] --dry-run for destructive/mutating commands
[ ] --yes/--force to bypass all prompts
[ ] Non-TTY detection (auto-skip prompts or fail + hint)
[ ] --quiet/-q for bare pipe-friendly output
[ ] Consistent field names and types across commands
[ ] Noun-verb command hierarchy
[ ] Structured error with error_code, input, suggestion, retryable
[ ] Batch operations for bulk work
[ ] Input validation (paths, IDs, encoding)
Note on Design Philosophy
Most CLIs are subtly hostile to agents. The goal isn't a rewrite — it's layering agent-friendly patterns on top of human-friendly ones. Support both paths in the same binary: rich tables for humans when stdout is a TTY, clean JSON when it isn't.
More from akhy/agent-skills
buffer
Manage Buffer social media posts and ideas — create and schedule posts to connected channels, manage the post queue, and create ideas in the Buffer Create space. Supports all Buffer-connected services (Instagram, Twitter/X, Facebook, LinkedIn, TikTok, Pinterest, YouTube, Mastodon, Bluesky, Threads, Google Business).
31memos
Manage memos using a self-hosted Memos instance — create, list, update, delete memos, post comments, manage reactions, attachments, and relations via the Memos REST API.
29vikunja-vja
Manage Vikunja tasks via VJA CLI, supporting CRUD operations, assignment, priority, and labeling. Use for task-related requests like creating, listing, updating, or deleting tasks. Always append --json to commands for structured results, and pipe to jq for compact and filtered output where possible.
22fizzy-workflow
High-level workflows for managing work using Fizzy cards — start, work on, complete, and delegate cards using the Fizzy CLI.
19mdq
Query and filter Markdown documents using jq-like selector syntax — extract headings, list items, tasks, links, images, tables, code blocks, blockquotes, and paragraphs from markdown files. Useful for parsing README files, docs, changelogs, and any structured markdown.
14plurk
Read and respond to Plurk social network content — fetch your timeline, get individual plurks, view another user's public plurks, read responses to a plurk, and post responses. Requires OAuth credentials.
14