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

# Non-interactive mode

> When the to11 CLI does not prompt, and the action_required object it answers with instead.

A coding agent runs `to11` in a shell with nobody at the keyboard. In that shell a question would wait forever, so the CLI does not ask it: it prints what it needs as one JSON object, and the agent either finishes the work with a command from that object or hands one sentence to a person.

## When the CLI does not prompt

A run is non-interactive when **any** of these holds:

| Condition | Notes |
| - | - |
| stdin is not a terminal | there is nobody to type an answer |
| stderr is not a terminal | questions are written to stderr. stdout carries only the result, so `to11 login \| tee log` still asks |
| `--non-interactive` | on `to11`, `to11 link`, `to11 login` and `to11 skill import` |
| `TO11_NON_INTERACTIVE` is set | any value except empty, `0`, `false`, `no` and `off` |
| an agent is detected | one of the variables below is set |

**`--interactive` overrides the flag, the variable and agent detection** — for a person working inside an agent's shell. It never overrides a missing terminal. `--interactive` with `--non-interactive` is a usage error.

The commands that can prompt are a bare [`to11`](/docs/reference/cli/commands#to11), [`to11 link`](/docs/reference/cli/commands#to11-link), [`to11 login`](/docs/reference/cli/commands#to11-login), [`to11 skill import`](/docs/reference/cli/commands#to11-skill-import), and [`to11 skill sync`](/docs/reference/cli/commands#to11-skill-sync), which asks one question: whether to remove a skill you picked that is no longer published. [`to11 ui`](/docs/reference/cli/commands#to11-ui) is a full-screen program and exits `1` without a terminal instead.

### Agent markers

An agent is detected from the variables a coding agent sets for the processes it runs. Any non-empty value counts, except where a value is given.

| Variable | Set by |
| - | - |
| `AI_AGENT` | the generic marker |
| `CLAUDECODE`, `CLAUDE_CODE` | Claude Code |
| `CURSOR_AGENT` | Cursor |
| `CURSOR_EXTENSION_HOST_ROLE=agent-exec` | Cursor, this value only |
| `GEMINI_CLI` | Gemini CLI |
| `CODEX_SANDBOX`, `CODEX_CI`, `CODEX_THREAD_ID` | Codex |
| `AUGMENT_AGENT` | Augment |
| `OPENCODE_CLIENT` | OpenCode |

Variables that a person's own shell also carries are not markers, because they would make a person at a terminal non-interactive: `CURSOR_TRACE_ID`, set in every Cursor terminal; `REPL_ID`, set in every Replit shell; `COPILOT_GITHUB_TOKEN`, `COPILOT_MODEL` and `COPILOT_ALLOW_ALL`; and `ANTIGRAVITY_AGENT`.

**A flag always wins over detection.** A marker changes whether the CLI asks, never what `--project`, `--organization` or any other flag means.

## What changes

Nothing is asked. Each value [`to11 link`](/docs/reference/cli/commands#what-it-decides) takes is read from its flag, its variable, the location's file and what can be derived, exactly as at a terminal. Then:

* a value that is still missing is the `action_required` answer below, and nothing is written;
* `Change targets?` is not asked, and the targets are what was detected or given;
* `Which skills?` is not asked, and the file's per-skill choices are left as they are — unless `--skill` names the skills to receive, which works the same with or without a terminal: `to11 link --project acme/web --skill code-review --skill incident-triage`, or `--skill '*'` for all. A name the project does not have fails the link, and nothing is written;
* the plugin offer is skipped, unless `--yes` was given;
* with nobody signed in, nothing is attempted — the answer is `not_signed_in`;
* after the link is written, skill folders already in the targets that to11 did not deliver are not adopted, uploaded or asked about: the answer is [`unmanaged_skills`](#unmanaged_skills), and the sync does not run.

## The `action_required` object

The command prints one JSON object on **stdout**, exits **`1`**, and writes nothing. Header lines such as `to11 CLI <version>` stay on stderr, so stdout parses as exactly one object.

```json theme={null}
{
  "status": "action_required",
  "reason": "missing_project",
  "message": "Name the project this directory receives skills from.",
  "choices": [
    {
      "name": "acme/web",
      "id": "proj_web",
      "matched": "directory name"
    },
    {
      "name": "acme/platform",
      "id": "proj_platform"
    }
  ],
  "next": [
    {
      "command": "to11 link --project acme/web --yes",
      "when": "Link this repository, then run `to11` with no flags"
    },
    {
      "command": "to11 link --project acme/platform --yes",
      "when": "Link this repository, then run `to11` with no flags"
    }
  ],
  "hint": "Run one of the commands in next[] to complete without prompting."
}
```

| Field | Type | Holds |
| - | - | - |
| `status` | string | always `action_required` |
| `reason` | string | what is missing — one of the [reasons](#reasons) |
| `message` | string | one sentence a person can read |
| `choices` | array of objects | the values the question would have listed. Absent when there is nothing to choose from |
| `next` | array of objects | commands that finish the work without prompting. Present only when such a command exists |
| `ask` | object | what a person has to do first. Present only when no command can finish the work |
| `hint` | string | one of two fixed sentences, chosen by which of `next` and `ask` is present |

Fields come in this order and are absent rather than null. The objects in `choices`, `next` and `ask` are flat: each field is a string. This is the one place the [JSON contract](/docs/reference/cli/output.md#action_required) nests, and it stays additive only.

**Exactly one of `next` and `ask` is present.** `next` means the caller can finish on its own; `ask` means it has to stop and hand the sentence to a person.

| Object | Field | Holds |
| - | - | - |
| `choices[]` | `name` | the organization slug, or the project as `workspace/project` |
| | `id` | its id |
| | `matched` | `directory name` when the project's name matches the repository's folder. Otherwise absent |
| `next[]` | `command` | a complete command line |
| | `when` | what it does: Link this repository, then run `to11` with no flags — or Link your home, then run `to11` with no flags. A `--global` step from inside a repository says to run `to11 skill sync` instead |
| `ask` | `message` | the sentence to relay to a person |
| | `url` | where the person does it — the dashboard. Absent for `not_signed_in` |

### The two hints

| Present | `hint` |
| - | - |
| `next` | `Run one of the commands in next[] to complete without prompting.` |
| `ask` | `No command completes this without a person. Relay ask.message to one, then run the original command again.` |

Both are fixed, so a script can match either string.

### Reasons

| `reason` | Carries | When |
| - | - | - |
| `missing_organization` | `choices`, `next` | you belong to several organizations and nothing names one. `next` has a step for every project, in every organization |
| `missing_project` | `choices`, `next` | nothing names exactly one project. A single directory-name match counts only with `--yes` |
| `not_signed_in` | `ask` | nobody is signed in and `TO11_API_KEY` is not set |
| `no_organization` | `ask` | you are not a member of any organization |
| `no_projects` | `ask` | the organization has no project you can read |
| `unmanaged_skills` | `choices`, `next` | the location's targets hold skill folders to11 did not deliver, and no flag says what to do with them. From `to11 link` and a bare `to11` after the link is written, and from `to11 skill import` |
| `not_linked` | `next` | `to11 skill import` ran where no location it lists is linked. `next` is `to11 link` |
| `ambiguous_skill` | `choices`, `next` | a `to11 skill import` flag named a slug waiting in both the repository and your home. Each choice is one folder, with its `location`; each `next` names by path a folder the flag can act on, and a choice it cannot carries a `reason`. When the flag fits neither folder, the command is refused as an error instead |

**A value you cannot read is the same question.** When `--organization`, `--project` or their variables name something you cannot read, the reason is the matching `missing_` one, `message` starts with a sentence naming the value — `acme has no project acme/nope that you can read.` — and `choices` holds only what you can read.

**Signing in is always an `ask`, never a `next`.** Non-interactive `to11 login` is itself `action_required`, so a `next` naming it would point an agent at the command that printed the object it was trying to resolve:

```json theme={null}
{
  "status": "action_required",
  "reason": "not_signed_in",
  "message": "Nobody is signed in on this machine.",
  "ask": {
    "message": "Run to11 login in a terminal and sign in, then run this command again."
  },
  "hint": "No command completes this without a person. Relay ask.message to one, then run the original command again."
}
```

### `unmanaged_skills`

Its `choices` are skill folders, each with the `location` it is in, and its `next` steps are `to11 skill import` lines — with `--global` for your home's folders, and a path in place of a slug waiting in both locations. A folder in a location that is not linked is a choice with a `reason`, and that location's `to11 link` is a step. The link file is already written when a link stops here; nothing else is.

```json theme={null}
{
  "status": "action_required",
  "reason": "unmanaged_skills",
  "message": "3 skills in ./.claude/skills were not delivered by to11. Say what to do with each, or skip them.",
  "choices": [
    {
      "name": "commit-style",
      "id": ".claude/skills/commit-style",
      "matched": "acme/web commit-style v4",
      "location": "repo"
    },
    {
      "name": "review-checklist",
      "id": ".claude/skills/review-checklist",
      "matched": "differs from acme/web review-checklist v2",
      "location": "repo"
    },
    {
      "name": "my-notes",
      "id": ".claude/skills/my-notes",
      "location": "repo"
    }
  ],
  "next": [
    {
      "command": "to11 skill import --adopt commit-style --yes",
      "when": "Record it as the published v4; nothing is uploaded"
    },
    {
      "command": "to11 skill import --keep review-checklist --yes",
      "when": "Keep the local copy and never deliver the published one here"
    },
    {
      "command": "to11 skill import --upload review-checklist --yes",
      "when": "Store it in acme/web as v3; whoever follows `latest` receives it on their next sync"
    },
    {
      "command": "to11 skill import --take review-checklist --yes",
      "when": "Replace the folder with the published v2; the files in it now are deleted"
    },
    {
      "command": "to11 skill import --upload my-notes --yes",
      "when": "Store it in acme/web as v1; whoever follows `latest` receives it on their next sync"
    },
    {
      "command": "to11 skill import --skip --yes",
      "when": "Leave every folder as it is; the sync reports them as conflicts"
    }
  ],
  "hint": "Run one of the commands in next[] to complete without prompting."
}
```

| Field | Holds |
| - | - |
| `choices[].name` | the folder's name, which is the skill's slug |
| `choices[].id` | the folder, relative to the location's root |
| `choices[].matched` | the published skill and version the folder is, or `differs from` the one it differs from. Absent for a folder the project does not have |
| `choices[].reason` | why the folder has no step in `next`, and what to do about it: `needs a description in SKILL.md; add a \`description:\` line to the front matter of SKILL.md, then run \`to11 skill import\` again\`. Absent otherwise |

`next` has one step per folder per outcome it can have — adopt for an exact match; keep, upload and take for one that differs; upload for one the project does not have, when a copy of it has a description in its `SKILL.md` (otherwise the choice carries a `reason`) — and a last step, `--skip`, that leaves every folder as it is. Each step acts on the folder it names and leaves the others, so any one of them exits `0`. A keep step promises the published skill is never delivered here only when no other target holds a copy of it that is, or can be adopted as, to11's; otherwise its `when` says the other targets keep receiving it. Run [`to11`](/docs/reference/cli/commands#to11) afterwards to sync: in a linked location it does not look at the folders again. A step carries `--project` when the location's file names several projects, and `--global` when the location is your home and the command runs inside a repository.

## The `next` commands

**A `next[]` command finishes without prompting** and exits `0`. Each carries every value already settled — `--organization` when you belong to several, `--project` — and the inputs that shape the file: any `--target`, `--prefix`, `--skill` and `--no-plugin` you gave, `--yes`, and `--global` when the location is your home and the command runs inside a repository.

**A `next[]` command never carries a credential.** The CLI takes no token flag, so none can reach a suggested command line.

After a link, `to11` with no flags syncs the location — the `when` field says so. A home linked from inside a repository is synced with `to11 skill sync`, because `to11` there acts on the repository. After a `to11 skill import` step, so does `to11`, or `to11 skill sync` for that home.

## `--yes`

`--yes` answers confirmations, never data questions. It accepts a single directory-name match, the detected targets and the plugin offer. It does not choose an organization or a project from several: with any of those open, the answer is still `action_required`.

## Next steps

> **[Commands](/docs/reference/cli/commands.md#to11-link)**
>
> What `to11 link` decides, in which order, and where it writes.

> **[Output formats](/docs/reference/cli/output.md)**
>
> Plain versus JSON, and what the JSON contract promises.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.