Autonomic TMC — CLI and developer portal
Project: A fleet-telemetry CLI and developer portal for onboarding and observing thousands of connected vehicles, with an API reference that cannot drift from the code.
Role: Product designer and builder, across CLI, portal, and API design.
Method: Human-centered API design (Harmon), task analysis of the operator's jobs, grammar-as-design-system with mechanical enforcement.
Outcome: One noun–verb grammar across 15 nouns and 64 operations; every documented command dispatched by a test; 284 tests, ~10 ms first paint; a self-contained portal that answers "can I build on this" by running a product on the stream.
Design for developers. The API is the product.
Autonomic's platform connects vehicles to the products built on top of them, and the people who meet that platform first are developers: the operator with five thousand vehicles arriving on Monday, and the engineer who has to decide whether to trust the API before writing a line against it. When we started, that decision was being made by reading a reference that could describe operations the code did not have, and by learning a command surface where two commands given the same flags could act on different sets of vehicles without anything on screen saying so. The problem was never the telemetry. It was that the interface asked developers to hold the system's inconsistencies in their heads, and the documentation asked them to take its word for it.
Design goals
One grammar. Every command is the same sentence — noun, verb, scope, output — and every noun answers the same verbs the same way. A developer who has learned one command has learned the shape of all of them.
Never lie by omission. The system says what it knows and marks what it doesn't. A check that hasn't run reads watching, not pass. A link is LIVE because frames are arriving, not because the transport said so. A map plots where a vehicle last reported, with the age of that fix beside it.
The pipe is a user too. Every screen a person can reach has a scriptable equivalent that emits JSON, because a view reachable only by hand is a view no script can check.

Product discovery
Developer interviews. Working with product and architecture, we ran discovery sessions with a body of customer developers — the people integrating against the platform today — on what made an API trustworthy in practice. The pattern was consistent: they judged an API by its consistency before its features, they read the reference before the code, and one wrong example in the docs cost more trust than a missing operation. That set the bar: the documentation had to be generated from the code and tested against it.
Task analysis. We mapped the operator's actual jobs — test a vehicle, onboard a fleet, create a group, push an update, see how the fleet is doing, chase a quiet vehicle — and found that no listing of commands answered the question they arrived with, which was "where do I start." The menu now opens on those tasks, in order, with the reason each step is a step.
Validation against the build. Developers worked with the CLI and portal as they shipped. The findings were specific and unglamorous: a manifest named Fleet Onboarding – Wave 2 (final).csv could not be typed at a shell without getting escaping right, so the tool accepts a file dragged from Finder and cleans every way a terminal mangles the path. Four examples in the command reference and five in the API reference turned out to be wrong the first time a test tried to run them — the kind of error no reviewer had caught and every developer would have.
Key solutions
The command grammar. auto <noun> <verb> [scope] [output]. Ten nouns, each with its own page. Verbs in three layers: list and show on every noun; validate | plan | apply | watch borrowed from terraform and kubectl so that "apply a manifest" arrives with its meaning already learned; and only then the verbs that belong to one noun. A single selector grammar — --vehicles, --group, --match, and their excludes — with identical semantics on every command, resolved by one implementation. The rules are assertions in a test, not conventions in a style guide, because a rule enforced by review lasts until the reviewer is busy.
[Diagram 1: the command grammar]
One source, every surface. The noun table and the API reference live beside the code. The menu, the help pages, auto docs, the OpenAPI spec and the portal's reference all render that one table, and a test walks every example each of them offers and dispatches it. Add, rename or drop a field and the documentation fails until it matches. The portal never authors a sentence about the contract; it renders what the CLI emits.
[Diagram 2: one source, many surfaces]
Honesty in the instrument. Link state is a glyph and a word, never colour alone. A frame that was buffered on the vehicle during an outage arrives tagged, keeps the time it was measured, and never refreshes liveness or inflates the arrival rate — it says nothing about now. A geofence crossing is shown as a window, not an instant, because position is sampled. At fleet scale, silence is decomposed into never-provisioned, parked, and stopped unexpectedly, and only the last one is a fault; a dashboard that totals them makes a depot of parked vehicles look like a depot that has fallen over.
The portal proves it rather than claiming it. A single self-contained HTML file, zero external requests, runs from a USB stick. It replays real traces the CLI produced through twenty-one conformance checks, plots the vehicle on real street geometry, models the fleet at 48,000 vehicles, and then runs an actual end-user application — a web dashboard and a phone app — on the same event stream. When the link drops, you watch what each surface admits to. That tab answers "can I build my product on this" by showing the product.
[Image: device preview tab during an outage]
The reference says what isn't built. Twenty-seven of the sixty-four documented operations are designed and not yet implemented. Rather than let a reader infer that from an absence, every operation carries its status — implemented, simulated, or designed — on the page and in the OpenAPI spec, and the spec leads with an empty servers block and a note saying why, because a generator will point a client at whatever base URL it finds.
For developers. One grammar to learn instead of a surface to memorise. A reference that is correct by construction, with every example proven to run. A conformance surface a developer can open before writing code and show a colleague afterward. The customer developers who validated the build were the ones who found the errors that mattered, which is the outcome discovery is for. For the platform. Documentation, spec and command surface can no longer disagree, because there is one of them. 284 tests across 16 packages guard the invariants; first paint measured at about 10 ms; a 2,000-frame reconnect burst lands without freezing input. The live adapter is deliberately a stub with the full shape and a loud failure, so the transport decision — still open — becomes one adapter rather than an architecture change.
