Skip to content

fix(cursor): write repo-relative shim path in project hooks.json - #397

Open
stefanwalther wants to merge 1 commit into
trailhq:mainfrom
stefanwalther:fix-cursor-hooks-relative-path
Open

stefanwalther wants to merge 1 commit into
trailhq:mainfrom
stefanwalther:fix-cursor-hooks-relative-path

Conversation

@stefanwalther

@stefanwalther stefanwalther commented Sep 15, 2026

Copy link
Copy Markdown

Problem

graft init writes the checkout's absolute path into the committed .cursor/hooks.json:

{
  "command": "node \"/Users/me/code/proj/.cursor/hooks/graft-hooks.cjs\" cursor-post-tool"
}

That path is different on every machine and worktree. In a repo with committed wiring, each fresh init rewrites these lines, so hooks.json shows as modified everywhere. It also breaks pulls: anyone who ran init locally before fetching the wired branch holds entries that collide with the incoming commit, and git aborts the merge.

Fix

Cursor runs project hooks from the repo root, so the command is now repo-relative:

{
  "command": "node .cursor/hooks/graft-hooks.cjs cursor-post-tool"
}

The stale-entry check matches on graft-hooks.cjs, so the next init swaps old absolute entries in place. Nothing to clean up by hand.

Verification

New test assertion that no checkout path leaks into the commands. Full suite green (1221 tests), tsc clean.

init baked the absolute checkout path into .cursor/hooks.json commands. Every clone and worktree then showed the file as modified after its own init run, and pulling a branch that committed the wiring failed when local untracked copies collided with it. Cursor runs project hooks from the repo root, so a relative path resolves the same everywhere and stays committed clean. Old absolute entries still match isGraftEntry, so the next init upgrades them in place.
@trailhq-graft

trailhq-graft Bot commented Sep 15, 2026

Copy link
Copy Markdown

🌱 graft blast radius

1 area changed → 2 areas can be affected. 3 dependent symbols, depth 2.
Tests: 1 area updated its tests.
Tag: @anirudhkumar-nanonets — wireTarget · @afeddersen — Cursor Hook Installation, Host Initialization · @Frankie-Xu — wireTarget

flowchart TB
  A0(("wireTarget<br/>2 symbols"))
  A1(("Host Initialization<br/>1 symbol"))
  classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
  class A0,A1 reached;
Loading
Can be affected Symbols Nearest hop Reached from
wireTarget 2 src/cli.ts:L1088-L1173 wireTarget — calls, depth 2 Cursor Hook Installation
Host Initialization 1 src/hosts/init.ts:L40-L98 runHostsInit — calls, depth 1 Cursor Hook Installation
Who knows this code — 4 people across 3 areas
Area Who knows it
Cursor Hook Installation · changed @afeddersen — 1 commit, last 15d ago
wireTarget · affected @anirudhkumar-nanonets — 5 commits, last 5d ago · @Frankie-Xu — 2 commits, last 15d ago
Host Initialization · affected @afeddersen — 1 commit, last 15d ago · @shhdwi — 1 commit, last 19d ago

Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no @ has no GitHub handle in its commit email — tag them by hand, or add a .mailmap entry. A suggestion from history, not a CODEOWNERS rule.

All 3 dependent symbols, grouped by area

wireTarget — 2 symbols in 2 files

  • src/cli.ts:L1088-L1173 — wireTarget (calls, depth 2)
  • src/upkeep-run.ts:L42-L51 — rewriteWiring (calls, depth 2)

Host Initialization — 1 symbol in 1 file

  • src/hosts/init.ts:L40-L98 — runHostsInit (calls, depth 1)
Test signal per changed area — 1 ✓

Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.

  • Cursor Hook Installation — 1 of 1 reached · 1 test file changed here: test/hosts-cursor-hooks.test.ts
4 test suites also reference this code

4 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.

  • test/hosts-antigravity.test.ts
  • test/hosts-init.test.ts
  • test/hosts-plan.test.ts
  • test/hosts-retract.test.ts

graft blast · refs/graft/base...HEAD · depth 2 · 2 changed files

Open the interactive graph → — click an area to see the code that changed, and the line that reaches it.

github-actions Bot added a commit that referenced this pull request Sep 15, 2026
@stefanwalther stefanwalther changed the title fix(cursor): write repo-relative shim paths in project hooks.json fix(cursor): write repo-relative shim path in project hooks.json Sep 15, 2026
@stefanwalther
stefanwalther marked this pull request as draft September 15, 2026 13:55
@stefanwalther
stefanwalther marked this pull request as ready for review September 15, 2026 14:02
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