Skip to content

chore(worktree): put worktrees under .claude and carry the overrides into them - #124

Merged
anilcancakir merged 1 commit into
mainfrom
chore/worktree-layout
Sep 3, 2026
Merged

chore(worktree): put worktrees under .claude and carry the overrides into them#124
anilcancakir merged 1 commit into
mainfrom
chore/worktree-layout

Conversation

@anilcancakir

Copy link
Copy Markdown
Contributor

What

  • .gitignore: ignore .claude/worktrees/ (only that subdirectory; the rules under .claude/ stay tracked)
  • .worktreeinclude: new, copies pubspec_overrides.yaml into every worktree Claude Code creates

Why

Worktrees were opened beside the checkout as magic_starter-<slug>, so they landed in the workspace directory next to the real repositories, and Claude Code's EnterWorktree could not be used at all: it writes to a fixed .claude/worktrees/<slug>.

Moving them inside exposes a problem the old layout hid. pubspec_overrides.yaml is gitignored, so a worktree never receives it, and the absence is silent rather than loud: the siblings resolve from pub.dev, flutter pub get succeeds, and the suite passes against the PUBLISHED packages while the diff under review is of the local ones. An unreleased sibling API is where that bites.

For the copy to be correct the local file needs ABSOLUTE paths, since a relative ../magic resolves to .claude/worktrees/magic from inside a worktree. That file is machine-local and not committed, so this PR cannot carry it; the requirement is documented in .worktreeinclude.

CI is unaffected. It writes its own pubspec_overrides.yaml with relative paths, which is correct there, because the siblings job clones the six repositories beside the checkout.

Testing

Ran locally on this branch:

  1. Rewrote the local pubspec_overrides.yaml to absolute paths, flutter pub get in the main checkout: resolved.
  2. git worktree add .claude/worktrees/probe: confirmed pubspec_overrides.yaml is absent there, which is the failure this PR is about.
  3. Copied the file in (what .worktreeinclude automates) and ran flutter pub get in the worktree: resolved, and package_config.json points at the local checkouts:
magic                 file:///Users/anilcan/Code/fluttersdk/magic
magic_notifications   file:///Users/anilcan/Code/fluttersdk/magic_notifications
fluttersdk_wind       file:///Users/anilcan/Code/fluttersdk/wind
fluttersdk_artisan    file:///Users/anilcan/Code/fluttersdk/artisan
  1. git status in the main checkout shows no trace of the worktree, so the ignore rule works.

Probe worktree and its branch removed afterwards.

…into them

Worktrees were opened beside the checkout as `magic_starter-<slug>`, which put
them in the workspace directory next to the real repositories and left Claude
Code's own `EnterWorktree` unusable, since that tool writes to a fixed
`.claude/worktrees/<slug>`.

The move exposes a second problem that the old layout hid. `pubspec_overrides.yaml`
is gitignored, so a worktree never receives it, and its absence is silent: the
siblings resolve from pub.dev, `flutter pub get` succeeds, and the suite then
passes against the PUBLISHED packages while the diff under review is of the local
ones. `.worktreeinclude` is what copies the file in.

For that copy to be correct the local file needs absolute paths, because a
relative `../magic` resolves to `.claude/worktrees/magic` from inside a worktree.
That file is machine-local and not committed, so this commit cannot carry it; the
note lives in `.worktreeinclude`. CI is unaffected: it writes its own copy with
relative paths, which is right there because it clones the siblings beside the
checkout.
@kodizm

kodizm Bot commented Sep 3, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

Two config-only files, both correct: the ignore rule scopes to .claude/worktrees/ without touching the tracked rules, and the .worktreeinclude entry fixes a real silent-fallback problem.

Minor

.worktreeinclude:1.pubignore excludes .claude/, CLAUDE.md and .github/, but not .worktreeinclude, so this developer-only file ships inside the published pub.dev archive. Adding it to .pubignore keeps the package clean. (maintainability)

