Skip to content

quest: plan dev shells from user settings instead of repo hooks - #458

Merged
kixelated merged 5 commits into
mainfrom
quest-unblock/no-repo-hooks
Nov 3, 2026
Merged

kixelated merged 5 commits into
mainfrom
quest-unblock/no-repo-hooks

Conversation

@kixelated

@kixelated kixelated commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

This /quest-unblock run 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 or quest on them. Instead, each maintainer's own Claude Code and Codex settings load the dev shell, so agents never have to care about Nix.

Changes

  • New epic quest/m0/user-dev-shell/, ranked where worktree-hooks was. It records the decisions below and has two children:
    • [S] init-hooks.md: quest init stops writing hook entries and removes plain or wrapped worktree hook entries. The hooks become an opt-in user-level setup. It absorbs the matching rule from the deleted wrapped-hooks quest.
    • [S] allow-rule.md: the dotfiles hook's automatic direnv allow covers only trusted repositories and reviewed code. It waits on the maintainer's choice of rule (see below).
    • [S] repo-config.md: quest, moq, moq.pro, rind and rust2 drop their direnv SessionStart hooks (Claude and Codex), moq's four Quest worktree hooks, and AGENTS.md's nix develop instructions, one PR per repository. It waits until the maintainer's dotfiles are on every host, and on allow-rule.md.
  • Deleted:
  • Amended:
    • session-checkouts.md: adds its hooks to the opt-in user-level setup instead of init.
    • 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 -p and codex exec sessions on fresh worktrees. On 2026-11-03 the hook was installed on desktop and nixos2, but not on nixos or kixtop. repo-config.md's waiting item names those two hosts.

