Worktree Setup logo

Worktree Setup

Community
LeeJuOh
worktree-setup

Set up worktree-plus for a repo — manage git config (baseBranch, branchPrefix, dirBase, guessRemote) and build the .worktreeinclude / .worktreelink files by scanning which gitignored files actually exist. Use when the user asks to set up or configure worktree-plus, view or change worktree settings, reset the plugin config, or decide which gitignored files should be copied or symlinked into new worktrees.

Overview

PublisherLeeJuOh
Repositoryclaude-code-zero
Skill nameworktree-setup
Stars
53
Forks
4
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by LeeJuOh on GitHub. Read the source before you install it.

Installation

Install the Worktree Setup AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/LeeJuOh/claude-code-zero/tree/main/plugins/worktree-plus/skills/worktree-setup
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/LeeJuOh/claude-code-zero.git /tmp/claude-code-zero
mkdir -p .claude/skills
cp -r /tmp/claude-code-zero/plugins/worktree-plus/skills/worktree-setup .claude/skills/worktree-setup
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Worktree Setup in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Worktree Setup on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Worktree Setup is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

worktree-plus Setup

Two jobs live here, and a user usually wants one of them:

  • Settings — git config under the worktreeplus.* namespace (plugin-custom) plus one worktree.guessRemote (git-native). No env vars. Start at Settings.
  • Which gitignored files follow a worktree — the .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.

Settings

KeyDefaultScope guidance
worktreeplus.baseBranchHEADPer-repo typical (different repos have different default branches)
worktreeplus.branchPrefixworktree-Global typical (personal naming convention); per-repo for team rules
worktreeplus.dirBase.claude/worktreesPer-repo for a relative path; global works for an absolute one
worktree.guessRemotetrue (plugin override; git default is false)Global typical

View current settings

Always start by showing what's active. Run:

bash
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):

bash
git config --local  --get-regexp worktreeplus
git config --global --get-regexp worktreeplus

Change a setting

Ask scope before writing. "Just this repo" (--local, default) vs "all repos for me" (--global).

bash
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.

Reset / unset

Destructive. Confirm with the user first before running — name exactly what will be removed.

Single key:

bash
git config [--local|--global] --unset worktreeplus.baseBranch

All plugin settings at once:

bash
git config [--local|--global] --remove-section worktreeplus

Value validation

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: ~ is rejected — a value of ~ or ~/foo makes every worktree creation fail, so write the expanded absolute path. Relative paths resolve against the repo root. An absolute path set with --global gets a folder per repo — worktrees land in <dirBase>/<repo>/<name> — so repos sharing it never collide; a --local one is used as-is (<dirBase>/<name>). 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.

Migration check

If the user mentions WORKTREE_BASE_BRANCH / WORKTREE_BRANCH_PREFIX env vars:

  1. These were removed in v3.0.0. SessionStart migrated them to --global git config on first run.
  2. Check migration ran and inspect its record:
    bash
    ls  "${CLAUDE_PLUGIN_DATA}/migrated-envvars"
    cat "${CLAUDE_PLUGIN_DATA}/migrated-envvars"   # shows migration version + timestamp
  3. Verify current global config captured the old values:
    bash
    git config --global --get-regexp worktreeplus
  4. Tell the user to remove the env vars from their shell profile — they're now dead weight.

If the flag file is missing but env vars are still set, migrate by hand with git config --global (see Change a setting). Restarting Claude Code won't re-run the migration: the SessionStart hook exits before it whenever its hooks are already registered. Skip any key that already has a value, and add the - the old prefix variable inserted to a non-empty prefix (WORKTREE_BRANCH_PREFIX=feat → branchPrefix "feat-"); an empty prefix stays "", meaning no prefix.

Set up .worktreeinclude / .worktreelink

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.

Workflow: scan → propose → confirm → write

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.

1. Scan

Ground truth is what git actually ignores, not what .gitignore says:

bash
git ls-files --others --ignored --exclude-standard --directory --full-name

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:

bash
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:

  • Never propose the worktree directory itself (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.
  • Drop OS/editor junk (.DS_Store, .idea/) and regenerable caches (__pycache__/, .pytest_cache/) unless the user wants them.
  • Collapse child paths whose parent is already listed.

2. Propose

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.

3. Write

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:

  • No globs. .env* is looked up as a file literally named .env* and logged skipped (not found). List .env and .env.local as separate lines.
  • No negation. !foo reads as a path named !foo.
  • Comments need their own line. # only opens a comment at the start of a line — .env # secrets is read as a path named .env # secrets.
  • Paths are relative to the repo root; trailing slashes are optional (stripped).
# 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):.

Merging into a file that already exists

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.

  • Match on the normalized path: strip trailing slashes and skip comment lines before comparing, so an existing node_modules doesn't collect a second node_modules/ line.
  • Append at the end under a comment of their own. Leave every existing byte alone.
  • Check the file ends with a newline before appending. These are hand-edited files and often don't. Appending .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).
  • If the path already sits in the other file, say so rather than adding it. A path in both is copied first, and then the symlink step does nothing at all: it skips when the destination already exists, without a log line or an error. The user gets a copy while believing they configured a link.

Reporting dead entries

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.

Gotchas

  • Changing 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.

Frequently asked questions

What does the Worktree Setup AI skill do?

Set up worktree-plus for a repo — manage git config (baseBranch, branchPrefix, dirBase, guessRemote) and build the .worktreeinclude / .worktreelink files by scanning which gitignored files actually exist. Use when the user asks to set up or configure worktree-plus, view or change worktree settings, reset the plugin config, or decide which gitignored files should be copied or symlinked into new worktrees.

Why use Worktree Setup on TypingMind?

Because you install it once and use it with any model. Worktree Setup is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Worktree Setup in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/LeeJuOh/claude-code-zero/tree/main/plugins/worktree-plus/skills/worktree-setup. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Worktree Setup?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Worktree Setup?

As many as you like. As long as a model supports skills, you can use Worktree Setup with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Worktree Setup AI skill free?

Yes. It is published on GitHub by LeeJuOh under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