Repository navigation
feat(init)!: write no hook entries; worktree hooks become a user-level opt-in - #466
Conversation
Quest-Claim: 579425610148c647
…ttings
`quest init` no longer adds Claude Code hook entries to
`.claude/settings.json`; it removes the `quest worktree hook` entries earlier
versions wrote, including wrappers that run Quest such as
`nix run "${CLAUDE_PROJECT_DIR}#quest" -- worktree hook`, and names each on
stderr. `quest uninstall` removes both forms through the same match. The
README and SETUP.md describe the hooks as a user-level opt-in with the
entries to add.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… lookalikes The maintainer rejected the heuristic matcher (round-4 design checkpoint): Quest only ever wrote the exact `quest worktree hook`, so init and uninstall now delete only that command, on any event. Any other command hook ending in `worktree hook`, such as moq-dev/moq's `nix run ... -- worktree hook`, may be another tool's, so it stays and gets a stderr warning naming the event, command, and file; the setup PR lists it under "Left out". Drops QUEST_COMMAND and its launcher grammar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Design change: the maintainer settled the round-4 design checkpoint in /quest-complete on 2026-11-04, rejecting the heuristic matcher's premise ("I feel like we're doing something wrong here"). Facts behind it: Quest only ever wrote the exact command
Implemented in 8d8d2fc. Reviews restart with (Written by Claude Opus 5.5) |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Reviewed the whole PR head d6e260d (7 commits, 20 files) against main at e102ec7, reading the full diff and verifying the surrounding code (planInit/checkPath, the Checkout implementations, planned() and the setup service, the CLI warn contract) plus the test suites cover each claim in the PR body.
quest initwrites no hooks —planInitdropsinstallHooksand instead callsremoveHookson existing settings, returning the removed entries inside theInitChangefor.claude/settings.json.- Exact-removal with lookalike warnings —
removeHooksdeletes only handlers whose command is exactlyquest worktree hook, on every event, then the groups/events/file they empty;lookalikeHooksreports other command hooks ending inworktree hooksoinitanduninstallwarn instead of touching them. - CLI reporting —
init()now returnsInitChange[];mainwarnsremoved …/left …lines on stderr and lists only changed paths on stdout;uninstallapplies the same removal. - Cloudflare setup PR —
planned()still fetches.claude/settings.json, so the Worker removes Quest's entries and lists lookalikes under "Left out", rendered throughcode()for untrusted text; the page and commit message no longer mention hooks. - Docs and quest tree — README gives the user-level JSON opt-in, SETUP.md gains the consent-gated "Opt into worktree hooks" step and the uninstall note,
GITHUB.mdand the projects page match, theinit-hooksquest is deleted with its links reworded everywhere.
Verification notes:
- I checked the two guarantees the docs make about symlinks still hold: the Worker's
treeCheckout.statthrowsInitRefusedon any symlink prefix, including.claude/settings.jsonitself, so a linked settings file is still refused there; andcheckPathon that path usedstat(link-following) before, so local behavior is unchanged. The stale-lookingcheckPathdrop is fine. removeHookshandles the__proto__event-key hazard correctly (rebuilt withObject.fromEntries), preserves CRLF/indent, and thekept/remainingbookkeeping matches what the tests pin down: I rantest/init.test.tsandtest/cli.test.tshere — 78 passed.- The Worker's end-to-end hook-removal test could not run in this environment (the
cloudflare/workspace'snode_modulesisn't installed here) — treat that as covered by CI, which the PR body reports green at these commits.
glm-5.3-flash | 𝕏
The maintainer decided no cleanup: nobody carries the entries earlier versions wrote. init writes no hooks, and neither init, uninstall, nor the Worker's setup PR removes, detects, or warns about existing entries in .claude/settings.json. removeHooks, lookalikeHooks, HookEntry, the stderr reporting, the setup PR's hook lists, and uninstall's exact removal go, along with their tests and docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Design change: the maintainer settled hook cleanup in /quest-complete on 2026-11-04, superseding the previous "delete exact, warn others" decision. The maintainer: "Nobody is using this we dont need to cleanup."
Implemented in 21e0bf3. Reviews restarted with (Written by Claude Opus 5.5) |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Reviewed the delta since the prior pullfrog review (d6e260d): the merge of origin/main (364c25b) and commit 21e0bf3, which implements the maintainer's "no cleanup" decision — init and uninstall now leave .claude/settings.json entirely alone.
planInit(src/core/init.ts) droppedinstallHooks, thecheckPathon.claude/settings.json, and all settings parsing; init neither reads nor writes the file, and conflicts in it no longer refuse init.src/cli/setup.tsdeleteduninstallHooks;uninstallno longer edits.claude/settings.json.- The hook API left
quest/coreentirely (CLAUDE_SETTINGS,HOOK_COMMAND,HOOK_EVENTS,HookEntry,Settings,isQuestHook,parseSettings,renderSettings);HOOK_EVENTSmoved tosrc/cli/worktree-hook.ts, its only consumer. - The Cloudflare setup PR no longer fetches or names hook entries:
planned()dropped.claude/settings.json, thehookList/lookalikesplumbing and their tests are gone, and the commit message and setup page copy updated. - Tests pin the new contract: init creates no
.claude/settings.json, and init and uninstall leave an existing one byte-for-byte, including an exactquest worktree hookentry; the CLI test asserts the file never appears in output. The Worker's symlink refusal is still covered, retargeted to.claude/skills. - Docs and quest tree aligned: README's user-level opt-in JSON, SETUP.md's opt-in and remove steps,
GITHUB.md, the projects page, thequest/m0/README.mdamendment, and the now-unblockedquest/m2/hook-path-error.md.
Verified locally on 21e0bf3: tsc --noEmit clean and test/init.test.ts + test/cli.test.ts (72 tests) green. The cloudflare/ workspace's node_modules is absent in this environment, so its changes are covered by CI (reported green on this head).
glm-5.3-flash | 𝕏
|
quest land watch: the merge queue removed this pull request at 21e0bf3 because it conflicts with The land fixer works on it in the background, and the watcher re-enqueues it at the back of the queue once it is fixed or judged flaky, or hands it back here with what it needs. (written by quest land watch) |
|
quest land watch: armed auto-merge on this pull request at 1bfdb8f, so it joins the back of the merge queue once its required checks pass, with the land fixer's fix ( (written by quest land watch) |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Reviewed the delta since the prior pullfrog review (21e0bf3): only the merge commit 1bfdb8f, which merged origin/main at 42e3ad1 and resolved the conflict in the Git-call plumbing.
src/cli/setup.tsswitched from the PR branch's localgitOutput(./claims) to the sharedgithelper from./git, which additionally strips inherited repository-local variables (GIT_DIR,GIT_WORK_TREE,GIT_INDEX_FILE, …) viadiscoveryEnv()— the convention main landed in #478. Call sites (register,unregister) are otherwise unchanged; the shared helper's config-missing-returns-empty and error-shape behavior matches what those call sites already expect.src/cli/worktree-hook.tsdropped its privategithelper (which already diddiscoveryEnv()+ trim) for the same sharedgit. All call sites keep the same two-argument form with noinput, and the hook'swaiting()/Busyretry loop is untouched.- Nothing else in the PR changed versus the reviewed head;
tsc --noEmitis clean at1bfdb8fand CI's build check passed on it.
glm-5.3-flash | 𝕏

