AGENTS.md@packages/clones · git:20261019.5f26fa0 · 2026-10-19 · sha256 a9d28d48962e4f09

AGENTS.md@packages/clones git:20261019.5f26fa0A

Immutable. This exact content never changes and is served at /api/v1/blob/a9d28d48962e4f09.

# @shadowclone/clones

Runs clones: Claude Code or Codex works for the owner, as the owner, in Docker on a machine that the owner owns. The owner starts a clone from the CLI or the MCP server on that machine. The CLI and the MCP server call it. [Design record 049](../../docs/design/049-clones.md) explains the design.

<!-- package-facts:start -->

(generated by `bun run guides`; do not edit by hand)

- Package name: `@shadowclone/clones`
- Workspace dependencies: `@shadowclone/bot`, `@shadowclone/core`
- External dependencies: `smol-toml`, `zod`
- Export subpaths: `.`

<!-- package-facts:end -->

## Owns

- `src/config/`: the clone config schema, the providers and their secrets, and the host paths.
- `src/node/`: `localNode` and its `start`, `list`, `get`, and `stop` operations, the run folders, the request and record schemas, the progress lines, and the admission rules.
- `src/run/`: the run program inside the clone image (`runClone`), with target resolution, the workspace, git hooks, engine, review stages, save, and finish steps.
- `src/serve/`: `serveClones`, the Docker launcher, and the launchd or systemd service.
- `src/setup/`: setup on this machine, the default branch ruleset, the secrets file, the summary, and the checks.
- `image/Dockerfile`: the clone image that `release.yml` publishes to GHCR.

## Rules

- A clone starts only from a request in its run folder, which `localNode().start` writes. Nothing on GitHub starts a clone.
- `serveClones` is the only writer of `record.json`. It holds the `serve.lock` lock, so one machine runs one `serve`.
- `serve` runs at most `parallelClones` clones, and one clone at a time for a ChatGPT plan login.
- A container that exits with no final progress line is `failed`. A queued clone with a stop marker never starts.
- `start` refuses a repository with no setup and a setup from an earlier config version. It also refuses a clone over `dailyClones` and a second active clone for one issue or pull request. It holds the `start.lock` lock from the check to the written request.
- shadowclone never reads a model login or the GitHub token. The owner pastes them into the secrets file. Docker gets the secrets file path only.
- A clone never pushes to the default branch. The pre-push hook refuses it, and setup adds a ruleset with no bypass.
- A review runs the toolchain only on a pull request that the owner wrote in this repository. Other reviews turn the network off.
- Setup refuses a ChatGPT plan login on a public repository.

## Tests

Run `bun test` in this folder, or `bun test packages/clones` from the root. `src/fixtures.ts` has a fake GitHub, a sample config, and a temporary clones folder. `src/serve/fakeLaunch.ts` replaces Docker in the serve tests. The hook tests use real `git` in a temporary folder. No test needs an account or Docker.

To try a branch in Docker, run `bun run stage`, then `npm pack` in `packages/cli/out/package` with `--pack-destination packages/clones/image`. Build with `--build-arg SHADOWCLONE_PACKAGE=/tmp/shadowclone-build/<file>.tgz`, and pass the tag to `clone setup --image`.

Update this file in the same commit when you change the package purpose, public exports, dependencies, or a rule above.