use-worktrees
Use when starting feature work that needs isolation from current workspace or before executing implementation plans - ensures an isolated workspace exists via native tools or git worktree fallback
- License 许可
- Apache-2.0
- 所属仓库
- zak-keown/moe
- 最近更新
- 2026-09-05
- Stars
- ★ 0
- Forks
- 1
01 前言 Front Matter
- name
- use-worktrees
- description
- Use when starting feature work that needs isolation from current workspace or before executing implementation plans - ensures an isolated workspace exists via native tools or git worktree fallback
03 SKILL.md 正文
Using Git Worktrees
Overview
Ensure work happens in an isolated workspace. Prefer your platform's native worktree tools. Fall back to manual git worktrees only when no native tool is available.
Core principle: Identify the work lifecycle and pin its base first. Then
detect existing isolation, use native tools, or fall back to git. Never let the
caller's current HEAD choose a new branch's base implicitly.
Announce at start: "I'm using the use-worktrees skill to set up an isolated workspace."
Lifecycle Gate (before Step 0)
Before inspecting the checkout, establish four values:
WORKSPACE_ID— stable identity for this project, feature, or plan;WORK_MODE—neworcontinue;BASE_BRANCH— the branch this work must eventually merge into; andBASE_SHA— the verified commit from which a new worktree must fork.
The plan or calling workflow should provide these values. For new work with no declared base, resolve the repository's configured default branch and confirm it with your human partner before creating anything. Then resolve the commit:
BASE_SHA=$(git rev-parse "${BASE_BRANCH}^{commit}")
Record WORKSPACE_ID, BASE_BRANCH, and BASE_SHA in the plan ledger or other
durable workflow state. A branch name alone can move; a SHA alone does not
preserve merge intent.
WORK_MODE=continue is an explicit continuation declaration. It must name the
expected existing work branch or detached workspace. Never infer continuation
merely because the current directory is a linked worktree.
Step 0: Detect Existing Isolation
Before creating anything, check if you are already in an isolated workspace.
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
BRANCH=$(git branch --show-current)
Submodule guard: GIT_DIR != GIT_COMMON is also true inside git submodules. Before concluding "already in a worktree," verify you are not in a submodule:
# If this returns a path, you're in a submodule, not a worktree — treat as normal repo
git rev-parse --show-superproject-working-tree 2>/dev/null
If GIT_DIR != GIT_COMMON (and not a submodule): You are already in a
linked worktree. Reuse it only when WORK_MODE=continue and its branch/workspace
matches WORKSPACE_ID's recorded state. Verify that BASE_SHA is the recorded
base (or an ancestor when the base branch has advanced).
For WORK_MODE=new, or when the recorded identity does not match, this is an
unrelated linked worktree. Do not reuse it and do not branch from its HEAD.
Create the new workspace from the repository's main checkout using the pinned
BASE_SHA in Step 1.
Report with branch state:
- On a branch: "Already in isolated workspace at
<path>on branch<name>." - Detached HEAD: "Already in isolated workspace at
<path>(detached HEAD, externally managed). Branch creation needed at finish time."
If GIT_DIR == GIT_COMMON (or in a submodule): You are in a normal repo checkout.
Has the user already indicated their worktree preference in your instructions? If not, ask for consent before creating a worktree:
"Would you like me to set up an isolated worktree? It protects your current branch from changes."
Honor any existing declared preference without asking. If the user declines consent, work in place and skip to Step 2.
Step 1: Create Isolated Workspace
Choose the branch name first, then try the two creation mechanisms in order.
1a. Branch Name
A native worktree tool and the git fallback both need the work branch name. Derive it before creating either workspace.
For repos on any other forge, use whatever convention that repo's CONTRIBUTING
or CODEOWNERS documents; if there is none, feature/<slug> is a safe default.
1b. Native Worktree Tools (preferred)
The user has asked for an isolated workspace (Step 0 consent). Do you already
have a way to create a worktree? It might be a tool with a name like
EnterWorktree, WorktreeCreate, a /worktree command, or a --worktree
flag. In this repo, use moe jig worktree create <branch> [--base <ref>] —
it handles placement in .moe/worktrees/, gitignore, and lineage verification.
If you have a native tool, use it and skip to Step 2.
Native tools handle directory placement, branch creation, and cleanup
automatically, but they do not get to choose lineage. Pass BASE_SHA when the
tool accepts a base. If it only branches from the caller's HEAD, invoke it
only from a checkout whose HEAD equals BASE_SHA, then verify the created
workspace's merge base. If neither is possible, do not silently stack the new
work on the current branch; use the git fallback or report that the harness
cannot create the requested workspace safely.
Only proceed to Step 1c if you have no usable native worktree tool available.
1c. Git Worktree Fallback
Only use this if Step 1b does not apply — you have no native worktree tool available. Create a worktree manually using git.
Directory Selection
Resolve the primary checkout from the common Git directory so directory selection does not happen inside an unrelated linked worktree:
PRIMARY_ROOT=$(git -C "$GIT_COMMON/.." rev-parse --show-toplevel)
Follow this priority order under PRIMARY_ROOT. Explicit user preference
always beats observed filesystem state.
-
Check your instructions for a declared worktree directory preference. If the user has already specified one, use it without asking.
-
Check for an existing project-local worktree directory:
ls -d "$PRIMARY_ROOT/.moe/worktrees" 2>/dev/null # Preferred ls -d "$PRIMARY_ROOT/.worktrees" 2>/dev/null # Legacy ls -d "$PRIMARY_ROOT/worktrees" 2>/dev/null # AlternativeIf found, use the first match.
.moe/worktreeswins over.worktreeswins overworktrees. -
If there is no other guidance available, default to
.moe/worktrees/at the project root.
Safety Verification (project-local directories only)
MUST verify directory is ignored before creating worktree:
git -C "$PRIMARY_ROOT" check-ignore -q .moe/worktrees 2>/dev/null ||
git -C "$PRIMARY_ROOT" check-ignore -q .worktrees 2>/dev/null ||
git -C "$PRIMARY_ROOT" check-ignore -q worktrees 2>/dev/null
If NOT ignored: Add to .gitignore, commit the change, then proceed.
Why critical: Prevents accidentally committing worktree contents to repository.
Create the Worktree
# Determine path based on chosen location
path="$LOCATION/$BRANCH_NAME"
git -C "$PRIMARY_ROOT" worktree add "$path" -b "$BRANCH_NAME" "$BASE_SHA"
cd "$path"
test "$(git merge-base HEAD "$BASE_SHA")" = "$BASE_SHA"
Sandbox fallback: If git worktree add fails with a permission error (sandbox denial), tell the user the sandbox blocked worktree creation and you're working in the current directory instead. Then run setup and baseline tests in place.
1d. One Worktree Per Parallel Worker
When dispatching parallel implementer subagents per the worktree gate
(dispatch-agents, "The gate"), each concurrent worker gets its
OWN linked worktree. Two workers writing into one checkout defeats the
isolation the gate is built on and reintroduces the exact (conflicts)
hazard the parallel-implementation ban was rooted in.
For each worker, follow Step 1b first — use the harness's native worktree tool
when one is available, per the "never fight the harness" rule. Only fall back
to git worktree add (Step 1c) when no native tool is offered. Whichever path
you take, create the worktree BEFORE dispatch: the worker's brief hands it a
concrete path to cd into, not an instruction to make one for itself.
Each parallel worker's worktree branches from ONE recorded base SHA shared
across the wave (see sdd "Wave grouping" and
dispatch-agents "The divergent-tree rule"). A worker branched
from a stale base will cite the same file coordinates as its siblings but
read different content there. Recording the base once, before the wave
dispatches, is the safeguard.
Create every worktree first, then validate the complete set before dispatching
any worker. In this repo, use moe jig worktree create per worker and
moe jig worktree validate <path1> <path2> ... to check the set. Without
jig, verify manually:
git -C "$worker_cwd" rev-parse --path-format=absolute --git-dir
git -C "$worker_cwd" rev-parse --path-format=absolute --git-common-dir
For every worker, the resolved Git directory must differ from the resolved common directory; that proves the cwd is a linked worktree rather than the main checkout. The resolved paths must also be pairwise-unique linked Git directories across the wave; comparing cwd strings is not enough because two aliases or symlinks can name the same checkout.
Parallel implementation has exactly two rungs: (1) worktree-isolated parallel
dispatch after the complete set passes validation, then (2) sequential dispatch
of the entire wave. If native creation, git worktree add, or any validation
command fails for even one worker, use rung two from the controller's current,
validated tree. Do not dispatch the valid subset in parallel, and never fall
back to parallel dispatch without isolation.
Step 2: Project Setup
Auto-detect and run appropriate setup:
# Node.js
if [ -f package.json ]; then npm install; fi
# Rust
if [ -f Cargo.toml ]; then cargo build; fi
# Python
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
if [ -f pyproject.toml ]; then poetry install; fi
# Go
if [ -f go.mod ]; then go mod download; fi
Step 3: Verify Clean Baseline
Run tests to ensure workspace starts clean:
# Use project-appropriate command
npm test / cargo test / pytest / go test ./...
If tests fail: Report failures, ask whether to proceed or investigate.
If tests pass: Report ready.
Report
Worktree ready at <full-path>
Tests passing (<N> tests, 0 failures)
Ready to implement <feature-name>
Quick Reference
| Situation | Action |
|---|---|
| New work | Record WORKSPACE_ID, BASE_BRANCH, and BASE_SHA before inspecting isolation |
| Matching linked worktree + explicit continuation | Reuse it after verifying recorded identity and base |
| Unrelated linked worktree | Never reuse its branch or implicit HEAD |
| In a submodule | Treat as normal repo (Step 0 guard) |
| Branch name needed (any path) | Derive per Step 1a |
| Native worktree tool available | Use it with the pinned base (Step 1b) |
| No usable native tool | Git worktree fallback (Step 1c) |
| Parallel worker dispatch | Validate pairwise-unique linked Git dirs for every worker (Step 1d) |
| Any parallel worktree setup failure | Dispatch the entire wave sequentially (Step 1d) |
.moe/worktrees/ exists |
Use it (verify ignored) |
.worktrees/ exists |
Use it — legacy (verify ignored) |
worktrees/ exists |
Use it (verify ignored) |
| Multiple exist | .moe/worktrees/ wins over .worktrees/ wins over worktrees/ |
| None exists | Check instruction file, then default .moe/worktrees/ |
| Directory not ignored | Add to .gitignore + commit |
| Permission error on create | Sandbox fallback, work in place |
| Tests fail during baseline | Report failures + ask |
| No package.json/Cargo.toml | Skip dependency install |
Common Rationalizations
| Excuse | Reality |
|---|---|
| "I'm obviously not in a worktree — no need to check" | Run Step 0. Harness-created isolation and submodules both fool eyeballing; the detection commands settle it. |
"git worktree add is quicker than hunting for a native tool" |
A native tool (e.g. EnterWorktree) owns placement, branching, and cleanup. Bypassing it is the #1 mistake — it creates phantom state your harness can't see or manage. |
| "The worktree directory is surely ignored already" | Run git check-ignore. An unignored worktree directory commits the whole tree into the repo. |
| "Any directory name works" | Explicit instructions beat an existing project-local directory, which beats the .moe/worktrees/ default. |
| "The workspace is fresh — baseline tests can wait" | A dirty baseline makes every later failure ambiguous. Run the tests now; proceeding past failures is your human partner's call. |
04 同仓库更多 Skills
write-skill
Use when creating new skills, editing existing skills, or verifying skills work before deployment
write-plan
Use when you have a spec or requirements for a multi-step task, before touching code
write-clearly
Apply Strunk's timeless writing rules to ANY prose humans will read—documentation, commit messages, error messages, explanations, reports, or UI text. Makes your writing clearer, stronger, and more professional.
windows-vm
Create, manage, or connect to a headless Windows 11 VM running in Docker with SSH access. Use when the user wants to spin up, stop, restart, or SSH into a Windows VM.
verify-completion
Use when about to claim work is complete, fixed, or passing, before committing or creating MRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always
using-moe
Use when starting any conversation - establishes how to find and use skills, requiring skill invocation before ANY response including clarifying questions