Skip to content

Codex Hooks Integration

What this integration does

StatePlane can use Codex hooks as a local event source for shell-driven coding work.

The integration records:

  • user prompts
  • Bash commands before execution
  • Bash command results after execution
  • pytest failures when the output is parseable
  • changed files discovered at Stop
  • replay, diff, and artifact receipts for the Codex turn

It then injects compact StatePlane context back into Codex so the next turn starts from governed state instead of raw transcript replay.

Why hooks are useful for StatePlane

Codex hooks are a practical local-first boundary:

  • Codex already emits prompt and Bash lifecycle events
  • StatePlane already knows how to persist events, rebuild coding state, replay, diff, and export receipts

That means the integration can stay small:

Codex hook payload
-> StatePlane recorder
-> structured state
-> replay and diff
-> compact StatePlane context back into Codex

Current Codex hook limitations

Codex hooks are currently best suited for shell-driven coding workflows.

The current PreToolUse and PostToolUse events are Bash-focused. They do not provide a complete event stream for every Codex action.

StatePlane therefore records Bash commands and command results directly, then discovers changed files at Stop using git diff.

This is useful, but it is not complete prompt-injection protection and it is not a full runtime trace of every Codex action.

Install

  1. Enable Codex hooks:
[features]
codex_hooks = true
  1. Add .codex/hooks.json to your repo.

  2. Ensure the stateplane package is importable in the environment where Codex runs.

  3. Start Codex from the repository root or a subdirectory inside the repo.

You can also write starter files locally with:

stateplane codex install --repo .

Configure Codex hooks

The example starter hook file is:

  • examples/codex_hooks_integration/.codex/hooks.json

Its command target is:

stateplane codex hook

If you are working from a source checkout rather than an installed CLI, change that command to your local invocation, for example:

uv run --all-packages --all-groups --python 3.13 stateplane codex hook

Hook event mapping

Codex hook StatePlane behavior
SessionStart Load latest snapshot and inject compact context
UserPromptSubmit Start or continue a StatePlane run and record the user prompt
PreToolUse Bash Record planned command and optionally flag or block dangerous commands
PostToolUse Bash Record command result and parse pytest output when possible
Stop Record assistant message, discover changed files, complete run, export artifacts

Session and run mapping

The StatePlane session id is repo-scoped by default:

codex:<repo-name>:<short-hash-of-repo-root>

This keeps state stable across multiple Codex sessions in the same repository.

The default local database path is:

.stateplane/codex/state.db

Run ids are turn-scoped when Codex exposes turn_id:

codex-turn:<turn-id>

Fallbacks use the Codex session id or a deterministic unknown-turn hash.

What gets recorded

The integration uses the existing StatePlane APIs instead of inventing a second recorder:

  • observe_user_message(...)
  • observe_tool_call(...)
  • observe_tool_result(...)
  • record_command(...)
  • record_test_run(...)
  • record_file_patch(...)
  • record_risk(...)
  • start_run(...)
  • complete_run(...)
  • export_run_artifacts(...)

That means Codex hook data flows into the same replay, diff, snapshot, and artifact system already used by the structured coding-state examples.

What gets injected back into Codex

When there is useful prior state, the integration returns compact additional context such as:

StatePlane context for this repository:

STATEPLANE CONTEXT

Hard constraints:
- Do not edit tests.

Active goals:
- Fix the failing CLI test

Receipts:
- .stateplane/codex/latest_snapshot.md
- .stateplane/codex/latest_diff.md
- .stateplane/codex/latest_manifest.json

The injected context is truncated to stay compact and does not include raw long logs or raw quarantined instructions. If there is no useful prior state, StatePlane can intentionally inject no model-visible context at all.

Artifact layout

.stateplane/codex/
  state.db
  latest_snapshot.md
  latest_diff.md
  latest_context.md
  latest_manifest.json
  raw_hooks/
  artifacts/
    codex-turn-turn-1/
      manifest.json
      events.json
      run.json
      coding_projection.before.json
      coding_projection.after.json
      coding_diff_from_previous.json
      state_records.json
      snapshot.json
      snapshot.md
      receipt.md
      prepared_openai_request.json
      receipt.json

The exact run-artifact directory name depends on the turn or fallback run id.

Safety behavior

The default behavior is non-blocking.

StatePlane can flag obviously dangerous Bash commands and record them as risks. Blocking only happens when:

STATEPLANE_CODEX_BLOCK_DANGEROUS_COMMANDS=1

Bash output is treated as evidence, not authority. It may become:

  • command evidence
  • structured test evidence
  • risks
  • quarantined risks

It does not become a high-trust user constraint automatically.

Run the simulation

python examples/codex_hooks_integration/simulate_hooks.py

That script does not require Codex, network access, or an OpenAI API key.

Troubleshooting

  • If no latest files appear, make sure Codex started inside the repository you expect.
  • If hook commands do not run, verify the command in .codex/hooks.json matches your environment.
  • If you are using a source checkout, prefer a uv run ... stateplane codex hook command in the hook file.
  • If Stop does not record changed files, confirm the repository is a git worktree and the files are tracked by git diff.

Limitations

  • Codex hooks are experimental.
  • Current PreToolUse and PostToolUse coverage is Bash-focused.
  • This integration does not observe every Codex action directly.
  • File edits are inferred at Stop via git diff.
  • No live OpenAI calls are made by this integration.
  • No network access is required.

Next steps

  • Start with the simulation example.
  • Use stateplane codex install --repo . to create starter local hook files.
  • Inspect .stateplane/codex/latest_snapshot.md and the exported artifact directory after a real Codex turn.