同一层不要同时写 hooks.json 和 [hooks]
同一配置层里两份会合并并在启动时警告。高层配置不会替换低层钩子,重复的 SessionStart 会跑两遍。
官方 Hooks 页写明:匹配到的钩子源全部加载,高层不会覆盖低层。用户 ~/.codex/hooks.json、项目 .codex/hooks.json、以及各层 config.toml 里的 [hooks] 会叠在一起。
同一层(例如都在 ~/.codex/)如果既有 hooks.json 又有内联 [hooks],Codex 会合并两边,并在启动时警告。不要复制同一份 SessionStart 到两个文件里指望「后面那份赢」——两边都会跑。
选一种表示法:
[[hooks.PostToolUse]]
matcher = "Bash"
[[hooks.PostToolUse.hooks]]
type = "command"
command = "python3 /home/you/.codex/hooks/post_tool_use.py"
timeout = 30
或只保留 ~/.codex/hooks.json,把 config.toml 里的 [hooks] 删掉。项目层还要目录受信任才会加载。改完新开会话,用 /hooks 看实际来源,而不是数文件。
prompt / agent handler 会解析但跳过;真正会跑的是 command 和 mcp_tool。后台跑用 async = true,但 SessionEnd 仍强制同步。