The gap
treehouse builds each tree with git worktree add --detach, so a new tree
only contains tracked files at HEAD. Anything gitignored but still needed
to actually run the project gets left behind: .env, .env.local, local
tool config like .claude/, and so on. So right after treehouse get you
land in a worktree that won't boot until you copy those files over by hand,
every single time.
The pool model makes this sharper than it sounds. The README notes that a
tree is reused after being reset, which cleans it -- wiping any gitignored
files I copied in on the last go-round. So it's not a one-time setup cost,
it's a re-seed I have to remember on every acquire.
Prior art
Claude Code shipped exactly this and it's a clean design worth copying:
https://code.claude.com/docs/en/worktrees ("Copy gitignored files into
worktrees").
A .worktreeinclude file at the repo root, using .gitignore syntax. The
key rule that keeps it safe: a file is only copied if it matches a pattern
and is gitignored, so tracked files are never duplicated and you can't
accidentally clobber version-controlled content.
Proposed behavior
- Read
.worktreeinclude from the repo root if it exists.
- On acquire -- both fresh create and pool reuse/reset -- copy every
gitignored file matching a pattern from the main checkout into the tree.
- Support full
.gitignore syntax, including ! negation so a subtree can
be excluded even when its parent is included.
- No file present means current behavior, so it's fully opt-in.
Example:
# .worktreeinclude
.env
.env.local
.claude/
config/secrets.json
docs/local-notes/
!docs/local-notes/archive/
Why native, not just a post_create hook
A post_create hook can do this today, but it has two real problems:
- Repo-level hooks are deliberately ignored. The README is explicit:
"Hooks in repo-level treehouse.toml are ignored for safety." Only the
user-level ~/.config/treehouse/config.toml runs hooks. That's the right
call for arbitrary shell execution, but it also means a team can't commit
a shared seed config -- everyone has to wire up their own machine-local
hook independently.
- Each person ends up hand-rolling the same
git worktree list --porcelain
discovery plus copy script, and getting the reuse/reset re-seed right.
A .worktreeinclude manifest is data, not executable code. It's safe to
commit and share with the whole team, which is the whole point of pinning it
in the repo. It solves the one copy case that everyone hits without opening
the door that the hook security model was built to keep shut.
The gap
treehouse builds each tree with
git worktree add --detach, so a new treeonly contains tracked files at HEAD. Anything gitignored but still needed
to actually run the project gets left behind:
.env,.env.local, localtool config like
.claude/, and so on. So right aftertreehouse getyouland in a worktree that won't boot until you copy those files over by hand,
every single time.
The pool model makes this sharper than it sounds. The README notes that a
tree is reused after being reset, which cleans it -- wiping any gitignored
files I copied in on the last go-round. So it's not a one-time setup cost,
it's a re-seed I have to remember on every acquire.
Prior art
Claude Code shipped exactly this and it's a clean design worth copying:
https://code.claude.com/docs/en/worktrees ("Copy gitignored files into
worktrees").
A
.worktreeincludefile at the repo root, using.gitignoresyntax. Thekey rule that keeps it safe: a file is only copied if it matches a pattern
and is gitignored, so tracked files are never duplicated and you can't
accidentally clobber version-controlled content.
Proposed behavior
.worktreeincludefrom the repo root if it exists.gitignored file matching a pattern from the main checkout into the tree.
.gitignoresyntax, including!negation so a subtree canbe excluded even when its parent is included.
Example:
Why native, not just a post_create hook
A
post_createhook can do this today, but it has two real problems:"Hooks in repo-level
treehouse.tomlare ignored for safety." Only theuser-level
~/.config/treehouse/config.tomlruns hooks. That's the rightcall for arbitrary shell execution, but it also means a team can't commit
a shared seed config -- everyone has to wire up their own machine-local
hook independently.
git worktree list --porcelaindiscovery plus copy script, and getting the reuse/reset re-seed right.
A
.worktreeincludemanifest is data, not executable code. It's safe tocommit and share with the whole team, which is the whole point of pinning it
in the repo. It solves the one copy case that everyone hits without opening
the door that the hook security model was built to keep shut.