mirror of
https://github.com/openai/codex.git
synced 2026-04-30 09:26:44 +00:00
## Why We need `PermissionRequest` hook support! Also addresses: - https://github.com/openai/codex/issues/16301 - run a script on Hook to do things like play a sound to draw attention but actually no-op so user can still approve - can omit the `decision` object from output or just have the script exit 0 and print nothing - https://github.com/openai/codex/issues/15311 - let the script approve/deny on its own - external UI what will run on Hook and relay decision back to codex ## Reviewer Note There's a lot of plumbing for the new hook, key files to review are: - New hook added in `codex-rs/hooks/src/events/permission_request.rs` - Wiring for network approvals `codex-rs/core/src/tools/network_approval.rs` - Wiring for tool orchestrator `codex-rs/core/src/tools/orchestrator.rs` - Wiring for execve `codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs` ## What - Wires shell, unified exec, and network approval prompts into the `PermissionRequest` hook flow. - Lets hooks allow or deny approval prompts; quiet or invalid hooks fall back to the normal approval path. - Uses `tool_input.description` for user-facing context when it helps: - shell / `exec_command`: the request justification, when present - network approvals: `network-access <domain>` - Uses `tool_name: Bash` for shell, unified exec, and network approval permission-request hooks. - For network approvals, passes the originating command in `tool_input.command` when there is a single owning call; otherwise falls back to the synthetic `network-access ...` command. <details> <summary>Example `PermissionRequest` hook input for a shell approval</summary> ```json { "session_id": "<session-id>", "turn_id": "<turn-id>", "transcript_path": "/path/to/transcript.jsonl", "cwd": "/path/to/cwd", "hook_event_name": "PermissionRequest", "model": "gpt-5", "permission_mode": "default", "tool_name": "Bash", "tool_input": { "command": "rm -f /tmp/example" } } ``` </details> <details> <summary>Example `PermissionRequest` hook input for an escalated `exec_command` request</summary> ```json { "session_id": "<session-id>", "turn_id": "<turn-id>", "transcript_path": "/path/to/transcript.jsonl", "cwd": "/path/to/cwd", "hook_event_name": "PermissionRequest", "model": "gpt-5", "permission_mode": "default", "tool_name": "Bash", "tool_input": { "command": "cp /tmp/source.json /Users/alice/export/source.json", "description": "Need to copy a generated file outside the workspace" } } ``` </details> <details> <summary>Example `PermissionRequest` hook input for a network approval</summary> ```json { "session_id": "<session-id>", "turn_id": "<turn-id>", "transcript_path": "/path/to/transcript.jsonl", "cwd": "/path/to/cwd", "hook_event_name": "PermissionRequest", "model": "gpt-5", "permission_mode": "default", "tool_name": "Bash", "tool_input": { "command": "curl http://codex-network-test.invalid", "description": "network-access http://codex-network-test.invalid" } } ``` </details> ## Follow-ups - Implement the `PermissionRequest` semantics for `updatedInput`, `updatedPermissions`, `interrupt`, and suggestions / `permission_suggestions` - Add `PermissionRequest` support for the `request_permissions` tool path --------- Co-authored-by: Codex <noreply@openai.com>
103 lines
2.1 KiB
JSON
103 lines
2.1 KiB
JSON
{
|
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
"additionalProperties": false,
|
|
"definitions": {
|
|
"HookEventNameWire": {
|
|
"enum": [
|
|
"PreToolUse",
|
|
"PermissionRequest",
|
|
"PostToolUse",
|
|
"SessionStart",
|
|
"UserPromptSubmit",
|
|
"Stop"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"PreToolUseDecisionWire": {
|
|
"enum": [
|
|
"approve",
|
|
"block"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"PreToolUseHookSpecificOutputWire": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"additionalContext": {
|
|
"default": null,
|
|
"type": "string"
|
|
},
|
|
"hookEventName": {
|
|
"$ref": "#/definitions/HookEventNameWire"
|
|
},
|
|
"permissionDecision": {
|
|
"allOf": [
|
|
{
|
|
"$ref": "#/definitions/PreToolUsePermissionDecisionWire"
|
|
}
|
|
],
|
|
"default": null
|
|
},
|
|
"permissionDecisionReason": {
|
|
"default": null,
|
|
"type": "string"
|
|
},
|
|
"updatedInput": {
|
|
"default": null
|
|
}
|
|
},
|
|
"required": [
|
|
"hookEventName"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"PreToolUsePermissionDecisionWire": {
|
|
"enum": [
|
|
"allow",
|
|
"deny",
|
|
"ask"
|
|
],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"continue": {
|
|
"default": true,
|
|
"type": "boolean"
|
|
},
|
|
"decision": {
|
|
"allOf": [
|
|
{
|
|
"$ref": "#/definitions/PreToolUseDecisionWire"
|
|
}
|
|
],
|
|
"default": null
|
|
},
|
|
"hookSpecificOutput": {
|
|
"allOf": [
|
|
{
|
|
"$ref": "#/definitions/PreToolUseHookSpecificOutputWire"
|
|
}
|
|
],
|
|
"default": null
|
|
},
|
|
"reason": {
|
|
"default": null,
|
|
"type": "string"
|
|
},
|
|
"stopReason": {
|
|
"default": null,
|
|
"type": "string"
|
|
},
|
|
"suppressOutput": {
|
|
"default": false,
|
|
"type": "boolean"
|
|
},
|
|
"systemMessage": {
|
|
"default": null,
|
|
"type": "string"
|
|
}
|
|
},
|
|
"title": "pre-tool-use.command.output",
|
|
"type": "object"
|
|
} |