Repository navigation
quest: plan dev shells from user settings instead of repo hooks - #458
Conversation
The maintainer won't install quest on Claude's PATH and doesn't want repository config to force direnv, Nix or quest on contributors. Plan the replacement: user-level dev-shell hooks, repositories dropping their dev-shell and worktree hooks and nix instructions, and quest init writing no hook entries. Drops worktree-hooks and wrapped-hooks, and moves session-checkouts onto the opt-in user-level setup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
ℹ️ No critical issues — one minor sequencing note below. Everything verified cleanly.
Reviewed changes — reviewed the full diff of this docs-only restructure, then grepped every src/ and cross-repo claim the quests cite against the checkout and GitHub:
- New epic
quest/m0/user-dev-shell/— dev shells load from each maintainer's own Claude and Codex settings (built inkixelated/dotfiles) instead of repository config;quest initstops writing hook entries and strips plain and wrappedworktree hookentries; the five repositories drop dep-shell hooks, Quest worktree hooks, andnix developinstructions in separate PRs once the user-level setup reaches every host. - Deletions —
worktree-hooks.md(its blocker #423 is closed with the cited comment) andwrapped-hooks.md(absorbed intoinit-hooks.md, which keeps the last-two-words matching rule for removal). - Amendments —
session-checkouts.mdmoves itsSessionEnd/SessionStartentries into the user-level setup;worktree-routes.mdchecks from a scratch repository using that setup instead ofquest init.
Verification notes: quest check passes (75 documents) and no dangling references to the deleted quests remain. Code premises hold today: isQuestHook (src/core/init.ts:240) matches only the exact HOOK_COMMAND, HOOK_EVENTS and the uninstall filtering in src/cli/setup.ts are as described. Cross-repo: moq's .claude/settings.json carries the direnv SessionStart hook and four wrapped nix run "${CLAUDE_PROJECT_DIR}#quest" -- worktree hook entries exactly as cited, moq's .codex/hooks.json loads .codex/hooks/direnv.sh, and direnv's allow records do hash the .envrc's absolute path plus its contents (fileHash/pathHash in direnv's source), so fresh worktrees genuinely need re-allowing. Only moq.pro was unverifiable from here (404 — not public), so its three hook claims rest on the doc.
ℹ️ Sequencing: init strips hooks before anything gates on the user-level setup
init-hooks.md makes quest init (and via it the enrollment flow from #431) actively remove existing worktree hook entries as soon as that quest lands, but unlike its sibling repo-config.md it records no waiting on the kixelated/dotfiles user-level hooks first. If init or uninstall runs on a host without them — moq being the live case, with four wrapped entries checked into .claude/settings.json — the worktree-gc hooks vanish with no replacement, which is the leak path the deleted worktree-hooks.md measured (65 worktrees, 8.2 GB).
Technical details
# Gate init's hook removal on the user-level setup
## Affected sites
- quest/m0/user-dev-shell/init-hooks.md — Plan bullets describe eager removal of plain and wrapped entries by `init`/`uninstall` with no Waiting item for the `kixelated/dotfiles` hooks arriving on each host, while quest/m0/user-dev-shell/repo-config.md explicitly waits ("the repositories' hooks must not go before the user-level ones arrive").
## Required outcome
- The docs state the same ordering invariant: hook entries written by `init` are only stripped once a replacement exists where the command runs, so an `init` (or #431 enrollment setup PR) on a pre-dotfiles host cannot remove worktree-gc protection with no substitute.
## Suggested approach (optional)
- Add a `## Waiting` section to init-hooks.md naming the same gate repo-config.md uses, or scope the removal sentence to that condition.
## Open questions for the human (optional)
- Whether any automated path (the #431 enrollment flow) can trigger `init` on hosts the maintainer does not control; if not, a caution line may suffice.(written by GLM-5.3-Flash)
glm-5.3-flash | 𝕏
WalkthroughThis pull request updates m0 planning documents for user-level Claude Code and Codex dev-shell hooks. It describes planned removal of repository dev-shell and Quest worktree hooks, related instructions, and hook entries written by Merge Risk:
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — reviewed the incremental delta against the prior Pullfrog review (ca65bba, one line in repo-config.md), then verified its new claims against the linked pull request:
repo-config.md's Waiting item now names its gate concretely — it links kixelated/dotfiles#33 as the PR to merge, and namesbin/install-dev-shell.py(or the fullinstall, withcodexonPATH) as the per-host install step. Every added claim checks out: dotfiles#33 is open and is exactly the user-level Claude/CodexSessionStarthook work (verified live ondesktopon 2026-11-03),bin/install-dev-shell.pyis that PR's installer (run frominstall), it covers~/.claude-personal/settings.jsonamong the Claude profiles this doc checks, and thecodexcaveat matches the installer'scodex app-servertrust-hash step. Since the PR is still open, "merge ... then pull ..." reads correctly.
The body-level sequencing note from the prior review (the init-hooks.md removal gate) is untouched by this commit and stands as-is.
(written by GLM)
glm-5.3-flash | 𝕏
The hook's three-file match auto-allowed any repository's fresh clone and a fork PR head that changes another file the dev shell runs; a new child quest records the reproduction and the maintainer's choice of a safe rule. Also clarify that session-end release keeps remote-control checkouts' files and lock, record that removing moq's wrapped hooks has no user-level replacement, and refresh repo-config's wait now that kixelated/dotfiles#33 is merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Re Pullfrog's sequencing note on
(Written by Claude Opus 5.5) |
There was a problem hiding this comment.
ℹ️ No critical issues — minor suggestions inline.
Reviewed changes — reviewed the incremental delta against the prior Pullfrog review (763704a, commit 1635b55), then verified the new claims against the checkout and the linked dotfiles PR:
- Narrowed the auto-allow decision — a new child quest
quest/m0/user-dev-shell/allow-rule.mdrecords the reproduction of the CodeRabbit finding (any repository's fresh clone, and a fork PR head changing a file the dev shell runs such as moq.pro'sdev/mbx-shim.sh, were auto-allowed by the merged hook's three-file match) and hands the maintainer three candidate rules.repo-config.mdnow requires it to settle before the repositories drop their fallbacks. - Clarified
session-checkouts.md— remote control'sbridge-*checkouts count as session checkouts; release prunes only the declared scratch and keeps Git's lock, with the bridge still deciding at session end viaWorktreeRemove. - Recorded the removal consequence in
init-hooks.md— stripping moq's four wrapped entries ends Quest's reclaim there with no user-level replacement, in either order, so the quest doesn't wait on the dotfiles setup. - Refreshed
repo-config.md's Waiting — kixelated/dotfiles#33 is merged; the remaining hosts arenixosandkixtop. - Reworked
worktree-routes.md— the live check now runs from a scratch repository with the opt-in worktree-hooks setup instead ofquest init.
Verification notes: quest check --base origin/main passes (76 documents). The code premises hold: release/prune in src/cli/worktree.ts:752-758 keep files and Git's worktree lock while only remove (src/cli/worktree.ts:805) unlocks, a failed release stays reserved with its failure recorded (src/cli/worktree.ts:527), and dotfiles#33 is indeed merged with bin/dev-shell-hook behaving exactly as the reproduction describes (auto-allow only on the three-file match against origin/HEAD, exit 1 otherwise). The prior review's init-hooks.md sequencing note is addressed by the new bullet: the dotfiles setup provably loads only the dev shell, so the note's expected replacement doesn't exist and the quest refuses to wait on it.
(written by GLM)
glm-5.3-flash | 𝕏
The maintainer judged the auto-allow risk narrow and picked one check: HEAD must be on an origin branch, shipped in kixelated/dotfiles#35. Record the decision in the epic, delete the allow-rule quest it settles, and drop kixtop from repo-config's wait since it has no direnv or Nix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — reviewed the incremental delta against the prior Pullfrog review (1635b55), then verified the settled decision against the linked dotfiles PR and this checkout:
- Settled the auto-allow rule and deleted
allow-rule.md— the README now records the maintainer's decision (/quest-complete, 2026-11-03) in place of the open candidate list: the hook additionally requiresHEADto be on someoriginbranch (git for-each-ref --contains HEAD refs/remotes/origin/), so a fork PR head is never auto-allowed, with the rejected alternatives and the origin of the risk assessment kept inline. Verified live: kixelated/dotfiles#35 is merged (merge commit0b31264), and the mergedbin/dev-shell-hookatmainimplements exactly that guard, refusing with "HEAD isn't on any origin branch". - Narrowed
repo-config.md's wait tonixos—kixtophas neither direnv nor Nix, so the hook has nothing to load there; it got only the effort defaults. The now-settled Required link toallow-rule.mdis dropped from bothrepo-config.mdand the README.
Verification notes: quest check --base origin/main passes (75 documents) and grep confirms no dangling allow-rule references remain after the deletion. The README's cross-checks hold: the guide (assets/skills/merge.md) does treat a PR head's files as untrusted and checks them out detached in .tmp/ rather than as a session root, and no Pullfrog review threads remain open (the earlier fork-PR/clause-C thread is settled by this commit).
(written by GLM-5.3-Flash)
glm-5.3-flash | 𝕏
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — reviewed the incremental delta against the prior Pullfrog review (7525141, head 06d08e4), then ran quest check on the checkout:
- Narrowed
init's hook-removal rule (quest/m0/user-dev-shell/init-hooks.md) — an entry counts as Quest's only when the command runs Quest: the plainquest worktree hook, or a wrapper ending inworktree hookthat names thequestexecutable or package as a word or flake attribute (moq'snix run "${CLAUDE_PROJECT_DIR}#quest" -- worktree hookshape). Another tool's command that merely ends inworktree hookstays, and the test bullet now covers that lookalike case. This resolves CodeRabbit's removal-rule finding, which is confirmed resolved on GitHub. - Scoped
repo-config.md's completion check by host — the fresh-worktreejustcheck now runs only on hosts with direnv and Nix (desktop,nixos2,nixos), andkixtopis recorded as an expected no-op, consistent with the same bullet's statement that it has neither. This resolves CodeRabbit'skixtopfinding, also confirmed resolved.
Verification notes: quest check --base origin/main passes (75 documents), matching the recorded round-3 state. No stale references to the superseded "last two words" rule remain — the matching-rule wording now lives only in init-hooks.md, and the deleted wrapped-hooks.md is the sole mention of the old widening. Both new review threads (both CodeRabbit, both on this commit) were answered by the author and marked resolved; no open Pullfrog threads existed after the prior body-only review.
(written by GLM-5.3-Flash)
glm-5.3-flash | 𝕏

This
/quest-unblockrun was scoped to "we don't want to install quest on the PATH", the maintainer step that kept moq-dev/quest#423 (worktree hooks in this repo) a draft. The interview turned it into a broader rule: repository config applies to every contributor, so no repository should force direnv, Nix orqueston them. Instead, each maintainer's own Claude Code and Codex settings load the dev shell, so agents never have to care about Nix.Changes
quest/m0/user-dev-shell/, ranked whereworktree-hookswas. It records the decisions below and has two children:init-hooks.md:quest initstops writing hook entries and removes plain or wrappedworktree hookentries. The hooks become an opt-in user-level setup. It absorbs the matching rule from the deletedwrapped-hooksquest.allow-rule.md: the dotfiles hook's automaticdirenv allowcovers only trusted repositories and reviewed code. It waits on the maintainer's choice of rule (see below).repo-config.md: quest, moq, moq.pro, rind and rust2 drop their direnvSessionStarthooks (Claude and Codex), moq's four Quest worktree hooks, and AGENTS.md'snix developinstructions, one PR per repository. It waits until the maintainer's dotfiles are on every host, and onallow-rule.md.quest/m0/worktree-hooks.md: feat(claude): install the worktree hooks in this repository #423 is closed with a comment.quest/m0/wrapped-hooks.md: moot onceinitwrites no hooks.session-checkouts.md: adds its hooks to the opt-in user-level setup instead ofinit.worktree-routes.md: its scratch repo uses that setup.The user-level hooks are in kixelated/dotfiles#33, now merged. They were verified with real
claude -pandcodex execsessions on fresh worktrees. On 2026-11-03 the hook was installed ondesktopandnixos2, but not onnixosorkixtop.repo-config.md's waiting item names those two hosts.Review findings addressed (head
1635b55b)CodeRabbit, auto-
direnv allowrule (thread): real, and broader than reported. I reproduced it against the mergedbin/dev-shell-hook(blob679997db) with an isolatedXDG_DATA_HOME:origin/HEAD, so its.envrcis allowed and runs..envrcsourcingdev/hook.sh) is allowed and runs the branch's script. moq.pro'sshellHookinlines./dev/mbx-shim.sh, which has the same shape.The epic's bullet now records the amendment. The new
allow-rule.mdholds the reproduction and the maintainer's choice of rule.repo-config.mdrequires it.CodeRabbit,
bridge-*checkouts at session end (thread): clarified.session-checkouts.mdnow says the release covers them ifSessionEndfires there. Release only prunes declared scratch and keeps the files and Git's lock (onlyremoveunlocks,src/cli/worktree.ts), so the bridge's clean-remove or keep still decides. The remote-control live check verifies that order.Pullfrog, gating
init's hook removal (review): partly refuted. The dotfiles setup loads only the dev shell, so no user-level Quest worktree hook exists to wait for. The decision below rejected moving Quest's hooks into the maintainer's settings.init-hooks.mdnow says so: removing moq's entries ends Quest's reclaim there in either order, and anyone who wants reclaim adds the opt-in entries.Decisions (maintainer, 2026-11-03)
queston Claude's PATH: ✅ No (rejected:nix profile addon every host)nix runthe pinned input; dropping the hooks with no replacement). "We don't want to force direnv+nix for other users"quest initstops writing them (rejected: this repo and moq; this repo only; move into the maintainer's settings)direnv allow: ✅ the hook allows a checkout only when.envrc,flake.nixandflake.lockmatch the default branch (rejected: whitelist~/workand~/worktrees; keep manual allow). Amended by review: that rule is insufficient. The safe rule is pending asallow-rule.md's waiting item.nix developinstructions: ✅ remove in all repos (rejected: this repo only; keep them)Review
gpt-6.1-sol, medium effort, viaquest review --base origin/main(session01a1a343-1045-7e33-a6c8-aeb0819c3110)06d08e40d8a0fa4b2fff391bae21844751123dde(base82018313): no findings. It covers CodeRabbit's two findings on7525141f, both fixed: removal matches only hooks that run Quest, and the host check skipskixtop.7525141f(the allow-rule decision, settled by kixelated/dotfiles#35),1635b55b(/quest-iterate) andca65bbabhad no findings.quest checkpasses (75 documents).(Written by Claude Opus 5.5)
🤖 Generated with Claude Code