# How the Stop-Time Review Gate Works in the Claude-Codex Workflow

> Discover how the stop-time review gate in the Claude-Codex workflow ensures session safety. Learn how Codex reviews code changes and approves or blocks termination.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: internals
- Published: 2026-07-10

---

**The stop-time review gate is a safety checkpoint that automatically runs when a Claude session ends, using Codex to review the previous turn's code changes and returning either `ALLOW` or `BLOCK` to determine if the session may safely terminate.**

The `openai/codex-plugin-cc` repository implements this gate as a hook script that intercepts the session stop event. When enabled, it ensures that no Claude session concludes without a final automated verification of the most recent code modifications. Understanding this mechanism helps developers configure reliable AI-assisted development workflows.

## Where the Gate Lives

The stop-time review gate consists of two primary components registered within the plugin architecture.

The **hook script** at `plugins/codex/scripts/stop-review-gate-hook.mjs` contains the orchestration logic that Claude invokes automatically when the `stop` command is issued. This script manages input parsing, prompt construction, and decision emission.

The **prompt template** at [`plugins/codex/prompts/stop-review-gate.md`](https://github.com/openai/codex-plugin-cc/blob/main/plugins/codex/prompts/stop-review-gate.md) defines the instructions fed to the Codex model. It establishes the review criteria and mandates a deterministic output format that the hook can parse reliably.

Registration occurs in [`.claude-plugin/plugin.json`](https://github.com/openai/codex-plugin-cc/blob/main/.claude-plugin/plugin.json), which maps the `stop` event to the hook script path, ensuring Claude calls the gate automatically during session termination.

## Execution Flow

The gate operates through a sequential seven-step process designed to fail safely.

### Input Processing and Early Exits

The hook begins by calling `readHookInput()` (lines 21‑27) to parse JSON session context from stdin. This payload includes the current working directory, session ID, and the previous assistant message containing the code changes.

Before invoking Codex, the script performs two validation checks (lines 54‑57):

1. **Configuration check**: If `config.stopReviewGate` is false, the hook exits immediately with an ALLOW decision.
2. **Availability check**: If Codex is not configured (`getCodexAvailability`), the hook logs a setup note via `buildSetupNote()` (lines 59‑66) and skips the review.

### Prompt Construction and Execution

When validation passes, `buildStopReviewPrompt()` (lines 48‑57) loads the template using `loadPromptTemplate` and interpolates the previous Claude response into the `{{CLAUDE_RESPONSE_BLOCK}}` placeholder.

The hook then executes `runStopReview()` (lines 98‑130), which spawns `codex-companion.mjs` via `spawnSync` with a **15‑minute timeout**. This subprocess runs the Codex model against the constructed prompt in an isolated environment.

### Decision Parsing and Session Control

After execution, `parseStopReviewOutput()` (lines 69‑95) extracts the `rawOutput` field from the returned JSON and inspects the first line for the mandatory prefix:

- **`ALLOW:`** → The hook permits session termination.
- **`BLOCK:`** → The hook calls `emitDecision()` (lines 29‑31) to write a JSON block to stdout, instructing Claude to prevent session closure and display the provided reason.

The system also reports any still-running Codex jobs through `logNote()` (lines 33‑38), ensuring users are aware of background tasks before the session ends.

## Prompt Logic and Response Contract

The [`stop-review-gate.md`](https://github.com/openai/codex-plugin-cc/blob/main/stop-review-gate.md) prompt template enforces strict constraints on Codex behavior to guarantee deterministic outcomes.

The template instructs Codex to **only** review work from the immediately preceding Claude turn. It mandates an **immediate ALLOW** if that turn produced no direct code edits, optimizing for the common case of conversational or planning sessions.

The output contract (lines 14‑20) requires a single-line response beginning with either `ALLOW:` or `BLOCK:` followed by an explanation. This structured format enables reliable machine parsing without ambiguity.

Default policy rules (lines 22‑26) establish that Codex should ALLOW when no edits are detected and reserve BLOCK for genuine issues or unfinished work, preventing unnecessary session interruptions.

## Configuration and Integration

The gate integrates with the broader Claude-Codex ecosystem through configuration files and shared libraries.

The `config.stopReviewGate` setting, typically defined in `.codexrc` or `.codex` configuration files, acts as the master switch. Disabling this boolean bypasses the gate entirely, allowing immediate session termination.

The hook leverages utilities from `plugins/codex/scripts/lib/state.mjs` for configuration retrieval and job tracking. It queries the workspace job store via `listJobs` and `filterJobsForCurrentSession` to detect concurrent Codex tasks, warning users if background processes remain active.

All failure paths implement **fail-safe** semantics. If the Codex task exceeds the 15‑minute timeout (lines 12‑18), returns a non-zero exit code (lines 20‑27), or emits invalid JSON (lines 33‑38), the hook automatically BLOCKS the session rather than risking premature termination with unreviewed changes.

## Debugging the Stop-Time Review Gate

You can manually invoke the gate for testing or debugging purposes without running a full Claude session.

Simulate a stop-time review by piping JSON context directly to the hook script:

```bash
cat <<EOF | node plugins/codex/scripts/stop-review-gate-hook.mjs
{
  "cwd": "/path/to/project",
  "session_id": "abc123",
  "last_assistant_message": "Edited src/utils.ts to fix bug #42"
}
EOF

```

The script outputs a JSON decision to stdout:

```json
{"decision":"block","reason":"Codex stop-time review found issues that still need fixes before ending the session: ..."}

```

When properly registered in [`.claude-plugin/plugin.json`](https://github.com/openai/codex-plugin-cc/blob/main/.claude-plugin/plugin.json), Claude automatically triggers the hook when users issue `/codex:stop` or end their session:

```json
{
  "stop": "plugins/codex/scripts/stop-review-gate-hook.mjs"
}

```

To check for running jobs before manual invocation, inspect the job state using the internal utilities:

```javascript
const runningTaskNote = runningJob
  ? `Codex task ${runningJob.id} is still running. Check /codex:status and use /codex:cancel ${runningJob.id} if you want to stop it before ending the session.`
  : null;

```

## Summary

- The stop-time review gate runs automatically when Claude sessions end, providing a final safety check on recent code changes.
- The implementation resides in `plugins/codex/scripts/stop-review-gate-hook.mjs` with logic split across `readHookInput()`, `runStopReview()`, and `parseStopReviewOutput()`.
- A 15‑minute timeout and strict `ALLOW:`/`BLOCK:` response format ensure reliable, deterministic behavior.
- The gate respects the `config.stopReviewGate` configuration setting and can be bypassed by disabling this flag.
- All failure modes—including timeouts, non-zero exits, and invalid JSON—default to BLOCK to prevent unsafe session termination.

## Frequently Asked Questions

### What triggers the stop-time review gate?

The gate triggers automatically when a user ends a Claude session or issues the `/codex:stop` command. Claude invokes the registered hook script from [`.claude-plugin/plugin.json`](https://github.com/openai/codex-plugin-cc/blob/main/.claude-plugin/plugin.json), passing the session context and previous assistant message as JSON via stdin.

### How does the gate decide to ALLOW or BLOCK a session?

The gate spawns `codex-companion.mjs` with the [`stop-review-gate.md`](https://github.com/openai/codex-plugin-cc/blob/main/stop-review-gate.md) prompt, which instructs Codex to review only the previous turn's changes. Codex must return a single line starting with `ALLOW:` if the changes are acceptable or `BLOCK:` if issues remain. The hook parses this output in `parseStopReviewOutput()` (lines 69‑95) and emits the corresponding decision.

### Can I disable the stop-time review gate?

Yes. Set `stopReviewGate: false` in your `.codexrc` or `.codex` configuration file. When `config.stopReviewGate` evaluates to false, the hook exits early (lines 54‑57) without invoking Codex, allowing immediate session termination.

### What happens if the Codex review times out?

If the review exceeds 15 minutes, the hook catches the timeout in `runStopReview()` (lines 12‑18) and automatically emits a BLOCK decision. This fail-safe design ensures that sessions cannot end while the safety review is incomplete or unresponsive.