Finishes
quest/m0/user-dev-shell/init-hooks.md:quest initwrites no Claude Code hook entries, and Quest's worktree hooks become an opt-in each user adds to their own Claude settings, as the maintainer decided on 2026-11-03 (seequest/m0/user-dev-shell/README.md).Decisions
Settled by the maintainer in /quest-complete on 2026-11-04, superseding the earlier "delete exact, warn others" pick. Recorded in the Design change comment.
init,uninstall, and the Worker's setup PR handle hook entries already in a repository's.claude/settings.json? The maintainer: "Nobody is using this we dont need to cleanup."quest initsimply stops writing hook entries.init,uninstall, and the setup PR neither remove, detect, nor warn about existing entries.removeHooks,lookalikeHooks,HookEntry, the "removed/left" stderr reporting, the setup PR's hook lists, and their tests and docs go. The user-level opt-in docs (README JSON, SETUP.md opt-in step) stay.quest worktree hookentries and warn about lookalikes (the previous pick).uninstall's removal of the exactquest worktree hookthat main has today?uninstallno longer edits.claude/settings.jsoneither. Nothing in the code or docs needs it: the Worker never uninstalls, and no other caller reads.claude/settings.json.uninstall's exact removal.Changes
quest initno longer adds hooks to.claude/settings.jsonand never reads it, so a malformed or conflicting settings file no longer refuses init.quest uninstallno longer edits.claude/settings.json.planInit, so it stops proposing hooks and stops fetching.claude/settings.json. The setup page, commit message, andcloudflare/GITHUB.mdno longer mention hooks.~/.claude/settings.json. SETUP.md's Initialize step says init writes no Claude Code hooks, a new "Opt into worktree hooks" step offers them with the user's consent, and the Remove step says to drop the user-level entries oncequestis gone.quest worktree hook --help,quest init --help, andquest uninstall --helpmatch.HOOK_EVENTSmoves tosrc/cli/worktree-hook.ts, its only consumer.CLAUDE_SETTINGS,HOOK_COMMAND,isQuestHook,parseSettings,renderSettings, andSettingsare deleted.quest/m0/session-checkouts.md(whoseSessionStart/SessionEndentries extend the README's JSON block andHOOK_EVENTS),quest/m0/worktree-routes.md, andquest/m2/hook-path-error.md, which is now unblocked. Amends m0's static-stubs decision inquest/m0/README.md, which still listed hook entries among what init installs.quest/m0/user-dev-shell/repo-config.mdand the epic's Required line no longer include moq's worktree hook entries, which moq-dev/moq#7889 removes.Public API
Breaking for
quest init: it no longer installs Claude Code worktree hooks, andquest uninstallno longer removes them. Existing entries in a repository's.claude/settings.jsonstay as they are. Migration: a user who wants Quest to manage Claude Code's worktrees merges the README's JSON entries into~/.claude/settings.json, and a repository that carries entries removes them by hand, as moq does in moq-dev/moq#7889.quest/coredrops the exportsCLAUDE_SETTINGS,HOOK_COMMAND,HOOK_EVENTS,isQuestHook,parseSettings,renderSettings, andSettings; the Worker is the only consumer. No wire impact.Choices made without asking
~/.claude/settings.json), not.claude/settings.local.json. A local settings file is untracked, so it is missing from every checkout under.worktrees/.~/.claude/settings.json, since SETUP.md is a script agents follow..claude/settings.json, and init and uninstall leave an existing one byte for byte, including an exactquest worktree hookentry. The CLI and Worker tests check that neither the printed paths nor the setup PR include the file.Validation
just check: passed on21e0bf33.just test: passed on21e0bf33(vitest 1049 passed, 5 skipped; Worker 531 passed; shell suites and both lifecycle checks passed).Review
mechanical fix by codex / Codex:
Merged base and re·solved the hook header conflict, preserving the PR comment and base import removal; passed bun run build, bun run check, bun run test (root), and bun run build, bunx tsc --noEmit, bun run test (cloudflare; CLOUDFLARE_SEND_METRICS=false).(head 1bfdb8f)Codex
gpt-6.1-solat xhigh effort, new session01a1a7b3(started with--newafter the design change), round 1 againstorigin/mainatde0e7e4e. Reviewed head:21e0bf33. No findings.The previous sessions (
01a1a56bon the heuristic matcher and01a1a772on exact removal with lookalike warnings) are superseded: the code they reviewed is deleted.Suggested follow-ups
quest worktreeshould keep.worktrees/out ofgit status. Now that the hooks are a user-level opt-in, they apply in every repository the user opens, and Quest puts Claude's checkouts under each repository's.worktrees/. A repository that doesn't ignore that directory then shows?? .worktrees/in its main checkout'sgit status. Fix: whenquest worktreecreates the first checkout, add/.worktrees/to$GIT_COMMON_DIR/info/excludeif nothing ignores it yet. [S]🤖 Generated with Claude Code
(Written by Claude Opus 5.5)