> ## Documentation Index
> Fetch the complete documentation index at: https://to11.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Client output formats

> Plain output is for people and may improve. `--format json` is a stable contract, and this is what it promises.

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` and `to11 skill` report nothing of their own, `init` is a conversation, and `code` prints nothing by design.

## 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.

```bash theme={null}
to11 skill list --format json 2>/dev/null | jq '.[] | select(.state == "dirty")'
```

**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.
* **Stable ordering**, so a diff of two runs is meaningful.

## `to11 skill list`

One row per skill and target.

```json theme={null}
[{ "slug": "incident-triage", "description": "Triage a production incident",
   "state": "unchanged", "target": "claude-code", "tracking": "pinned",
   "installedVersion": 4, "resolvedVersion": 4, "labelVersion": 7,
   "path": "/home/you/.claude/skills/incident-triage",
   "location": "home", "project": "acme/sre/runbooks", "label": "live" },
 { "slug": "house-style", "description": "How we write migrations",
   "state": "dirty", "target": "claude-code", "tracking": "label",
   "installedVersion": 2, "resolvedVersion": 4, "labelVersion": 4,
   "changedFiles": ["SKILL.md"],
   "path": "/work/api/.claude/skills/house-style",
   "location": "repo", "project": "acme/web/checklists", "label": "live" },
 { "slug": "my-own-notes", "state": "unmanaged", "target": "claude-code",
   "path": "/home/you/.claude/skills/my-own-notes", "location": "home" }]
```

| Field              | Type    | Present                                                      |
| ------------------ | ------- | ------------------------------------------------------------ |
| `slug`             | string  | always                                                       |
| `state`            | string  | always — one of the [states](#states)                        |
| `target`           | string  | always — the configured target this row is about             |
| `location`         | string  | always — `home` or `repo`                                    |
| `path`             | string  | always — the directory this row is about                     |
| `description`      | string  | when the platform returns one                                |
| `tracking`         | string  | `pinned` or `label`; **absent whenever no version resolved** |
| `installedVersion` | number  | when something of ours is on disk                            |
| `resolvedVersion`  | number  | what configuration resolves to                               |
| `labelVersion`     | number  | what the label publishes now                                 |
| `project`          | string  | `organization/workspace/project`                             |
| `label`            | string  | when a label is in play                                      |
| `archivedUpstream` | boolean | when the skill is archived and the label still resolves      |
| `changedFiles`     | strings | on `dirty` and `orphaned` — the files that differ            |

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 label 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.

```json theme={null}
[{ "slug": "incident-triage", "outcome": "installed",
   "diskAction": "install", "stateAction": "add",
   "target": "claude-code", "version": 7,
   "path": "/home/you/.claude/skills/incident-triage",
   "location": "home", "project": "acme/sre/runbooks", "label": "live" },
 { "slug": "house-style", "outcome": "dirty",
   "diskAction": "none", "stateAction": "none",
   "target": "claude-code", "version": 4,
   "path": "/work/api/.claude/skills/house-style",
   "location": "repo", "project": "acme/web/checklists", "label": "live" },
 { "slug": "audit-runbook", "outcome": "conflict",
   "diskAction": "none", "stateAction": "none",
   "target": "claude-code",
   "path": "/work/api/.claude/skills/audit-runbook",
   "location": "repo", "project": "acme/web/checklists" },
 { "slug": "legacy-migration", "outcome": "failed",
   "diskAction": "install", "stateAction": "add",
   "target": "codex",
   "reason": "the response from the platform was not what this client expects",
   "path": "/home/you/.agents/skills/legacy-migration",
   "location": "home", "project": "acme/sre/runbooks", "label": "live" }]
```

**`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`.

## `to11 whoami`

```json theme={null}
{ "person": "marius@to11.ai",
  "organizations": ["acme"],
  "profile": "default",
  "credentialKind": "person" }
```

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

## `to11 skill store`

```json theme={null}
{ "slug": "incident-triage", "version": 4, "versionId": "pv_01M2…",
  "project": "sre/runbooks", "location": "home",
  "created": false,
  "published": false,
  "installedTo": ["~/.claude/skills/incident-triage"] }
```

`published` is always `false` — [`release`](/docs/reference/cli/commands#to11-skill-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`

```json theme={null}
{ "slug": "incident-triage", "version": 4, "label": "live",
  "project": "sre/runbooks", "location": "home" }
```

## `to11 version`

```json theme={null}
{ "version": "0.4.2" }
```

## States

One word per state, the same in `list`, in `sync` and in JSON. Every one of
them 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`.

| State       | When                                                                              | Sync does                                    |
| ----------- | --------------------------------------------------------------------------------- | -------------------------------------------- |
| `installed` | Configuration includes it and nothing was at the destination                      | writes the file set                          |
| `updated`   | We had a record, and configuration resolves something else                        | writes what configuration resolves           |
| `replaced`  | `--force` took content at the destination we did not write                        | writes over it                               |
| `removed`   | Configuration no longer includes it, and it is ours                               | takes the directory, or just the record      |
| `unchanged` | Already what configuration resolves                                               | nothing                                      |
| `conflict`  | Configuration includes it, and something we never wrote is at the destination     | nothing — names the path, `--force` takes it |
| `dirty`     | Our directory holds changes we did not write, and configuration still asks for it | nothing — `--force` replaces it              |
| `orphaned`  | Our directory holds changes we did not write, and no configuration tracks it      | nothing — `--force` removes it               |
| `unmanaged` | A directory in a target path that was never ours and is not wanted                | nothing, ever                                |

**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.** The label moved from v7 to v4, so 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 label 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

| Reads                    | Means                                                                                                     |
| ------------------------ | --------------------------------------------------------------------------------------------------------- |
| `live · 4`               | following `live`, holding v4                                                                              |
| `live · 4 → 7`           | the label moved; a sync writes 7                                                                          |
| `pinned 4`               | pinned to v4, and the label publishes v4                                                                  |
| `pinned 4 (live: 7)`     | pinned and deliberately behind                                                                            |
| `pinned 5 (live: 4)`     | stored v5 and not released — you have work nobody has received                                            |
| `pinned 2 → 4 (live: 7)` | the pin changed and is behind; a sync writes 4                                                            |
| `7`                      | on disk at v7 and nothing resolves — the platform stopped publishing it, or your configuration dropped it |
| `—`                      | nothing on disk and nothing resolved                                                                      |
