machinemode.io
Companion to AOI‑CLI v1.0-alpha · Forward‑looking, non‑normative

Direction

Where AOI‑CLI goes after v1.0-alpha, and how it fits next to the standards around it.

Nothing on this page is normative in the current specification. It's committed direction: design that the work after v1.0-alpha will build on. Conforming tools should implement the AOI‑CLI v1.0-alpha spec today.

Editor · Kevin Hunt

Modes

§ 01 · Batch today, Session next

Everything in the current specification defines Batch Mode: one process invocation per operation, JSONL on stdout, a terminal aoi:summaryand a clean exit. That matches how agents call CLIs today, and it's the only normative mode in v1.0-alpha.

Session Modeis the next mode under design. A long‑lived process accepts a sequence of requests over stdin and writes responses and server‑initiated notifications to stdout. That's the shape LSP and MCP already use, generalized for any agent‑operable CLI: JSON‑RPC 2.0 messages, one per line (NDJSON framing), with id correlation for several in‑flight requests and $/event notifications for server pushes.

$ outline --mode session
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocol_version":"1.0-alpha","client":{"name":"my-agent","version":"1.0.0"}}}
{"jsonrpc":"2.0","id":1,"result":{"tool":"outline","tool_version":"1.8.2","capabilities":{"commands":["search","watch"],"wire_formats":["jsonl","cbor"],"push_notifications":true}}}
{"jsonrpc":"2.0","id":2,"method":"search","params":{"query":"agent operable","limit":2}}
{"jsonrpc":"2.0","method":"$/event","params":{"type":"hit","aoi":{"seq":0,"run":"01JZQ7X4TQ9"},"rank":1,"id":"doc_91"}}
{"jsonrpc":"2.0","method":"$/event","params":{"type":"hit","aoi":{"seq":1,"run":"01JZQ7X4TQ9"},"rank":2,"id":"doc_177"}}
{"jsonrpc":"2.0","id":2,"result":{"type":"aoi:summary","aoi":{"seq":2,"run":"01JZQ7X4TQ9"},"ok":true,"count":2,"truncated":false}}
Session Mode handshake: initialize, then a search request
  • NDJSON framing (one JSON message per line) instead of LSP's Content-Lengthheaders. MCP made the same choice for its stdio transport; it's simpler to implement, and AOI Session Mode tools and MCP servers end up sharing a transport.
  • Each event from the Batch Mode vocabulary (hit, match, aoi:warning, …) arrives as a $/event notification with the event object as params, and the terminal aoi:summary arrives as the JSON‑RPC result. The vocabulary stays the same while the transport changes.
  • Multiplexing comes free with JSON‑RPC id correlation: several requests can be in flight and their responses interleave as they complete, so it needs no separate spec.

Wire formats

§ 02 · JSONL by default, binary when needed

JSONL is the only normative wire format in v1.0-alpha, and it will remain the required baseline for every conforming tool. A wire you can read with your own eyes is a feature, not a compromise.

A tool may also offer compact binary encodings, advertised in capabilities and selected through HTTP‑style content negotiation:

FormatStatusWhen it earns the complexityReference
JSON / JSONLbaseline · requiredalwaysRFC 8259
CBORoptionalhigh‑rate telemetry · constrained bandwidth · large binary payloadsRFC 8949
MessagePackoptionalsame as CBOR, with broader language coveragemsgpack.org
Protobuf / Cap’n Protoout of scopewould force every tool to ship .proto / .capnp files; not justified yetnone

Negotiation works in the spirit of an HTTP Accept header:

shellshell
outline search "x" --output jsonl --accept "application/cbor, application/x-ndjson;q=0.5"

When negotiation finds no overlap, the tool must fall back to the baseline (JSON / JSONL) instead of failing.

Until you're credibly emitting thousands of events per second, or shipping large binary payloads, JSONL is the right answer.

Other profiles

§ 03 · The standard, on other surfaces

AOI‑CLI is the first formal profile of the Machine Mode standard. Each interface surface gets its own profile, because process boundaries, HTTP connections, message queues and physical actuators don't share I/O, framing, error or cancellation models.

SurfaceProfileStatus
Command‑line tools (local process)AOI‑CLIv1.0-alpha · shipping
HTTP services (remote endpoint)OpenAPI + AOI HTTP supplementOpenAPI de facto · supplement planned
Message queues / event streamsAOI‑Queuefuture
Embedded devices / sensors / actuatorsAOI‑Devicefuture

