Codex CLI 0.129.0+ · v4.9.0 stable

Codex CLI Testing.
PostToolUse + Stop, two-hook safety net.

tailtest-codex runs inside OpenAI Codex CLI sessions. PostToolUse hook fires after every apply_patch, parses the patch envelope to find the changed file, and queues it for testing. Stop hook fires at turn end as the catch-all for files modified outside apply_patch. 400 plugin tests. MIT.

Install (2 commands)

$ git clone https://github.com/avansaber/tailtest-codex ~/.codex/plugins/tailtest
$ cd <your-project> && bash ~/.codex/plugins/tailtest/scripts/init.sh

# Start codex. Hooks fire automatically.

Codex CLI 0.129.0+ has hooks GA by default. No feature flag needed. The init.sh script writes .codex/hooks.json in your project pointing at the plugin's hook scripts.

Marketplace install (alternative)

$ codex plugin marketplace add avansaber/tailtest-codex

Replaces git-clone step. You still need init.sh per project until Codex's upstream plugin_hooks feature ships stable.

How tailtest hooks into Codex CLI

Codex CLI uses an apply_patch tool for file edits. The patch payload is a unified diff (sometimes wrapped in Codex's *** Update File: path envelope). tailtest's PostToolUse hook parses both forms to extract the file path.

For shell-style tool calls that write files indirectly (the agent runs echo "..." > foo.py, or a build command generates files), patch parsing returns nothing. The hook falls back to an mtime sweep since the last fire, catching any qualified source file the patch parser missed.

The Stop hook at turn end is the safety net. Sweeps mtimes since turn_start_mtime. Returns decision: block if any qualified file is still pending. Codex then writes tests + runs them before closing the turn.

Why Codex CLI is special

Of the 4 tailtest hosts, Codex CLI is the one we built the deepest patch-parsing for. apply_patch's envelope is non-trivial; the unified diff format mixes with Codex-flavor headers, and getting the file path right matters for performance (the alternative -- mtime sweep on every fire -- is slower).

tailtest-codex v4.9.0 (May 2026) introduced PostToolUse migration. Earlier versions only ran Stop at turn end, so feedback was per-turn not per-edit. The v4.9.0 jump matched the Claude Code per-edit experience.

What you get

PostToolUse + Stop dual hooks

Per-edit catch + turn-end safety net. Stop never fires alone if PostToolUse handled the edit.

Two patch envelope formats parsed

Standard unified diff and Codex's *** Update File: envelope. Falls back to mtime sweep when both fail.

400 plugin tests

tailtest-codex's own dogfood suite. +20 added in v4.9.0 covering the PostToolUse code paths.

10 languages

Python, JS, TS, Go, Ruby, Java, Kotlin, C#, PHP, Rust. Runners auto-detected.

Common questions

Does this work in codex exec (non-interactive) mode?

No. Codex 0.130.0's exec mode does not load .codex/hooks.json. Hooks fire only in interactive codex sessions. This is an upstream Codex limitation.

I'm on Codex 0.128 or older. Will tailtest work?

Yes with the legacy flag. Add [features] hooks = true to ~/.codex/config.toml. The deprecated codex_hooks = true still works but emits a warning. Upgrade Codex when you can.

When does init.sh go away?

When Codex's upstream plugin_hooks feature ships stable. Today plugin-bundled hooks don't auto-activate; init.sh wires them at the project level. Once the feature ships, marketplace install becomes single-step. Targeting v5.0.0 of tailtest-codex.

Install in your Codex project