agentsclimarketplace

Worktree

Skill GhostlyGawd/recursive-harness/skills/worktree

Portable, evidence-driven agent development harness for Codex, Claude Code, and generic Agent Skills. Active beta v0.1.2.

Install
npx -y skills add GhostlyGawd/recursive-harness --skill worktree

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Create + manage git worktrees in this harness — when to isolate vs when one is overhead, how to EnterWorktree/ExitWorktree (they live at .claude/worktrees/<name>), and the gotchas that bite here: results don't auto-merge to main; state/ is gitignored so `harness` writes in a worktree miss the main ledger; committed memory/ rides in; shared DB/ports aren't isolated; the guard protects the trunk, not a worktree's own copies. Use whenever a second session opens, independent tasks fan out, or file-mutating agents run beside other work — the user never asks for a worktree or recites a gotcha.

SKILL.md

16.2 KB, ~3.7k tokens by cl100k_base, as published. Nobody here has run it

Worktree — isolate parallel work without clobbering

A worktree is a second checkout sharing the same .git/ history but with its own HEAD, branch, and working files. Edits in one never touch another — that isolation is the whole point, and the source of every gotcha below. The description above is the always-loaded when; this body is the how. The user should never have to instruct either.

Re-verified against the live Claude Code worktree docs + empirical repo tests on 2026-06-14. Docs change under us — see §5; treat the live docs as truth over this file.

0. Is a worktree actually warranted?

Make one when work could collide on shared files — a second concurrent session, parallel independent tasks, or file-mutating agents running beside other work. Do not wrap a solo single-task session: a worktree you don't need just buys untracked noise and a merge-back tax. When unsure whether two efforts can collide, make it.

1. Create / enter

  • This session into its own worktree: call EnterWorktree with a short name. It creates .claude/worktrees/<name>/ at the repo root, on a new branch worktree-<name>, and switches the session's working dir into it. From inside a worktree you cannot nest another — only switch into an existing one via path, and that path must be under .claude/worktrees/.
  • EnterWorktree is UNAVAILABLE under a pinned cwd / from a subagent — you can't move yourself in; spawn an isolation:worktree Agent for file-mutating steps instead (full mechanics in §6, When EnterWorktree is blocked).
  • A separate parallel session: the user runs claude --worktree <name> in another terminal, or git worktree add ../<dir> -b <branch> then claude there.
  • Base ref: new worktrees branch from origin/HEAD by default — a clean tree matching the remote, NOT your local uncommitted work. To carry unpushed local commits instead, set worktree.baseRef: "head" (project-level .claude/settings.json, or your account config). This repo's account config sets worktree.baseRef: "fresh" (the default — branch from origin/<default-branch>).