The ten factors are normative across every profile. What changes from one profile to the next is how each factor gets expressed at that surface's operational layer.

On OpenAPI

§ 04 · HTTP is already standardized

OpenAPI is the mature, widely adopted standard for describing HTTP service interfaces. When the Machine Mode HTTP profile gets written, it won'treinvent OpenAPI. It'll reference OpenAPI as the wire format and add the remaining factors (idempotency keys, terminal completion signals, dry‑run plans, structured error retryability) as a profile and style guide on top, likely as OpenAPI vendor extensions (x-aoi-*) plus a conformance document.

A well‑designed OpenAPI service already satisfies most of the ten factors implicitly. AOI‑CLI exists because the command line has no equivalent standard. The factors that apply to an OpenAPI service apply to CLIs too, but at the process boundary they're expressed differently.

The longer argument for why CLIs need their own profile, rather than turning into HTTP services, is in § 05 of the essay.

Relationship to Stainless and similar code generators

Several commercial products generate CLIs, MCP servers and SDKs from OpenAPI specs, and Stainless is the most prominent of them. These generators already produce structured, paginated, typed CLIs for HTTP services that publish OpenAPI documents. If you have an HTTP API and want a great CLI for it, Stainless is the best‑in‑class answer today.

AOI isn't a competing pipeline; it's a public conformance spec for the CLI surface. A serious version of the relationship would have Stainless and similar generators emit AOI‑conformant CLIs as one output target, with aoi-lintproviding the conformance check. Stainless would get vendor‑neutral spec backing for how its generated CLIs behave, and AOI would get a high‑quality codegen path that covers every Stainless customer's API.

AOI matters most on the surfaces commercial codegen can't reach:

  • CLIs with no OpenAPI spec behind them, which is most CLIs. git, kubectl, docker and terraform have API foundations, but each CLI is hand‑written on top and carries a lot of local‑state semantics.
  • Transformation and computation tools with no API at all, like ffmpeg, pandoc, jq, gpg, rustc and imagemagick.
  • System inspection and instrumentation: top, strace, tcpdump, perf, htop.
  • The coreutils gap (§ 07).

So the honest framing is that AOI is what Stainless's CLI output could conform to, not that AOI competes with Stainless. They occupy adjacent slots in the stack: Stainless is a codegen product for API‑derived tools, and AOI is a spec the whole CLI category can claim conformance to.

On MCP

§ 05 · Same transport; auth deliberately left out

The Model Context Protocol standardizes how an agent discovers and invokes tools, which makes it a transport and invocation layer. AOI is an operating contractfor what a tool does once it's invoked, so the two compose. AOI Session Mode (§ 01) uses the same transport MCP uses, and a conforming AOI‑CLI tool can sit behind an MCP server with a thin adapter. The ten factors describe good behavior for an MCP server's tools as well, though AOI‑CLI conformance itself is defined for command‑line tools. Machine Mode and MCP walks through the adapter field by field.

Authentication is deliberately out of scope

AOI doesn't standardize authentication, and that's on purpose. A CLI runs as the invoking user, with that user's credentials already in place: keychain, AWS credential chain, kubeconfig, ssh agent, gpg keyring, Vault token, gh PAT, corporate SSO session. Those ecosystems hold decades of work on MFA, role assumption, certificate pinning, browser‑based flows and credential renewal, and an AOI tool inherits all of it by inheriting the process environment.

MCP draws the same line. Its authorization spec covers HTTP transports and tells stdio servers to take credentials from the environment. A remote, wire‑level auth layer has to model federated identity itself; a local process doesn't, because authentication happens beneath the AOI invocation rather than at it. What AOI does specify is how a tool reports auth state: the standard error categories authn and authz, and aoi:check events from doctor.

Lineage

§ 06 · Where AOI sits in stream‑processing history

AOI isn't the first standard to formalize typed event streams between processes. It belongs to a long line of stream‑processing systems (Kafka, Flink, Spark Streaming, Apache Beam, materialized views and the rest of the data‑engineering stack), and it deliberately takes the smallest, simplest slice of that line.

The parallels are direct:

AOI conceptStream-processing analogue
source (emits JSONL)Kafka producer / Flink source
sink (reads --input-jsonl)Kafka consumer / Flink sink
transformer (reads + emits)Flink operator / Kafka Streams app
shell pipeinter-operator channel
schema_name@schema_version in metaConfluent Schema Registry subjects + versions
--idempotency-keyKafka idempotent producer / exactly-once writes
aoi:summary.next_cursorconsumer offsets
aoi:summary.truncated:true + cursorconsumer pagination
SIGPIPE / clean pipe-close handlingbackpressure propagation
terminal summaryend-of-stream / watermark
malformed-input handling modesdead-letter queue patterns

