Codex hooks
The CLI can install hooks into Codex without changing application code.
pip install staso
export STASO_API_KEY=ak_...
staso setup --target codexThe setup flow writes hook configuration and keeps the API key in the user credential file. Review and trust each generated Codex hook command in Codex Settings before running the integration.
Setup installs all 11 current lifecycle hooks: SessionStart, SessionEnd, UserPromptSubmit, PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, SubagentStart, SubagentStop, and Stop.
Run Codex
Open the Staso dashboard, then run a Codex session. The session appears after its trace is query-visible.
What it captures
All 11 lifecycle hooks listed above are installed. Each Codex turn is correlated
by its own turn ID, so steering and
overlapping turns keep their tool calls and completion attached to the correct
trace. The first prompt emits a provisional root and Stop finalizes that same
root ID and timestamp. Session end safely timeout-finalizes any interrupted turn.
Every root keeps the structural name Codex Turn. Its input stores the canonical
human request from the exact turn's transcript as prompt and the exact first
hook payload as raw_prompt. Same-turn steering stays on that root in the ordered
steering list, with both prompt and raw_prompt for each message. Transcript
parsing is enrichment only; when the semantic request cannot be correlated, Staso
fails closed instead of borrowing text from another turn or interpreting provider
markup.
Existing prompt, tool, and completed-compaction callbacks refresh the captured
request and available model. Each observed model response contributes its own
reported usage, model, and stable span ID; repeated transcript snapshots do not
add another response. Stop reuses those IDs and collects any remaining usage.
Cost remains unavailable until the host reports usage and Staso recognizes the
model's pricing. When the transcript does not expose a model-call start time,
Staso does not treat the whole turn duration as that call's latency.
Guard
Guard checks are on by default. PreToolUse evaluates proposed tool calls against active configured policies. A matching audit policy records a would-block finding and allows the proposal. A matching Enforce policy can block it before execution. Built-in templates are inactive until attached to a policy. Disable the check with --no-guard.
Keep hooks current
All five content categories default to enabled. The interactive setup lets you choose them, or use paired flags in scripted setup:
staso setup --target codex \
--no-capture-request \
--no-capture-tool-arguments \
--capture-output| Category | Codex hook data |
|---|---|
request | Submitted user prompt, turn input, prompt-derived turn label, and cached transcript path. |
system_prompt | No host system prompt is exposed to these hooks. |
tool_schema | No host tool schema is exposed to these hooks. |
tool_arguments | Hook and transcript-derived tool input, including patch/file payloads. Guard evaluates the proposed input in memory and never rewrites it. |
output | Assistant transcript content, tool results, and Guard reason prose. |
The hook reads the host transcript to derive assistant spans, models, token counts, turn offsets, and tool paths that were not already captured by hooks. Completed hook call IDs prevent transcript fallback from creating duplicate tool spans. When output is suppressed it parses a content-free assistant shape. When both tool_arguments and output are suppressed it skips transcript tool-call extraction. A suppressed request is not stored locally or included in live updates; the structural root name remains Codex Turn.
Guard evaluates tool proposals during PreToolUse; PermissionRequest leaves Codex's normal approval prompt unchanged instead of evaluating the same proposal twice. A completed compaction emits a context:compact child span. A completed subagent emits an agent child span with the timing, model, token, and permitted output data exposed by the host.
Hook subprocesses keep short-lived session state in ~/.staso/codex. The directory is restricted to mode 0700 and state files to 0600; symlinked or non-regular paths are refused. Normal SessionEnd removes the state, and a later SessionStart removes interrupted state older than 24 hours. The hooks can only govern fields their host exposes; an enabled category is not a claim that hidden host content was received.
Useful maintenance commands:
staso status --target codex
staso sync --target codex
staso uninstall --target codexRun each command with --help for its current options.