Skip to main content

Overview

Codex CLI ships a Claude-style hook system. A PreToolUse hook runs a script before a tool executes and can block it. Sigil Open Framework (SOF) plugs into that hook: the script forwards the intended action to Sigil Sign /v1/authorize and blocks when the policy returns DENIED.
Coverage today. A valid Codex PreToolUse denial blocks supported Bash, exec_command, apply_patch, MCP, and the local function-tool calls that the registered matchers cover. Hosted tools, specialized paths, and continued write_stdin streams are not fully covered. A hook crash, timeout, malformed output, or unsupported output can also leave the host call on its normal path. Treat this as a guardrail, not a complete enforcement boundary. For broader MCP governance, route tools through the Sigil MCP Proxy. Track the Codex hooks docs as coverage expands.
HTTP note: Codex emits typed http only when a web tool input explicitly carries a valid method. Web inputs without a method remain web_fetch; the adapter never infers GET.

Prerequisites

You need a Sigil API key and a signed warranty.md policy file deployed to Sigil Sign. Node.js 18 or newer is required for the hook script below.

1. Register the PreToolUse hook

Hooks are enabled by default in current Codex releases. Use the canonical hooks configuration. The older codex_hooks feature flag is deprecated. In ~/.codex/hooks.json (global) or <repo>/.codex/hooks.json (per project):

2. Add the hook script

Install the package in a location the script can resolve, then create ~/.codex/hooks/sigil-pretooluse.mjs:
Make the package resolvable to the script (a global install plus NODE_PATH=$(npm root -g) in your shell profile is the simplest path), set SIGIL_API_KEY in your environment, and Codex will check Bash, file edits, and the registered MCP tools against your policy before they run. Add one matcher entry per MCP tool name you expose. The adapter resolves task ids in this order: config.taskId, session_id, conversation_id, run_id, turn_id, then SIGIL_TASK_ID. ## execution_limits uses this value to apply per-task tool-call ceilings.

How It Works

Codex pipes a JSON payload to the hook on stdin. The adapter maps Bash to bash, apply_patch/Edit/Write to file_write, and MCP tool names to their lowercase canonical names. On a DENIED or PENDING decision it writes the documented Codex hookSpecificOutput.permissionDecision = "deny" shape to stdout. Codex then refuses the tool call and returns the reason to the model.

Fail Mode

The script above uses failMode: 'closed', so the adapter returns a denial if Sigil Sign is unreachable. Codex blocks when it receives that valid denial. This does not cover failure of the hook process itself. Codex documents hooks as guardrails rather than a complete security boundary, so pair them with the OS sandbox, managed approval policy, and an in-path MCP proxy for consequential connector actions.

Adapter Status

Codex has a dedicated package export: createCodexPreToolUseHook. It preserves the current Codex deny shape, framework id, task id fallbacks, fail-closed default, and coverage warnings in request metadata.

Governing MCP and File Tools

Codex PreToolUse covers matching MCP tool calls and file edits through apply_patch. Two paths still matter:
  • MCP tool calls: use the adapter for matched calls, or point Codex at the Sigil MCP Proxy when you need protocol-level enforcement for every MCP tools/call.
  • Web tools: governed natively once Codex extends hook coverage to WebSearch and related non-shell tools.

Configuration

Source