From worktree-plus
Configures worktree-plus git settings (baseBranch, branchPrefix, dirBase, guessRemote) and builds .worktreeinclude/.worktreelink files by scanning gitignored files.
How this skill is triggered — by the user, by Claude, or both
Slash command
/worktree-plus:worktree-setupThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Two jobs live here, and a user usually wants one of them:
Two jobs live here, and a user usually wants one of them:
worktreeplus.* namespace (plugin-custom) plus one worktree.guessRemote (git-native). No env vars. Start at Settings..worktreeinclude (copy) and .worktreelink (symlink) files at the repo root. Start at Set up .worktreeinclude / .worktreelink.If the user's ask is vague ("set up worktree-plus"), show the current settings first — it's cheap and orients both of you — then offer the include/link scan.
| Key | Default | Scope guidance |
|---|---|---|
worktreeplus.baseBranch | HEAD | Per-repo typical (different repos have different default branches) |
worktreeplus.branchPrefix | worktree- | Global typical (personal naming convention); per-repo for team rules |
worktreeplus.dirBase | .claude/worktrees | Per-repo typical |
worktree.guessRemote | true (plugin override; git default is false) | Global typical |
Always start by showing what's active. Run:
git config --get-regexp '^worktreeplus\.|^worktree\.guessRemote'
If nothing prints, the user is on defaults. State that explicitly — don't leave them guessing.
For layered view (local vs global vs system):
git config --local --get-regexp worktreeplus
git config --global --get-regexp worktreeplus
Ask scope before writing. "Just this repo" (--local, default) vs "all repos for me" (--global).
git config [--local|--global] worktreeplus.baseBranch develop
git config [--local|--global] worktreeplus.branchPrefix "feat-"
git config [--local|--global] worktreeplus.dirBase ".worktrees"
git config [--local|--global] worktree.guessRemote false
Writes take effect on the next EnterWorktree / claude -w. Existing worktrees are not affected.
Destructive. Confirm with the user first before running — name exactly what will be removed.
Single key:
git config [--local|--global] --unset worktreeplus.baseBranch
All plugin settings at once:
git config [--local|--global] --remove-section worktreeplus
Before writing, sanity-check the value:
branchPrefix: literal — "feat-" produces feat-name, "feat" produces featname. If user says "use feat prefix" they almost certainly want the -. Ask.dirBase: no tilde expansion (~/foo stays literal). Relative paths resolve against the repo root. Trailing slash is stripped automatically. Empty value falls back to default.baseBranch: must be a resolvable ref. git rev-parse --verify <value> works? If not, warn.If the user mentions WORKTREE_BASE_BRANCH / WORKTREE_BRANCH_PREFIX env vars:
--global git config on first run.ls "${CLAUDE_PLUGIN_DATA}/migrated-envvars"
cat "${CLAUDE_PLUGIN_DATA}/migrated-envvars" # shows migration version + timestamp
git config --global --get-regexp worktreeplus
If the flag file is missing but env vars are still set (shouldn't happen in normal flow), run the migration manually by re-triggering SessionStart (restart Claude Code).
Two files at the repo root decide which gitignored paths follow a new worktree:
.worktreeinclude — copied into each worktree. Independent per worktree; later edits don't leak back to the source..worktreelink — symlinked to the original. One copy shared by every worktree: no disk cost, but every worktree sees the same bytes.The WorktreeCreate hook reads both and records each outcome in <worktree>/.worktree.log.
The confirm step isn't a formality. These files land at the user's repo root and usually get committed, so writing one they didn't agree to is an unrequested change to their project. Show the candidate list and get a yes before writing or editing either file. Write/Edit sit outside this skill's allowed-tools on purpose, so a permission prompt fires too — that's a backstop, not the approval.
Ground truth is what git actually ignores, not what .gitignore says:
git ls-files --others --ignored --exclude-standard --directory --full-name
Run it on its own, not chained behind another command — the pre-approval in allowed-tools is a prefix match, so git rev-parse --show-toplevel && git ls-files … doesn't match Bash(git ls-files *) and costs the user a permission prompt for a read they already approved.
This folds in every ignore layer (.gitignore, .git/info/exclude, global core.excludesFile) and prints only paths that exist on disk — the same criterion the hook uses, since anything absent is logged skipped (not found). --directory collapses a fully-ignored directory to a single line. --full-name keeps paths relative to the repo root; without it, running from a subdirectory yields cwd-relative paths, and the hook resolves them against the repo root instead — silently wrong entries.
Size the plausible candidates, since large is the main argument for link over copy:
du -sh node_modules .venv assets/media
Read .gitignore as well, but for its comments — a line like # model weights, downloaded once states intent that the path alone doesn't.
Prune the scan output before proposing anything:
worktreeplus.dirBase, default .claude/worktrees/). It's gitignored, so it appears in the scan, and copying it would clone every existing worktree into the new one..DS_Store, .idea/) and regenerable caches (__pycache__/, .pytest_cache/) unless the user wants them.Show each candidate with the evidence behind the call — size, whether the content varies by branch, what sharing would mean. The user can only overturn a classification they can see the reasoning for:
.env 4 KB copy — per-worktree secrets; branches may need different values
references/ 1.2 GB link — vendored read-only repos, branch-invariant; copying costs 1.2 GB per worktree
node_modules/ 680 MB copy — dependency state tracks the branch's manifest
copy vs link is a judgment call, not a lookup table. The question underneath: would two worktrees ever need this path to differ? If yes, copy it (or leave it out and let the user regenerate it). If no, and it's big, link it.
When the user wants to link a per-branch dependency directory (node_modules/, .venv/, target/), don't refuse — explain and let them choose. A symlink makes every worktree share one directory, so an install on a branch that bumped a dependency silently rewrites what the other worktrees run against; the breakage surfaces later, elsewhere, as a version mismatch nobody made. Some users take that trade for the disk savings on branches that never touch the manifest. The point is that they take it knowingly.
One literal path per line. The file resembles .gitignore but is not a pattern file — the hook tests each line with [ -d ] / [ -f ] against <repo-root>/<line>, so:
.env* is looked up as a file literally named .env* and logged skipped (not found). List .env and .env.local as separate lines.!foo reads as a path named !foo.# only opens a comment at the start of a line — .env # secrets is read as a path named .env # secrets.# secrets — per-worktree
.env
config/secrets.yaml
Then point the user at verification: the next worktree's .worktree.log lists every entry as copied:, linked:, or skipped (not found):.
Read the existing file first and append only what's missing. Never regenerate it. Those lines carry intent your scan can't reconstruct — the grouping, the ordering, the comment explaining why a path earns its place, and entries deliberately listed before they exist on disk. A wholesale rewrite destroys all of that silently, and the user finds out later.
node_modules doesn't collect a second node_modules/ line..env to a file whose last line is references/ with no trailing newline yields references/.env — a single path matching nothing, logged skipped (not found).While merging, test each existing entry against disk and report the ones that don't resolve:
.worktreeinclude:
config/old-secrets.yaml not found on disk
Report, then stop — don't delete. A path missing from disk isn't necessarily stale: it may exist on the user's other machine, be generated later by a build step, or just not be created yet. The hook already tolerates it (skipped (not found), then it moves on), so a dead entry costs one log line, not a failure. Quietly deleting a line the user wrote to tidy that up is the worse trade. Name the likely reasons and let them decide.
dirBase does not move existing worktrees. New worktrees go to the new location; old ones stay at the old path. Both still appear in git worktree list and can be removed normally, but the mixed layout is confusing. Tell the user to finish/remove pending worktrees before changing dirBase.git config --remove-section errors if the section doesn't exist. Check first: git config --get-regexp '^worktreeplus\.' — if empty, skip remove.--global writes go to ~/.gitconfig. If the user wants truly project-scoped, use --local (writes to .git/config). Local overrides global.worktree.guessRemote=true is the plugin's non-default. Setting it explicitly to false disables auto-tracking of remote branches — user gets pure HEAD branch creation. Git's own default is false; the plugin flips it for better UX but respects explicit user config.branchPrefix is literal (no auto-separator). Different from the pre-v3 env var which inserted - automatically. The migration adds the - for you when converting, but fresh writes don't.allowed-tools scope. Pre-approved here: git config (read/write), plus the read-only git worktree list, git rev-parse, git ls-files, du, ls, and Read. Anything else — Write, Edit, git worktree remove — raises a permission prompt, and that's the design. This skill writes git config directly, but .worktreeinclude / .worktreelink are user files at the repo root: the skill scans and proposes, the user approves, and the prompt confirms. Worktree lifecycle itself belongs to the worktree-plus hooks, not here.npx claudepluginhub leejuoh/claude-code-zero --plugin worktree-plusGenerates a .worktreeinclude file so Claude Code copies gitignored env/secret/config files into new worktrees. Use when worktrees miss .env or local config.
Creates isolated git worktrees for parallel development without disrupting the main workspace. Includes safety verification to prevent accidental commits of worktree contents.
Manages Git worktrees for isolated parallel development, including creation, listing, switching, and cleanup with environment cloning and dependency installation.