native-approvals · git:20261031.ffaeccb · 2026-10-31 · sha256 f247c9eff3ab05d7

native-approvals git:20261031.ffaeccbA

Immutable. This exact content never changes and is served at /api/v1/blob/f247c9eff3ab05d7.

---
name: native-approvals
description: Maintain native CLI request identity, owned transports, and approval cards without reopening screen-derived PTY approvals.
---

# Native approvals

Read `electron/features/terminal/native-{approvals,protocol,questions,session,ipc}.cjs`, `NativeApprovalCard.tsx`, `NativeQuestionCard.tsx`, and `ManagedSession.tsx` before changing native request behavior. `agent:launch` with mode `native` binds a fresh terminal generation directly to its owned provider transport. Codex uses its real remote TUI; Claude is explicitly SDK-managed. Legacy/SSH permissions stay terminal-only.

Keep CLI-issued IDs typed and unchanged; tokens are renderer capabilities only. Never correlate hooks, screen text, events or epochs with a native request. Never add approval PTY writes or automatic response retries. Preserve tool input, provider/project/terminal/generation bindings, cancellation, tombstones, bounds and TUI/host arbitration. Never inject blanket PreToolUse allow hooks.

Questions share that registry and lifecycle, but use `terminal:native-question` / `answerNativeQuestion` with `{ token, decision: 'submit', values }` or `{ token, decision: 'decline' | 'cancel' }`. Approval tokens cannot be answered through the question endpoint, or conversely. Validate exact keys, every field's type, required presence, enum membership and declared constraints in main before consuming the capability. Only explicitly enabled free text is allowed (Codex `isOther`, or Claude AskUserQuestion's CLI-declared automatic Other). Preserve original Claude tool input except for the validated `answers` field. Never put user input into a command, URL or tool definition. Cards use native form controls and never focus themselves when they appear.

Establish Codex request shapes from the installed CLI's `app-server generate-json-schema --experimental --out <isolated-dir>` output with a fresh `CODEX_HOME`, not guessed method names. Codex 0.166.0 emits `item/tool/requestUserInput` (answer map; cancellation sends an empty answer map) and `mcpServer/elicitation/request` (accept/decline/cancel). Support flat MCP forms only when every schema keyword is understood; reject additional/unknown fields and validate string formats, numeric bounds, titled/untitled enums and multi-select limits. Unsupported modes/schemas remain in the real Codex TUI. Claude's `can_use_tool` AskUserQuestion uses `updatedInput.answers` keyed by question text; multi-select answers are joined as the CLI expects. Claude `elicitation` uses `action` and optional `content` in the control response. Unknown managed Claude forms/modes show an explanation and native decline/cancel only; there is no operable TUI fallback.

Run `node --test tests/native-approvals.test.cjs tests/native-approval-ui.test.cjs tests/native-questions.test.cjs tests/native-question-ui.test.cjs tests/native-approval-probe.test.cjs tests/approval-aba.test.cjs tests/agent-permissions.test.cjs tests/agent-launch.test.cjs tests/reading-ui.test.cjs` and `npx tsc --noEmit`. Use harmless Node subprocess fixtures; describe them as synthetic.

When executing the actual `startTerminal` function in a VM, test Windows/PowerShell, Linux/Bash and macOS/zsh explicitly rather than inheriting the host platform. Supply `app.getPreferredSystemLanguages` and the real `terminalLocale` with deterministic locale availability; assert the locale and integration options through the real shell environment helpers while retaining native provider, fresh generation and no-shell assertions.

The lead can run `node scripts/native-approval-probe.cjs codex --run-installed` and the equivalent `claude` command to test installed CLIs against `scripts/native-approval-model.cjs`, a local stand-in. Without `--run-installed` the probe does not execute any CLI. It resolves executables through `resolveCli`, creates fresh homes and an empty probe cwd, inherits only an environment allowlist, uses dummy local credentials, bounds timeouts and cleans up owned processes. It records installed versions and CLI-issued native IDs in `.test-output/native-approval-probe/<provider>-*/report.json`. Codex cancellation must be selected from the actual supported decisions (prefer `cancel`, then `decline`); Claude requests harmless creation of `native-proof.txt` inside probe cwd to trigger permission review, then denies it. Never replace that write with an automatically permitted echo. Inspect successful reports before claiming installed-CLI proof; unit/Node/VM fixtures are synthetic evidence only. Desktop checks remain the lead's responsibility, sequentially with isolated `AGENTRIX_DATA_DIR`; never use real account directories or sessions. Do not copy private prompts/auth into fixtures or documentation.

The Claude probe also accepts `--questions` (AskUserQuestion) or `--elicitation` (a local MCP form from `native-approval-mcp.cjs`). Both answer only synthetic local data; the MCP probe may approve only its exact harmless `mcp__native_probe__request_input` tool to reach the form. This is probe-only permission handling, never a production allow hook.