Best for
- Use when building, modifying, or reviewing any agent-facing CLI.
kunchenguid/axi/.agents/skills/axi/SKILL.md
Agent eXperience Interface (AXI) — ergonomic standards for building CLI tools that agents use via shell execution. Use when building, modifying, or reviewing any agent-facing CLI.
Decision brief
AXI defines ergonomic standards for building CLI tools that autonomous agents interact with through shell execution.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/kunchenguid/axi --skill ".agents/skills/axi"Inspect the Agent Skill "axi" from https://github.com/kunchenguid/axi/blob/46d02d35f46a173dec5bd6be18827684fd1e885c/.agents/skills/axi/SKILL.md at commit 46d02d35f46a173dec5bd6be18827684fd1e885c. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Read the TOON specification before building any AXI output.
Use TOON (Token-Oriented Object Notation) as the output format on stdout. TOON provides 40% token savings over equivalent JSON while remaining readable by agents. Convert to TOON at the output boundary — keep internal logic on JSON.
Every field in stdout costs tokens — multiplied by row count in collections. Default to the smallest schema that lets the agent decide what to do next: typically an identifier, a title, and a status.
Detail views often contain large text fields. Omitting them forces agents to hunt; including them wastes tokens. Truncate by default and tell the agent how to get the full version.
The most expensive token cost is often not a longer response — it's a follow-up call. If your backend has data that agents commonly need as a next step, compute it and include it.
Permission review
The documentation asks the agent to run terminal commands or scripts.
**Make the error self-correcting in one turn.** The agent's deterministic next move after an unknown-flag error is to run `<command> --help` (e.g. `tasks list --help`) — so fold that lookup into the error: list the valid flags inline, or prThe documentation asks the agent to run terminal commands or scripts.
npx skills add <owner>/<repo> --skill <name>Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 94/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 1,908 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
AXI defines ergonomic standards for building CLI tools that autonomous agents interact with through shell execution.
Read the TOON specification before building any AXI output.
Use TOON (Token-Oriented Object Notation) as the output format on stdout. TOON provides ~40% token savings over equivalent JSON while remaining readable by agents. Convert to TOON at the output boundary — keep internal logic on JSON.
tasks[2]{id,title,status,assignee}:
"1",Fix auth bug,open,alice
"2",Add pagination,closed,bob
Every field in stdout costs tokens — multiplied by row count in collections. Default to the smallest schema that lets the agent decide what to do next: typically an identifier, a title, and a status.
--fields flag to let agents request additional fields explicitlyDetail views often contain large text fields. Omitting them forces agents to hunt; including them wastes tokens. Truncate by default and tell the agent how to get the full version.
task:
number: 42
title: Fix auth bug
state: open
body: First 500 chars of the issue body...
... (truncated, 8432 chars total)
help[1]: Run `tasks view 42 --full` to see complete body
--full) only when content is actually truncatedThe most expensive token cost is often not a longer response — it's a follow-up call. If your backend has data that agents commonly need as a next step, compute it and include it.
Aggregate counts: include the total count in list output, not just the page size. Agents need "how many are there?" and will paginate if the answer isn't definitive.
count: 30 of 847 total
tasks[30]{number,title,state}:
1,Fix auth bug,open
...
Derived status fields: when the next step almost always involves checking related state, include a lightweight summary inline.
task:
number: 42
title: Deploy pipeline fix
state: open
checks: 3/3 passed
comments: 7
Only include derived fields your backend can provide cheaply — a summary ("3/3 passed"), not the full data.
When the answer is "nothing", say so explicitly. Ambiguous empty output causes agents to re-run with different flags to verify.
$ tasks list --state closed
tasks: 0 closed tasks found in this repository
State the zero with context. Make it clear the command succeeded — the absence of results is the answer.
Don't error when the desired state already exists. If the agent closes something already closed, acknowledge and move on with exit code 0. Reserve non-zero exit codes for situations where the agent's intent genuinely cannot be satisfied.
$ tasks close 42
task: #42 already closed (no-op) # exit 0
Errors go to stdout in the same structured format as normal output, so the agent can read and act on them. Include what went wrong and an actionable suggestion. Never let raw dependency output (API errors, stack traces) leak through.
error: --title is required
help: tasks create --title "..." [--body "..."]
Every operation must be completable with flags alone. If a required value is missing, fail immediately with a clear error — don't prompt for it. Suppress prompts from wrapped tools.
Reject unknown flags and arguments — never silently ignore them. A dropped flag is worse than an error: the agent gets plausible-looking output it believes is scoped or filtered, then proceeds confidently on wrong data. This is the same guarantee a CLI already owes for an unknown command; extend it to flags.
$ tasks list --stat closed
error: unknown flag --stat for `list`
help: valid flags for `list`: --state, --assignee, --limit (--help always allowed)
--help always passes — it's the one universal flag. Beyond it, a CLI may standardize its own always-allowed globals (e.g. an --account selector); whatever the set, those flags pass on every command and are never reported as unknown.--status was renamed; use --state instead) so the agent self-corrects in one step.list vs a create under the same noun), validate against the subcommand's flags — they differ, and only the subcommand layer knows which is in play.<command> --help (e.g. tasks list --help) — so fold that lookup into the error: list the valid flags inline, or print the command's concise --help block directly beneath it. Per §4 the expensive cost is the follow-up call, and per §10 per-command help is already concise, so inlining it collapses the two-turn correction into one.Never mix progress messages into stdout. An agent that reads "Fetching data..." will try to interpret it as data.
Register your tool into the agent's session lifecycle so every conversation starts with relevant state already visible — before the agent takes any action.
Pattern:
# Agent sees this at session start — no invocation needed:
specs[2]{id,title,status}:
1,Fix auth bug,open
2,Add pagination,in-progress
help[2]:
Run `mytool specs view 1` for details
Run `mytool specs create --title "..."` to add a spec
Rules:
How to integrate with each app:
~/.claude/settings.json or project .claude/settings.json. Prefer SessionStart to inject compact context via stdout~/.codex/hooks.json or <repo>/.codex/hooks.json, and ensure [features].hooks = true in config.toml. Prefer SessionStart for ambient context via stdout~/.config/opencode/plugins/ or <repo>/.opencode/plugins/. Prefer ambient system-context injection for the home view rather than adding a custom toolAlso ship an installable skill (secondary recommendation):
The session hook is the primary integration, but it only helps agents whose harness supports hooks, and it loads on every session. Offer an installable Agent Skill as a secondary discovery path. It loads on demand when the agent recognizes a matching task, carries no per-session token cost, and works in any agent that supports the skill format. Recommend the hook first (ambient context plus live state) and the skill second (lower overhead, broader agent support) - they are complementary, and a user installs whichever fits, or both.
npx skills add <owner>/<repo> --skill <name>
SKILL.md from the same content your no-args home view prints, so the skill never drifts from the CLI's own guidance. Add a --check build step to CI that fails if the committed skill is stalenpx -y mytool ...), since a skill may be installed without the binary on PATHname and a description written as a trigger — terse and outcome-focused so the agent loads it on the right intentRunning your CLI with no arguments should show the most relevant live content — not a usage manual. When an agent sees actual state it can act immediately. When it sees help text, it has to make a second call.
$ tasks
tasks[3]{id,title,status}:
1,Fix auth bug,open
2,Add pagination,open
3,Update docs,closed
help[2]:
Run `tasks view <id>` to see full details
Run `tasks create --title "..."` to add a task
Include a few next steps that follow logically from the current output. The agent discovers your CLI's surface area organically by using it, not by reading a manual upfront.
Rules:
--repo, --source)<id> or "<title>" instead of guessing a concrete value that may mislead the agentRun 'mytool list' for all 47 items). Don't encode pagination into TOON array headers — use help hints instead.--help"The top-level home view should also identify the tool itself before the live data:
~$ tasks
bin: ~/.local/bin/tasks
description: Manage project tasks in the current workspace
...
Every subcommand should support --help with a concise, complete reference: available flags with defaults, required arguments, and 2-3 usage examples. Keep it focused on the requested subcommand — don't dump the entire CLI's manual.
--version fast path-v, -V, and --version must all print the bare version and exit 0. Agents and their harnesses probe --version constantly - to confirm a tool is installed, to check whether a fix has shipped, to decide whether to suggest update. That makes latency an ergonomics property, not just a perf tweak: a probe that takes 80 ms is 80 ms of every session start, paid before any useful work happens.
The trap is ESM static imports. If bin/<tool>.js statically imports the module that builds the command graph, every dependency in that graph is fully evaluated before the version check runs. One heavy import anywhere in the tree - an SDK, a server framework - is then paid on every --version.
Answer the version before the graph loads: keep the version in a leaf module that imports only node builtins, and defer the real CLI to a dynamic import().
#!/usr/bin/env node
import { tryFastPath } from "axi-sdk-js/fast-path";
import { VERSION } from "../src/version.js"; // leaf module - node builtins only
if (!tryFastPath(process.argv.slice(2), { version: VERSION })) {
const { main } = await import("../src/cli.js"); // heavy graph loads only here
await main();
}
axi-sdk-js/fast-path is a dedicated subpath export that imports nothing at all, so pulling it in never drags in runAxiCli or its dependencies. tryFastPath handles only a bare, single-argument version flag and returns false for everything else, so all other argv - including version flags in trailing positions - falls through to runAxiCli, which stays the single owner of the general case. Its accepted flags and output are identical to the SDK's own version handling, so adopting it changes nothing an agent can observe except the latency.
Two things keep this honest:
VERSION is defined inside cli.ts, importing it re-pulls the whole graph and the fast path buys nothing.node -e "console.log(1)" floor measured in the same process, rather than an absolute millisecond budget that goes flaky across machines.Frequently asked questions
AXI defines ergonomic standards for building CLI tools that autonomous agents interact with through shell execution.
The source record exposes this install command: npx skills add https://github.com/kunchenguid/axi --skill ".agents/skills/axi". Inspect the command and pinned source before running it.
Static rules flagged exec-script in the source; the page lists the matching lines and excerpts.