Help us improve
Share bugs, ideas, or general feedback.
From jig
Creates and removes fully-provisioned git worktrees for isolated parallel development, syncing .env and other gitignored artifacts with configurable post-create setup.
npx claudepluginhub duronext/jig --plugin jigHow this skill is triggered — by the user, by Claude, or both
Slash command
/jig:worktreeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**PURPOSE**: Create and remove fully-provisioned git worktrees for
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 sessions with safety checks for uncommitted changes and unpushed commits.
Manages git worktrees via unified bash script for parallel development: creates isolated feature environments, lists/switches status, copies .env files, cleans up merged/stale worktrees.
Share bugs, ideas, or general feedback.
PURPOSE: Create and remove fully-provisioned git worktrees for parallel development. Convention over configuration — opinionated defaults with team-configurable provisioning.
Announce at start: "I'm using the worktree skill to set up an isolated workspace." (create) or "I'm using the worktree skill to clean up a worktree." (remove)
Invoke this skill when:
kickoff, build) need isolated agent workspacesfinish)/worktreeDo NOT use when:
git checkout)git worktree add without
provisioningRead the worktree section from jig.config.md. All fields optional.
worktree:
naming: branch # ticket | ticket-branch | branch
sync: # gitignored artifacts to rsync
- .env* # always included regardless
# - node_modules
# - dist
post-create: # commands after create + sync
# auto-detects install if omitted
# - pnpm install
# - pnpm build
If no worktree section exists, all defaults apply.
Usage: /jig:worktree <branch-name> or /jig:worktree (prompts)
jig.config.md branching format).Read worktree.naming from config (default: branch).
| Strategy | Example branch | Directory |
|---|---|---|
ticket | dustin/jig-42-worktree-skill | .worktrees/jig-42/ |
ticket-branch | dustin/jig-42-worktree-skill | .worktrees/jig-42-worktree-skill/ |
branch | dustin/jig-42-worktree-skill | .worktrees/jig-42-worktree-skill/ |
Ticket extraction: Parse the ticket ID from the branch name using
the ticket prefix in jig.config.md (e.g., JIG, ENG). If no
ticket prefix is configured, look for common patterns like
[A-Z]+-[0-9]+. If no ticket ID is found, fall back to branch
strategy silently.
Branch slug: Everything after the last / in the branch name.
If the branch has no /, use the full name.
Gitignore verification (non-negotiable):
git check-ignore -q .worktrees 2>/dev/null
If .worktrees is NOT ignored:
.worktrees/ to .gitignorechore: add .worktrees to gitignoreExisting worktree check:
If .worktrees/<name> already exists, ask the user:
git fetch origin <main-branch>
git worktree add .worktrees/<name> -b <branch> origin/<main-branch>
Read main-branch from jig.config.md (default: main).
Sync gitignored artifacts from the main working tree into the new worktree.
What to sync — resolution order:
worktree.sync is configured: use that list as source of truthAuto-detection (when no sync config):
| Project file | Sync directory |
|---|---|
package.json | node_modules/ |
go.mod or composer.json | vendor/ (if it exists) |
pyproject.toml or requirements.txt | .venv/ or venv/ (if either exists) |
Cargo.toml | target/ |
Gemfile | vendor/bundle/ (if it exists) |
.env* files are ALWAYS synced, regardless of config. Find all
env files in the main tree:
find . -maxdepth 4 \
\( -name '.env' -o -name '.env.*' \) \
-not -path '*/node_modules/*' \
-not -path '*/.worktrees/*'
Copy each file preserving directory structure:
for f in <found-env-files>; do
mkdir -p ".worktrees/<name>/$(dirname "$f")"
cp "$f" ".worktrees/<name>/$f"
done
For directories (node_modules, vendor, etc.):
rsync -a <dir>/ .worktrees/<name>/<dir>/
Resolution order:
worktree.post-create is configured: run those commands in
order inside the worktree directoryAuto-detect install (when no post-create config):
| Lockfile | Command |
|---|---|
pnpm-lock.yaml | pnpm install |
package-lock.json | npm install |
yarn.lock | yarn install |
bun.lockb | bun install |
go.mod | go mod download |
Cargo.toml | cargo build |
pyproject.toml | poetry install |
requirements.txt | pip install -r requirements.txt |
composer.lock | composer install |
Gemfile.lock | bundle install |
If nothing is detected, skip this step.
Run commands inside the worktree:
cd .worktrees/<name>
<command>
✓ Worktree created at .worktrees/<name>
✓ Branch: <branch> (from origin/<main>)
✓ Synced: <list of what was synced>
✓ Post-create: <what ran> (completed)
cd .worktrees/<name>
Usage: /jig:worktree remove <name> or /jig:worktree remove
git worktree list, present the list
(excluding the main working tree), and ask which to remove.Check for uncommitted changes:
git -C .worktrees/<name> status --porcelain
If there are uncommitted changes:
If currently inside the worktree, navigate out first:
cd <main-working-tree>
git worktree remove .worktrees/<name> --force
Get the branch name from the worktree before removal, then offer:
Delete branch '<branch>'?
1. Local only
2. Local + remote
3. Keep
Execute the chosen option:
git branch -D <branch>git branch -D <branch> then
git push origin --delete <branch>✓ Worktree .worktrees/<name> removed
✓ Branch <branch> deleted (local)
Remaining worktrees:
<output of git worktree list>
If no worktrees remain, report: No active worktrees.
Usage: /jig:worktree list
Run git worktree list and format the output. No side effects.
| Command | Action |
|---|---|
/jig:worktree <branch> | Create provisioned worktree |
/jig:worktree remove <name> | Safely remove worktree |
/jig:worktree list | List active worktrees |
Never:
.worktrees is gitignored.env* file sync (even if sync config is empty)Always:
jig.config.md for naming, sync, and post-create configbranch naming when ticket ID can't be extracted