From 89cc38285add2219060010cc711430ccd041d7ac Mon Sep 17 00:00:00 2001 From: Siddhant Khare Date: Thu, 11 Jun 2026 02:17:43 +0000 Subject: [PATCH] Clarify Codex hook setup troubleshooting Co-authored-by: Codex --- docs/setup.md | 6 ++++++ src/agent_trace/__init__.py | 2 +- src/agent_trace/cli.py | 8 ++++++++ tests/test_codex_hooks.py | 7 ++++++- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/setup.md b/docs/setup.md index a031aad..225d916 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -73,6 +73,12 @@ agent-strace explain # plain-English summary Codex sends one JSON object to each command hook on stdin. agent-strace records the common Codex fields (`session_id`, `turn_id`, `tool_use_id`, `tool_name`, `tool_input`, `tool_response`, `prompt`, and `last_assistant_message`) into the same `.agent-traces/` session store used by Claude Code. +If Codex does not list the hooks after you create the file: + +- Use the root `~/.codex/hooks.json` file for user-level hooks, or `/.codex/hooks.json` for project-level hooks. `~/.codex/hooks/hooks.json` is for plugin-bundled hooks and is not the normal user config path. +- Check `~/.codex/config.toml` and remove `[features].hooks = false` if present. Hooks are enabled by default unless a user, system, or admin config layer disables them. +- Reload Codex or press refresh in the Hooks view. Non-managed command hooks must be reviewed and trusted before they run. + ### Gemini CLI hooks `agent-strace setup --cli gemini` writes a Gemini CLI extension: diff --git a/src/agent_trace/__init__.py b/src/agent_trace/__init__.py index e2a8e25..c7f4a3c 100644 --- a/src/agent_trace/__init__.py +++ b/src/agent_trace/__init__.py @@ -1,3 +1,3 @@ """agent-trace: strace for AI agents.""" -__version__ = "0.79.0" +__version__ = "0.79.1" diff --git a/src/agent_trace/cli.py b/src/agent_trace/cli.py index 0972080..15ffad4 100644 --- a/src/agent_trace/cli.py +++ b/src/agent_trace/cli.py @@ -779,6 +779,14 @@ def cmd_setup(args: argparse.Namespace) -> None: sys.stderr.write(f"Add this to {path} for {name}:\n\n") sys.stdout.write(json.dumps(config, indent=2) + "\n") + if cli in ("codex", "all"): + sys.stderr.write( + "\nCodex hook checklist:\n" + "- Put the JSON at ~/.codex/hooks.json or /.codex/hooks.json, not ~/.codex/hooks/hooks.json.\n" + "- In ~/.codex/config.toml, remove [features].hooks = false if present.\n" + "- Reload Codex, then review and trust command hooks in the Hooks UI or /hooks.\n" + ) + if cli == "gemini": sys.stdout.write(json.dumps(_gemini_hooks_config(args), indent=2) + "\n") if cli == "cursor": diff --git a/tests/test_codex_hooks.py b/tests/test_codex_hooks.py index fa9640d..03e15f3 100644 --- a/tests/test_codex_hooks.py +++ b/tests/test_codex_hooks.py @@ -172,7 +172,11 @@ def test_setup_cli_codex_outputs_hooks_json(self): cmd_setup(args) config = json.loads(out.getvalue()) - self.assertIn("~/.codex/hooks.json", err.getvalue()) + err_text = err.getvalue() + self.assertIn("~/.codex/hooks.json", err_text) + self.assertIn("Codex hook checklist", err_text) + self.assertIn("~/.codex/hooks/hooks.json", err_text) + self.assertIn("[features].hooks = false", err_text) self.assertIn("SessionStart", config["hooks"]) self.assertEqual( config["hooks"]["PreToolUse"][0]["hooks"][0]["command"], @@ -201,6 +205,7 @@ def test_setup_cli_all_outputs_claude_and_codex_sections(self): self.assertIn("agent-strace hook --provider codex user-prompt", text) self.assertIn("~/.claude/settings.json", err.getvalue()) self.assertIn("~/.codex/hooks.json", err.getvalue()) + self.assertIn("Codex hook checklist", err.getvalue()) if __name__ == "__main__":