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

# Context, launcher and MCP commands

> context emit, the outerlayer claude launcher, and the mcp commands.

## outerlayer context emit

Compile `.outerlayer/` into each configured target's native files.

```bash theme={"system"}
outerlayer context emit [--check] [--dir <path>] [--json]
```

| Flag | Default | What it does |
| - | - | - |
| `--check` | off | Compute the outputs and compare them with disk. Writes nothing. For CI. |
| `--dir <path>` | current directory | The repository root to read from. |
| `--json` | off | Print the result as one JSON document. |

For a repository whose targets are only `claude-code` or `codex`, `emit` prints a notice that names `outerlayer init --update`. Both tools read `AGENTS.md` and `.agents/skills/` as written, so the generated copies are not needed. The notice stops once the repository has declared `"layout": 2`. In that layout `emit` rewrites no maintained skill and deletes no orphaned `AGENTS.md`, `CLAUDE.md` or skills file. The `cursor` target still gets `.cursor/commands/` and `.cursor/mcp.json` from `emit`.

Targets come from `targets` in `.outerlayer/config.json`: `claude-code`, `cursor`, `codex`, `copilot`, `factory`. There is no `--target` flag. Bare `outerlayer emit` with no name still runs this, with a deprecation line.

A maintained skill (`outerlayer-evidence`, `outerlayer-amend`, `outerlayer-findings`, `outerlayer-cli`, `outerlayer-build`) whose directory exists is rewritten to the installed CLI's copy. `--check` reports one that differs as drift. Template skills (`spec`, `writing-specs`, `writing-tests`, `build`) are never rewritten or reported.

An earlier CLI may have written a copy under the skill's former name (`amend`, `emitting-evidence`, `reporting-findings`, `outerlayer`). Emit replaces it. It writes the skill under its current name, then deletes the old source directory and every copy compiled from it. `--check` reports those files as `retired`. Only a directory whose `SKILL.md` carries the "maintained by OuterLayer" line is removed. A skill of your own with one of those names is left alone.

```bash theme={"system"}
outerlayer context emit
outerlayer context emit --check
```

`--check` reports missing files and changed content for every output. It reports an orphaned output only when the file carries the generated-by header. `.mcp.json` and `.cursor/mcp.json` are JSON and carry no header, so they are never reported as orphaned.

An orphaned output is a generated file whose source is gone. `emit` deletes each one `--check` would report, and each directory that leaves empty. A file without the header is never deleted.

Neither form reads inside another repository's tree: a directory that holds a `.git` entry (a nested clone or a submodule) or a `.outerlayer-pin.json` file (a governed clone). Its files are neither sources nor outputs.

Exit codes: 0 on success. 1 on drift under `--check`. 1 when `.outerlayer/config.json` is missing or has no targets; the message shows the fix, such as `{"targets": ["claude-code"]}`.

See also: [Agent context](/agent-context), [The .outerlayer directory](/reference/outerlayer-directory).

## outerlayer claude

`outerlayer claude [args…]` starts Claude Code with the control plane that governs the checkout attached.

```bash theme={"system"}
outerlayer claude [args…]
```

It takes no flags of its own. Every argument goes to Claude Code unchanged, `--help` included. It runs the first `claude` on `PATH` that is not the build's own `claude` program.

Where a control plane governs the checkout, it starts Claude Code with these added before your arguments:

