Skip to content

Commit 5b69f3b

Browse files
Centralize agent hook runner packaging (#1557)
## Summary - moved the shared hook runner wrapper to `packages/agent/policy/hook-runner.nix` - updated Claude Code and Codex wrappers to import hook runner packaging from the shared policy location - updated hook docs to point at the new shared location ## Verification - `nix fmt packages/agent/policy/hook-runner.nix packages/agent/claude-code/default.nix packages/agent/codex/default.nix` - `nix-instantiate --parse packages/agent/policy/hook-runner.nix` - `nix-instantiate --parse packages/agent/claude-code/default.nix` - `nix-instantiate --parse packages/agent/codex/default.nix` - `nix-instantiate --parse packages/agent/policy/hooks.nix` - `nix build .#codex --no-link` - `nix build .#claude-code --no-link` Fixes #1556 (sent by an AI agent via Codex) <!-- Macroscope's pull request summary starts here --> <!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. --> <!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. --> > [!NOTE] > ### Move hook runner to shared location at `packages/agent/policy/hook-runner.nix` > Relocates the hook runner Nix package from `packages/agent/claude-code/hooks.nix` to `packages/agent/policy/hook-runner.nix` so it can be shared between the Claude Code and Codex agents. Both `packages/agent/claude-code/default.nix` and `packages/agent/codex/default.nix` are updated to import from the new path, and documentation is updated to match. > > <!-- Macroscope's review summary starts here --> > > <sup><a href="https://app.macroscope.com">Macroscope</a> summarized 182404a.</sup> > <!-- Macroscope's review summary ends here --> > <!-- macroscope-ui-refresh --> <!-- Macroscope's pull request summary ends here -->
1 parent 13f8e3c commit 5b69f3b

5 files changed

Lines changed: 12 additions & 11 deletions

File tree

doc/claude-code/overview.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,12 @@ independent work, do work through the index Python kernel and `search` priors,
125125
gate admin/force merges on a fresh local build, never use em dashes, and more
126126
(`system-prompt.nix:7-37`). Set to `null` to ship the stock prompt alone.
127127

128-
### Hooks (`hooks.nix`, `default.nix:209-285`)
128+
### Hooks (`packages/agent/policy/hook-runner.nix`, `default.nix:209-285`)
129129

130-
Three hooks, all subcommands of one compiled binary (`packages/claude-hooks`)
130+
Lifecycle hooks, all subcommands of one compiled binary (`packages/agent/claude-hooks`)
131131
wrapped with their tool paths and the baked primary-checkout default; each fails
132132
open and silent
133-
(`hooks.nix:1-20`):
133+
(`packages/agent/policy/hook-runner.nix:1-20`):
134134

135135
- `SessionStart` -> `session-digest`: cats the pre-rendered fleet context digest
136136
(`~/.cache/ix/context-digest.md`), capped ~6000 chars. Kill switch

doc/claude-hooks/overview.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# claude-hooks
22

3-
`packages/claude-hooks` is one compiled binary with three Claude Code hook
3+
`packages/agent/claude-hooks` is one compiled binary with Claude Code hook
44
subcommands, replacing the old hand-rolled `writeShellScript` hooks in
55
`packages/agent/claude-code`. The governing rule: every hook fails OPEN and SILENT.
66
Any missing input, parse error, or kill-switch returns with no stdout, because a
@@ -97,16 +97,16 @@ capped to `PRIORS_CAP = 4800` chars (~1200 tokens) (`render_priors`,
9797
[timestamp] score N` (`provenance`, `src/main.rs:376-396`), matching the old jq
9898
projection so the model can discount stale content. In claude-code this hook (and
9999
`IX_SEARCH`) is wired only when the `search` sibling package is in scope
100-
(`hooks.nix:17-20,35`).
100+
(`packages/agent/policy/hook-runner.nix:17-20,35`).
101101

102102
## How it is built and wired
103103

104104
`default.nix` selects the `claude-hooks` binary with
105105
`ix.cargoUnit.selectBinaryWithTests` (flake output `claude-hooks`,
106106
`package.nix`). The claude-code layer re-wraps it in
107-
`packages/agent/claude-code/hooks.nix`: `makeBinaryWrapper` sets `IX_GIT`,
107+
`packages/agent/policy/hook-runner.nix`: `makeBinaryWrapper` sets `IX_GIT`,
108108
`IX_DEFAULT_PRIMARY_CHECKOUTS`, and (conditionally) `IX_SEARCH`, then registers
109-
the three subcommands as hook commands in the generated settings JSON
109+
the subcommands as hook commands in the generated settings JSON
110110
(`packages/agent/claude-code/default.nix:244-285`) with generous per-hook timeouts (5s,
111111
10s, 5s) that sit well past the fail-open budgets. `install-check.nix` asserts
112112
the fail-open behavior, the digest cap, and the guard deny/allow paths.

packages/agent/claude-code/default.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ let
169169
# Claude treats repeated settings flags as first-wins.
170170

171171
# Build the hook runner once; shared policy renders it for each wrapper.
172-
hookRunner = import ./hooks.nix {
172+
hookRunner = import (ix.paths.packagesRoot + "/agent/policy/hook-runner.nix") {
173173
inherit
174174
lib
175175
runCommand

packages/agent/codex/default.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ let
122122

123123
# Codex reads hooks from config, not from launch flags, so expose the rendered
124124
# shared hook policy for home-manager or managed requirements consumers.
125-
hookRunner = import (ix.paths.packagesRoot + "/agent/claude-code/hooks.nix") {
125+
hookRunner = import (ix.paths.packagesRoot + "/agent/policy/hook-runner.nix") {
126126
inherit
127127
lib
128128
runCommand
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
# The hooks are subcommands of one compiled binary (packages/agent/claude-hooks)
2-
# rather than hand-rolled shell scripts. Each fails OPEN and SILENT (any
1+
# Shared hook runner wrapper for Claude Code and Codex. The hooks are
2+
# subcommands of one compiled binary (packages/agent/claude-hooks) rather than
3+
# hand-rolled shell scripts. Each fails OPEN and SILENT (any
34
# missing input, parse error, or kill-switch exits with no stdout: a noisy or
45
# broken hook is strictly worse than no hook). See that crate for the full
56
# design and its measured rationale:

0 commit comments

Comments
 (0)