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

# Upgrade OuterLayer

> What to run after a new CLI version, on a laptop, in a repository and on a build host, and the changes that need you to act.

A new CLI version reaches three places: the machines people work on, the repositories they work in, and the runners that run builds. Each needs one step.

## On each machine

Install the new version the way you installed the first:

```bash theme={"system"}
npm install -g @outerlayer/cli@latest
```

If you run the CLI with npx, name the version, as in `npx -y @outerlayer/cli@latest`. Without it, npx can run a copy from its cache. Then run `outerlayer init --local` on a machine where a person works. It installs the [maintained skills](#the-maintained-skills-move-to-each-machine) in `~/.agents/skills/`. Then run `outerlayer doctor`. It names anything else on the machine that still needs a step.

The CLI names a newer version after a command in a terminal and at session start. That version is the newest release, or the version that the factory pins. The notice gives an exact-version install command, such as `npm install -g @outerlayer/cli@0.26.1`. It repeats until the machine runs that version. A machine with no login gets no notice. Set `OUTERLAYER_NO_UPDATE_NOTICE` to turn it off. At session start the CLI also tells you when the maintained skills in `~/.agents/skills/` come from another CLI version. Run `outerlayer init --local` to fix it.

Keep one CLI version across a team. In a repository that still keeps its own `.outerlayer/` directory, a teammate on an older version sees the maintained skills as changed, and their `context emit --check` fails.

## In each repository

A repository on the [`AGENTS.md` layout](/agent-context#move-a-repository-to-this-layout) needs one command and a commit. The command also removes the copies of the maintained skills that the repository still commits:

```bash theme={"system"}
outerlayer init --update
```

A repository that still keeps its own `.outerlayer/` directory needs two:

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

* `context emit` rewrites the [maintained skills](/starter-skills) to the installed version and recompiles every tool's copy.
* `init --update` brings the template skills, the policy and the two checks up to date where you have not edited them. In the `AGENTS.md` layout, it also rewrites the maintained skills. See [Update the files init wrote](/reference/cli-capture#update-the-files-init-wrote).

Review the diff and commit it. Nothing is committed for you.

A repository whose instructions come from a control plane needs neither command. Each session writes the maintained skills at the installed CLI's version. Run them in the control plane repository instead.

## On each build host

A runner started as a service updates itself and needs nothing. A runner with updates off is upgraded by hand. See [Keep the runner up to date](/run-a-host-as-a-service#keep-the-runner-up-to-date).

Then check the commands in its config file with `outerlayer runner check`. A command that names a skill by a name it no longer has is listed under `note`.

## Changes that need you to act

Each change names the CLI version that brought it. Act on it when you upgrade from an earlier version.

### Maintained skills start with `outerlayer-`

From CLI 0.16.0, the maintained skills have new names, so they can no longer land on a skill of your own:

| Earlier name | Name now |
| - | - |
| `amend` | `outerlayer-amend` |
| `emitting-evidence` | `outerlayer-evidence` |
| `reporting-findings` | `outerlayer-findings` |
| `outerlayer` | `outerlayer-cli` |

What to do:

1. **In a repository with its own `.outerlayer/`**, run `outerlayer context emit` and commit. It writes each skill under its new name, then deletes the old directory and every copy compiled from it, such as `.claude/skills/amend/`. Until you do, `context emit --check` reports the old files as `retired`. A skill of your own with one of the earlier names is left alone: only a directory the CLI wrote, whose `SKILL.md` says "maintained by OuterLayer", is removed.
2. **In your template skills**, replace the earlier names. `outerlayer init --update` does this for a template you have not edited. For one you edited, `outerlayer doctor` lists each file that still names a skill by an earlier name.
3. **On a build host**, change `/amend` to `/outerlayer-amend` in `runner.commands.amend`. Until you do, the runner runs `/outerlayer-amend` in its place and says so in the build's log and in `runner check`.
4. **When you start a skill by hand**, type `/outerlayer-amend` instead of `/amend`.

A repository whose instructions come from a control plane shows each skill once, under its new name, even before the control plane is updated. Update the control plane with step 1, so its own copies match.

### The build skill splits in two

From CLI 0.22.0, the build process lives in `outerlayer-build`, a maintained skill that follows the CLI. Your `build` skill holds only your repository's changes, so later changes to the process reach you when you upgrade.

What to do:

1. **If you never edited `build`**, run `outerlayer init --update` and commit. It replaces `build/SKILL.md` with the short skill. It removes the files under `build/` that the CLI no longer ships, such as `references/` and `scripts/`. A file there that you edited is kept. The short skill reads `outerlayer-build` from `~/.agents/skills/`.
2. **If you edited `build`**, `init --update` keeps it as it is, with the `references/` and `scripts/` beside it. `outerlayer doctor` says it gets no updates from the core, and shows the short `build`. To move onto it:
   1. Replace the contents of `build/SKILL.md` with the short skill. It starts with `Read ~/.agents/skills/outerlayer-build/SKILL.md and follow it from start to finish.`
   2. Under `## Changes for this repository`, add each of your edits under a `###` heading with the name of the phase it applies to: Intake, Criteria, Implement, Review, Pull request or Evidence. Express an edit as an added step, a setting, or a step turned off.
   3. Run `outerlayer context emit` and commit.
3. **If your criteria check names a brief under `build/references/`**, change `brief:` in `.outerlayer/validators/acceptance-criteria.yaml` to `.agents/skills/outerlayer-build/references/criteria-judge.md`. A repository that has not moved to the `AGENTS.md` layout keeps the skills in `.outerlayer/skills/`, so use that folder there. `init --update` does this for a check you have not edited. After `init --update`, the repository no longer holds that file. A runner host reads the brief from its own CLI, so the check still runs.

Run `outerlayer doctor` after. It names a heading that matches no phase, and an agent's skills folder that holds `build` without `outerlayer-build`.

### The maintained skills move to each machine

From CLI 0.27.0, the CLI keeps the five maintained skills once per machine, in `~/.agents/skills/`. Each skill has a link in `~/.claude/skills/`. A repository in the `AGENTS.md` layout carries none of them. `outerlayer init` installs them, and each later `outerlayer` command keeps them at its own version.

A CLI from before this release does not read `~/.agents/skills/`. Do these steps in this order:

1. **Upgrade the CLI on every machine and runner host.** This covers every laptop and every host that runs builds.
2. **Run `outerlayer init --local` on each machine a person works on.** It installs the skills and makes no network call. A build host installs them when a build starts its agent, so it needs no more.
3. **Run `outerlayer init --update` in each repository that carries copies of the maintained skills.** It removes each maintained skill folder that carries the "maintained by OuterLayer" line. It keeps a folder without the line. From CLI 0.27.3, it also changes each path to a removed folder to `~/.agents/skills/`, in `AGENTS.md`, `CLAUDE.md` and the repository's skills. In an edited `build`, `../outerlayer-build/SKILL.md` becomes `~/.agents/skills/outerlayer-build/SKILL.md`, and the rest of the file stays as it was. Review the diff and commit it.

Start step 3 only when every machine that works in the repository has finished steps 1 and 2. For runner hosts, `outerlayer init --update` from CLI 0.27.3 checks for you. With a login, it lists the factory's runner hosts from the gateway. It names each host on a CLI older than 0.27.0, and each host whose heartbeats stopped on one. It says not to commit until each one updates. It cannot check the machines people work on. A machine that has not finished them has no maintained skills after it pulls your commit. When a session starts on such a machine, the agent tells the person to run `outerlayer init --local`.

Run `outerlayer doctor` after. It names the maintained skill folders a repository still commits. It also names missing per-machine copies, in a repository whose `build` reads `~/.agents/skills/outerlayer-build/SKILL.md`.

A repository that has not moved to the `AGENTS.md` layout keeps its compiled copies. `outerlayer init --update` moves it first, then removes the copies. A cloud session on a machine with no CLI gets no maintained skills once a repository stops carrying them.

### Move a repository to the `AGENTS.md` layout

The `AGENTS.md` layout keeps instructions in `AGENTS.md` and skills in `.agents/skills/`, with nothing generated. See [Agent context](/agent-context). An earlier layout kept the sources in `.outerlayer/AGENTS.md`, `.outerlayer/skills/` and `.outerlayer/mcp.json`. `outerlayer context emit` then wrote copies into `CLAUDE.md`, `AGENTS.md`, `.claude/skills/` and `.mcp.json`, and you committed both. A repository in that layout keeps working until you move it.

Move it with one command:

```bash theme={"system"}
outerlayer init --update
```

Run `outerlayer init --update --dry-run` first to see the plan. The command works in this order, in every scope. A scope is the repository root, or a folder below it that has its own `.outerlayer/` directory.

1. It removes each generated file. These are the root `CLAUDE.md` and `AGENTS.md`, and the files under `.claude/skills/` and `.agents/skills/`. A file counts as generated when it has the header and exactly the bytes `emit` writes from its source.
2. It moves `.outerlayer/AGENTS.md` to `AGENTS.md`. It moves `.outerlayer/skills/` to `.agents/skills/`.
3. It moves the servers in `.outerlayer/mcp.json` into `.mcp.json`.
4. It links `.claude/skills` to `../.agents/skills`.
5. It sets `"layout": 2` in `.outerlayer/config.json`.

The command never deletes a file you edited. A generated file with other bytes is kept, and the command lists its path. A source stays where it is when its new place holds a file of yours. The command lists it, and does not set the layout. Resolve the clash and run the command again.

A committed source also stays when git ignores its new place. After the move, the next commit would delete it from the repository. Add an exception to `.gitignore`, such as `!/.agents/`, and run the command again.

If `.claude/skills/` still holds a file that is not generated, the command leaves the folder as it is. It makes no link, because a link would hide the file. It lists the file.

To move without the link, run `outerlayer init --update --no-skills-link`.

Two things stay where they are, because they have no new home:

* Command sources in `.outerlayer/commands/`, and the commands compiled from them. Run `outerlayer context emit` after you change a command.
* An `.outerlayer/mcp.json` in a repository with a `cursor` target. Cursor needs it to write `.cursor/mcp.json`.

After the move, `outerlayer context emit --check` exits 0. The update also changes the paths in starter files you have not edited. A file you edited may still name `.outerlayer/skills/`. The command lists such files so you can change the path.

**A control plane repository** holds the skills that govern other repositories. A CLI or runner older than 0.21.0 does not read `.agents/skills/`. It delivers none of those skills.

Move a control plane with `outerlayer init --update --control-plane`. The command prints this warning and makes no link. Keep `.claude/skills/` as an identical copy of `.agents/skills/` until those CLIs and runners upgrade, as [Move a control plane without breaking older CLIs](/share-instructions-across-repositories#move-a-control-plane-without-breaking-older-clis) describes.

### Compile a repository that has not moved

A repository that has not moved to the `AGENTS.md` layout keeps its sources in `.outerlayer/` and compiles them. Create `.outerlayer/config.json` naming the tools you run:

```json theme={"system"}
{
  "targets": ["claude-code"]
}
```

Put the shared instructions in `.outerlayer/AGENTS.md` and skills in `.outerlayer/skills/<name>/SKILL.md`. Then compile:

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

This writes each target's native files. For the `claude-code` and `codex` targets, `emit` prints a notice that names `outerlayer init --update`. The notice stops once the repository has moved. In CI, `outerlayer context emit --check` checks that the committed outputs match their sources. It cannot spot an orphaned `.mcp.json` or `.cursor/mcp.json`, because JSON has no room for the generated-file header. See [`outerlayer context emit`](/reference/cli-context#outerlayer-context-emit).

### Files an earlier CLI left in a governed repository

Earlier CLI versions wrote `.outerlayer-pin.json` at the repository root and asked you to commit it. The launcher and the session hook do not read it. A governed repository can delete `.outerlayer-pin.json`. A repository that no longer carries it shows no trace of its control plane.

A governed repository commits its own `AGENTS.md` or `.claude/`, or deletes `.outerlayer-pin.json`, only after everyone who works in it has upgraded the CLI. A CLI from before this change still refuses a repository that commits its own `AGENTS.md` or `.claude/`, and that repository's sessions then get no control plane.

Earlier CLI versions also copied `AGENTS.md`, `.claude/` and `.outerlayer/` into the working tree. At the next session start, and at the next `outerlayer claude`, the CLI removes exactly the files its record of those copies lists. It also removes the exclude block it added to `.git/info/exclude`, and the pre-commit guard it installed. Any other file under `.claude/`, such as `settings.local.json`, stays, and so does any other pre-commit hook. When an earlier CLI rewrote the committed `.outerlayer-pin.json` and the change is not staged, the file is put back to its committed version. A staged change to it, or one that is not in the pin's format, is left alone.

### A `governs` list is no longer read

A `governs` list in the control plane's `.outerlayer/config.json` decides nothing, and you do not need to keep one. `outerlayer doctor`, run in the control plane, warns when one is left. CLI versions before 0.17.0 still read it, so delete the list once every machine and runner runs 0.17.0 or later.

### Move an existing host to `claude.env`

A service that an earlier release set up keeps Claude's credential in
`runner.env`. Update the CLI, then run this command:

```bash theme={"system"}
outerlayer runner install --service --replace
```

The command asks for `sudo`. It does these steps in order:

1. It copies the credential line from `runner.env` into `claude.env`.
2. It writes the new unit and reloads systemd.
3. It removes the credential line from `runner.env`. Every other line stays.

You enter nothing again. The service restarts when no build runs. Otherwise
the new unit applies at the next restart.

A host that updates itself before you run the command already starts
Firecracker with an empty environment. Its runner also removes the
credential from its own environment at start. Its old unit still loads the
credential into the runner's environment until you run the command.

### Move an existing host onto the install layout

A runner installed without the layout, or whose service starts a version
directory instead of `current`, cannot update itself. It logs once that it
cannot, naming `outerlayer runner install`, and keeps taking work. To move
it:

1. Run `outerlayer runner install --service [--config <path>]`. It puts the
   CLI in the layout and rewrites the unit to start `current`.
2. If it says the unit differs, the unit was not written by this command.
   Run it again with `--replace`.

`outerlayer runner init` does this for a new host. `runner install` needs
the CLI installed with npm, not a source checkout. For a runner with its
own executables as hooks, run `outerlayer runner install` without
`--service`. It prints the `ExecStart=` line for its own unit.

### A microVM helper from an earlier release

A root helper that an earlier release installed for `builtin:vm` builds
differs from this release's helper in two ways:

* It ignores the runner's time limit, so the units it starts have no
  runtime limit.
* It does not write the CPU template that hides VMX and SVM, so its guests
  still see VMX and SVM.

Run `outerlayer runner install --service --replace` to install this
release's helper. See [The microVM helper](/build-security#the-microvm-helper).


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