Review findings addressed (head 1635b55b)

  • CodeRabbit, auto-direnv allow rule (thread): real, and broader than reported. I reproduced it against the merged bin/dev-shell-hook (blob 679997db) with an isolated XDG_DATA_HOME:

    • Any repository's fresh clone matches its own origin/HEAD, so its .envrc is allowed and runs.
    • A branch that changes only a file the dev shell runs (an .envrc sourcing dev/hook.sh) is allowed and runs the branch's script. moq.pro's shellHook inlines ./dev/mbx-shim.sh, which has the same shape.

    The epic's bullet now records the amendment. The new allow-rule.md holds the reproduction and the maintainer's choice of rule. repo-config.md requires it.

  • CodeRabbit, bridge-* checkouts at session end (thread): clarified. session-checkouts.md now says the release covers them if SessionEnd fires there. Release only prunes declared scratch and keeps the files and Git's lock (only remove unlocks, 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.md now 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)

  • Install quest on Claude's PATH: ✅ No (rejected: nix profile add on every host)
  • How sessions reach the dev shell: ✅ a dev-shell hook in the maintainer's own Claude settings (rejected: hook entries that nix run the pinned input; dropping the hooks with no replacement). "We don't want to force direnv+nix for other users"
  • Repo-level direnv hooks: ✅ remove from all repos (rejected: keep them)
  • Quest worktree hooks: ✅ drop from repos, and quest init stops writing them (rejected: this repo and moq; this repo only; move into the maintainer's settings)
  • Close feat(claude): install the worktree hooks in this repository #423: ✅ close with a comment (rejected: leave it open)
  • Codex: ✅ a user-level Codex hook (rejected: Claude only)
  • direnv allow: ✅ the hook allows a checkout only when .envrc, flake.nix and flake.lock match the default branch (rejected: whitelist ~/work and ~/worktrees; keep manual allow). Amended by review: that rule is insufficient. The safe rule is pending as allow-rule.md's waiting item.
  • AGENTS.md nix develop instructions: ✅ remove in all repos (rejected: this repo only; keep them)

Review

  • Reviewer: Codex gpt-6.1-sol, medium effort, via quest review --base origin/main (session 01a1a343-1045-7e33-a6c8-aeb0819c3110)
  • Round 3 on head 06d08e40d8a0fa4b2fff391bae21844751123dde (base 82018313): no findings. It covers CodeRabbit's two findings on 7525141f, both fixed: removal matches only hooks that run Quest, and the host check skips kixtop.
  • Round 2 on 7525141f (the allow-rule decision, settled by kixelated/dotfiles#35), 1635b55b (/quest-iterate) and ca65bbab had no findings.
  • quest check passes (75 documents).

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

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>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ 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 in kixelated/dotfiles) instead of repository config; quest init stops writing hook entries and strips plain and wrapped worktree hook entries; the five repositories drop dep-shell hooks, Quest worktree hooks, and nix develop instructions in separate PRs once the user-level setup reaches every host.
  • Deletions — worktree-hooks.md (its blocker #423 is closed with the cited comment) and wrapped-hooks.md (absorbed into init-hooks.md, which keeps the last-two-words matching rule for removal).
  • Amendments — session-checkouts.md moves its SessionEnd/SessionStart entries into the user-level setup; worktree-routes.md checks from a scratch repository using that setup instead of quest 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)

Pullfrog  | Fix it ➔ | View workflow run | Using glm-5.3-flash | 𝕏

@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Walkthrough

This 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 quest init. It also updates hook enrollment and worktree test plans, records checkout approval conditions, and removes two earlier worktree-hook proposals.

Merge Risk: Low · up to 75251

Use recognized Quest hook forms before merging to avoid deleting unrelated user hooks during future setup changes.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title "quest: plan dev shells from user settings instead of repo hooks" matches the main change. The PR adds a user-dev-shell epic and removes repository-level direnv and Quest worktree hooks, so …
Linked Issues check Passed Directly linked issue #423 is closed and completed. It provides historical context only. No active directly linked issue remains, so this pull request has no coding requirements from linked issues.
Out of Scope Changes check Passed The changes are limited to Quest planning documents under quest/m0/. They add the user-dev-shell plan, update session-checkouts and worktree-routes, update the README, and delete superseded worktree-h…
Description check Passed The description is specific and on-topic. It names the Quest plan changes (the new user-dev-shell epic, the deleted worktree-hooks and wrapped-hooks quests, the amended session-checkouts and worktree-…
Full details: Title check

Explanation

The title "quest: plan dev shells from user settings instead of repo hooks" matches the main change. The PR adds a user-dev-shell epic and removes repository-level direnv and Quest worktree hooks, so that dev shells load through each maintainer's own Claude Code and Codex settings. The title is concise, specific, and does not use vague terms.

Full details: Out of Scope Changes check

Explanation

The changes are limited to Quest planning documents under quest/m0/. They add the user-dev-shell plan, update session-checkouts and worktree-routes, update the README, and delete superseded worktree-hook plans. These changes match the pull request intent to plan user-level dev-shell setup and remove repository hook requirements. No unrelated source or test changes are present in the supplied summary.

Full details: Description check

Explanation

The description is specific and on-topic. It names the Quest plan changes (the new user-dev-shell epic, the deleted worktree-hooks and wrapped-hooks quests, the amended session-checkouts and worktree-routes quests), the decisions behind them, and the review findings addressed. This matches the changeset summary and PR objectives, so the description is clearly related to the changes.

Finishing Touches
Simplify code
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e3f88e64-83ab-4004-ab8d-383c001b62bc
Commits

Reviewing files that changed from the base of the PR and between ca65bba and 7525141.

Files selected for processing: 4
  • quest/m0/session-checkouts.md
  • quest/m0/user-dev-shell/README.md
  • quest/m0/user-dev-shell/init-hooks.md
  • quest/m0/user-dev-shell/repo-config.md
Files skipped from review as they are similar to previous changes: 2
  • quest/m0/session-checkouts.md
  • quest/m0/user-dev-shell/README.md

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread quest/m0/session-checkouts.md Resolved
Comment thread quest/m0/user-dev-shell/README.md Resolved
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 names bin/install-dev-shell.py (or the full install, with codex on PATH) as the per-host install step. Every added claim checks out: dotfiles#33 is open and is exactly the user-level Claude/Codex SessionStart hook work (verified live on desktop on 2026-11-03), bin/install-dev-shell.py is that PR's installer (run from install), it covers ~/.claude-personal/settings.json among the Claude profiles this doc checks, and the codex caveat matches the installer's codex app-server trust-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)

Pullfrog  | View workflow run | Using 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>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Re Pullfrog's sequencing note on init-hooks.md (review, restated in the follow-up): part of this is real, and the gate it suggests doesn't apply. Addressed in 1635b55.

  • No gate to wait on. The user-level setup in kixelated/dotfiles#33 installs only the dev-shell SessionStart hook. It installs no quest worktree hook entries. So waiting on it would never bring back worktree reclaim. The maintainer's 2026-11-03 decision in the epic also rejected moving Quest's hooks into the maintainer's settings.
  • The consequence wasn't written down, and is now. init-hooks.md now says that removing moq's four wrapped entries ends Quest's reclaim of Claude Code checkouts in moq. That holds whether init or repo-config.md removes them first, since both reach the same end state. A user who wants reclaim adds the opt-in entries the docs describe. Any removal through the enrollment setup PR shows in that PR's diff.

(Written by Claude Opus 5.5)

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ 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.md records 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's dev/mbx-shim.sh, were auto-allowed by the merged hook's three-file match) and hands the maintainer three candidate rules. repo-config.md now requires it to settle before the repositories drop their fallbacks.
  • Clarified session-checkouts.md — remote control's bridge-* checkouts count as session checkouts; release prunes only the declared scratch and keeps Git's lock, with the bridge still deciding at session end via WorktreeRemove.
  • 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 are nixos and kixtop.
  • Reworked worktree-routes.md — the live check now runs from a scratch repository with the opt-in worktree-hooks setup instead of quest 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)

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using glm-5.3-flash | 𝕏

Comment thread quest/m0/user-dev-shell/allow-rule.md Resolved
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>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 requires HEAD to be on some origin branch (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 commit 0b31264), and the merged bin/dev-shell-hook at main implements exactly that guard, refusing with "HEAD isn't on any origin branch".
  • Narrowed repo-config.md's wait to nixos — kixtop has neither direnv nor Nix, so the hook has nothing to load there; it got only the effort defaults. The now-settled Required link to allow-rule.md is dropped from both repo-config.md and 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)

Pullfrog  | View workflow run | Using glm-5.3-flash | 𝕏

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread quest/m0/user-dev-shell/init-hooks.md Resolved
Comment thread quest/m0/user-dev-shell/repo-config.md Resolved
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 plain quest worktree hook, or a wrapper ending in worktree hook that names the quest executable or package as a word or flake attribute (moq's nix run "${CLAUDE_PROJECT_DIR}#quest" -- worktree hook shape). Another tool's command that merely ends in worktree hook stays, 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-worktree just check now runs only on hosts with direnv and Nix (desktop, nixos2, nixos), and kixtop is recorded as an expected no-op, consistent with the same bullet's statement that it has neither. This resolves CodeRabbit's kixtop finding, 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)

Pullfrog  | View workflow run | Using glm-5.3-flash | 𝕏

@kixelated
kixelated added this pull request to the merge queue Nov 3, 2026
Merged via the queue into main with commit 69d899a Nov 3, 2026
11 checks passed
@kixelated
kixelated deleted the quest-unblock/no-repo-hooks branch November 3, 2026 22:36
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