kendex.ai

Marketplaces / vanillagreencom/kendex / worktree

worktree

Load to create, list, remove, push, or repair a git worktree.

skill · git · @ 8ee7099

Supported tools: all tools

Install in kendex: kendex add --skill worktree after subscribing to vanillagreencom/kendex.

Worktree Management

.agents/skills/worktree/scripts/worktree <command> [options]

Worktrees live at <parent-of-checkout>/.worktrees/<checkout-name>/{id}, outside the repo root. A hosted lane's worktree lives at one path beside its clone instead, so a compile cache keyed by absolute source path hits across lanes: create --help, --hosted. Every command's contract is its --help: flags, exit codes, failure semantics, recovery. The top-level worktree --help carries the command index, path and issue-ID rules, configuration variables, and setup-path hardening.

Commands

CommandDescription
createClaim a new issue worktree, a new-work claim, not a discovery command: existing ownership exits 75, and owned work is inspected or monitored, never given a second implementer. Reuse and conflict recovery: create --help
restackGuardedly continue, skip, or abort a tool-created paused restack
listList all worktrees
removeRemove worktree, clean symlinks, prune branches
cleanupRemove worktrees whose branches are merged; --targets-only prunes build output instead, keeping every worktree and branch
path / existsPrint / check the worktree path for an issue ID; path --hosted prints the hosted lane path
mergedPrint the commit the issue tree's pull request merged as, asking about the branch that tree has checked out; exit 1 when none did, 2 when the lookup could not answer, a detached tree included (merged --help)
checkPre-create git state check (JSON: uncommitted, unpushed)
pushPush worktree branch with auto-rebase and pinned --force-with-lease; on a merge-queue base with no up-to-date rule it pushes a cleanly merging branch unrebased and refuses a conflicting one toward create --restack. The rebase-map: contract for remapping pre-rebase SHAs is in push --help
fix-links / repair-linksRestore configured symlinks; repair-links is the git-hook-driven variant that never destroys untracked data
codex-setup / codex-branch / codex-cleanup, claude-setup / claude-cleanupApp-created worktree hooks. Installation wiring: references/hooks.md

Policy-blocked rebase (cherry-pick replay fallback)

When an execution policy rejects top-level git rebase porcelain, never retry the porcelain and never substitute a raw --force push. Add --replay to the guarded restack (create --help); the controls stay restack continue|skip|abort <ID>.

A branch is rebased only through worktree push, create --restack, or create --reuse, never a bare git rebase; use this section's replay fallback for recovery.

create --reuse --keep-on-conflict aborts a conflicting rebase and hands the tree back on its pre-rebase head with exit 76, for a relaunch that must start the session before the restack; a caller that needs the base omits the flag and keeps the failure (create --help).

A branch whose pull request the merge lookup confirms merged is not rebased by create. A squash merge rewrites the branch into a fresh commit, so a rebase replays the merged work onto its own squash and stops on conflicts: create --reuse keeps the tree as it stands, and create --restack and create --replay refuse, all three naming the merge commit. When the lookup cannot answer, create records worktree-merge-unverified and rebases as for a branch in flight (merged --help).

Recovering a broken .agents entry

Route by shape, not by whether test -L .agents passes. Ask both indexes what sits under the path: git -C <worktree> ls-files -- '.agents/', and the same command against the main checkout. The trailing slash is the query; descendants decide the layout and the entry itself does not count. Neither index alone decides, and both answer while the path itself is broken:

  • Either non-empty. The repo commits its render, and .agents is a REAL DIRECTORY by design: the tracked files, plus one symlink per untracked child, except an untracked .gitignore, which is a copy of main's file. A child missing its link, or a real path where a link belongs, is fix-links. A modified or corrupt TRACKED file is git checkout -- <path>, run in the checkout the file really lives in: the main checkout when the path sits under a configured symlink, the worktree otherwise.
  • Both empty. The entry is untracked-only and must itself be a symlink. fix-links is the repair; with no tracked content at the path, git checkout -- .agents changes nothing while the link stays broken.

Run .agents/skills/worktree/scripts/worktree fix-links <ID|PATH> from the main checkout naming the target; a bare invocation there is refused. A non-zero exit names the paths it did not restore, and until they are restored that tree is not trustworthy for local verification. Routing table and link mechanics: fix-links --help.

A consumer wanting this file locally gets a pointer, never a copy: cat "$(dirname "$(git rev-parse --path-format=absolute --git-common-dir)")"/.agents/skills/worktree/SKILL.md resolves the main checkout from any worktree, at any depth. A verbatim copy in a tracked AGENTS.md or CLAUDE.md is out of kendex refresh's reach and goes stale silently.

Session guard (ownership leases)

scripts/worktree-session-guard stops cleanup from destroying a claimed worktree, using a native Git worktree lock whose reason line carries the owner and a heartbeat. The catalog's worktree-session-claim hook claims, when a session starts in it, a worktree carrying the kendex-issue record every tree create returns carries, one adopted through --reuse or --restack included, and the orchestrating workflow's claim --owner <ISSUE_ID> --adopt takes that lease over. Who claims and when, what staleness measures, and the guard's limits: references/session-guard.md; commands, exit codes and --repo scope: worktree-session-guard --help.

Reclaiming build output

cleanup --targets-only prunes build output and keeps the worktree, its branch and every tracked and untracked source file. It runs on a worktree with uncommitted work: output is written by a compiler or a package manager, so uncommitted work is no reason to leave it on disk, and on a machine hosting many worktrees the trees holding the output are the ones still in use. It previews by default and deletes only under --apply, and wherever it cannot establish that a path is safe to remove it keeps that path and says why. Run it from the main checkout, read the preview, then repeat with --apply. It skips every leased worktree, with one exception: --worktree PATH --owner ID lets the session holding a worktree's lease prune that one worktree's Cargo profiles, with no retention window.

The layout table is data, one row per ecosystem, in scripts/worktree-output-prune; covering a further ecosystem is a new row there and no other change. cleanup --help owns everything else: the flags, the layouts, the locking, what the walk excludes, every reason a path is kept, and the recovery for an --apply that did not finish.

JS Dependencies

worktree --help § Dependencies owns install and linked-node_modules behavior.

System Dependencies

git; authenticated gh for reading the repository's default branch (without it, git's record of origin's HEAD answers), for new-work PR ownership discovery and for proving a squash-merged branch merged in cleanup and remove; flock for repository-local per-issue claim serialization; Bash 3.2+ (macOS system bash is supported).

Configuration

Set non-sensitive defaults in committed kendex.settings.toml under [env]; .env.local wins for secrets or personal overrides, and a .env file is never read. Symlink only what git does not carry. An entry does nothing when git carries every path under it, and a directory holding tracked content stays a real directory with its untracked children linked, bar an untracked .gitignore, which is copied (fix-links --help). Variable semantics and setup-path hardening: worktree --help.