What Hooks Does the Codex Plugin Register? SessionStart, SessionEnd, and Stop Explained
The Codex plugin registers three lifecycle hooks—SessionStart, SessionEnd, and Stop—defined in plugins/codex/hooks/hooks.json that execute Node.js scripts for session initialization, cleanup, and review gate control.
The openai/codex-plugin-cc repository implements a Claude plugin that automates Codex Companion workflows through a declarative hook system. According to the source code, the plugin registers exactly three execution hooks that trigger at specific lifecycle events, enabling deterministic startup, shutdown, and abort behaviors that integrate tightly with the Claude plugin runtime.
The Three Codex Plugin Hooks
The hook registry in plugins/codex/hooks/hooks.json declares three distinct event points that the Claude plugin engine executes automatically.
SessionStart
The SessionStart hook fires at the beginning of a Codex Companion session. It runs session-lifecycle-hook.mjs with the SessionStart argument and enforces a 5-second timeout. This script initializes environment variables required for the new session.
SessionEnd
The SessionEnd hook triggers when a session finishes or is cancelled. It executes the same lifecycle script with the SessionEnd argument (also with a 5-second timeout), terminating running jobs and shutting down the broker to ensure clean resource cleanup.
Stop
The Stop hook activates when the optional "stop-review-gate" is triggered, such as when a user aborts a review. It runs stop-review-gate-hook.mjs with a 900-second (15-minute) timeout, allowing the script to block the review gate and wait for in-flight review processes to complete before cancellation.
Hook Registration Configuration
The JSON configuration file maps each event to a command invocation using the ${CLAUDE_PLUGIN_ROOT} environment variable. The structure defines the hook type, the executable command, and the timeout duration.
{
"description": "Optional stop-time review gate for Codex Companion.",
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/session-lifecycle-hook.mjs\" SessionStart",
"timeout": 5
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/session-lifecycle-hook.mjs\" SessionEnd",
"timeout": 5
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/stop-review-gate-hook.mjs\"",
"timeout": 900
}
]
}
]
}
}
Implementation Scripts
The actual behavior resides in two JavaScript modules referenced by the hook definitions in the repository.
Session Lifecycle Handler
The session-lifecycle-hook.mjs script handles environment-variable setup during SessionStart and performs comprehensive cleanup during SessionEnd, including terminating running jobs and shutting down the broker.
Stop Review Gate Handler
The stop-review-gate-hook.mjs script implements the logic that blocks the review gate when a user explicitly stops a review. It respects the 900-second timeout defined in the hook registration, waiting for in-flight processes to finish before aborting.
Debugging and Manual Invocation
You can inspect the registered hooks programmatically or trigger them manually for testing purposes.
Inspecting Registered Hooks
Use Node.js to read and parse the hook registry:
import fs from "node:fs";
import path from "node:path";
const hooksPath = path.resolve(
process.cwd(),
"plugins/codex/hooks/hooks.json"
);
const hooks = JSON.parse(fs.readFileSync(hooksPath, "utf8"));
console.log(Object.keys(hooks.hooks)); // → [ 'SessionStart', 'SessionEnd', 'Stop' ]
Simulating SessionStart
Mirror the plugin runner behavior by passing JSON via stdin:
node plugins/codex/scripts/session-lifecycle-hook.mjs SessionStart < <(echo '{"session_id":"abc123","transcript_path":"tmp/transcript.txt"}')
Triggering the Stop Hook
Execute the review gate abort logic directly:
node plugins/codex/scripts/stop-review-gate-hook.mjs
This command will wait up to 15 minutes for any in-flight review processes to finish before cancelling them, as defined by the timeout in the hook registration.
Summary
- The Codex plugin registers three lifecycle hooks in
plugins/codex/hooks/hooks.json: SessionStart, SessionEnd, and Stop. - SessionStart and SessionEnd both use
session-lifecycle-hook.mjswith 5-second timeouts for initialization and cleanup. - The Stop hook uses
stop-review-gate-hook.mjswith a 900-second timeout to handle user-initiated aborts and review gate blocking. - All hooks execute as Node.js commands referenced via the
${CLAUDE_PLUGIN_ROOT}environment variable path.
Frequently Asked Questions
What file contains the Codex plugin hook registration?
The hook registration is defined in plugins/codex/hooks/hooks.json in the openai/codex-plugin-cc repository. This JSON file maps lifecycle events to specific command invocations that the Claude plugin runtime executes automatically when those events occur.
How long does the Stop hook wait before timing out?
The Stop hook configured in hooks.json specifies a 900-second (15-minute) timeout. This extended duration allows the stop-review-gate-hook.mjs script to wait for in-flight review processes to finish before cancellation occurs, preventing abrupt termination of active operations.
Can I manually trigger Codex plugin hooks for testing?
Yes, you can invoke the hook scripts directly using Node.js. For example, run node plugins/codex/scripts/session-lifecycle-hook.mjs SessionStart followed by a JSON payload via stdin to simulate the SessionStart event outside of the Claude plugin runtime, or invoke the Stop script directly to test review gate behavior.
Do SessionStart and SessionEnd use the same script?
Yes, both hooks invoke the same session-lifecycle-hook.mjs script but pass different arguments (SessionStart vs SessionEnd). The script handles initialization logic when the argument is SessionStart and cleanup logic—including broker shutdown and job termination—when the argument is SessionEnd.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →