Most CLIs are built for humans. Some are built for scripts. We built one for both — and for AI agents too.
DeployHQ CLI (dhq) is a Go command-line tool for the DeployHQ deployment platform. It manages projects, servers, deployments, and releases. But what makes it different is that it was designed from day one to work equally well when a human is typing, when a shell script is piping, or when an AI agent is orchestrating.
Here's what that looks like in practice.
The Output Contract
The single most important design decision: stdout is always data, stderr is always human text.
# Human sees a nice table on stderr, data goes to stdout
dhq projects list
# Pipe it and get JSON automatically — no flag needed
dhq projects list | jq '.data[].name'
When stdout is a TTY, you get a formatted table. When it's piped, you get JSON. No --json flag required (though you can use it explicitly).
Field Selection with --json
Most CLIs give you --json and dump everything. We give you --json <fields>:
# Only get what you need
dhq deployments list -p my-app --json identifier,status,timestamps.duration
# An agent requesting just the deployment ID and status
dhq deploy -p my-app -s prod --use-latest --json identifier,status
This matters for agents because tokens cost money. A full deployment object might be 50+ fields. An agent checking status needs two.
Breadcrumbs: Teaching Agents What To Do Next
Every JSON response includes a breadcrumbs array — suggested next commands based on what just happened:
{
"data": { "identifier": "abc123", "status": "completed" },
"breadcrumbs": [
"dhq deployments logs abc123 -p my-app",
"dhq deployments show abc123 -p my-app --json"
]
}
An AI agent doesn't need to memorize your API. It reads the breadcrumbs and knows what's possible next. This turns a stateless CLI into a guided workflow.
Agent Detection
The CLI detects when it's being used by an agent:
export DEPLOYHQ_AGENT=1 # Explicit agent mode
export CLAUDE_CODE=1 # Auto-detected
export CI=true # Auto-detected
In agent mode, the CLI adjusts its behavior — suppressing interactive prompts, defaulting to structured output, and including richer metadata.
JSONL Capture
Set DEPLOYHQ_OUTPUT_FILE=log.jsonl and every command's output gets appended as a JSONL line. Useful for:
- Agent audit trails
- CI pipeline debugging
- Replaying what happened during an automated workflow
Non-Interactive Auth
Three env vars, no browser popup:
export DEPLOYHQ_ACCOUNT=myaccount
export DEPLOYHQ_EMAIL=me@example.com
export DEPLOYHQ_API_KEY=abc123
This is table stakes for CI, but it matters even more for agents. An AI agent can't click "Authorize" in a browser.
Exit Codes That Mean Something
-
0— success -
1— failure (with structured error in JSON) - Empty results return
0with emptydata— that's not an error
Simple, but surprisingly rare. Many CLIs return 0 on errors or don't include error details in their JSON output.
The Go SDK Inside
The CLI wraps a public Go SDK at pkg/sdk/ with 97 methods. The SDK has zero internal imports — it's designed to be extractable as a standalone module:
client := sdk.NewClient("account", "email", "apikey")
projects, err := client.ListProjects()
If you're building Go tooling around DeployHQ, you can use the SDK directly without shelling out to the CLI.
What We Learned
Building for agents changed how we think about CLIs:
- Structured output isn't optional — if your CLI can't produce JSON, agents can't use it reliably
- Field selection saves tokens — agents pay per token, don't make them parse 50 fields to get 2
- Breadcrumbs beat documentation — agents don't read man pages, but they read JSON responses
- Non-interactive is non-negotiable — if it needs a human to click something, agents can't use it
- Piped detection is free UX — detect TTY vs pipe and adjust automatically
The future of CLIs isn't human OR machine. It's both.
Links:
- GitHub: https://github.com/deployhq/deployhq-cli
- Install:
brew install deployhq/tap/dhq - DeployHQ: https://www.deployhq.com
Top comments (0)