6 specs · MIT · language-neutral

Agent-First CLI Specs

Five open conventions that make any CLI fully agent-first: learnable, drivable, reportable, and self-updating — and finally, measurable. Adopt any subset in 30 minutes per spec.

The agent lifecycle

An agent lands on a fresh machine with only the binary. Six commands, six specs.

myapp guide # learn the tool — embedded mental model
myapp help-json # discover commands — machine-readable catalog
myapp leads --json # drive the tool — data on stdout, errors typed
myapp feedback "…" # report issues — dual-write to app + relay
myapp update # stay current — content-hash, atomic swap
myapp telemetry # and the author finally knows it ran — disclosed, opt-out
myapp daemon start # background it — poll /_health, never a fixed sleep

The six specs

Each is independently adoptable. Together they make a CLI fully agent-first.

foundational output

cli-output-spec

The output contract. stdout = data only (JSON, parseable, versioned). stderr = context only (progress, logs). Semantic exit codes (80–119). Typed errors with recoverable and suggestions. help-json introspection. No internal retries.

stdout=data exit codes typed errors help-json
github.com/javimosch/cli-output-spec
capability guide

cli-guide-spec

The embedded mental model. <tool> guide bakes the full operator manual into the binary — the model, the loop, the concepts, the gotchas. An agent reads it once and drives the tool with no external docs. Optional HTTP: GET /guide + GET /llms.txt.

embedded JSON by default --human llms.txt
github.com/javimosch/cli-guide-spec
capability feedback

cli-feedback-spec

The dual-write relay. <tool> feedback sends feedback to the tool's own endpoint AND a central relay — same idempotency key, never fails the caller. Open submission, admin-gated reads. FEEDBACK_RELAY=off to opt out.

dual-write idempotent never-fail swappable relay
github.com/javimosch/cli-feedback-spec
capability update

cli-update-spec

Content-hash self-update. <tool> update downloads, verifies sha256[:12], smoke-tests, atomically swaps (current → .bak, new → in place). Passive stderr nudge when stale. No silent auto-update — manual by default. v1.1 adds <tool> install/uninstall — relocate or remove a binary already in hand (default ~/.local/bin, idempotent, never sudo).

content-hash verify-then-swap smoke test .bak rollback self-install
github.com/javimosch/cli-update-spec
capability telemetry

cli-telemetry-spec

An honest usage signal. Downloads, clones and stars all report the same zero whether nobody wants your tool or the install command has been broken since the first release — and an agent-operated CLI has no human who will ever file an issue. One POST, seven non-identifying fields, disclosed on stderr before the first send, and <tool> telemetry prints the real next payload so a reviewer verifies instead of trusting. DO_NOT_TRACK=1 honoured; CI defaults to off.

disclosed-first allow-list opt-out never-blocks inspectable
github.com/javimosch/cli-telemetry-spec
capability daemon new

cli-daemon-spec

Daemon lifecycle. <tool> serve --host --port binds loopback by default — never 0.0.0.0. GET /_health + POST /_shutdown, token-gated the instant the bind isn't loopback. <tool> daemon start|stop|status polls health instead of a fixed sleep, fully idempotent. Formalizes what chatsnip and machin-cms had already reinvented independently.

loopback by default health-probe shutdown token idempotent
github.com/javimosch/cli-daemon-spec

Reference implementations

Same contract, two languages, five tools. Each is a worked example.

#10003;#10003;#10003;
Tool Language output guide feedback update
grepapi machin + shell
mago Go
automaintainer Go
remotecmd Go
chatsnip machin

Shared design principles

The old Unix philosophy, tightened for LLMs.

Small on purpose

One command, one endpoint, one JSON shape. Addable in 30 minutes.

Language-neutral

The contract is the JSON shape and the behavior, not the implementation.

Independent

Each spec is adoptable alone. No cross-dependencies.

Agent-first

JSON by default, stderr for context, semantic exit codes, self-describing.

Unix-native

stdout is a pipe-friendly API. stderr is ignorable context. Exit codes are actionable.

MIT licensed

Copy them, fork them, adopt them. No attribution required.