| Added | Value |
| - | - |
| `--add-dir` | The directory that holds the control plane's copy. |
| `--add-dir` | A folder under `~/.outerlayer/context/own/` that links the checkout's own `.agents/skills/` skills, so Claude Code loads them under their own names. Added only when the checkout has such skills. |
| `--settings` | `<directory>/settings.json` |
| `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD` | `1`. Claude Code reads the directory's `CLAUDE.md`, for subagents too. |
| `OUTERLAYER_CONTROL_PLANE_DIR` | The directory. See [Variables `outerlayer claude` sets](/reference/environment-variables#variables-outerlayer-claude-sets). |

Where no control plane governs the checkout, it starts Claude Code with your arguments alone, plus the `--add-dir` for the checkout's own skills.

Before it starts Claude Code, it installs the maintained skills in `~/.agents/skills/`, as every `outerlayer` command does.

**On a laptop**, it asks OuterLayer which control plane governs the checkout and which commit it stored. It keeps a composed copy of that commit in `~/.outerlayer/context/<owner>/<repo>/<commit>/`, and records the copy in the checkout's git directory. Nothing from the control plane is written into the working tree. With OuterLayer unreachable, it starts with the last copy and says the copy may be out of date. See [Share instructions across repositories](/share-instructions-across-repositories#what-a-laptop-session-does-in-a-governed-repository). To make plain `claude` start it, see [Make plain claude start the launcher](/reference/cli-capture#make-plain-claude-start-the-launcher).

**In a build**, the runner delivers the control plane first. A governed build reads its control plane from a directory outside the checkout. In a governed build, `claude` runs `outerlayer claude`. The runner writes a `claude` program to `~/.outerlayer/bin/` and puts that directory first on the command's `PATH`, in every build. A configured command needs no change. A command such as `claude -p "Build the issue"` works as it is. `outerlayer claude` finds the runner's delivery record and attaches that directory. See [A governed repository's context](/container-builds#a-governed-repositorys-context).

In a build that no control plane governs, the runner sets `OUTERLAYER_GOVERNANCE=self`. `outerlayer claude` then asks the gateway nothing and does not check the Claude Code version. The runner's delivery record decides in a governed build, whatever the variable says.

It refuses to start Claude Code older than 2.1.284 in a governed checkout. That is the oldest version known to load a control plane's `CLAUDE.md` for subagents. In a build, the runner refuses the build earlier, at provision, from the version in the image.

`outerlayer hook SessionStart` copies nothing into the checkout when `OUTERLAYER_CONTROL_PLANE_DIR` is set. It still records the session start, renews the lease and uploads the session.

A control plane's hooks name their scripts as `${OUTERLAYER_CONTROL_PLANE_DIR:-$CLAUDE_PROJECT_DIR}/.claude/…`. The delivery also rewrites `$CLAUDE_PROJECT_DIR/.claude`, `"$CLAUDE_PROJECT_DIR"/.claude` and `${CLAUDE_PROJECT_DIR}/.claude` in the delivered `settings.json`. Run `outerlayer doctor` in a control plane to name any hook command that reaches `.claude/` another way.

Exit codes: Claude Code's own exit code once it starts. 127 when no `claude` is on `PATH`. 1 when it refuses: the control plane cannot be attached, or Claude Code is too old.

## outerlayer mcp install

Write or update the `outerlayer` MCP server entry. It writes the entry to `.outerlayer/mcp.json` when that file exists, else `.mcp.json`. It never writes an API key.

```bash theme={"system"}
outerlayer mcp install [--transport stdio|http] [--command <exe>] [--url <url>] [--name <name>]
                       [--dir <path>] [--app-id <uuid>] [--json]
```

| Flag | Default | What it does |
| - | - | - |
| `--transport stdio\|http` | `stdio` | `stdio`: the client spawns `outerlayer mcp serve`, which reads the key on each connect. `http`: the entry calls the gateway directly with `${OUTERLAYER_API_KEY}`, which the client resolves from its environment. |
| `--command <exe>` | `outerlayer` | Stdio only. The executable the client spawns. Use an absolute or `${HOME}`-relative path when the CLI is not on the client's `PATH`. |
| `--url <url>` | stdio: none; http: the gateway you logged in to, plus `/v1/mcp` | The gateway MCP endpoint. With stdio and no `--url`, `mcp serve` resolves it at connect time. For a self-hosted gateway, pass its origin plus `/v1/mcp`. |
| `--name <name>` | `outerlayer` | The `mcpServers` key to write under. |
| `--dir <path>` | current directory | The repository root to write into. |
| `--app-id <uuid>` | none | Self-host only. The factory id, sent as `X-Outerlayer-App-Id`. Without it a self-hosted gateway answers 401. |
| `--json` | off | Print `path`, `server`, `transport`, `url` and `changed`. |

```bash theme={"system"}
outerlayer mcp install
outerlayer mcp install --transport http
```

Exit codes: 0 when written or already current. 1 when `--transport` is not `stdio` or `http`, or `--dir` does not exist. 1 with `--transport http` and no gateway: pass `--url` or run `outerlayer login`. 1 when `.mcp.json` is not valid JSON, its top level is not an object, or its `mcpServers` is not an object: fix or remove the file, then rerun.

See also: [Use the MCP server](/mcp).

## outerlayer mcp serve

Run a stdio MCP server that bridges to the gateway. The stdio `.mcp.json` entry runs this.

```bash theme={"system"}
outerlayer mcp serve [--url <url>] [--app-id <uuid>]
```

| Flag | Default | What it does |
| - | - | - |
| `--url <url>` | `OUTERLAYER_URL`, or the config file's gateway, plus `/v1/mcp` | The gateway MCP endpoint. |
| `--app-id <uuid>` | `OUTERLAYER_APP_ID`, then the repository's connection or the config file | The factory id, sent as `X-Outerlayer-App-Id`. |

It reads a factory key, or your login, at start-up. See [Credential resolution](/reference/cli#credential-resolution).

It exits 1 before reading any input when it cannot connect. The MCP client shows the message as the connect error:

| Message | Fix |
| - | - |
| no API key | Run `outerlayer login`, or set `OUTERLAYER_API_KEY`. |
| no gateway URL | Run `outerlayer login`, set `OUTERLAYER_URL`, or pass `--url`. |
| logged in, but no factory is chosen | `work` and `emit` commands such as `work build` and `emit artifact` connect automatically when one factory fits, but the MCP server never does. Run `outerlayer connect` in the repository, or pass `--app-id` or set `OUTERLAYER_APP_ID`. See [Automatic connection](/reference/cli-cloud#automatic-connection). |

See also: [Use the MCP server](/mcp).


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