Problem
Agents working in a git worktree in this repo are graph-blind: they cannot query the graphify knowledge graph, and silently fall back to grep.
graphify-out/ is gitignored by design (only its .gitignore is tracked — the graph is multi-MB, rewritten every commit, and would conflict across parallel worker branches), so git worktree add materialises an empty graphify-out/. And graphify query resolves graphify-out/graph.json strictly relative to cwd — no upward walk, and query has no --graph override (only path/explain/diagnose do).
claude-coordinator solved this in PRs #1613 + #1614. This issue ports that solution here.
What to do
Copy the .githooks/ directory from the claude-coordinator checkout, which exists at ~/src/claude-coordinator/.githooks/ on every machine in the fleet:
_lib.sh — shared gfy_abs / gfy_common_dir / gfy_is_linked_worktree / gfy_chain
post-checkout — in a linked worktree, symlinks graphify-out at the base checkout's graph, then exits without rebuilding; in the main worktree, chains to $GIT_COMMON_DIR/hooks/post-checkout
post-commit, post-merge — skip in linked worktrees, otherwise chain to the machine-local hook
Adapt only the comments that name claude-coordinator specifics. Do not change the logic — it is load-bearing and was arrived at by trial and error (see the two PRs above).
Non-negotiable details, each of which broke during the original work
- The hooks MUST be committed mode
100755. Git silently ignores a non-executable hook — it prints an advice hint at most and carries on as if no hook existed. Verify with git ls-files -s .githooks/ and confirm every hook (not _lib.sh) shows 100755.
core.hooksPath REPLACES .git/hooks wholesale — no merge, no fallback. Every hook kind graphify installs locally needs a counterpart in .githooks/ or it is silently disabled. That is why post-commit and post-merge shims exist alongside post-checkout; shipping only post-checkout was the #1614 bug.
- Never rebuild inside a linked worktree.
graphify-out there is a symlink to the SHARED base graph, so a rebuild would overwrite it from a feature-branch tree — and a worktree can be reaped mid-rebuild.
Testing
Add an integration test that drives the hook through real git — build a temp repo, copy in the real .githooks/, git config core.hooksPath .githooks, commit the hooks, seed a fake graphify-out/graph.json, run git worktree add, and assert the worktree's graphify-out is a symlink resolving to the base graph. std::process::Command is sufficient; no new dependencies.
Cover at minimum:
worktree add produces the symlink
- no symlink when the base checkout has no
graph.json (must not create a dangling link)
- a real graph already in the worktree is never clobbered
- anti-vacuity: assert the hook is actually reachable from inside a worktree before asserting "X does not happen" there. Git resolves a relative
core.hooksPath against the invoking directory, so .githooks/ must be committed or in-worktree checkouts never run the hook at all — two of the original tests passed for weeks without the hook ever running.
- the checked-in hooks are mode
100755
Out of scope
- Do not edit
CLAUDE.md, README, or any shared docs — the coordinator handles documentation.
- Do not add a
coord diagnose --graph equivalent; that lives in claude-coordinator and already covers every repo on the machine.
- Enabling the hook (
git config core.hooksPath .githooks) is a per-checkout deployment step the operator runs; it is not part of this PR.
Before coding
Verify this isn't already present — check whether .githooks/ already exists in this repo.
Problem
Agents working in a git worktree in this repo are graph-blind: they cannot query the graphify knowledge graph, and silently fall back to grep.
graphify-out/is gitignored by design (only its.gitignoreis tracked — the graph is multi-MB, rewritten every commit, and would conflict across parallel worker branches), sogit worktree addmaterialises an emptygraphify-out/. Andgraphify queryresolvesgraphify-out/graph.jsonstrictly relative to cwd — no upward walk, andqueryhas no--graphoverride (onlypath/explain/diagnosedo).claude-coordinator solved this in PRs #1613 + #1614. This issue ports that solution here.
What to do
Copy the
.githooks/directory from the claude-coordinator checkout, which exists at~/src/claude-coordinator/.githooks/on every machine in the fleet:_lib.sh— sharedgfy_abs/gfy_common_dir/gfy_is_linked_worktree/gfy_chainpost-checkout— in a linked worktree, symlinksgraphify-outat the base checkout's graph, then exits without rebuilding; in the main worktree, chains to$GIT_COMMON_DIR/hooks/post-checkoutpost-commit,post-merge— skip in linked worktrees, otherwise chain to the machine-local hookAdapt only the comments that name claude-coordinator specifics. Do not change the logic — it is load-bearing and was arrived at by trial and error (see the two PRs above).
Non-negotiable details, each of which broke during the original work
100755. Git silently ignores a non-executable hook — it prints an advice hint at most and carries on as if no hook existed. Verify withgit ls-files -s .githooks/and confirm every hook (not_lib.sh) shows100755.core.hooksPathREPLACES.git/hookswholesale — no merge, no fallback. Every hook kind graphify installs locally needs a counterpart in.githooks/or it is silently disabled. That is whypost-commitandpost-mergeshims exist alongsidepost-checkout; shipping onlypost-checkoutwas the #1614 bug.graphify-outthere is a symlink to the SHARED base graph, so a rebuild would overwrite it from a feature-branch tree — and a worktree can be reaped mid-rebuild.Testing
Add an integration test that drives the hook through real git — build a temp repo, copy in the real
.githooks/,git config core.hooksPath .githooks, commit the hooks, seed a fakegraphify-out/graph.json, rungit worktree add, and assert the worktree'sgraphify-outis a symlink resolving to the base graph.std::process::Commandis sufficient; no new dependencies.Cover at minimum:
worktree addproduces the symlinkgraph.json(must not create a dangling link)core.hooksPathagainst the invoking directory, so.githooks/must be committed or in-worktree checkouts never run the hook at all — two of the original tests passed for weeks without the hook ever running.100755Out of scope
CLAUDE.md,README, or any shared docs — the coordinator handles documentation.coord diagnose --graphequivalent; that lives in claude-coordinator and already covers every repo on the machine.git config core.hooksPath .githooks) is a per-checkout deployment step the operator runs; it is not part of this PR.Before coding
Verify this isn't already present — check whether
.githooks/already exists in this repo.