Notes on the claims, all of which check out

  • git check-ignore -v .claude/worktrees/probe/foo.gitignore:48:.claude/worktrees/, and .claude/rules/* plus .claude/settings.json stay tracked, so the narrow scope is real.
  • .claude/settings.json registers only a PostToolUse hook, so the file's "this project has no WorktreeCreate hook" caveat is accurate today. Worth remembering that adding one later silently disables this copy.
  • "CI is unaffected" is right: .github/workflows/ci.yml:48-63 writes its own pubspec_overrides.yaml with relative paths after checkout, in a job that clones the six siblings beside it, so nothing here reaches CI.
  • The absolute-path requirement is documented but unenforceable from the repo, since the file is gitignored. If a stale relative copy gets picked up, version solving fails loudly in the worktree rather than falling back to pub.dev, so the failure mode is the safe one.

Tests

No test covers this and none could: both files are consumed by git and by the harness, not by the package. No Dart changed.

Checks I ran

  • mcp__kodizm__read_pull_request_diff — 2 files, both read in full, nothing dropped.
  • git check-ignore -v .claude/worktrees/probe/foo → matched .gitignore:48.
  • git status --porcelain → clean.
  • Read .pubignore, .claude/settings.json, .github/workflows/ci.yml to verify the description's claims.
  • No linter, formatter or test run: no Dart, YAML or lib/ file is touched, so flutter analyze and flutter test have nothing to say about this diff.

@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@anilcancakir

Copy link
Copy Markdown
Contributor Author

Thanks, the four verification notes all match what I measured. The .pubignore finding does not hold though, and the reason is one level below it.

.worktreeinclude is a dotfile, and pub excludes hidden entries before .pubignore is ever consulted. From the publishing docs: "Any hidden files or directories. These have names that begin with dot (.)".

Measured on this branch rather than reasoned about:

$ flutter pub publish --dry-run > /tmp/pubdry.txt 2>&1
$ grep -c worktreeinclude /tmp/pubdry.txt
0
$ sed -n "83,90p" /tmp/pubdry.txt
Publishing magic_starter 0.0.1-alpha.26 to https://pub.dev:
├── CHANGELOG.md (94 KB)
├── LICENSE (1 KB)
├── README.md (26 KB)
├── analysis_options.yaml (<1 KB)
├── assets

The listing is 560 lines and contains no dotfile at all, not even .pubignore itself. So the file does not ship, and adding it to .pubignore would be a no-op.

Same reasoning applies to the .claude/, .idea/, .github/ and .vscode/ lines already in .pubignore: they are redundant for the same reason. Harmless, and out of scope here, so I am leaving them alone.

Merging.

@anilcancakir
anilcancakir merged commit 25949dd into main Sep 3, 2026
5 checks passed
@anilcancakir
anilcancakir deleted the chore/worktree-layout branch September 3, 2026 16:23
anilcancakir added a commit to fluttersdk/magic that referenced this pull request Sep 3, 2026
…into them (#145)

* chore(worktree): put worktrees under .claude and carry the overrides into them

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): record that git clean now reaches a live worktree

* docs(worktree): put the absolute-path requirement in Key Gotchas

* 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.
anilcancakir added a commit to fluttersdk/dusk that referenced this pull request Sep 3, 2026
…into them (#40)

* chore(worktree): put worktrees under .claude and carry the overrides into them

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): record the session-ownership guard this layout retires

* 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.
anilcancakir added a commit to fluttersdk/telescope that referenced this pull request Sep 3, 2026
…into them (#29)

* chore(worktree): put worktrees under .claude and carry the overrides into them

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): stop claiming there is no overrides file, and pin it to absolute paths

* 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.
anilcancakir added a commit to fluttersdk/magic_devtools that referenced this pull request Sep 3, 2026
…into them (#18)

* chore(worktree): put worktrees under .claude and carry the overrides into them

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): correct the .claude claim and record the git clean reach

* 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.
anilcancakir added a commit to fluttersdk/magic_deeplink that referenced this pull request Sep 3, 2026
…into them (#16)

* chore(worktree): put worktrees under .claude and carry the overrides into them

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): record that git clean now reaches a live worktree

* docs(worktree): put the absolute-path requirement in Key Gotchas

* 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.
anilcancakir added a commit to fluttersdk/magic_notifications that referenced this pull request Sep 3, 2026
…into them (#24)

* chore(worktree): put worktrees under .claude and carry the overrides into them

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): record that git clean now reaches a live worktree

* 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.
anilcancakir added a commit to fluttersdk/magic_social_auth that referenced this pull request Sep 3, 2026
…into them (#18)

* chore(worktree): put worktrees under .claude and carry the overrides into them

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): record that git clean now reaches a live worktree

* 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.
anilcancakir added a commit to fluttersdk/magic_example that referenced this pull request Sep 3, 2026
…into them (#11)

* chore(worktree): put worktrees under .claude and carry the overrides into them

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* fix(worktree): copy pubspec_overrides.yaml in bin/check, not only on the Claude Code path

* 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.
anilcancakir added a commit to fluttersdk/artisan that referenced this pull request Sep 3, 2026
)

* chore(worktree): keep Claude Code worktrees out of the working tree

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): record that git clean now reaches a live worktree

* 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.
anilcancakir added a commit to fluttersdk/magic_payments that referenced this pull request Sep 3, 2026
* chore(worktree): keep Claude Code worktrees out of the working tree

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): record that git clean now reaches a live worktree

* 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.
anilcancakir added a commit to fluttersdk/wind_diagnostics_contracts that referenced this pull request Sep 3, 2026
* chore(worktree): keep Claude Code worktrees out of the working tree

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): correct the .claude claim and record the git clean reach

* 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.
anilcancakir added a commit to fluttersdk/magic-starter-laravel that referenced this pull request Sep 3, 2026
)

* chore(worktree): keep Claude Code worktrees out of the working tree

Worktrees used to sit beside the checkout as <repo>-<slug>, which left EnterWorktree unusable since that tool writes to a fixed .claude/worktrees/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): record that git clean now reaches a live worktree

* 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.
anilcancakir added a commit to fluttersdk/wind that referenced this pull request Sep 3, 2026
…into them (#194)

* chore(worktree): put worktrees under .claude and carry the overrides into them

Worktrees used to sit beside the checkout as <repo>-<slug>, 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/<slug>. Pattern proven on fluttersdk/magic_starter#124.

* docs(worktree): record that git clean now reaches a live worktree

* 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.
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