Skip to content

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

Merged
anilcancakir merged 3 commits into
masterfrom
chore/worktree-layout
Sep 3, 2026
Merged

chore(worktree): put worktrees under .claude and carry the overrides into them#29
anilcancakir merged 3 commits into
masterfrom
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 <repo>-<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.

Testing

The pattern was proven end to end on fluttersdk/magic_starter#124 first: probe worktree opened under the new path, pubspec_overrides.yaml confirmed absent, copied in, flutter pub get resolved and package_config.json pointed at the local checkouts. Here I verified that every rewritten absolute path resolves to a real package directory and that flutter pub get still succeeds.

No Dart, YAML or lib/ file is touched, so analyze, format and test have nothing to say about this diff.

…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.
@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!

@kodizm

kodizm Bot commented Sep 3, 2026

Copy link
Copy Markdown

Note

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

Tooling-only change, and it does what it says: the ignore rule is correctly scoped to .claude/worktrees/ and the new .worktreeinclude stays out of the published archive.

Minor

.worktreeinclude:21 — maintainability / doc sync. CLAUDE.md:14 still states that production deps are hosted only "(no pubspec_overrides.yaml)", and no such file exists in the checkout. This PR's whole rationale is that a machine-local overrides file must reach worktrees, so the root spec and the new tooling now read as contradicting each other. A one-line amendment to CLAUDE.md saying the file is machine-local, gitignored, and must use absolute paths would put the requirement where a contributor looks for it, rather than only in a file they will never open.

Tests

Nothing to test: no Dart, YAML or lib/ file is touched, so the suite, dart analyze and dart format are unaffected by this diff. Agreed with the author on that point.

Checks I ran

  • git check-ignore -v .claude/worktrees/foo/x.dart -> matched .gitignore:48; git check-ignore -v .claude/rules/tests.md -> no match, and git ls-files .claude still lists rules/tests.md and rules/watchers.md, so the tracked rules are unaffected.
  • dart pub publish --dry-run -> "Package has 0 warnings", 112 KB archive; grepping the file listing for worktree returns nothing, so .worktreeinclude does not ship (dotfiles are excluded before .pubignore even applies).
  • Grepped both files for U+2014 / U+2013 -> none, per the no-dash style rule.
  • Confirmed pubspec_overrides.yaml is gitignored (last line of .gitignore), which is the precondition for .worktreeinclude copying it at all.

@anilcancakir

Copy link
Copy Markdown
Contributor Author

Fixed, and the contradiction was worse than the report could see. CLAUDE.md:14 said "Production deps are hosted only (no pubspec_overrides.yaml)", and a pubspec_overrides.yaml does exist here; it is gitignored, so it is absent from the CI checkout you read. The claim was already false before this PR, and this PR made it visibly so.

The parenthetical is gone and the paragraph now says local sibling development goes through that gitignored file and that its paths must be absolute, with the .claude/worktrees/artisan failure spelled out.

@kodizm

kodizm Bot commented Sep 3, 2026

Copy link
Copy Markdown

Note

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

Incremental re-review of 82b1f3f only: the earlier doc-sync finding is settled, and the one thing left in the new commit is a stray character in a comment.

Since my last pass: CLAUDE.md:14 lost the false "(no pubspec_overrides.yaml)" parenthetical and gained a paragraph pinning the file to absolute paths and naming the .claude/worktrees/artisan failure; .gitignore gained a comment about git clean -xdf wiping a live worktree. No behaviour, no Dart.

Minor

.gitignore:47 — typo. The line reads # under it are part of the repository.# : a trailing # where the blank comment separator between the two paragraphs was meant to go, so the two comment blocks run together. Cosmetic only; the ignore rule itself is unaffected.

Tests

Nothing to test; the commit touches only .gitignore comments and CLAUDE.md prose.

Checks I ran

  • cat -A .gitignore -> line 47 ends repository.#$, confirming the stray # is in the file and not a diff artefact.
  • git check-ignore -v .claude/worktrees/x/y.dart -> matched .gitignore:52; git check-ignore -v .claude/rules/tests.md -> no match, so the scoping still holds after the edit.
  • Grepped .gitignore, CLAUDE.md and .worktreeinclude for U+2013 / U+2014 -> none, per the no-dash style rule.

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.
@kodizm

kodizm Bot commented Sep 3, 2026

Copy link
Copy Markdown

Note

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

Incremental re-review of a95dc75 only: the stray # is gone and the corrected git clean claim is accurate, verified end to end. No findings.

Since my last pass, .gitignore is the only file touched: line 47 now ends at repository. with a proper blank # separator, and the second paragraph was rewritten from "git clean -xdf here wipes a live worktree" to the opposite. The rewrite is the correct reading, not just a wording change: git resolves a gitfile in its nested-repository guard, so plain -xdf skips the worktree and only -xdff destroys it. The comment even quotes git's own wording, which matches byte for byte.

Tests

Nothing to test; the commit changes comment lines in .gitignore and no rule pattern, so the suite, dart analyze and dart format are untouched.

Checks I ran

  • Built a throwaway repo with a worktree at .claude/worktrees/probe under the same ignore rule: git clean -xdfn -> Would skip repository .claude/worktrees/probe; git clean -xdf -> Skipping repository ..., live file survived; git clean -xdff -> file wiped while ls .git/worktrees still listed probe. Both sentences in the new comment hold, including the leftover registration.
  • cat -A .gitignore -> line 47 now ends repository.$, so the trailing # from my previous review is fixed and the separator is a bare # line.
  • git check-ignore -v .claude/worktrees/x/y.dart -> matched .gitignore:54; git check-ignore -v .claude/rules/tests.md -> no match, so the scoping is unchanged by the comment edit.
  • Grepped .gitignore for U+2013 / U+2014 -> none, per the no-dash style rule.

@anilcancakir
anilcancakir merged commit 4f2320e into master Sep 3, 2026
4 checks passed
@anilcancakir
anilcancakir deleted the chore/worktree-layout branch September 3, 2026 18:03
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