From a830464b90130fb3e86ad4bb8f8dd77861ca6bcf Mon Sep 17 00:00:00 2001 From: Anilcan Cakir Date: Thu, 3 Sep 2026 19:27:33 +0300 Subject: [PATCH 1/4] chore(worktree): put worktrees under .claude and carry the overrides into them Worktrees used to sit beside the checkout as -, which put them in the workspace directory next to the real repositories and left EnterWorktree unusable, since that tool writes to a fixed .claude/worktrees/. Pattern proven on fluttersdk/magic_starter#124. --- .gitignore | 5 +++++ .worktreeinclude | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 .worktreeinclude diff --git a/.gitignore b/.gitignore index 2fda639..a1a85e1 100644 --- a/.gitignore +++ b/.gitignore @@ -43,5 +43,10 @@ CLAUDE.local.md # Agent-instruction sync cache (machine-specific absolute paths; regenerated locally) .sync-agents-cache.json +# Worktrees Claude Code creates for parallel sessions and isolated subagents. +# Only this subdirectory: the rest of `.claude/` is tracked, because the rules +# under it are part of the repository. +.claude/worktrees/ + # Local development path wiring (never committed; breaks CI which has no sibling paths) pubspec_overrides.yaml diff --git a/.worktreeinclude b/.worktreeinclude new file mode 100644 index 0000000..1c9f3cf --- /dev/null +++ b/.worktreeinclude @@ -0,0 +1,21 @@ +# Gitignored files copied into every worktree Claude Code creates, for `--worktree`, +# for `EnterWorktree`, and for a subagent with `isolation: worktree`. +# +# A worktree is a fresh checkout, so `pubspec_overrides.yaml` is absent from it, and +# its absence fails silently rather than loudly: the siblings resolve from pub.dev +# instead of the working trees beside this one, `flutter pub get` succeeds, and the +# suite then passes against the PUBLISHED packages while the diff under review is of +# the local ones. An unreleased sibling API is where that bites. +# +# `.gitignore` syntax, and only files that match AND are gitignored are copied, so a +# tracked file can never be duplicated by this list. +# +# The paths inside `pubspec_overrides.yaml` have to be ABSOLUTE for this to work. +# Worktrees live under `.claude/worktrees/`, so a relative `../magic` resolves +# to `.claude/worktrees/magic`, which does not exist, and version solving fails on +# the first path dependency. +# +# NOT processed when a WorktreeCreate hook replaces the default git logic; such a +# hook has to copy these itself. + +pubspec_overrides.yaml From f3f07d6719335db7ff87141985675dec30613bac Mon Sep 17 00:00:00 2001 From: Anilcan Cakir Date: Thu, 3 Sep 2026 20:01:03 +0300 Subject: [PATCH 2/4] docs(worktree): record that git clean now reaches a live worktree --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a1a85e1..8897f78 100644 --- a/.gitignore +++ b/.gitignore @@ -45,7 +45,11 @@ CLAUDE.local.md # Worktrees Claude Code creates for parallel sessions and isolated subagents. # Only this subdirectory: the rest of `.claude/` is tracked, because the rules -# under it are part of the repository. +# under it are part of the repository.# +# They sit inside the working tree rather than beside it, so `git clean -xdf` here +# wipes a live worktree's contents while `.git/worktrees/` survives, leaving a +# registration that needs `git worktree prune`. A worktree's `.git` is a file rather +# than a directory, so git's nested-repo guard does not stop it. .claude/worktrees/ # Local development path wiring (never committed; breaks CI which has no sibling paths) From 32d45e913841507d4db98b9ebf9dbe06229f733b Mon Sep 17 00:00:00 2001 From: Anilcan Cakir Date: Thu, 3 Sep 2026 20:03:32 +0300 Subject: [PATCH 3/4] docs(worktree): put the absolute-path requirement in Key Gotchas --- CLAUDE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CLAUDE.md b/CLAUDE.md index 50abc74..a820391 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -91,6 +91,7 @@ Every `setUp()` MUST call `MagicApp.reset()` + `Magic.flush()` — it clears the | `ValidatesRequests` import | From `lib/src/concerns/`, not `http/` | | Web vs mobile DB | Web = in-memory SQLite (needs `web/sqlite3.wasm`), mobile = file-based | | `MagicResponse.errors` format | Parses Laravel's `{"errors": {"field": ["msg"]}}` | +| Relative paths in `pubspec_overrides.yaml` | Use ABSOLUTE ones. `.worktreeinclude` copies that file into worktrees under `.claude/worktrees/`, where `../magic_starter` resolves to `.claude/worktrees/magic_starter` and version solving fails on the first path dependency | ## Branching & release From 851e73479d0a2ef1de36cc1c161d9776e6197b93 Mon Sep 17 00:00:00 2001 From: Anilcan Cakir Date: Thu, 3 Sep 2026 20:30:40 +0300 Subject: [PATCH 4/4] fix(worktree): git clean -xdf skips a worktree, only -xdff does not The comment claimed plain -xdf wipes a live worktree because its .git is a file rather than a directory. Measured on a scratch repo: the dry run prints "Skipping repository .claude/worktrees/slug", the worktree survives -xdf with its untracked files intact, and only -xdff removes it and leaves the registration prunable. The guard keys on the gitlink, not on the form of .git. Also splits the stray # that joined the two comment blocks. --- .gitignore | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 8897f78..62c412c 100644 --- a/.gitignore +++ b/.gitignore @@ -45,11 +45,13 @@ CLAUDE.local.md # Worktrees Claude Code creates for parallel sessions and isolated subagents. # Only this subdirectory: the rest of `.claude/` is tracked, because the rules -# under it are part of the repository.# -# They sit inside the working tree rather than beside it, so `git clean -xdf` here -# wipes a live worktree's contents while `.git/worktrees/` survives, leaving a -# registration that needs `git worktree prune`. A worktree's `.git` is a file rather -# than a directory, so git's nested-repo guard does not stop it. +# under it are part of the repository. +# +# They sit inside the working tree rather than beside it. `git clean -xdf` leaves them +# alone: git's nested-repository guard resolves a gitfile too, so it reports "Skipping +# repository .claude/worktrees/" and the contents survive. `git clean -xdff` does +# not skip them, and wipes a live worktree while `.git/worktrees/` survives, +# leaving a registration that `git worktree prune` then has to clear. .claude/worktrees/ # Local development path wiring (never committed; breaks CI which has no sibling paths)