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

# CLI errors and exit codes

> What a to11 failure looks like, which exit code it carries, and what keeps working when one happens.

An agent runs these commands unattended, so a failure has to be legible to a program as well as to a person.

## Exit codes

**By default there are two.** A caller branches on *worked* or *did not*, and which kind of failure it was is in the message.

| Code | Meaning                                                                                                                                                                             |
| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0`  | Did what was asked                                                                                                                                                                  |
| `1`  | Did not — network, credentials, the platform does not publish a skill you configured, two projects publish one skill into one target, a write failed, or the command line was wrong |

[Hook modes](/docs/reference/cli/commands#refresh-hook-modes) always exit `0` whatever happens: a refresh does not get a vote on whether your work proceeds.

`to11 code` exits with **the agent's** exit code, so wrapping your agent in it changes nothing about what your shell sees.

The exception is a session that never starts. A missing [`code.claude.yaml`](/docs/reference/cli/configuration#codeclaudeyaml), or a project, environment or provider in it that cannot serve the session, exits `1` — the agent was not launched, so there is no exit code of its own to pass on.

### Detailed exit codes

`to11 skill sync --detailed-exitcode` splits the outcome. **Only when asked for** — without the flag, `sync` exits `0` or `1` like everything else.

| Code | Meaning                                                                                                             |
| ---- | ------------------------------------------------------------------------------------------------------------------- |
| `0`  | Nothing differed. The machine already matched its configuration                                                     |
| `1`  | Error — a location could not be reconciled                                                                          |
| `2`  | Something differed, and nothing failed. Installed, replaced, updated, removed, or left alone because you changed it |
| `3`  | The command line was wrong                                                                                          |

**`3` exists because `2` took the meaning `1` used to carry for it.** With detailed codes on, a non-zero exit is ambiguous unless a bad flag is distinguishable from a real failure — a script that treats `2` as drift and `1` as broken would otherwise read a typo as a broken platform and start alerting.

Paired with `--dry-run` this is a drift check, which is what a build step wants:

```bash theme={null}
$ to11 skill sync --dry-run --detailed-exitcode
house-style  2 → 4  would update
$ echo $?
2
```

`0` means the machine matches its configuration, `2` means it does not, `1` means the question could not be answered — which is different from the answer being no.

**Skipped counts as differing, not as failing.** A skill you edited on disk means the machine does not match its configuration, and a build step should see that; but nothing went wrong, so it is not `1`.

**It is opt-in** because a non-zero exit on a successful run breaks every script that does not know about it.

## What an error says

Every error names three things: **what failed, where, and what to do about it.**

```text theme={null}
error: cannot reach api.to11.ai
  your skills are unchanged and your agent keeps working
  retry, or check your connection
```

```text theme={null}
error: not configured
  looked in ~/.to11/skills.yaml and /work/api/.to11/skills.yaml
  run `to11 init` to set one up
```

```text theme={null}
error: /work/api/.to11/skills.yaml is not readable
  line 7: mapping values are not allowed here
  fix the file — we will not fall back to your home config, because that
  would silently give you fewer skills than the repository intends
```

**No stack traces**, ever. A panic is a defect in this CLI, and printing our internals at you asks you to debug our code.

Everything above goes to **stderr**, so `--format json` on a failing command still parses.

## Partial failure

**Locations fail independently.** One location reconciling while the other cannot is reported as exactly that, and the exit code is `1` because something was asked for and did not happen:

```text theme={null}
home   2 installed, 1 updated
repo   error: no access
1 of 2 locations failed
```

**Each file is written whole or not at all.** Files land in place, one at a time, so nothing ever reads half of one. A skill that fails part-way can leave the destination holding some files from the new version and some from the old. The run records what is there and reports the skill as failed, so running `to11 skill sync` again repairs it — no `--force`, and nothing calls your own directory a conflict. A location that fails leaves every skill it had not yet reached untouched.

## Degraded beats broken

When something breaks, less still beats nothing — so failure has a shape:

* **A fetch that fails changes nothing.** Previously installed skills stay exactly as they are, and your agent keeps working with what it has.
* **An expired credential is an error, not a wipe.** Nothing is removed on the assumption that access was lost: that is indistinguishable from a network problem, and the recovery from guessing wrong is losing every skill at once.
* **An unreadable repository config is an error, not a fallback.** Silently resolving from your own config alone would install fewer skills than the repository intends, without saying so.
* **A skill you edited is left alone, not overwritten** — the row reads `dirty`. The recovery is yours to choose: commit it with `to11 skill store`, or discard it with `to11 skill sync --force`.
* **Two projects publishing one skill name installs neither, and exits `1`.** One directory cannot hold both, and picking one would depend on the order the projects appear in your config. The run names both projects and the skill, leaves whatever is already at that directory alone, and every other skill in the run is installed normally. Anything already installed there stays installed, and stays recorded — a skill your config asks for twice is not a skill your config dropped. This is the one warning-shaped outcome that still fails the run: no flag resolves it, so a `0` would report success for a sync that installed fewer skills than you asked for. Give one project a different [prefix](/docs/reference/cli/configuration), or name the skill under one project.

## Failing while nobody is watching

An automatic refresh has no terminal to print to. So:

* It **exits `0` regardless.**
* It **says nothing, and leaves no note behind.** Nothing about a failed refresh is stored for a later command to report.
* It **never retries in a loop.**

**`to11 skill sync` performs the same reconciliation and reports what that run finds** — what is in sync, what conflicted, what it updated, and anything it could not do.

## Common failures

| Message                                          | Usually means                                                                                                          | Do                                                                                                                                                               |
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `not configured`                                 | Neither location has a `skills.yaml`                                                                                   | `to11 init`                                                                                                                                                      |
| `your credential was refused`                    | The stored credential expired, or `TO11_API_KEY` is wrong                                                              | Fix `TO11_API_KEY` if it is set — it wins over the stored credential, so `to11 init` cannot replace what it supplies. Otherwise `to11 init`. Nothing was removed |
| `no access`                                      | The credential cannot reach that project                                                                               | Ask whoever administers the organization                                                                                                                         |
| `unknown key … in configuration`                 | A typo in `skills.yaml`                                                                                                | Fix the spelling — the error names the key                                                                                                                       |
| `… is not ours — use --force`                    | A directory the CLI did not write occupies a skill's path                                                              | Move it, or `to11 skill sync --force` to take it                                                                                                                 |
| `changed on disk`                                | You edited an installed skill                                                                                          | `to11 skill store` to keep it, or `--force` to revert                                                                                                            |
| `… is no longer configured, and has been edited` | Your configuration stopped asking for that skill or that target, and the directory it left behind is not what we wrote | Move what you want to keep, then `to11 skill sync --force`. Reported on every sync until it is dealt with                                                        |
| `configuration is version N`                     | The file was written by a newer CLI                                                                                    | Upgrade the CLI                                                                                                                                                  |
| `unknown option "-format"`                       | A single-dash long option                                                                                              | Write `--format` — long options take two dashes                                                                                                                  |
