Reflex

Codex CLI guardrails

Reflex adds Codex hooks that judge each Bash command inside whatever sandbox mode and approval policy Codex runs with; those stay in charge. Codex hooks cannot show a prompt, so a Reflex ask blocks with a reason and the human runs the exact command with reflex run in their own terminal.

Install: npx @ursuciprian/reflex setup starts with local rules in shadow mode, no account or key. Plugins for Claude Code, Codex CLI and opencode: setup guide.

What guardrails can I add to Codex CLI, and how does Reflex work with the Codex sandbox?

Reflex adds Codex hooks (PreToolUse and PostToolUse in ~/.codex/hooks.json) that judge each Bash command inside whatever sandbox mode and approval policy Codex runs with; those stay in charge. Codex hooks cannot show a prompt or approve, so a Reflex ask blocks with a reason, and the human runs the exact command with reflex run "command" --cwd /path in their own terminal. The injection guard reads Bash and MCP results in Codex (web search is not hookable). Hooks must be trusted once in Codex's /hooks before they run.

See: supported agents, docs/SETUP.md: install the hooks.

How do I install Reflex as a Codex CLI plugin?

Add the marketplace in this repository and install the plugin from a shell: codex plugin marketplace add ursuciprian/reflex, then codex plugin add reflex@reflex. Open codex, run /hooks and trust the Reflex entries: Codex runs no plugin hook it has not been told to trust. The plugin wires the same Codex hooks as reflex setup --agent codex: the PreToolUse command gate on Bash and spawn_agent, the post-tool records, conditional instructions and the prompt injection guard on Bash and MCP results and on prompts. It needs Node.js 18+ on the PATH and no build step or API key; with no saved settings it runs the local engine in shadow mode. If reflex setup hooks are also in ~/.codex/hooks.json, the plugin's hooks stand down so nothing is judged twice, and reflex doctor shows which one is active.

See: README: Codex CLI plugin, docs/SETUP.md: Codex CLI plugin.

Codex CLI plugin

The same repository is a Codex plugin marketplace (.agents/plugins/marketplace.json) that lists the reflex plugin at the repository root. Codex reads .codex-plugin/plugin.json there, which points at hooks/codex.json, not at the Claude Code hooks/hooks.json. Codex copies the plugin to $CODEX_HOME/plugins/cache/reflex/reflex/<version>/ and runs the hooks from that copy with node.

codex plugin marketplace add ursuciprian/reflex
codex plugin add reflex@reflex
codex plugin marketplace upgrade reflex             # later, for a new release,
codex plugin add reflex@reflex                      # then add it again to copy the new version

Inside Codex, /plugins shows the same marketplace. Then open codex, run /hooks and trust the Reflex entries: Codex runs no plugin hook it has not been told to trust, and it asks again when a new release changes one.

PartWhat it is
hooks/codex.jsonthe same Codex events, matchers and timeouts as install.mjs --agent codex (see step 3): PreToolUse on ^(Bash|spawn_agent)$ (15 s), PostToolUse records on ^(Bash|spawn_agent)$ (5 s), the injection guard on PostToolUse for ^Bash$|^mcp__ (15 s), UserPromptSubmit instructions (10 s) and prompt guard (5 s). Each runs node "$PLUGIN_ROOT/<script>.mjs" <flag> --plugin (an environment variable Codex sets; the form works in sh, bash, zsh and fish); a test keeps the file in step with install.mjs
skills/reflextells the agent when to use reflex check and reflex replay, and not to work around a deny

Codex loads skills/ by default and turns two of the Claude Code commands (status, queue) into skills (checked with Codex 0.157: they appear under .codex-plugin/migrated-command-skills/ in the installed copy). The reflex CLI is not put on the PATH by Codex; install the package (npm install -g @ursuciprian/reflex) if you want those skills and reflex status to work. Configuration, defaults and logs are the same as for reflex setup: config.json, the environment and, for Jev, the key variable or the Keychain item (the Claude Code plugin options above do not apply to Codex).

Plugin and reflex setup together. Codex runs every matching hook from every source, so both would judge each call. When reflex setup (or install.mjs --agent codex) has written Reflex hooks into ~/.codex/hooks.json, every plugin hook exits at once without reading its input or writing a log line. The plugin checks the file Codex reads, $CODEX_HOME/hooks.json when CODEX_HOME is set. A hook whose script no longer exists does not count, and reflex status reports it as an error. reflex status and reflex doctor print which path is active (Codex CLI hooks: ...); doctor also runs the plugin's installed PreToolUse command through $SHELL -lc, as Codex does, when the plugin is the active one. Codex runs a hooks.json entry only after you trust it, but the plugin stands down for it either way; reflex status warns when setup hooks silence the plugin and none of them has run yet. To switch to the plugin only: node <copy that installed them>/install.mjs --agent codex --uninstall; to switch to setup only: codex plugin remove reflex@reflex. The plugin's gate timeout is 15 s, the same as reflex setup without System 2; with the autonomous profile use reflex setup --profile autonomous.

To remove the plugin: codex plugin remove reflex@reflex, and codex plugin marketplace remove reflex for the marketplace. The gate's tamper rule asks before the agent runs either of them.