worktree
The worktree worker gives every agent its own isolated checkout of a shared repository.
Tech stack
Works with
Agent Skills format with YAML frontmatter. Claude Code reads it as-is.
---
name: "worktree"
description: "The worktree worker gives every agent its own isolated checkout of a shared repository."
license: "Apache-2.0"
---
# worktree
The worktree worker gives every agent its own isolated checkout of a shared
repository. Instead of two sessions fighting over one working tree,
`worktree::create` mints a locked `git worktree` on a fresh branch, records
who owns it, and returns a path to use as the agent's working directory.
When the work is done, `worktree::land` automates the merge-back: rebase
onto the target branch, run an optional test command, fast-forward the
target atomically, and clean the worktree up. Lands are serialized per
repository through an engine FIFO queue, so parallel agents never race a
merge.
The land test gate delegates to `shell::exec`, so the shell worker must be
installed and `worktree_root` must sit inside its `fs.host_roots` jail.
Landing never pushes to remotes; it moves local branches only.
Destructive surfaces are gated by configuration: every mutating function
checks its gate first, the force paths (claim takeover, forced removal,
land `force_restart`) ship closed, and a denial names the exact config key
to flip. The path `worktree::create` returns doubles as the turn's
filesystem scope root (`metadata.fs_scope.root`), so file access inside the
worktree is fenced by the shell worker while the gates cover the lifecycle
door the scope cannot see (remove, prune, branch deletion, landing).
## When to Use
- A task should run in isolation from the primary checkout or from other
agents working on the same repo (`worktree::create`, then use the
returned `path` as the agent's working directory).
- You need to see which worktrees exist, who owns them, and whether they
carry uncommitted or unlanded work (`worktree::list`,
`worktree::status`).
- A GitHub pull request should be reviewed or exercised in isolation
(`worktree::create` with `pr: <number>` fetches `refs/pull/<n>/head`
from `origin` and branches at it).
- A finished branch should merge back into `main` (or any target) with
tests enforced first (`worktree::land` with `test_cmd`).
- A land was blocked on conflicts and the agent resolved them in place:
finish the rebase, then rerun `worktree::land`; pass `force_restart` to
abort and start over instead.
- Hand a worktree between sessions (`worktree::claim`,
`worktree::release`) or clean up abandoned ones (`worktree::remove`,
`worktree::prune`).
## Boundaries
- Not a PR or code-review tool: landing fast-forwards a local branch; it
never pushes, opens pull requests, or talks to a forge.
- Worktrees created out of band are reported as unmanaged and never
adopted; only worktrees minted by `worktree::create` are managed.
- One worker instance per engine: the registry has no compare-and-set, so
multi-instance deployments must shard by repository.
- Merges are fast-forward only (after the rebase); there is no merge-commit
or squash strategy.
- For running commands or editing files inside a worktree, use the `shell`
worker with the worktree path as `cwd`; this worker only manages the
worktrees themselves.
## Functions
- `worktree::create` — mint a locked, isolated worktree off a base ref or
a pull request head (`pr`); auto-claims for `session_id` when given,
names the branch by id or deterministic codename per config, and returns
an advisory `dev_port` derived from the id (never reserved anywhere).
- `worktree::list` — registry view, filterable by repo or session, with
optional git status per worktree.
- `worktree::get` — one worktree with status.
- `worktree::validate` — check a path is a live managed worktree;
reconciles records whose directories were removed by hand.
- `worktree::claim` — take session ownership (`force` to take over).
- `worktree::release` — release ownership (`force` to override).
- `worktree::status` — clean flag, ahead/behind, staged/unstaged/untracked
counts, diffstat, rebase-in-progress, and `integrated` with an
`integration_reason`, so squash- or rebase-landed branches read as
merged even while ahead of their base.
- `worktree::remove` — remove a worktree; refuses dirty or unlanded work
unless forced, and refuses while running processes hold files open under
it (`W222`); the directory leaves its path instantly (staged into a
trash area, deleted in the background); can delete the branch.
- `worktree::prune` — sweep: drop records whose directories are gone and
remove clean, unclaimed, expired worktrees, including integrated ones
whose work already landed (cron-bound, `{}` payload).
- `worktree::land` — queue the rebase / test / fast-forward / cleanup
pipeline; returns a `job_id` immediately.
- `worktree::land-step` — internal queue consumer that executes land
phases; never call it directly (denied to agents).
With `provision.copy_ignored` enabled in config, every create also
replicates the source repo's gitignored files (.env files, caches) into
the new worktree in the background; the create response never waits on it.
Errors carry stable `W###` codes; the ones worth branching on are `W210`
(already claimed), `W220` (dirty), `W221` (unmerged work), `W222` (files
held open by running processes), `W401` (land already queued), `W402`
(unresolved rebase from a previous land), and the land-block reasons
carried on events (`W410` conflict, `W411` tests, `W412` target kept
moving, `W413` target checked out dirty). `W5xx` means configuration
denied the operation, not that it failed: `W500` gate off, `W501` force
disabled, `W502` land target not in `gates.land_targets`, `W503`
repository not in `gates.repos`, `W504` per-repo worktree budget hit. The
message names the exact key; do not retry, surface that key to the
operator (or drop the force flag) instead.
## Reactive triggers
Register a `worktree::*` trigger when a different worker should react to
lifecycle changes without polling `worktree::list` — announce lands in
chat, start a follow-up agent when a sibling's branch merges, or alert on
blocked lands.
Reach for it when:
- A land's outcome should drive the next step (`worktree::landed`,
`worktree::land-blocked` with `reason` and `conflict_files`).
- Ownership changes matter to an orchestrator (`worktree::claimed`,
`worktree::released`).
- Cleanup should cascade (`worktree::removed`).
The caller of `worktree::land` gets only `{ job_id, queued }` back; the
outcome arrives on these triggers, so a landing workflow should always bind
one instead of polling.
### How to bind
1. Register a handler: `registerFunction('notify::on-land', handler)`.
2. Register the trigger:
```typescript
iii.registerTrigger({
type: 'worktree::landed',
function_id: 'notify::on-land',
config: {
// optional equality filters:
// repo_path, worktree_id, session_id
},
})
```
All six types accept the same three optional filters; unknown config keys
are rejected at registration. For event payload shapes, call
`get function info` on the trigger type.More General & Other skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
grill-me
mattpocock/skills
A relentless interview to sharpen a plan or design.
grill-with-docs
mattpocock/skills
A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.