2. The gotchas (this is why the skill exists)

  • Results do NOT auto-merge. Changes live on worktree-<name>, isolated. Reaching main is deliberate: review the diff, open a PR (ONE TRUNK, kernel prime directive 6). Never assume worktree work has reached main.
  • state/ is gitignored and per-checkout, but the harness CLI resolves to the MAIN ledger. state/* is not copied into a worktree. As of follow-up 1d30be, bin/harness resolves state/ to the MAIN checkout via _resolve_state_dir() (git --git-common-dir), so ./bin/harness predict|outcome|corrections|followup|gc run inside a worktree write to the ONE canonical ledger — no longer the worktree's throwaway state/. Caveat (residual): the enforcement HOOKS (log_skill_use, session_start/session_end) still root state at their OWN tree, so skill-usage and similar logged during a worktree session write tree-local and vanish on cleanup until that locked half is fixed (tracked with 3939d8/d72eec). The ledger is the kernel's self-knowledge; a split is silent prediction/correction debt.
  • memory/ is committed → it rides in automatically. It's part of the checkout, so every worktree has the team memory natively. No junction needed.
  • Shared runtime is NOT isolated. Same DB, ports, services across worktrees. Worktrees isolate files, not runtime — use separate schemas/containers/ports when running migrations or binding a port.
  • The enforcement guard protects the TRUNK, not your worktree's own copies. The active guard hook is wired by absolute path to the trunk copy (silo settings.json), so it blocks edits to the trunk's hooks/lint/evals/autonomy.json no matter which worktree you're in — but it does NOT fire on a worktree's OWN copies of those files (verified: editing <worktree>/hooks/… exits 0). What keeps enforcement safe is ONE TRUNK: a worktree edit can't reach main without a PR + human review. Route enforcement/config changes via /harness-pr; never treat the guard as a backstop for a worktree-local edit.
  • node_modules, build artifacts, gitignored config (.env, settings.local.json) are NOT copied into a fresh worktree. Plugin enablement is a case of this: /plugin writes a plugin's code to the machine-global account cache (present everywhere), but records its enable flag in .claude/settings.local.json — gitignored, so a Claude-created worktree starts with installed plugins OFF. This repo ships a root .worktreeinclude (gitignore-syntax; only files that are also gitignored get copied) listing .claude/settings.local.json, so plugin enablement and the project permission allowlist ride into every new worktree. (That propagates already-granted permissions.allow entries without re-prompting — intentional here, since worktrees are same-user/same-machine on one repo; drop the include line if you'd rather re-consent per worktree.) Add lines there as a product grows gitignored config it needs. Caveat: a custom WorktreeCreate hook replaces git creation and skips .worktreeinclude (this repo configures none). (Verified 2026-06-18 — live docs + an empirical subagent-worktree test: the copied settings.local.json arrived with its enabledPlugins block intact.) worktree.symlinkDirectories exists for heavy dirs but has known bugs (cleanup can silently fail; a write can replace the symlink with a regular file) — prefer .worktreeinclude, use symlinks only knowingly.
  • Untracked files in a worktree are not automatically THIS repo's work. A harness worktree can accumulate strays from a different project — you ran a sibling project's task here, or a trial dropped its output in. Before git add/committing an untracked dir, resolve its home first: is the same dir tracked, and newer, in a sibling repo (ls the projects dir; git -C <sibling> log -- <dir>)? If so, the copy here is a stray — remove it, don't commit it into the trunk. (2026-06-17: a 162-file skills/yc-venture-foundry/ was committed into the harness before we caught it lived, newer, as yc-venture-foundry/ in the sibling yc-foundry-experiment; had to git reset + rm.)

3. Cleanup — and where it bites

Two paths with two different bars — don't conflate them:

  • ExitWorktree (interactive): auto-removes the worktree and its branch only when pristine — no uncommitted changes, no untracked files, and no new commits (any commit counts, pushed or not). Otherwise it prompts keep or remove. A named session also prompts (so you can resume the worktree later) rather than auto-removing.
  • Background sweep (cleanupPeriodDays): a looser bar — auto-removes aged subagent- and background-session worktrees with no uncommitted changes, no untracked files, and no unpushed commits. --worktree user sessions are never swept.
  • claude --worktree and -p non-interactive runs are NOT auto-cleaned. Manual: git worktree remove <path> (--force to discard changes), then git worktree prune.
  • Return to trunk from a worktree with git switch --detach origin/main, never a bare git switch main. Inside a LINKED worktree git switch main checks main OUT into that worktree and leaves the PRIMARY checkout detached on an old commit, so main migrates between worktrees and the next session's git switch main fails ("already used by worktree X"). --detach origin/main lands on trunk's commit without moving the main ref. The post_merge_return_to_trunk hook now emits the --detach form when it detects a linked worktree (follow-up 1c9cea); do the same by hand. Detail in references/cleanup.md.
  • Before removing, reconcile this worktree's gitignored state/ (see §2) — cleanup discards it.
  • Pruning a BATCH is rule-driven, not list-driven. State is non-stationary while a peer session is live (it can swap a branch, push, or open a PR mid-pass), so: re-read the git worktree list / git branch -vv SNAPSHOT before each destructive batch; drive each delete off a RULE ("merged into main AND not pinned by a worktree AND no open PR"), never a memorized name list; and lean on git's own refusals (git worktree remove without --force refuses a dirty tree; git branch -d not -D refuses an unmerged branch). Run each git worktree remove "<literal path>" as its OWN command — a for … do git worktree remove … loop is BLOCKED (Guard A's exemption matches the segment START, and the loop body leads with do). Spot live peers by .jsonl mtimes under projects/*<repo>*.
  • A locked worktree may be held by THIS session's own long-lived host, not a dead peer — locks leak from isolation:worktree agents and outlive them. Before reaping one or killing the holder pid, walk the current shell's process-ancestry (PowerShell: Win32_Process.ParentProcessId from $PID up): if the holder is an ANCESTOR it's your own session, and killing it ends the conversation. Reclaim self-held locks losslessly with git worktree unlock "<path>"git worktree remove "<path>" (never --force/kill), or let them free on the next CLI restart.
  • Full batch-GC empirics — the snapshot/rule/refusal discipline, the Guard-A loop trap, git branch -d's merged-into-HEAD pitfall, and lock self-vs-peer diagnostics (with provenance) — live in references/cleanup.md.

4. Windows / this repo's housekeeping

  • Paths with spaces (D:\GitHub Projects\...) must be quoted in shell commands.
  • Keep .claude/worktrees/ in .gitignore. The docs recommend it, and it's confirmed here: a worktree created under .claude/worktrees/ otherwise shows up as ?? .claude/ in the main checkout's git status. (Added to this repo's .gitignore alongside this skill.)
  • Windows symlink behavior is finicky — see the worktree.symlinkDirectories caveat in §2; prefer .worktreeinclude.

5. Verify against live docs — don't trust this file blindly

Claude Code changes under us, and stale worktree knowledge is dangerous. So:

  • Before anything non-trivial, or the moment behavior surprises you, WebFetch the canonical page: https://code.claude.com/docs/en/worktrees (and /sub-agents, /settings, /tools-reference). Treat the live docs as truth over this file.
  • If the live docs contradict a step here, follow the docs and update this skill in the same motion (branch + PR) so the next session inherits the correction. A skill that silently drifts is worse than no skill.

6. Sessions: launch, resume, and the guard hatches

Terse rules below; recipes, exact error strings, and provenance live in references/sessions.md (re-verify against live docs if behavior surprises you).

  • Launching the harness against a foreign repo needs CLAUDE_CONFIG_DIR=<harness>/.claude-private/accounts/<name> claude from inside that repo — a plain claude loads the global config, not the harness, and /cd cannot relocate a live session (ADR 0004). Recipe in references/sessions.md.
  • A session "missing" from /resume is almost never data loss — it is either still open in a live process (withheld from the picker) or just re-titled. claude --resume <session-id> opens it regardless; prove integrity with the .jsonl byte-count, not prose. Detail in references/sessions.md.
  • Guard A allows cross-worktree READS; only writes are gated. Read/Glob/Grep a sibling worktree directly; for a cross-worktree WRITE the env hatch can't be set mid-session, so lead the command with HARNESS_ALLOW_CROSS_WORKTREE=1 <cmd> (powershell form + Guard B's launch-only hatch in references/sessions.md).
  • Before reimplementing a trunk fix, reconcile against ALL in-flight work, not just merged history. git fetch, then scan merged AND open PRs (gh pr list --state all) AND live sibling worktrees (git worktree list) — a near-complete rebuild can already sit in an OPEN PR or peer worktree, not yet on main. (retro-backlog 2026-06-19 b7488db6+dc1c3470; extended 2026-06-23 d1917edc — re-derived an SDD phase open PR #99 already carried.)
  • Two sessions sharing one checkout race on .git/HEAD. Prevent with separate worktrees (Guard C's lease blocks a stale-HEAD mutate on main); to commit mid-race, build from git objects (write-treecommit-treepush <oid>:refs/heads/…) off a TEMP GIT_INDEX_FILE, never checkout/reset a HEAD a peer holds. (sessions b7488db6 + dc1c3470.)
  • A finished isolation:worktree agent can leave the session's cwd inside its now-empty worktree. Confirm pwd is the PRIMARY checkout before any bin/harness op: the CLI resolves state/ to the main ledger regardless of cwd (§2), but the enforcement HOOKS still log tree-local, so a drifted cwd silently drops skill-usage/session logs. (session b3314a63, 2026-06-23.)
  • When EnterWorktree is blocked (subagent / pinned cwd — see §1), don't fight the guards inline: spawn an isolation:worktree Agent to do the Write + commit in its own clean worktree, then git push its branch from the primary checkout. Full create-time and amend-time recipes in references/sessions.md.

Rules

  • The user never asks for a worktree and never recites the gotchas — that's this skill's job.
  • A worktree is single-agent, single-branch, temporary. Integration happens via PR to main, never a merge inside it.
  • Worktree changes are not on main until a PR merges them. Say so plainly; never imply otherwise.
  • Enforcement-layer / config changes (settings keys, .worktreeinclude, hooks) go via /harness-pr — and the trunk guard won't catch a worktree-local edit, so don't rely on it as a backstop.

Gives 0 of the 12 instructions most agent orchestration skills give in ~3.7k tokens

Counted across 742 of the 995 authors here whose files we hold, read 2026-08-06

  • run the full test suite after integrating changesin 53 of 742, across 20 files
  • reference existing artifacts by path or URLin 52 of 742, across 22 files
  • dispatch one agent per independent problem domainin 50 of 742, across 17 files
  • verify fixes do not conflictin 45 of 742, across 13 files
  • include a suggested skills section in the documentin 45 of 742, across 15 files
  • redact sensitive informationin 41 of 742, across 11 files
  • save to the temporary directory of the operating systemin 39 of 742, across 9 files
  • tailor the document to user-provided focus argumentsin 39 of 742, across 9 files
  • spot check agent changes for systematic errorsin 34 of 742, across 7 files
  • write a handoff document summarising the current conversationin 31 of 742, across 6 files
  • assign each agent a specific scopein 23 of 742, across 8 files
  • provide specific scope and clear goalin 23 of 742, across 5 files

Said here and by no other author read

  • create a worktree when work could collide on shared files
  • avoid worktrees for solo single-task sessions
  • spawn an isolation worktree agent when EnterWorktree is blocked
  • use separate schemas containers or ports for runtime resources
  • review the diff and open a PR to merge to main
  • verify untracked files belong to the current repo before committing

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.