Codex Hooks Pack: 10 Ready Hooks + Linter + Simulator

Stop Codex from force-pushing main or editing your .env, and make it run the tests before it says it's done.

Codex Hooks Pack: 10 Ready Hooks + Linter + Simulator product illustration

What it does

10 ready hooks for OpenAI Codex (CLI, IDE extension and app), an installer, a linter for hooks.json and inline [hooks], and a simulator that checks every hook answer against the Codex output contract. Python 3.9+, standard library only, works offline.

What you get

The screenshot is real output from the kit’s own commands. Tested from a fresh download of this exact zip: ./run_tests.sh ran 40 tests OK on Python 3.13 and 3.10.

Real terminal output from Codex Hooks Pack: 10 Ready Hooks + Linter + Simulator: demo and passing tests

What's inside

Hook idEvent (matcher)What it does
block-dangerous-bashPreToolUse (^Bash$)Denies rm -rf / ~ *, force pushes to main/master/production, git reset --hard, git clean -fdx, curl | sh, chmod 777, mkfs/dd to disks, DROP DATABASE from a CLI, terraform destroy, kubectl delete namespace. Normal commands (rm -rf node_modules, force push to a feature branch) pass.
protect-filesPreToolUse (^apply_patch$|^Bash$)Stops edits to .env*, keys, secrets/, .git/ and the hooks themselves, through apply_patch (Add/Update/Delete/Move) or shell writes (>, >>, sed -i, tee, cp, mv, rm). .env.example stays editable.
mcp-guardPreToolUse (^mcp__)Allowlist / denylist for MCP tools (mcp__github__*, mcp__*__delete_*) and a secret check on tool arguments.
approve-safe-commandsPermissionRequest (^Bash$)Answers approval prompts for read-only commands you list (git status, npm test, rg ...), denies dangerous ones, stays silent for the rest. Rejects anything with redirects, $( ), backticks or sudo.
scan-prompt-secretsUserPromptSubmitBlocks prompts that contain OpenAI, Anthropic, AWS, GitHub, Slack, Stripe or Google keys, JWTs or private keys, without echoing the secret.
session-contextSessionStart (startup|resume|compact)Hands Codex the branch, uncommitted files, last 5 commits and .codex/notes.md, capped in size.
subagent-briefSubagentStartGives every subagent the first lines of AGENTS.md, the protected paths and a "report changed files" instruction.
stop-require-testsStopIf code changed, runs your tests before Codex finishes; on failure returns decision: block so Codex keeps fixing. Never loops (stop_hook_active). Always prints JSON, as Stop requires.
precompact-notesPreCompact (manual|auto)Writes a checkpoint (branch, diff stat) to .codex/notes.md before compaction; session-context feeds it back after.
audit-logPostToolUse (all, async)One JSON line per tool call in .codex/logs/audit.jsonl, secrets redacted. Runs in the background.

Also: templates/ (hooks.json for the strict, balanced, guardrails and logging profiles, a user-level ~/.codex/hooks.json, and the inline TOML form), tools/codex_hooks_lint.py, tools/simulate.py, tools/install.py, examples/ (a broken setup and two buggy hooks to learn from), docs/events.md (event and output cheat sheet).

60-second demo

./tools/demo.sh

Install

python3 tools/install.py /path/to/repo                      # balanced profile (7 hooks)
python3 tools/install.py /path/to/repo --profile strict     # all 10
python3 tools/install.py /path/to/repo --only block-dangerous-bash,protect-files
python3 tools/install.py --user --profile guardrails         # ~/.codex/hooks.json for every project
python3 tools/install.py --toml --profile balanced           # print inline [hooks] tables for config.toml

The installer copies the scripts to .codex/hooks/, merges our matcher groups into .codex/hooks.json (your existing hooks stay) and writes hooks-config.json once. Commands resolve from the git root ($(git rev-parse --show-toplevel)), so they work when Codex starts in a subdirectory.

Then trust them. Codex skips new or changed non-managed hooks until you review them: start Codex in the repo, run /hooks, review and trust each one (in the app: Settings > Hooks). Project hooks load only when the project's .codex/ layer is trusted.

Configure

Edit .codex/hooks/hooks-config.json: protected_paths, allowed_env_examples, protected_branches, mcp_allow, mcp_deny, safe_commands, test_command (empty = auto-detect npm / pytest / unittest / go / cargo), test_timeout, notes_file, audit_log, context_limit_chars. Changing a hook script changes its hash, so Codex asks you to review it again.

Lint your hooks

