Building an AI-Agent-Friendly CLI: Lessons from deployhq-cli
AI coding agents can run shell commands. That means every CLI tool you ship is potentially an agent tool -- but most CLIs are built for humans staring at a terminal, not for an LLM parsing stdout. When we built deployhq-cli, we designed it for both from day one. Here is what we learned.
Why CLIs Are Natural Agent Tools
Before reaching for SDKs, MCP servers, or custom integrations, consider what a CLI already gives you:
Structured output via --json. An agent does not need to scrape table formatting. One flag and it gets clean JSON it can parse reliably.
Exit codes. Zero means success, non-zero means failure. An agent can branch on this without parsing error messages.
Self-documenting via --help. Every subcommand describes itself. An agent can explore the tool's surface area without external docs.
Composability. Pipes, redirects, and shell scripting work the same whether a human or an agent is driving.
The gap is not capability -- it is discoverability and consistency. A human reads a README and builds a mental model. An agent needs that mental model handed to it in a format it can consume in one shot.
The SKILL.md Pattern
The single most impactful thing we did was create a SKILL.md file -- a structured markdown document that teaches any AI agent how to use the CLI.
Here is the structure:
# DeployHQ CLI -- Agent Skill Guide
## Identity
What this tool is and does, in one paragraph.
## Authentication
Three methods, checked in order: env vars, config files, interactive login.
## Output Contract
stdout is ALWAYS data. stderr is ALWAYS human messages.
--json forces JSON. Exit codes: 0 = success, non-zero = failure.
## Command Groups
Table mapping group names to descriptions and reference docs.
## Decision Trees
Step-by-step workflows for common tasks.
## Invariants
Rules that always hold true.
## Gotchas
Things that will trip up an agent if not warned about.
The decision trees are the most valuable section. Instead of making the agent figure out that deploying code requires listing projects, then listing servers, then creating a deployment, you spell it out:
### "Deploy code"
1. `dhq projects list --json` -- find project permalink
2. `dhq servers list -p <project> --json` -- find server identifier
3. `dhq deploy -p <project> -s <server> --json` -- create deployment
4. `dhq deployments watch <id> -p <project>` -- monitor progress
The gotchas section prevents the agent from learning things the hard way. For example: dhq env-vars create will prompt for a value interactively if --value is omitted. That hangs an agent. The SKILL.md warns: "always pass --value."
One file. No SDK. No API wrapper. The agent reads it, and it knows how to drive your CLI.
Design Decisions for Agent-Friendliness
Breadcrumbs in JSON Output
Every JSON response includes a breadcrumbs array with suggested next commands:
{
"ok": true,
"data": {
"identifier": "abc123",
"status": "completed"
},
"summary": "Deployment abc123 completed",
"breadcrumbs": [
{"action": "logs", "cmd": "dhq deployments logs abc123 -p my-app"},
{"action": "rollback", "cmd": "dhq rollback abc123 -p my-app"}
]
}
This is the single best feature for agent workflows. The agent does not need to construct the next command from scratch -- it picks from contextually relevant suggestions. After a deployment completes, the breadcrumbs suggest checking logs or rolling back. After creating a project, they suggest connecting a repo.
Self-Discovery via dhq commands --json
An agent can dump the full command catalog at runtime:
dhq commands --json
This returns every command, its flags, required arguments, and descriptions. Combined with SKILL.md for workflow logic and --help for individual commands, an agent has three layers of discovery: strategic (SKILL.md), catalog (commands), and tactical (help).
Consistent Error Shapes
Every error follows the same JSON structure regardless of which command failed. The agent does not need different error-parsing logic per subcommand. Combined with non-zero exit codes, error handling is mechanical.
Non-Interactive Guarantee
The CLI never prompts when all required flags are provided. This is documented as an invariant in SKILL.md. Three commands (dhq init, dhq hello, dhq auth login) are interactive by design -- the rest are fully non-interactive when flags are supplied. An agent knows to avoid the interactive commands and supply all flags explicitly.
Stderr for Humans, Stdout for Machines
This separation means an agent can safely parse stdout as JSON without worrying about progress spinners, warnings, or decorative output contaminating the data stream. Humans still see friendly output on stderr when running interactively.
The Plugin Ecosystem
A SKILL.md file is useful, but how does an agent find it? We built multiple discovery paths:
plugin.json manifest. A .claude-plugin/plugin.json file declares the skill's name, version, description, and location:
{
"name": "deployhq",
"version": "1.0.0",
"description": "Deploy code, manage servers, and automate infrastructure via the DeployHQ CLI",
"skills": ["skills/deployhq"]
}
dhq setup claude installs the skill directly into a project's Claude Code configuration. One command and the agent has the SKILL.md in its context. Same for Codex, Cursor, and Windsurf.
Directory listings. Sites like skills.sh and claudepluginhub.com, plus GitHub topics, let users discover agent-ready CLI tools. The plugin.json manifest is what these directories index.
The goal is zero-friction adoption: a developer installs the CLI, runs dhq setup claude, and their agent can deploy code.
Real Workflow Examples
Deploy to Production
# Agent discovers available projects
dhq projects list --json
# Agent picks the right server
dhq servers list -p my-app --json
# Deploy latest code
dhq deploy -p my-app -s production --wait --json
# On success, breadcrumbs suggest: view logs, open in browser
# On failure, breadcrumbs suggest: view logs, retry, rollback
Debug a Failed Deployment
# Check recent deployments
dhq deployments list -p my-app --json
# Get details on the failed one
dhq deployments show dep-456 -p my-app --json
# Read the step logs to find the error
dhq deployments logs dep-456 -p my-app
# Roll back to the last good state
dhq rollback dep-456 -p my-app --json
Rollback Under Pressure
# One command -- rollback creates a reverse deployment
dhq rollback dep-456 -p my-app --json
# Monitor the rollback
dhq deployments watch <rollback-id> -p my-app
In each case, the agent follows the decision tree from SKILL.md, uses --json for parsing, and follows breadcrumbs for next steps. No guesswork.
How to Make YOUR CLI Agent-Friendly
Here are the concrete steps, roughly in priority order:
1. Add --json to every command. This is table stakes. If your output is only human-readable tables, agents cannot use your tool reliably. Bonus: let users select fields with --json field1,field2.
2. Separate data from decoration. Stdout should be pure data (tables or JSON). Progress bars, warnings, and color codes go to stderr. This lets agents pipe stdout safely.
3. Write a SKILL.md. One markdown file with: what the tool does, how to authenticate, what the output contract is, decision trees for common workflows, and gotchas. This is the highest-leverage documentation you can write.
4. Add breadcrumbs to JSON output. After every operation, include a breadcrumbs array with contextually relevant next commands. This turns your CLI from a bag of commands into a guided workflow.
5. Never prompt when flags are provided. If all required arguments are supplied via flags, the command should run without interaction. Document which commands are interactive and which are not.
6. Add a commands subcommand. Let agents dump your full command catalog as JSON at runtime. This is the self-discovery escape hatch.
7. Use consistent exit codes and error shapes. Zero for success, non-zero for failure. Errors should follow one JSON schema across all commands.
8. Ship a plugin manifest. A plugin.json with your tool's metadata lets agent ecosystems index and auto-discover your CLI.
None of these changes hurt the human experience. Structured output, consistent errors, and self-documentation make a CLI better for everyone. The agent-friendliness comes for free once you commit to these patterns.
The Takeaway
The best agent integration is often the simplest one. You do not need an MCP server, a custom SDK, or a SaaS integration layer. A well-structured CLI with --json output, a SKILL.md file, and breadcrumbs in responses gives any AI agent everything it needs to drive your tool competently.
Build for machines and humans at the same time. They want the same things: clear contracts, predictable behavior, and good error messages. The only difference is that machines read JSON and humans read tables.
deployhq-cli is open source under MIT. Try dhq setup claude to see the skill pattern in action.
Top comments (0)