Why Worktrees?
Without worktrees, running two agents on the same project means they share the same working directory and branch. Changes from one agent can conflict with the other. Worktrees solve this by giving each agent its own checkout of the repository on a separate branch. Common patterns:- Run a feature development loop while a review agent works on a different branch
- Test multiple approaches to the same problem in parallel
- Keep the main branch clean while agents experiment on feature branches
Creating Worktrees
~/.local/share/clawker/worktrees/<repoName>-<projectName>-<sha256(uuid)[:12]>/. If the branch already exists, it’s checked out in the new worktree. If it doesn’t exist, it’s created from the base ref (default: HEAD).
If the worktree already exists in the registry, the command returns an error. Use clawker worktree list to check existing worktrees, or use the --worktree flag on container/loop commands for idempotent “get or create” behavior.
Listing Worktrees
| Column | Description |
|---|---|
| BRANCH | Branch name (or “(detached)” for detached HEAD) |
| PATH | Filesystem path to worktree |
| HEAD | Short commit hash |
| MODIFIED | Relative time since last change |
| STATUS | Health status |
- healthy — Directory,
.gitfile, git metadata, and branch all exist - registry_only — Directory deleted but registry entry remains (safe to prune)
- dotgit_missing — Directory exists but the
.gitfile inside is missing or is a directory instead of a file - git_metadata_missing — Directory and
.gitfile exist, but git’s internal worktree metadata (.git/worktrees/<slug>/) is gone - broken — Directory and git metadata exist, but the branch has been deleted
git worktree lock) have IsLocked set internally and are protected from pruning, but lock status is independent of health — a locked worktree can have any status.
Removing Worktrees
- Refuses to remove worktrees with uncommitted changes (unless
--force) --delete-branchrefuses to delete unmerged branches (usegit branch -Dmanually)--delete-branchrefuses to delete the currently checked-out branch
Health Checks
When you list or inspect worktrees, Clawker performs a multi-layer health check on each entry:- Directory existence — Does the worktree directory still exist on disk?
.gitfile check — Linked worktrees contain a.gitfile (not a directory) that points back to the main repository’s.git/worktrees/<slug>/metadata. Clawker verifies this file exists and is indeed a file.- Git metadata check — The main repository’s
.git/worktrees/<slug>/directory must exist. This is where git stores the worktree’s HEAD, index, and config. - Branch existence — The branch associated with the worktree must still exist in the repository.
- Lock detection — Checks for a
lockedfile in the worktree’s git metadata. Locked worktrees are protected from pruning.
Pruning Stale Entries
If worktree directories are deleted manually or bygit worktree remove (bypassing Clawker), registry entries become stale. Prune them:
git worktree lock, it’s skipped during pruning and reported separately in the output.
Automatic Worktree Creation via --worktree
Container and loop commands accept a --worktree flag that automatically creates or reuses a worktree:
branch or branch:base. If the branch doesn’t exist, it’s created from the base ref (default: HEAD). If it already exists, it’s checked out in the worktree.
Idempotent behavior
The--worktree flag is idempotent — if the worktree already exists and is healthy, it is reused rather than recreated. This means you can run the same command repeatedly without error:
.git file missing, git metadata gone, or branch deleted), the command fails with a message suggesting clawker worktree prune to clean up the stale entry first. Only worktrees with a healthy status are accepted for reuse.
This differs from
clawker worktree add, which is a strict creation command — it errors if the worktree already exists. The --worktree flag on container/loop commands is designed for repeated use in workflows where you want “get or create” semantics.Path mirroring
When--worktree is used, the worktree directory is mounted into the container at its host absolute path — not at a generic /workspace. This is essential for session persistence: Claude Code discovers sessions by matching the container’s current working directory against git worktree paths. If the container used a synthetic path, session resume would fail because the paths wouldn’t match.
See Container Internals for the full explanation of path mirroring and session persistence.
Loop conflict detection
If a loop is already running in the project root, Clawker detects the conflict and offers to create a worktree automatically:- Interactive mode: Prompts with three choices — use a worktree, proceed anyway, or abort
- Non-interactive mode: Warns and suggests
--worktree
Example: Parallel Feature Development
How Worktrees Interact with the Project Registry
Worktrees are tracked in the project registry (~/.local/share/clawker/registry.yaml) under each project:
/var → /private/var). The registry is the single source of truth for project identity.
How Worktrees Work Inside Containers
When a container is created with--worktree, two mounts are set up:
-
Worktree directory — The worktree’s checkout directory is mounted at its host absolute path (e.g.,
~/.local/share/clawker/worktrees/my-app-my-app-abc123def456/). This becomes the container’s working directory. -
Main
.gitdirectory — The main repository’s.gitdirectory is mounted at its original host absolute path (e.g.,/Users/dev/my-app/.git). This is necessary because the worktree’s.gitfile contains an absolute path reference back to the main repository’s.git/worktrees/<slug>/metadata.
.git file’s reference resolves, git finds the shared metadata, and operations like git log, git status, and git commit behave normally.
See Container Internals for the complete explanation of workspace mounting, git integration, and session persistence.