Skip to content

Repository files navigation

codex-inspect

A Claude Code plugin that runs automatic, read-only Codex inspections of document-like artifacts — plans, designs, proposals — and loops on the findings until they are fixed or waived. It is the document-side sibling of codex-review (which reviews code commits).

Install

Prerequisites: see Requirements.

/plugin marketplace add sorelmitra/codex-inspect
/plugin install codex-inspect@sorelmitra-inspect
/reload-plugins

Pull updates later with:

/plugin marketplace update sorelmitra-inspect
/plugin update codex-inspect@sorelmitra-inspect
/reload-plugins

What it does

  • /codex-inspect-artifact [<work-item> <artifact>] | [<path>] — inspect a document. The command runs a small sentinel script; the plugin's PostToolUse hook detects its token, runs codex exec with a strict prompt contract, parses [P1]/[P2]/[P3] findings with the parser vendored from codex-review, and returns a verdict.
    • <work-item>: if using the directory layout (see below), specifies the work item where the inspections would land and be read from
    • <artifact>: specifies the artifact for the same directory layout
    • <path>: full path to artifact to inspect; Codex will probably ask for a work item if you have the directory layout enabled
    • if none of the above is specified:
      • if directory layout is on, it will search for the latest artifact by modification date
      • else it will ask for it
  • Optional opinionated directory layout for reading artifacts and storing inspection results: Enable workItemLayout, configure docRoot, and then codex-inspect will :
    • look for artifacts to review under <docRoot>/<work-item>/plan/ or documents/
    • expect specifications (based on which artifacts are inspected) under spec/
    • write inspection result as the next <docRoot>/<work-item>/inspect/inspect-NN-...md with a JSON metadata block. Without a layout, findings return through hook context. This suggest the following user flow: -> Write your spec that the agent should work on in spec/ -> Have the agent produce artifacts (plans, analysis, any documents) based on the spec -> Inspect the artifacts with this plugin's layout, with the benefit of having all requirements, decisions, designs and plans documented.
  • Optional loop (enable loop): a FAIL blocks the session until the findings are applied and a re-inspection passes, capped at loopMax rounds. With firstStopHumanReview on (default), the first FAIL hard-stops the turn so the user can decide if the inspector is moving in the right direction before any automatic iteration. The first-stop messages carry a HUMAN REVIEW REQUIRED banner with the operator's steps: where the result is, /codex-inspect-waive to overrule, /codex-inspect-resume to continue. Once the loop starts, the human operator doesn't have further checkpoints, but can interrupt it at any time using standard Claude Code commands (Esc).
  • /codex-inspect-waive — waive a disputed finding.
  • /codex-inspect-resume — the only way out of the first-stop review: applies waivers, then either releases or continues the loop.
  • /codex-inspect-settings — show/change settings, toggle the skip switch (see "safety" section below).

Settings

${CLAUDE_CONFIG_DIR:-~/.claude}/codex-inspect/settings.json, strictly validated (unknown keys rejected; invalid settings stop inspections visibly):

{
  "workItemLayout": true,
  "docRoot": "~/1data/work/doc",
  "loop": true,
  "loopMax": 5,
  "firstStopHumanReview": true,
  "sandboxMode": "read-only",
  "valveMax": 5
}

Defaults:

  • docRoot: null
  • workItemLayout: false
  • loop: false
  • loopMax: 5
  • firstStopHumanReview: true
  • sandboxMode: "read-only"; accepts only read-only, workspace-write, danger-full-access (elevated values warn visibly; there is no "bypass" value). You will need danger-full-access if your Claude Code is already in a sandbox.
  • valveMax: 5 — Stop-valve budget: blocked turn-ends without a new inspection or a user prompt before the loop force-releases. Values above Claude Code's consecutive-block limit of 8 let the harness cut off first.

An active saga runs on the settings snapshot taken when it started. valveMax is the exception: the Stop hook reads it live, so a change applies to the running saga too.

Inspection file format

