Hooks
codexclaw registers 29 hook files with 30 event handlers in its plugin manifest.
The compact-affordance file handles both PostCompact and UserPromptSubmit. Each handler runs a compiled component CLI
under node. All commands resolve ${PLUGIN_ROOT} to the installed plugin directory.
The removed hook JSON files live under hooks/_deprecated/ from the 2026-07-05 hook diet.
Subagent turn guard (2026-07-09): every pabcd-state turn-level hook no-ops when the
stdin payload carries agent_id/agent_type — codex-rs stamps these into hook inputs for
thread-spawned subagent turns and reuses the parent session id, so without the guard a child
turn would read/write the parent’s PABCD state and receive root-only directives
(request_user_input is root-thread-only in codex-rs). SubagentStop is the intentional
child-scoped surface and stays exempt; the automation ownership guard also runs before the child early exit; the spawn-attach hook only enriches spawn messages
and is also unaffected.
Hook table
Section titled “Hook table”| Hook file | Event | Matcher | Command | statusMessage | Timeout |
|---|---|---|---|---|---|
session-start-ensuring-provider-bridge.json |
SessionStart |
— | node "${PLUGIN_ROOT}/components/provider-bridge/dist/cli.js" hook session-start |
(codexclaw) Detecting provider bridge |
20 s |
session-start-bootstrapping-pabcd-state.json |
SessionStart |
— | node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook session-start |
(codexclaw) Bootstrapping PABCD session state |
15 s |
session-start-healing-declared-features.json |
SessionStart |
— | node "${PLUGIN_ROOT}/components/config-guard/dist/cli.js" hook session-start |
(codexclaw) Ensuring declared codex features |
20 s |
session-start-announcing-map-affordance.json |
SessionStart |
— | node "${PLUGIN_ROOT}/components/cxc-ops/dist/cli.js" hook session-start |
(codexclaw) Announcing cxc map affordance |
10 s |
user-prompt-submit-checking-pabcd-trigger.json |
UserPromptSubmit |
— | node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook user-prompt-submit |
(codexclaw) Checking PABCD trigger |
15 s |
stop-checking-pabcd-continuation.json |
Stop |
— | node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook stop |
(codexclaw) Checking PABCD continuation |
15 s |
pre-tool-use-guarding-goal-budget.json |
PreToolUse |
^create_goal$ |
node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook pre-tool-use |
(codexclaw) Guarding goal budget |
15 s |
pre-tool-use-guarding-interview-in-goal.json |
PreToolUse |
^request_user_input$ |
node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook pre-tool-use |
(codexclaw) Denying interview/user-input in goal mode |
15 s |
pre-tool-use-guarding-goal-complete.json |
PreToolUse |
^update_goal$ |
node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook pre-tool-use |
(codexclaw) Gating lazy goal completion (E8) |
15 s |
post-tool-use-capturing-interview-answers.json |
PostToolUse |
^request_user_input$ |
node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook post-tool-use |
(codexclaw) Capturing interview answer |
15 s |
subagent-stop-verifying-evidence.json |
SubagentStop |
^worker$ |
node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook subagent-stop |
(codexclaw) Verifying subagent evidence |
10 s |
subagent-stop-observing-review.json |
SubagentStop |
.* |
node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook subagent-stop-review |
(codexclaw) Recording review verdict |
10 s |
pre-tool-use-attaching-skills.json |
PreToolUse |
^(collaboration[._]?)?spawn_agent$ |
node "${PLUGIN_ROOT}/components/subagent-config/dist/spawn-attach-hook.js" hook pre-tool-use |
(codexclaw) Attaching skills to spawn |
10 s |
session-start-announcing-subagent-fallback.json |
SessionStart |
— | node "${PLUGIN_ROOT}/components/subagent-config/dist/fallback-dispatch-cli.js" hook session-start |
(codexclaw) Loading subagent fallback protocol |
10 s |
post-compact-resetting-reinject-cursor.json |
PostCompact |
— | node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook post-compact |
(codexclaw) Recovering PABCD state after compaction |
10 s |
pre-tool-use-linting-apply-patch.json |
PreToolUse |
^(apply_patch|Write|Edit)$ |
node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook pre-tool-use-edit |
(codexclaw) Checking structured edit |
10 s |
post-tool-use-tracking-render-observations.json |
PostToolUse |
^(view_image|browser:control-in-app-browser|chrome:control-chrome|computer-use:computer-use|apply_patch)$ |
node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook post-tool-use-render-observation |
(codexclaw) Tracking render observation |
10 s |
session-start-injecting-recall-context.json |
SessionStart |
— | node "${PLUGIN_ROOT}/components/recall/dist/cli.js" hook session-start |
(codexclaw) Injecting recall context |
10 s |
post-compact-injecting-recall-context.json |
PostCompact |
— | node "${PLUGIN_ROOT}/components/recall/dist/cli.js" hook post-compact |
(codexclaw) Recovering recall context after compaction |
10 s |
post-compact-injecting-bg-terminal-affordance.json |
PostCompact |
— | node "${PLUGIN_ROOT}/components/cxc-ops/dist/cli.js" hook post-compact |
(codexclaw) Queuing compact affordance recovery |
10 s |
post-compact-injecting-bg-terminal-affordance.json |
UserPromptSubmit |
— | node "${PLUGIN_ROOT}/components/cxc-ops/dist/cli.js" hook user-prompt-submit |
(codexclaw) Restoring queued compact affordances |
10 s |
user-prompt-submit-detecting-recall-intent.json |
UserPromptSubmit |
— | node "${PLUGIN_ROOT}/components/recall/dist/cli.js" hook user-prompt-submit |
(codexclaw) Checking recall intent |
5 s |
session-start-detecting-managed-worktree.json |
SessionStart |
— | node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook worktree-guard |
(codexclaw) Checking managed-worktree identity |
10 s |
user-prompt-submit-guiding-worktree-rename.json |
UserPromptSubmit |
— | node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook worktree-guard |
(codexclaw) Checking worktree rename intent |
10 s |
pre-tool-use-guarding-managed-worktree-deletion.json |
PreToolUse |
^Bash$ |
node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook worktree-guard-pretool |
(codexclaw) Guarding managed worktree |
10 s |
pre-tool-use-guarding-automation-ownership.json |
PreToolUse |
automation_update native aliases | node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook pre-tool-use-automation-ownership |
(codexclaw) Checking automation ownership |
10 s |
pre-tool-use-guarding-memory-write.json |
PreToolUse |
^(memories[._]?add_ad_hoc_note|apply_patch|Write|Edit|Bash)$ |
node "${PLUGIN_ROOT}/components/pabcd-state/dist/cli.js" hook pre-tool-use-memory-write |
(codexclaw) Guarding memory write |
10 s |
stop-waking-on-background-completion.json |
Stop |
— | node "${PLUGIN_ROOT}/components/bg-wake/dist/cli.js" hook stop |
(codexclaw) Checking background task completions |
10 s |
user-prompt-submit-delivering-background-completions.json |
UserPromptSubmit |
— | node "${PLUGIN_ROOT}/components/bg-wake/dist/cli.js" hook user-prompt-submit |
(codexclaw) Delivering background completions |
10 s |
session-start-adopting-background-completions.json |
SessionStart |
— | node "${PLUGIN_ROOT}/components/bg-wake/dist/cli.js" hook session-start |
(codexclaw) Adopting background completions |
10 s |
What each hook does
Section titled “What each hook does”Session lifecycle
Section titled “Session lifecycle”- provider-bridge / session-start — detects
ocxstatus (detect-only) at session start. - pabcd-bootstrap / session-start — creates or resumes the per-session PABCD state file without clobbering existing state.
- map-affordance / session-start — announces
cxc mapavailability through thecxc-opsCLI at session start. - recall-context / session-start — injects recent past-session and memory context at
session start, scoped to the current working directory. Sessions are listed from
the sidecar index by
cwd, each shown by its opening user message plus a rollout-summary line when one exists. The block is labelled with the date of the newest session and wrapped as untrusted data. Whensourceiscompactthe block is capped to fewer sessions and this hook also carries the post-compaction recovery directive, sincePostCompactitself cannot.
Prompt & orchestration
Section titled “Prompt & orchestration”- pabcd-trigger / user-prompt-submit — parses the orchestrate grammar from the submitted prompt and injects the matching phase directive.
- recall-intent / user-prompt-submit — detects past-session recall phrasing and routes to the disk-artifact search before the agent asks the user.
- pabcd-continuation / stop — under an active goal with an in-flight cycle, blocks Stop to keep the loop advancing, bounded by the continuation guards.
Pre-tool guards
Section titled “Pre-tool guards”- goal-budget / pre-tool-use (
create_goal) — guards goal creation against the goal budget. - interview-in-goal / pre-tool-use (
request_user_input) — denies interactive interview prompts while a goal is active, so an autonomous goal does not stall on a question. - goal-complete / pre-tool-use (
update_goal) — gates lazy goal completion (E8): a goal cannot close while its bound goalplan has undone work or unproven criteria. - skill-attach / pre-tool-use (
spawn_agent) — normalizes known broken/bare cxc mentions already present in spawn messages; it never adds omitted role or surface skills. - edit-lint / pre-tool-use (
apply_patch|Write|Edit) — lints structured edits before they apply. - memory-write / pre-tool-use (
memories[._]?add_ad_hoc_note|apply_patch|Write|Edit|Bash) — denies an unauthorized write into the Codex memories directory. The shell leg classifies by write destination (>,>>,>|,tee,sed -i,cp/mvtarget,perl -i/ruby -i), not by a memories path string in the command body, sosed -nreads,2>/dev/nullstderr redirects, and heredoc bodies that mention the memories path are allowed. Fail-open on crash. Early warning, not enforcement: subshells, variable expansions, andpython -cwriters are residual bypasses.
Post-tool capture
Section titled “Post-tool capture”- interview-capture / post-tool-use (
request_user_input) — captures interview Q/A answers into the interview ledger. - render-observation / post-tool-use (
view_image|browser:control-in-app-browser|chrome:control-chrome|computer-use:computer-use|apply_patch) — tracks render observations for visual and surface-driving QA evidence.
Subagent & compaction
Section titled “Subagent & compaction”- evidence-verify / subagent-stop (
worker) — verifies subagent evidence bundles on completion. The retry budget is TERMINAL: afterMAX_ATTEMPTSblocks the child is released with an unresolved verdict recorded against the session, andGOAL-COMPLETE-GATE-01deniesupdate_goal {status:"complete"}until it is settled withcxc evidence resolve --receipt <path>. Blocking forever was not a safeguard: a read-only child cannot write the receipt, so re-prompting it only hid the outcome from the parent. Read-only lanes should dispatch asexplorer, which is never gated. - reinject-cursor / post-compact — recovers PABCD state and re-injection cursor after context compaction.
- recall-context / post-compact — registered but intentionally silent: it emits
no output and changes no recall context; the CLI may record invocation metadata. The PostCompact output wire accepts only the
universal fields, so an event-specific envelope is rejected and the run is
recorded as failed. The recovery text is delivered by the SessionStart handler,
which the runtime re-fires with
sourcecompactafter a compaction. The table’sstatusMessageis the registration string from the hook JSON; the handler’s stdout is the empty string. - bg-terminal-affordance / post-compact — queues a workspace/session-scoped recovery marker and emits no event-specific context. PostCompact cannot carry this guidance directly on hosts accepting only universal output fields.
- bg-terminal-affordance / user-prompt-submit — consumes that marker once on
the next root prompt and emits background-terminal, loop, stack and async-question
guidance through UserPromptSubmit. Either child stamp prevents enqueue/consume;
explicit
reset --stateclears pending markers. No prompt means no same-turn/Stop recovery guarantee. This is hint delivery, not permission or forced tool use.
Hooks run only after you trust them in Codex. See Installation → Hook trust.
Missing session binding
Section titled “Missing session binding”An ordinary Codex fork has its own native thread ID. A missing SessionStart
message or missing .codexclaw/sessions/<id>.json must not be repaired by copying
an ID from inherited chat history or by choosing the newest session file.
From the current Codex terminal tool, run cxc session current --json. It reads
native CODEX_THREAD_ID, corroborates the exact ID and cwd against Codex’s local
thread database, and reports whether FSM state exists. Run cxc session bind
explicitly in that verified cwd to create missing IDLE state. Existing state is
preserved; malformed state, subagent identity, mismatched cwd and unavailable
native metadata fail with a diagnostic. Do not assign CODEX_THREAD_ID yourself.
Binding repairs state only. hooksVerified: false means it does not establish that
SessionStart, prompt or Stop hooks ran. Check cxc doctor from the installed payload
for installation/trust issues; compare its version to a PATH-level development CLI.
A running process may retain old plugin paths after an update. Refresh/restart that
process when appropriate; successful installation alone is not live hook proof.
Implicit orchestrate status uses the verified native identity when present and
never falls back after a native validation failure. Explicit missing state reports
an error with phase: null, rather than inventing IDLE. Plain terminals without
native identity retain their read-only latest-file compatibility fallback.
Emitted hints prefer the emitting plugin’s dispatcher for commands it supports,
so an old development cxc on PATH cannot capture new recovery commands. Repo-only
map/gui keep their PATH routing; explicit CODEXCLAW_CXC overrides still win.
For direct commands from static docs, use node "<pluginRoot>/bin/cxc.mjs" when
the PATH CLI is older than the installed plugin.
Invocation evidence and automation ownership
Section titled “Invocation evidence and automation ownership”cxc doctor reports hook invocation observations separately from stored trust. Instrumented entrypoints record bounded metadata per session, actor and component/event, with payload digests. Missing, stale or mismatched records remain unverified. A record means the entrypoint ran, not that every registered hook fired or a policy succeeded. Direct CLI replay and same-user file edits can produce records, so these are diagnostics rather than authenticated host attestations.
pre-tool-use-guarding-automation-ownership.json invokes the PABCD CLI’s pre-tool-use-automation-ownership handler (10 second timeout) for matching automation_update tools. It permits read-only views. Heartbeat mutation requires the stored target_thread_id to match the calling task; children, unknown owners and foreign retargets are denied. Creation can target the current task. Standalone cron ownership is not inferred.
This safeguard depends on actual hook delivery and trust. Code Mode inner calls without hooks, app UI, direct file writes and an ownership change after inspection remain outside its protection. Native atomic ownership checks are still required to close that host defect. Before changing an automation, read its exact automation.toml, confirm the task association and use a task-specific name. Prefer a supported in-place update; never treat a numeric suffix as proof of a duplicate.