python3 tools/codex_hooks_lint.py .codex                  # hooks.json + config.toml in a layer
python3 tools/codex_hooks_lint.py ~/.codex/config.toml --json

It catches: misspelled or foreign events (Cursor/Claude names), invalid matcher regexes, matchers on events that ignore them, matcher values that never occur (SessionStart sources, compaction triggers), tool names Codex doesn't use (Shell, run_terminal_cmd, Read), prompt/agent handlers (skipped by Codex), mcp_tool without server/tool or on SessionEnd, non-integer timeouts, SessionEnd/Interrupt timeouts over 3 s, async on events that must block, additionalContextLimit where it's ignored or set to 0, relative .codex/hooks/ paths, missing scripts, secrets in commands, the deprecated codex_hooks feature key, hooks turned off, and hooks.json + inline [hooks] in the same layer. Exit 1 on errors, so it fits CI.

Test a hook before Codex runs it

python3 tools/simulate.py hooks/block_dangerous_bash.py PreToolUse --tool Bash --command "git reset --hard"
python3 tools/simulate.py "node my-hook.js" Stop --stop-hook-active
python3 tools/simulate.py my_hook.py PostToolUse --tool mcp__fs__write --tool-input '{"path":"a"}' --json

The simulator builds the event JSON Codex sends, runs the hook, and tells you what Codex would do (deny, rewrite, block, continue-turn, context...) plus contract problems: plain text from Stop, continue/stopReason from PreToolUse, permissionDecision: "ask", updatedInput without allow, reserved PermissionRequest fields, wrong hookEventName, exit 2 on events that can't block.

How it was tested

./run_tests.sh runs 40 tests (standard library unittest): 25 dangerous and 14 safe commands, protected paths through apply_patch and shell, prompt secrets with no false positives on normal text, MCP allow/deny, approval decisions, session context and caps, the Stop hook in a real temporary git repo (fail, pass, timeout, no loop), audit redaction, the linter on the broken example (every rule), clean templates, installer merge/idempotence/dry-run, TOML output, and the output contract rules. Tested on Python 3.13 and 3.10.

Honest limits

  • Hooks are a guardrail, not a sandbox. Codex says so too: some tool paths skip hooks, hosted tools such as web search don't run them, and a PreToolUse error or timeout lets the tool run. Keep Codex's sandbox and approvals on.
  • Pattern rules catch common destructive commands, not every possible one (an obfuscated command can get through).
  • Hook behavior follows the Codex hooks docs as of November 2026. Codex changes fast; docs/events.md lists the rules the linter and simulator check.
  • stop-require-tests runs your test command on your machine; give it a fast command.
  • Windows: the scripts are Python and run anywhere Python 3.9+ runs, but the git-root command form needs a POSIX shell (Git Bash/WSL) or a commandWindows override.

Format and license

Zip, 51 KB, v1.0, 40 files. You may use and modify this kit for your own work and for clients you serve, including paid client work. Not affiliated with or endorsed by OpenAI.

FAQ

Does it work with the Codex app and IDE extension?
Yes. Hooks live in hooks.json or config.toml, which the CLI, the IDE extension and the app all read. You review and trust them once with /hooks (or Settings > Hooks).
Will it block my normal work?
The rules target clearly destructive commands; rm -rf node_modules, force pushes to feature branches and git reset --soft pass. Every list is editable in hooks-config.json.
Can I lint hooks I already have?
Yes: python3 tools/codex_hooks_lint.py .codex (or ~/.codex). It exits 1 on errors, so it fits CI.
How do I get the files?
Pay by card right here on youraitools.co: your download links appear on this page the moment the payment goes through (claim window: 72 hours, up to 5 downloads per 7 days). Need the files re-sent later? Email hello@youraitools.co.
Refunds?
Email hello@youraitools.co within 14 days if it doesn’t work and we can’t fix it.
Can I pay with crypto?
Yes. Pay the same price in USDC or USDT on Base, Ethereum, Arbitrum, Optimism, Polygon or Solana from the "Pay with crypto" button, with no account or KYC. We check the payment on-chain and show your download links as soon as it confirms.

Get Codex Hooks Pack: 10 Ready Hooks + Linter + Simulator

10 ready OpenAI Codex hooks: block rm -rf and force pushes, protect .env, MCP allowlist, run tests on Stop, plus a hooks.json linter and simulator.

Pairs well with

Related

1 email a week: new x402 + MCP tools and free kits.

Short weekly digest of new x402 + MCP tools and free kits, including the MCP OAuth Checker. No spam, unsubscribe any time.