Codex
Quickstart
Section titled “Quickstart”handup serve --foreground # or install the handup servicehandup integrate codex --dry-runhandup integrate codexhandup prompt --agent codexcodex --sandbox workspace-write --ask-for-approval on-requestThe reversible installer merges handup hook codex into $CODEX_HOME/hooks.json (default ~/.codex/hooks.json) and the handup MCP server into $CODEX_HOME/config.toml (below); --no-mcp installs only the hook. It preserves other handlers, shows the config diffs, checks every file before writing any, and backs up changed configuration. Reapply is idempotent. Remove both with handup integrate codex --uninstall. Codex requires hook trust review; approve the reviewed hook in Codex before use. Requests have no deadline by default. The installed host hook timeout is still 660 seconds: increase it for longer human waits. If Codex kills the hook, the request remains pending and no approval is returned.
Behavior and fallback
Section titled “Behavior and fallback”The PermissionRequest hook runs only when Codex requests permission, not on commands already allowed by its sandbox or rules. Bash becomes a command preview; other tools show tool-input JSON. Requests carry source.agent=codex, the session ID, and cwd. A human can deny with handup deny ID -m 'Use staging instead', and Codex receives that feedback as decision.message. Approval returns only behavior: allow; denial, cancellation, and expiration return behavior: deny with feedback or a safe default. Codex never receives updatedInput or updatedPermissions: this hook cannot revise the tool call or grant Codex-native persistent permissions.
Exception: desktop Run approves the handup request with run_result, but
the hook returns behavior: "deny" and decision.message contains the run
summary and do not run again instruction. The original command is blocked
to avoid duplicate execution, including after a failed run; consume the result
rather than retrying. See result fields.
handup approve ID --scope session creates a handup rule for matching repeat requests in that session; the daemon handles these repeats automatically, with rule audit metadata. Agents must not grant themselves a scope. If the daemon is unreachable or presence routes to the keyboard, the hook prints no decision, leaving Codex’s native permission handling in place. It never grants fallback approval and does not auto-start a missing daemon.
MCP and limitations
Section titled “MCP and limitations”handup integrate mcp --client codex --dry-runhandup integrate mcp --client codexhandup integrate codex already includes this; the commands above install the MCP server alone. It uses $CODEX_HOME/config.toml, preserving comments and other servers. The [mcp_servers.handup] entry sets env_vars = ["XDG_RUNTIME_DIR"], since Codex scrubs the MCP server environment and handup needs it to find the daemon socket, and default_tools_approval_mode = "approve", since handup tools only ask the human and codex exec otherwise fails with “MCP tool call requires approval”. Reapplying adds these keys to an existing handup entry and keeps values you set. Codex defaults to a 60-second MCP tool timeout: prefer wait=false then wait_requests, or configure tool_timeout_sec. Read MCP for arguments and polling. Preview paths resolve from the MCP server cwd.
This adapter targets the Codex 0.159.2 PermissionRequest contract, not an app-server proxy. It gates only permission requests and does not enforce a separate pre-tool policy. In 0.159.2, codex exec forces approval policy never, even with -c 'approval_policy="on-request"', so use the interactive CLI for native approval round-trips. A command must actually need escalation to invoke this hook. Native headless behavior depends on Codex’s approval policy; a no-decision fallback is not permission.
Sources: https://developers.openai.com/codex/hooks#permissionrequest and https://developers.openai.com/codex/mcp