Summary
Add a [copy_ignored] config section and corresponding copy logic so newly-created worktrees can inherit gitignored build artifacts (node_modules/, target/, .next/, dist/, vendor/) from a source worktree. Use reflinks/CoW where available to keep the copy instantaneous and disk-cheap.
Motivation
Currently copy_files handles a small, explicit list of tracked or config-adjacent files (.env, CLAUDE.md). It has no gitignore awareness — internal/fileutil/copy.go:93 skips symlinks but otherwise copies every entry passed to it.
Build artifacts are the biggest cold-start cost in a new worktree. For a Node monorepo, npm install takes minutes; for Rust, cargo build can take 10+ minutes. Rimba already has copy-on-write dependency cloning (internal/deps/) for lockfile-resolved deps, so the concept of sharing state across worktrees is in-bounds. This extends the pattern to arbitrary gitignored artifacts.
Worktrunk's wt step copy-ignored validates the primitive.
Config surface (.rimba/settings.toml)
[copy_ignored]
source = "main" # "main" (default) | task name | branch name | "latest"
patterns = [
"**/node_modules/",
"**/target/",
".next/",
"dist/",
"vendor/",
]
strategy = "auto" # auto | reflink | hardlink | copy
strategy = "auto" tries reflink → hardlink → plain copy per-entry.
CLI surface
rimba add feat/x # honours [copy_ignored] from config on create
rimba sync-ignored feat/x # re-sync from source after source advances
rimba add feat/x --no-copy-ignored
Implementation
internal/config/config.go — add CopyIgnored section; validate patterns compile.
internal/fileutil/reflink.go (new, platform-gated) — ReflinkFile(src, dst) using ioctl(FICLONE) on Linux / clonefile on macOS. Fall through to os.Link (hardlink), then existing Copy as last resort.
internal/fileutil/ walker — match patterns against source worktree, preserve dir structure, skip destinations that already exist unless --force.
cmd/add.go — after worktree creation, if [copy_ignored] is configured and not --no-copy-ignored, resolve source worktree path and invoke the walker.
cmd/sync_ignored.go (new) — standalone command with --force to overwrite existing destinations.
Error handling
- Source worktree missing → warn and continue worktree creation.
- Reflink unsupported on filesystem → silently degrade to hardlink → copy.
- Partial copy on failure → leave partial state; log a hint to re-run
sync-ignored --force.
Out of scope
- Watching source for changes and auto-syncing. Manual
sync-ignored only.
- Cross-filesystem deduplication (reflinks require same FS; document this).
- GC/compaction of orphaned hardlinks.
Files likely touched
internal/config/config.go — new section.
internal/fileutil/reflink.go (new, + _linux.go, _darwin.go, _other.go build tags).
internal/fileutil/copy_ignored.go (new) — pattern walker.
cmd/add.go — invoke on create.
cmd/sync_ignored.go (new).
tests/e2e/copy_ignored_test.go (new).
Summary
Add a
[copy_ignored]config section and corresponding copy logic so newly-created worktrees can inherit gitignored build artifacts (node_modules/,target/,.next/,dist/,vendor/) from a source worktree. Use reflinks/CoW where available to keep the copy instantaneous and disk-cheap.Motivation
Currently
copy_fileshandles a small, explicit list of tracked or config-adjacent files (.env,CLAUDE.md). It has no gitignore awareness —internal/fileutil/copy.go:93skips symlinks but otherwise copies every entry passed to it.Build artifacts are the biggest cold-start cost in a new worktree. For a Node monorepo,
npm installtakes minutes; for Rust,cargo buildcan take 10+ minutes. Rimba already has copy-on-write dependency cloning (internal/deps/) for lockfile-resolved deps, so the concept of sharing state across worktrees is in-bounds. This extends the pattern to arbitrary gitignored artifacts.Worktrunk's
wt step copy-ignoredvalidates the primitive.Config surface (
.rimba/settings.toml)strategy = "auto"tries reflink → hardlink → plain copy per-entry.CLI surface
Implementation
internal/config/config.go— addCopyIgnoredsection; validate patterns compile.internal/fileutil/reflink.go(new, platform-gated) —ReflinkFile(src, dst)usingioctl(FICLONE)on Linux /clonefileon macOS. Fall through toos.Link(hardlink), then existingCopyas last resort.internal/fileutil/walker — match patterns against source worktree, preserve dir structure, skip destinations that already exist unless--force.cmd/add.go— after worktree creation, if[copy_ignored]is configured and not--no-copy-ignored, resolve source worktree path and invoke the walker.cmd/sync_ignored.go(new) — standalone command with--forceto overwrite existing destinations.Error handling
sync-ignored --force.Out of scope
sync-ignoredonly.Files likely touched
internal/config/config.go— new section.internal/fileutil/reflink.go(new, +_linux.go,_darwin.go,_other.gobuild tags).internal/fileutil/copy_ignored.go(new) — pattern walker.cmd/add.go— invoke on create.cmd/sync_ignored.go(new).tests/e2e/copy_ignored_test.go(new).