Install
openclaw skills install @iliaal/compound-eng-git-worktreeManage Git worktrees for isolated parallel development. Use when creating, listing, switching, or cleaning up git worktrees, or when needing isolated branches for concurrent reviews or feature work.
openclaw skills install @iliaal/compound-eng-git-worktreeGATE: If the task runs inside an existing worktree (a worktree path is given and no create/remove/switch is requested), none of the creation flow applies — work in place and skip this skill. To check: git rev-parse --show-toplevel appears as a linked entry in git worktree list.
Never call git worktree add directly -- always use the worktree-manager.sh script.
The script handles critical setup that raw git commands don't:
.env, .env.local, .env.test, etc. from main repo.worktrees is in .gitignorepackage.json → npm install, composer.json → composer install, pyproject.toml → pip install -e ., go.mod → go mod downloadAll commands use: bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh <command>. If CLAUDE_PLUGIN_ROOT is unset (non-Claude-Code harness), resolve the script relative to this skill's own directory.
Before creating worktrees, export a unique WORKTREE_SESSION_ID and retain that same value for this session's later manager calls. For example, export WORKTREE_SESSION_ID="$(python3 -c 'import uuid; print(uuid.uuid4())')". The manager records ownership in each new worktree's Git metadata. Creation without a session ID remains available, but manager cleanup then refuses that tree; never adopt a previous session's ID to bypass ownership.
The manager script fetches origin/<base> fresh and branches from it -- it never checks out <base> in the caller's working tree. If the fetch fails (offline, no remote), it falls back to the local <base> ref. Details: troubleshooting.md.
| Command | Description | Example |
|---|---|---|
create <branch> [from] | Create worktree + branch (default: from main) | ...worktree-manager.sh create feature-login |
list / ls | List all worktrees with status | ...worktree-manager.sh list |
switch <name> / go | Print the registered worktree's absolute path; the caller applies it as workdir | target=$(...worktree-manager.sh switch feature-login) |
copy-env <name> | Copy .env files to existing worktree | ...worktree-manager.sh copy-env feature-login |
cleanup <name> [...] / clean | Confirm removal of named, session-owned, clean worktrees | ...worktree-manager.sh cleanup feature-login |
Run commands with env -C "$target" <command> or the harness workdir argument. A child script cannot change the caller's working directory. Listing and resolving names work from the main checkout, linked checkouts, and their subdirectories.
Cleanup refuses the current checkout, another session's tree, and tracked, untracked, or ignored files. Auto-copied .env files and installed dependencies therefore require explicit user-managed disposition before cleanup. Confirm no process uses the named trees; the manager cannot detect every external reader. Git's normal removal safeguards remain enabled, including locked-tree refusal. Do not force deletion or suppress failures to finish cleanup.
Before creating a worktree, verify the worktree directory is gitignored:
# Verify .worktrees is ignored (should output ".worktrees")
git check-ignore .worktrees || echo "WARNING: .worktrees not in .gitignore"
If not ignored, add it to .gitignore before proceeding.
After creating a worktree, run the project's test suite (or the fastest relevant subset if the full suite exceeds a few minutes) to establish a clean baseline. Pre-existing failures in the worktree should be caught before starting new work -- not discovered mid-implementation.
git worktree list entry you did not create in this session as read-only -- a tree left from a previous round is not yours either. Reuse is most tempting exactly where it is most dangerous: an existing tree already has dependencies and env wired up, and another session may be running a suite in it.git status --short empty) has returned.git status --short) rather than trusting git checkout --.git add <mine> && git commit also commits whatever a peer staged, under your message. The protection is a pathspec on the commit itself (git commit -- <paths>), which takes those paths from the working tree and ignores the index; new files still need git add. It constrains your commit, not a peer's, so the residual control is latency between writing and committing. Read git show --stat HEAD afterwards and confirm only your files are there.git -C <repo> push <remote> HEAD:<branch> resolves HEAD in that repo, not in the worktree you edited. Edits made in a linked worktree and pushed with -C at the main checkout publish the main checkout's commit onto your branch, and --force-with-lease does not catch it because the lease checks the branch's old value, not what HEAD names. Never spell HEAD: in a -C push -- resolve the SHA in the worktree and push it explicitly, then confirm with git ls-remote. Two branches "updated" to one SHA, or a pushed subject unrelated to the work, is the tell.git stash writes to the common git directory, so a red/green cycle in one worktree can pop and drop a stash another worktree pushed in between. Never stash for red/green here: git diff > /tmp/red.patch, git checkout -- <files> (worktree-local) for the red run, git apply /tmp/red.patch for green. A dropped stash is still recoverable while its commit survives -- git stash store -m <message> <sha> re-registers the SHA that Dropped refs/stash@{0} (<sha>) printed.git -C <worktree> rev-parse HEAD describe a different branch and report a correct push as a mismatch. Refs are shared across every worktree: ask any one of them about the branch by name (rev-parse <branch>, rev-list --count origin/<branch>..<branch>, reflog <branch>).Use env -C <worktree> <cmd> for every command, never cd. A shell's cwd persists across calls, so one cd <repo-root> for an unrelated reason silently relocates every later command: probe files get written into the shared main tree and run against its bytes, and the tidy-up reflex git checkout -- <path> becomes a write aimed at the wrong tree. The git -C habit does not generalize -- interpreters, test runners, linters, and a heredoc cat > all take the cwd. Have any probe print the tree it ran in.
git worktree list shows the new entry.worktrees directory confirmed in .gitignoreRead the relevant reference before implementing or reviewing the matching behavior:
Existing specialized references, when the corresponding topic applies: