Skip to content

Support Claude and Codex hook adapters#22

Merged
jssblck merged 6 commits into
mainfrom
jssblck/codex
May 28, 2026
Merged

Support Claude and Codex hook adapters#22
jssblck merged 6 commits into
mainfrom
jssblck/codex

Conversation

@jssblck
Copy link
Copy Markdown
Contributor

@jssblck jssblck commented May 28, 2026

Why this change

  • Nudge was still centered on Claude Code hook payloads, even though the rule language already describes provider-neutral concepts like PreToolUse, UserPromptSubmit, Write, Edit, WebFetch, and Bash.
  • Codex CLI hooks are now generally available, so Nudge should support Codex without requiring users to fork rule files or think in terms of Codex-specific apply_patch payloads.
  • This PR introduces a normalized hook layer: provider adapters parse Claude Code or Codex wire formats, Nudge evaluates one shared event model, and provider-specific response renderers produce the correct hook output.
  • Codex apply_patch is normalized into Write, Edit, and parsed-but-unmatchable Delete events. PermissionRequest is parsed for both providers but intentionally passes through until Nudge has a permission-specific rule surface.
  • Claude setup is narrowed to events Nudge actually handles, and Codex setup installs local .codex/hooks.json command hooks for PreToolUse and UserPromptSubmit.

Configuration changes after merge

  1. Existing Claude Code users can keep their current rules. To refresh local hook setup and remove older Nudge-managed PostToolUse / Stop hooks, run:

    nudge claude setup
  2. Codex users can install equivalent project-local hooks with:

    nudge codex setup
  3. After nudge codex setup, restart open Codex sessions, run /hooks, review the new Nudge command hooks, and trust them.

  4. If Codex hooks do not appear, verify that the project .codex/ layer is trusted and [features].hooks has not been disabled in Codex config.

Testing steps performed

cargo test -p nudge
test result: ok. 56 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
test result: ok. 70 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 6.65s
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
cargo run -p nudge -- check
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.05s
Running `target/debug/nudge check`
Checked 73 files against 6 rules
  - .nudge.yaml: 6 rules
cargo run -p nudge -- claude docs
cargo run -p nudge -- codex docs
Running `target/debug/nudge claude docs`
Nudge Rule Writing Guide
...
Running `target/debug/nudge codex docs`
Nudge Rule Writing Guide
...
git diff --check
clean

I also installed Codex hooks locally in this repo:

cargo run -p nudge -- codex setup
Wrote hooks configuration to /Users/jess/org/attune/nudge/.codex/hooks.json

Then I smoke-tested the real Codex hook path by attempting to write a Rust file with an inline use statement through apply_patch. The hook blocked the write before the file was created:

Command blocked by PreToolUse hook: Nudge blocked operation due to rule violation.
Fix all issues immediately and try again:

error: Rule violation. Fix this error and immediately retry.
  |
1 | fn main() {
2 |     use std::io;
  |     ^^^^^^^^^^^^ Move this `use` statement to the top of the file with other imports, then retry.
3 |
4 |     let _ = io::stdout();
5 | }
  |. Command: *** Begin Patch
*** Add File: nudge_hook_probe.rs
+fn main() {
+    use std::io;
+
+    let _ = io::stdout();
+}
*** End Patch

Notes

  • Codex WebSearch / WebFetch interception is documented as unsupported for current Codex hooks, so the docs and nudge validate warn about WebFetch rules in Codex-targeted projects instead of claiming enforcement there.
  • nudge check remains repository-file validation. It evaluates file rules directly from the shared rule schema and does not attempt to replay Codex hook payloads.

jssblck added 6 commits May 27, 2026 12:35
Record the decisions from the design review: keep apply_patch as an adapter detail normalized into Write/Edit/Delete, keep Delete and PermissionRequest parsed but unmatchable for now, limit Codex setup to local hooks.json, and keep nudge check scoped to repository file validation. Remove the open questions section now that the RFC has concrete implementation direction.
Add a provider-neutral hook model and evaluator, then route Claude Code through it before adding Codex hook parsing, response rendering, setup, and docs. Codex apply_patch is normalized into Write, Edit, and Delete events so existing file-content rules work without exposing apply_patch as a rule target.

Keep PermissionRequest and Delete parsed but unmatchable, preserve fail-open behavior for unparseable patches, narrow Claude setup to handled events, and add Codex-local .codex/hooks.json setup with inline TOML-hook warnings. Update README, AGENTS, CLAUDE, and the rule docs to describe the shared agent-hook surface.

Testing: cargo fmt --all; cargo test -p nudge; cargo run -p nudge -- claude docs; cargo run -p nudge -- codex docs; git diff --check; ASCII/smart-punctuation scan for edited docs.
Run the repository-level CI mode against the Codex hook adapter implementation and address the dogfood rule findings it surfaced. Replace newly added qualified paths with local imports and use pretty_assert_eq! in the new tests so nudge check is green on the current tree.

Testing: cargo run -p nudge -- check; cargo test -p nudge; git diff --check.
@jssblck jssblck merged commit 130199f into main May 28, 2026
4 checks passed
@jssblck jssblck deleted the jssblck/codex branch May 28, 2026 22:20
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