Skip to content

feat: let agent sessions work across all worktrees of a repo - #36

Merged
MrPointer merged 3 commits into
mainfrom
feat/bare-worktree-layout
Oct 21, 2026
Merged

MrPointer merged 3 commits into
mainfrom
feat/bare-worktree-layout

Conversation

@MrPointer

Copy link
Copy Markdown
Owner

📝 Summary

Sandboxed agents could only reach the folder they started in, so worktrees that wt created next to a repository were out of reach for a running session. This branch gives every repository a predictable place for its worktrees and has the nono launcher grant that place at launch. Repositories we control use a bare layout (<repo>/.git plus one folder per worktree); classic clones whose location another tool decides keep working, with their worktrees in a central folder.

Key Decisions

🌳 Bare worktree layout

New git wtclone clones into <repo>/.git (bare) plus <repo>/<default-branch>, behaving like a normal clone otherwise: remote-tracking branches, origin/HEAD, one local branch with upstream, submodules initialized. git wtmigrate converts an existing clone in place, keeping uncommitted, staged, untracked, and ignored files, and moves linked worktrees into the container. It refuses cases it cannot convert safely, such as initialized submodules or an operation in progress. Both ship man pages, so git wtclone --help works.

The commands are git subcommands rather than shell aliases so the vendored oh-my-zsh git plugin, which refreshes weekly, cannot collide with them.

🗂️ Classic clones

Some repositories cannot become a container, such as the chezmoi source directory. For these, the worktrunk template sends worktrees to ~/.local/share/worktrees/<key>/<branch>, where the key is the checkout path with /, \, and . replaced by -. The template tells the two layouts apart by whether repo_path ends in /.git.

🔐 Launcher grants

_nono_agent_run now grants the folder holding .git (the container for bare repos, the checkout for classic ones), never widening to $HOME or /. For classic clones it also creates and grants the central worktree folder, derived with the same key rule as the worktrunk template. A tampered .git pointer can only redirect that extra grant within the central root.

🧭 Script-owned config in the chezmoi skill

chezmoi source-path reports files edited by run_* scripts as "not managed", which led to editing the worktrunk config directly instead of its owning script. The managing-chezmoi skill now says to search the run_* scripts first and change values there.

🔄 Before & After

Area Before After
Worktree location ../<repo>-<branch>, outside the sandbox grant <repo>/<branch> (bare) or ~/.local/share/worktrees/<key>/<branch> (classic)
Sandbox grant Current folder plus shared .git Container, or checkout plus its central worktree folder
Cloning Plain git clone git wtclone for the bare layout
Existing clones No conversion path git wtmigrate converts in place
Script-owned targets in the skill Treated as unmanaged Checked against run_* scripts first

Sandboxed agents could only reach the directory they started in, so
worktrees created by wt next to the repository were out of reach for
the running session. Keeping each repository as a container that holds
a bare .git and one folder per worktree lets the launcher grant the
whole container up front.

Add git wtclone to clone straight into that layout and git wtmigrate
to convert existing clones, both with man pages. The nono launcher now
grants the folder holding .git, and the worktrunk template places new
worktrees inside the container.
Some repositories live where another tool puts them, such as the
chezmoi source directory, so they cannot become a bare container.
With the container-only template, wt would place their worktrees in
the parent folder, outside what the agent sandbox grants.

The worktrunk template now sends worktrees of classic clones to a
central folder under ~/.local/share/worktrees, keyed by the checkout
path. The nono launcher derives the same key and grants that folder
alongside the checkout, so a session can work across those worktrees
too. The git wtclone and git wtmigrate man pages describe this case.
chezmoi source-path only knows targets backed by a source file, so a
config file that a run_* script edits, such as the worktrunk config,
reports "not managed". Agents following the skill then edited the
target directly, and the next apply would have reverted the change.

Tell the skill to search the run_* scripts for the target path first
and to change values in the owning script.
@MrPointer
MrPointer merged commit e46c47c into main Oct 21, 2026
5 checks passed
@MrPointer
MrPointer deleted the feat/bare-worktree-layout branch October 21, 2026 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant