feat(worktree): create worktrees outside repo tree with post-create init#214
feat(worktree): create worktrees outside repo tree with post-create init#214forketyfork merged 4 commits intomainfrom
Conversation
Issue: Agents running in worktrees under .architect/ walk up the directory tree and find the root repo's CLAUDE.md, causing duplicate instructions. Additionally, new worktrees lack project-local state (.env, .envrc.local) and require manual setup commands. Solution: Worktrees are now created at ~/.architect-worktrees/<repo>/<name> by default, fully outside the repository tree. A new [worktree] config section lets users override the base directory and specify a post-create init command. When no explicit init_command is set, the shell snippet auto-runs script/setup or .architect-init.sh if either is present and executable. Existing worktrees under .architect/ remain discoverable since the worktree picker reads from git metadata, which is location-agnostic.
There was a problem hiding this comment.
Pull request overview
This PR updates worktree creation to place new worktrees outside the repository directory tree and adds optional post-create initialization via config or auto-detected scripts.
Changes:
- Added
[worktree]configuration (directory + init command) toconfig.toml+ docs. - Implemented worktree target path resolution with
~expansion and per-repo subdirectories. - Extended the worktree creation command to create parent directories and run an init step after checkout.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/config.zig | Adds WorktreeConfig to config model, plus template config output and lifecycle management. |
| src/app/worktree.zig | Adds resolveWorktreeDir() and updates worktree creation command to target external dirs + run init. |
| src/app/runtime.zig | Wires new config options into worktree creation flow and records the new cwd. |
| docs/configuration.md | Documents [worktree] configuration and default behavior. |
| docs/ARCHITECTURE.md | Updates architecture docs to reflect new worktree behavior and config scope. |
| README.md | Highlights the new default worktree location + initialization behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f9c687f35e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…isions Issue: Three bugs in resolveWorktreeDir: tilde expansion passed a leading "/" into path.join which discarded $HOME; relative config paths resolved inside the repo root; and basename-only repo IDs caused collisions between repos with the same directory name. Solution: Split resolution into dedicated helpers. resolveConfigDir handles ~, ~/..., relative, and absolute paths correctly. repoSubpath uses the full path relative to $HOME (or minus leading / for repos outside $HOME) instead of just the basename, making the worktree directory structure collision-proof.
… paths in modal Issue: External worktrees displayed as ugly ../../.architect-worktrees/... relative paths in the Cmd+T overlay and removal modal. Long paths also overflowed the 520px-wide removal confirmation modal. Solution: makeDisplayPath now uses ~/... for worktrees outside the repo tree instead of relative paths with ../ prefixes. The removal modal wraps long paths at / boundaries across multiple centered lines when the path exceeds the modal's inner width.
Summary
Worktrees created via the worktree picker (Cmd+T > Cmd+0) were placed under
<repo>/.architect/<name>, which meant they lived inside the repository directory tree. When agents like Claude Code walked up the filesystem to discover project config, they'd hit the root repo'sCLAUDE.mdand load duplicate instructions. On top of that, new worktrees started bare -- no.env, nodirenv allow, no dependency install -- requiring manual setup every time.This PR moves worktree creation outside the repo tree entirely, adds automatic post-create initialization, and improves how worktree paths are displayed.
What changed
New
[worktree]config section inconfig.tomlwith two options:directory-- base path for new worktrees (default:~/.architect-worktrees). Supports~expansion. Relative paths are resolved against$HOME. Each repo gets a subdirectory mirroring its path relative to$HOME, so the full path becomes<directory>/<repo-subpath>/<worktree-name>(e.g.~/.architect-worktrees/dev/myproject/feature-xfor a repo at~/dev/myproject).init_command-- shell command to run after worktree creation. When omitted, the app auto-detects and runsscript/setupor.architect-init.shif either exists and is executable in the new worktree.Tilde-shortened display paths -- external worktrees now show as
~/.architect-worktrees/...instead of../../.architect-worktrees/...in both the Cmd+T overlay and the removal modal.Path wrapping in removal modal -- long worktree paths that exceed the modal width now wrap at
/boundaries across multiple centered lines instead of overflowing the borders.Backwards compatible -- existing worktrees under
.architect/still show up in the picker and can be switched to or removed, since discovery uses git's internal worktree metadata which is location-agnostic.How the shell command works: the generated command chain does
cd <repo-root> && mkdir -p <parent> && git worktree add <target> -b <name> && cd <target> && <init>. The init part is either the configured command verbatim, or a shell if/elif that checks for the well-known scripts.Fixes #213
Test plan
~/.architect-worktrees/<repo-subpath>/<name>teamA/apiandteamB/api) get distinct worktree directories[worktree] directory = "/tmp/my-worktrees"and verify the override works[worktree] directory = "~/custom-worktrees"and verify tilde expands to$HOME/custom-worktrees/...[worktree] directory = "relative-dir"and verify it resolves against$HOME[worktree] init_command = "echo hello"and verify it runs after creationscript/setupto a repo, leaveinit_commandunset, create a worktree, verify auto-detection runs it~/.architect-worktrees/...in the Cmd+T overlay (not../../...)/boundaries in the removal confirmation modal.architect/worktrees still appear in the picker and can be switched to