Each inspect-NN file (layout mode) has three parts:

  • A JSON metadata block — source path and hash, request and session ids, verdict, disposition, round.
  • ## Findings — the parsed finding lines, one per finding, marked (waived) where a waiver applies. This is the index the loop enforces: blocking counts and waive keys come from it.
  • ## Inspector notes — Codex's final message, verbatim. It carries what the findings list cannot: the legend, the overall assessment, the commentary — and it is the ground truth the findings are parsed from, so a malformed finding line the parser missed still shows up there.

The two sections overlap on purpose: the notes keep the verbatim record, the findings keep the machine-readable one.

Safety properties

  • The inspector is sandbox-enforced read-only by default; it never edits the artifact or prior inspections. Even if you enable danger-full-access, Codex is instructed to not touch your artifacts.
  • Every inspection runs against a hashed context manifest; inputs that change, appear, or disappear during the run make it ERROR, never a verdict.
  • Every verdict requires read evidence: the full contents of each input must appear in the Codex event stream and hash-match the manifest. A clean exit with no such evidence is INCONCLUSIVE (avoiding fake negative findings), and findings without read proof never block.
  • Enforcement is fail-closed: blocking state is published only after the inspection file and history entry are durable; releases (waive, valve, skip, staleness) are recorded as history transitions.
  • Escape hatches: /codex-inspect-settings skip on (mid-session kill switch), CODEX_INSPECT_SKIP env, a Stop-hook safety valve (valveMax blocked turn-ends, default 5), and age-based state Garbage Collection.
  • The valve targets unattended stuck loops only: any user prompt resets its counter (an attended session is not a stuck one), and a new inspection resets it too. Only a silent, unattended blocked loop releases at the budget; the release stays visible and audited (valve-released in the history).

Turn-end decision marker

On every turn end the Stop hook atomically writes stop-decision.<session>: {sessionId, eventId, epoch, decision}, where decision is blocked (the loop held the session), released (a blocking saga was force-released), or none, and eventId is the transcript's last assistant-message uuid at that Stop event (attachment and feedback entries appended by other hooks mid-event do not move it). Notification tooling (e.g. a Stop-hook sound script) can wait briefly for the marker matching its own event id and mute the blocked dings a fix loop would otherwise fire every round; everything else — released, none, no marker — should ring. The marker is observational only; it changes no plugin decision.

Inspections also export CC_NOTIFY_SILENCE=1 to the Codex process. Codex fires the user's trusted ~/.codex/config.toml hooks even under exec (and -c overrides cannot clear them), so notification tooling wired into those hooks can honor the variable to stay silent during automated inspection rounds.

Files

Under ${CLAUDE_CONFIG_DIR:-~/.claude}/codex-inspect/:

  • settings.json
  • state.<session>
  • last.<session> (pointer)
  • stopcount.<session> (Stop-valve counter)
  • stop-decision.<session> (per-event Stop decision marker)
  • codex-inspects.jsonl (append-only history: inspections + disposition transitions)
  • requests/ (sentinel request files)
  • waived (no-layout waivers)
  • skip.

Directory-layout mode waivers live in <work-item>/inspect/.codex-inspect-waived. Hand-written legacy inspections can be attributed via <work-item>/inspect/.codex-inspect-legacy-map (JSONL: {"file": ..., "path": ...}).

Known limitations

  • Waive-key normalization is copied from codex-review, including its global :N stripping — a title carrying a meaningful colon-number token (port:8080) shares its waive key with a sibling differing only in that number. Kept for behavioral parity.

Requirements

Development

Local install from a clone (sideload):

/plugin marketplace add /path/to/codex-inspect
/plugin install codex-inspect@sorelmitra-inspect
/reload-plugins

Tests:

  • npx --yes bats tests — hook, resume, and waive tests
  • tests/parser-parity.sh — proves the vendored parser matches the codex-review clone (CODEX_REVIEW_CLONE to point elsewhere); dev-only

About

Claude Code plugin to inspect artifacts (not code) with OpenAI Codex CLI — blocking findings trigger a fix loop

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages