Tools · · 3 min read
Why agents need their own CLIs
Most of my work now runs through coding agents. They read tickets, query databases, review pull requests and change infrastructure. The tools they use for that were built for people: hcloud, mysql, the Jira web UI, Bitbucket’s API. People skim, scroll and know when to stop. Agents read every byte, pay for it in tokens, and do exactly what the command allows.
So I started writing CLIs for agents instead. They follow AXI, an open set of ten design principles for agent-ergonomic tools, and they are published on npm:
| Tool | For | Can it write? |
|---|---|---|
mongo-axi |
MongoDB | No, read-only |
mysql-axi |
MySQL | No, read-only |
bb-axi |
Bitbucket pull-request review | Comments, approvals |
atl-axi |
Jira issues, sprints, transitions | Field edits, comments |
hetzner-axi |
Hetzner Cloud servers, firewalls, volumes, DNS | Destructive or paid changes need --confirm |
Three rules that matter most
1. Read-only unless a person decided otherwise. mongo-axi and mysql-axi cannot write. It is not a flag an agent can flip: the write commands live in separate packages (mongo-rw-axi, mysql-rw-axi) that only talk to a database on the local machine. If I allow mongo-axi in an agent’s permissions, the agent has no write command available at all. That makes it safe to auto-approve, which is the whole point: an agent that has to ask before every query is an agent nobody uses.
2. Everything that costs money or destroys data previews first. hetzner-axi server delete web-1 prints what would happen and stops. Only --confirm runs it, and every change waits for Hetzner’s own action to finish before reporting back. Agents are confident; previews give the person a moment to catch the wrong server name.
3. Output is for a model, not a terminal. Results come back in TOON, a compact table format, with counts, a clear “nothing found” when the list is empty, and one or two hints for the next command. A server list is a few lines instead of a page of JSON. Fewer tokens means cheaper runs and, more importantly, less noise for the model to misread.
Secrets stay out of the transcript
Agent sessions are logged. Anything an agent types can end up in a transcript, so hetzner-axi never takes a token as an argument. It reads it from standard input or an environment variable and stores it in the operating system’s keychain. The agent uses the token without having to see it.
What changed
When this site moved to new servers, an agent created the DNS records with hetzner-axi. No dashboard was opened, and the API token never appeared in the chat. Adding a record is not one of the commands that waits for --confirm, so the record appeared without a preview; that is a gap I want to close.
That is the pattern I bring to client projects too: before an agent touches a system, decide what it may read, what it may change, and where a person signs off. Then give it a tool that cannot do more than that.
All five are on npm, MIT licensed.