A pi extension that provides isolated branch workspaces using git worktrees (wtp) and optional devcontainer targeting.
pi install npm:@lanquarden/pi-dev-worktreesOr manually (global):
cp -r packages/pi-dev-worktrees ~/.pi/agent/extensions/pi-dev-worktrees
cd ~/.pi/agent/extensions/pi-dev-worktrees && npm installOr project-local:
cp -r packages/pi-dev-worktrees /your/project/.pi/extensions/pi-dev-worktreesInstall only when you want pi-agent-dashboard to show the active worktree and devcontainer state in the session card:
npm install @lanquarden/pi-dev-worktrees-dashboard-plugingitwtpv2+ (for worktree features)devcontainerCLI (for container features)
/worktree [set] <branch>— create or switch to awtp-managed worktree;setprefix is optional/worktree off— deactivate worktree routing (commands run in project root)/worktree prune— clear stale.git/worktrees/metadata left by manual deletions/worktree status— snapshot of all active worktrees and container status/worktree remove <branch>— remove a worktree (prompts for confirmation)/worktree init— interactively create.wtp.yml/worktree hooks [show | add <cmd> | remove <n> | clear]— manage post-create hooks in.wtp.yml/devcontainer [on | off | rebuild | logs]— target the project devcontainer;rebuildforces--no-cache- LLM tools (
worktree,devcontainer) — same operations callable by the LLM as tools in a single turn:worktree—action:"set"(branch required) |"remove"(branch required) |"off"|"prune"|"status"devcontainer—action:"on"|"off"|"rebuild"|"logs"
Create ~/.pi/agent/pi-dev-worktrees.config.json to configure base_dir and post-create hooks per repository. Optional — if absent, base_dir defaults to .pi/worktrees.
{
"repos": [
{
"repoGlob": "github.com/myorg/my-repo",
"worktreeRoot": "/fast-ssd/worktrees",
"postCreateHooks": [
{ "type": "command", "command": "mise install" },
{ "type": "copy", "from": ".env.local", "to": ".env.local" }
]
},
{ "repoGlob": "*", "worktreeRoot": ".pi/worktrees" }
]
}Schema:
repoGlob— matched against theoriginremote URL.*matches any sequence including/. First match wins.worktreeRoot— path used asbase_dirin.wtp.yml. Relative paths resolved from project root.postCreateHooks(optional) — extra hooks appended whenensureWtpYmlgenerates.wtp.yml.
Config is loaded once at session_start. Restart the pi session to apply changes.
On /worktree feature/auth (or /worktree set feature/auth), the extension:
- Auto-generates
.wtp.ymlat the project root (if absent) - Runs
wtp add feature/auth(orwtp add -b feature/authfor new branches) - Prefixes all subsequent bash tool calls with
cd <worktree-path> &&
On /devcontainer on, the extension:
- Generates
.pi/devcontainer.override.jsonthat mounts the project at the same absolute path inside the container - Probes the container with
devcontainer exec ... -- echo ok; if not running, spawnsdevcontainer upin the background - Wraps all bash tool calls with
devcontainer exec --workspace-folder <root> --override-config .pi/devcontainer.override.json -- sh -c '...'
Use /devcontainer rebuild when the Dockerfile or base image has changed — it passes --no-cache to force a full image rebuild.
When both are active, the worktree cd is embedded inside the container exec:
devcontainer exec ... -- sh -c 'cd .pi/worktrees/feature/auth && <cmd>'
Prefix any bash command with HOST: to bypass all routing and run directly on the host.
Interactive !<cmd> commands follow the same routing as LLM-initiated bash calls:
- Worktree active, no container:
!npm testexecutes withcd '<worktree-path>'prefix - Container active:
!npm testexecutes inside the container !!<cmd>(double-bang): NOT intercepted — runs unchanged on hostHOST:<cmd>: strips prefix, runs on host
git, gh, and find commands always run on the host regardless of routing state.
State (active branch, container status) is persisted to the pi session file via pi.appendEntry() and restored on session resume.
@sherif-fanous/pi-rtk— uses aspawnHook-based bash tool replacement that fires after alltool_callhandlers, receiving the fully-wrappeddevcontainer execstring. This breaks container routing silently. Do not load alongsidepi-dev-worktrees.
The dashboard plugin is optional. It adds worktree and devcontainer state to the session card in pi-agent-dashboard.
npm install @lanquarden/pi-dev-worktrees-dashboard-pluginThe plugin package lives in packages/pi-dev-worktrees-dashboard-plugin and contributes session-card-badge and an enhanced bash tool renderer.
pi-rtk-optimizer is optional. It compresses bash output to reduce context consumption. pi-dev-worktrees works without it.
pi-rtk-optimizer must load before pi-dev-worktrees so it rewrites commands before the devcontainer wrapping. Use the settings.json extensions array — not pi install:
// .pi/settings.json (project-level, or ~/.pi/agent/settings.json globally)
{
"packages": [
"npm:pi-rtk-optimizer",
"npm:@lanquarden/pi-dev-worktrees"
]
}When devcontainer routing is active, rewritten commands (e.g. | rtk compress) run inside the container. Add rtk via postCreateCommand in devcontainer.json:
/workspaces→/worktree status/workspace-cleanup→/worktree remove <branch>
{ "postCreateCommand": "cp $(which rtk) /usr/local/bin/rtk" }