What AOI borrows from the lineage

The spec uses the producer, consumer, transformer and sink vocabulary consistently. In the long term it also takes the schema‑registry idea: a central index of schema names, so a consumer can fetch the schema for a tool it doesn't have installed. From the same tradition come idempotent writes via --idempotency-key, explicit truncation and cursors, backpressure through clean pipe‑close handling, and dead‑letter patterns for malformed input.

What AOI deliberately leaves out

Distributed runtime semantics stay out: event time versus processing time, watermark generation, state backends, exactly‑once across failures. So do operator DAGs and query planners, since shell pipes already compose at AOI's scale and do it naively well. Stateful operators such as windowing, joins and aggregations are out too, because a single AOI invocation is the state lifecycle, and the same goes for cluster topology, broker coordination and any query language on top. AOI is a contract at one process boundary, not a runtime that manages clusters of them.

AOI composes with stream processors

AOI is the Unix‑pipe‑shaped version of the same idea, with the same vocabulary about streams and a radically smaller operational scope. You can pipe AOI output into a Flink job that ingests JSONL, or write a Kafka consumer that feeds an AOI sink over stdin. The contracts bridge cleanly, and the same schema discipline applies on both sides.

The coreutils gap

§ 07 · Where adoption would help agents most

Much of the friction agents hit in shell sessions comes from coreutils, not from fancy tools. Shell work keeps reaching for ls, find, grep, cat, wc, head, tail, sort, uniq, du, stat, cp, mv, rm, awk, sed and xargs, and none of them speak AOI. They all emit ad‑hoc text formatted for human eyes, in formats that vary between GNU and BSD and with locale, terminal width and tool version.

While those commands return human‑formatted text, the agent parses it line by line. It hallucinates columns, misreads trailing whitespace, trips over locale‑dependent date formats, and spends context on header rows it can't tell are header rows. This is where AOI could do the most for an agent's day‑to‑day work. For what widely used CLIs emit in machine mode today, see the state of CLI machine output.

Two complementary strategies

StrategyHow it worksProsCons
machinemode (wrapper)Spawns the system's existing ls/find/grep/… and parses its output into AOI events.Works today against existing system tools, with nothing to install on the target side. Broad coverage, fast.Parsing is brittle and OS-specific (GNU and BSD output differ), and it can break when a tool updates.
aoi-coreutils (native)Native re-implementations of the same utilities, AOI-first: aoi-ls, aoi-find, aoi-grep and so on.Clean event emission with no parsing, and identical output on every operating system.Each tool has to be reimplemented to feature parity, and users install new binaries.

The two complement each other. machinemode gives the agent broad coverage today against whatever the system already has installed, while aoi-coreutils gives the most‑used tools a reliable, OS‑independent native implementation for cases where parser brittleness or cross‑platform consistency matters.

The seed set

Both projects would start here, in rough priority order:

  • Filesystem inventory: ls, find, stat, du
  • Text inspection: cat, head, tail, wc
  • Search: grep, rg (ripgrep)
  • Mutation: cp, mv, rm, mkdir
  • Streaming transforms: sort, uniq, cut, tr, awk, sed, xargs
  • Network and data: curl, jq, git log

Each one is a single PR's worth of work in machinemode (one wrapper module per tool) or a small standalone project in aoi-coreutils. A thousand small adapters is exactly the shape of work where agent‑driven code generation pays off: write the first one well by hand, then iterate.

Both projects are in the tools registry, with their current status.

Open questions

§ 08 · Drafts beyond v1.0-alpha
  • Should Session Mode default to NDJSON framing (MCP‑compatible) or Content-Lengthframing (LSP‑compatible)? We're leaning NDJSON.
  • Should the AOI‑HTTP profile, when it's written, define its own conformance lint, or extend aoi-lint to drive OpenAPI documents through the same factor checks?
  • Should AOI‑Queue, once designed, inherit Session Mode framing over a different transport or define its own?
  • Should the per‑factor conformance report from aoi-lint follow a standard JSON Schema, so consumers can ingest lint reports as data?
  • What's the right cadence for promoting a forthcoming mode such as Session from “design committed” to “normative in the next minor version” without forcing existing tools to add support right away?

The current normative specification is AOI‑CLI v1.0-alpha. For conforming behavior on the wire today, see the examples.