A safety layer between AI coding agents and git worktrees — available as a Rust library, CLI, or MCP server.
Safe by default on every create, delete, and garbage-collect. Concurrency-safe state. A circuit breaker when git misbehaves. Drop in as a library, a CLI, or an MCP server.
Never deletes a branch with commits not in its upstream. Overriding requires force: true.
Bidirectional path check refuses to create a worktree inside an existing one — no more CWD-drift disasters.
Post-create check for encrypted blobs. If the smudge filter didn't run, the worktree is rolled back.
Atomic writes via tmp + fsync + rename. OS-level flock with network-FS warnings. 30s timeout with retry.
Allocates from a configurable range (default 3100–5100) with TTLs. Stale leases are swept on startup.
Trips after N consecutive git failures (default 3). Refuses to create more orphans when git is broken.
Uses reflink-copy on APFS, Btrfs, XFS. Falls back to standard copy. Required/Preferred/Disabled modes.
Shells out to the user's installed git. No libgit2, no gix, no reimplementation of git semantics.
git worktree list --porcelain is truth. state.json is a cache. If they disagree, git wins.
iso-code is one Rust library. The wt CLI and the MCP server are thin binaries that wrap it — both delegate every worktree operation to the library, so all three paths enforce the same safety guarantees.
For: Programmatic control
The Rust library. Add it to your Cargo.toml and call Manager directly.
# Cargo.toml [dependencies] iso-code = "0.1"
wt CLIFor: One-off commands
Drop-in command for humans, scripts, and hook handlers.
cargo install iso-code-cli
For: Autonomous agents
Stdio MCP server exposing worktree_* tools to agents.
cargo install iso-code-mcp
The same lifecycle operations are available through all three packages. Pick the one that matches your integration.
The Manager is the single entry point. Every lifecycle operation runs its safety sequence in order.
use iso_code::{Manager, Config, CreateOptions, DeleteOptions}; fn main() -> Result<(), Box<dyn std::error::Error>> { let mgr = Manager::new("/path/to/repo", Config::default())?; // Create — runs all pre-create guards, then `git worktree add`. let (handle, _) = mgr.create( "feature/my-branch", "/path/to/worktree", CreateOptions::default(), )?; // List — reconciles git's porcelain output with state.json. let worktrees = mgr.list()?; // Delete — 5-step unmerged check, then `git worktree remove`. mgr.delete(&handle, DeleteOptions::default())?; // GC — dry_run = true by default. Always preview first. let report = mgr.gc(Default::default())?; Ok(()) }
wt — command referenceSame operations as the library, from a terminal or script. Every command runs through the library's safety guards.
| Command | Description |
|---|---|
wt list | List all worktrees known to git for this repository. |
wt create <branch> <path> | Create a new worktree at <path> checking out <branch>. |
wt delete <path> | Delete a worktree after running the 5-step unmerged-commit check. |
wt attach <path> | Register an externally-created worktree under iso-code management. |
wt gc [--run] [--max-age-days N] | Garbage-collect orphans. Defaults to a dry run; pass --run to evict. |
wt hook --stdin-format <tool> | Wire up as a hook for Claude Code, Cursor, or VS Code. |
The stdio MCP server exposes the library as worktree_* tools to any MCP-aware orchestrator. Drop one of these into your config.
// ~/.claude/claude_desktop_config.json { "mcpServers": { "iso-code": { "command": "iso-code-mcp", "args": [] } } }
// .cursor/mcp.json { "mcpServers": { "iso-code": { "command": "iso-code-mcp" } } }
// .vscode/mcp.json { "servers": { "iso-code": { "type": "stdio", "command": "iso-code-mcp" } } }
// opencode.json { "mcp": { "servers": { "iso-code": { "type": "local", "command": ["iso-code-mcp"] } } } }
Every major AI coding orchestrator — Claude Code, Cursor, Claude Squad, OpenCode, VS Code Copilot — uses git worktrees to isolate parallel agent sessions, and each has reimplemented worktree lifecycle independently. The result is the same handful of failure modes showing up across tools:
Branches with unmerged commits get deleted during cleanup without warning. Agent ID collisions can cause sub-session cleanup to take down the parent's working directory.
Retry loops and missing circuit breakers accumulate hundreds of orphaned worktrees, burning tens of gigabytes against codebases a fraction that size.
Worktree creation races the smudge filter, producing commits that stage encrypted blobs as deletions of every file in the repository.
Context compaction or CWD drift causes new worktrees to be created inside existing ones, corrupting both.
Port collisions on shared defaults, missing .env files, and Docker namespace clobbering across parallel agent sessions.
--porcelain -z)junction crate)git worktree list --porcelain — state.json is cache only