Skip to main content
Two forms. --format plain is for people, and is not a contract — it may improve. --format json is a stable contract, and is the one an agent or a script reads. A command with nothing machine-readable to say takes no --format at all: to11 skill reports nothing of its own, ui is a screen, and code prints nothing by design. A bare to11 takes --format for the sync it runs, and its rows are to11 skill sync’s.

What holds in both forms

Nothing goes to stdout except the answer. Progress, warnings and errors go to stderr, so --format json piped into a parser stays valid even when something went wrong.
The scope is in the output, not assumed. Every row names its location and project, so nobody has to know which configuration produced an answer. Silence means nothing happened. A sync that changes nothing prints one line saying so, rather than nothing at all — an empty terminal is indistinguishable from a crash. --help is text on every command, never JSON: it describes a command rather than reporting anything, so there is no data in it to shape.

What --format json promises

Deliberately not the API’s shape. A chosen subset, so the API can change — fields renamed, endpoints reshaped — without breaking a script or an agent reading this output. An API field never reaches it by default; it reaches it because someone added it.
  • Additive only. No field is removed or retyped once shipped; new ones are added at the end.
  • Absent, not null. An unknown or inapplicable value omits the field.
  • Primitives and arrays of them — strings, numbers, booleans, and arrays of strings. Never a nested API object, so no API shape leaks through by accident. action_required is the one exception, below.
  • Stable ordering, so a diff of two runs is meaningful.

action_required

When it must not prompt, a command that needs an answer prints one action_required object on stdout instead of asking, whatever --format says, and exits 1. It is part of this contract, and the one type in it that nests, one level deep: choices and next are arrays of flat objects of strings, and ask is one flat object of strings. They follow the same rules — absent rather than null, additive only — and are objects because an agent acts on each choice or step as one record. Non-interactive mode has every field.

to11 skill list

One row per skill and target.
An unmanaged row carries only what the client knows without reading the directory: its name, its target, its path and its location. Never a version or an origin — guessing would be a claim about someone else’s files. labelVersion is how a pin behind its environment shows. The row is unchanged because configuration is satisfied, and the two numbers say the rest.

to11 skill sync

One row per skill and target. A skill configured for two targets is two rows.
outcome says what the run meant; diskAction and stateAction say what it did. They are separate because doing nothing to one and something to the other is an ordinary case rather than an exception — a skill dropped from configuration whose directory is already gone touches no files and still loses its record. outcome is installed, replaced, updated, removed, unchanged, conflict, dirty, orphaned, unmanaged or failed. diskAction is install, replace, uninstall or none. stateAction is add, update, remove or none. unchanged appears in JSON but not in plain — a machine wants the full set, a person wants the diff. It still carries version, because what is installed is a fact whether or not this run wrote it. failed replaces the outcome, it is not one of them. Every row whose diskAction is not none can fail, and reason says why: the platform does not publish the skill, the fetch broke, the write broke, the delete broke. A failure never reaches a field that means something else, and a run with one exits 1. releasedAt and releasedBy are the release a row installed. Present only when the platform said: on a row this run wrote from an environment, never on an unchanged row, a dry run, or a version installed by to11 skill store. releasedAt is RFC 3339 in UTC, with a fraction of a second when the release has one; releasedBy is a display name — never an email — and can be absent when releasedAt is present. heldBy is what holds a shadowed row’s name — the path in your own skills that already uses it. The row’s path stays its destination.

to11 whoami

With an API key, person is absent and apiKey carries the fingerprint — never the key.

to11 project list

to11 environment list

to11 provider list

to11 provider create

to11 provider kind list

to11 skill import

One row per skill folder the scan found, in the order the classification prints them.
class is match, differs or new. outcome is adopted, uploaded, kept, took, left or refused; reason is present on a refused row and on a new row whose SKILL.md has no description.

to11 skill store

published is always false — release is what changes that. created distinguishes a new skill from a new version of one, which is the guard against a mistyped slug.

to11 skill release

to11 version

States

One name per state, the same in sync and in JSON. The plain to11 skill list table says what the next sync would do instead, in the words of the list says column, and its summary counts with the same words. Each state in the first table except failed is decided from three things — whether configuration includes the skill, whether the state file records it, and whether anything is at the destination — plus two comparisons between those and --force. The states below are decided before anything at the destination is compared. Each is a reason a skill your configuration names is not delivered, so the row carries the reason instead of the skill being silently absent. Something at the destination we did not write outranks the version. A dirty directory is never asked what version it holds, because the answer cannot change what happens to it. A rollback needs no special state. Releasing v4 to the environment after v7 means what is recorded differs from what configuration resolves, and the row reads 7 → 4. The state says a sync will change this, not there is something newer. A pin behind its environment is unchanged, not a state of its own. Configuration is satisfied, so there is nothing to do — and the version column already shows both numbers, so a separate word would be a second way of saying it.

The version column, in plain output