Conversation
Add an `ask-always` access preset ("Ask every time") that sends
`approvalPolicy: "untrusted"` with the user as reviewer and the same
workspace-write sandbox as `workspace-write` (no network). Every command
and every file change, including plain reads, then reaches
`session/request_permission`.
The mode is not the default and the existing presets are unchanged.
karki011
marked this pull request as ready for review
September 27, 2026 15:15
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #555
Summary
Adds a fifth access preset, Ask every time (
ask-always). It uses the same sandbox asworkspace-write(workspace writable, no network), but sendsapprovalPolicy: "untrusted"with the user as reviewer. Every command and every file change then reachessession/request_permission, including reads such aslsorcat .env, which every other mode runs unasked.Motivation
Clients that mediate every agent action through their own policy (audit trails, allow lists, secret-file rules) need a mode in which nothing runs unasked. #480 made the presets honest about what they allow; this adds the strict end of the range without changing the existing four modes or the default.
untrustedis the app-server'sAskForApprovalvalue for Codex's untrusted-project policy ("Commands require approval unless an explicit exec policy rule allows them"). Codex retired it as a config.toml or CLI setting in 0.149 (openai/codex#39630), but it is still part of the app-server v2 protocol in 0.157, andturn/startaccepts it.Evidence from a raw ACP client (fresh session per action, requests answered
allow_once):on-requestuntrustedworkspace-writeask-alwayslscat README.mdcat .envapply_patchin the workspaceallow_onceecho hi > shell.txtallow_onceThe
untrustedcolumn was also reconfirmed on 1.13.2-preview.5 / Codex 0.157.1. The issue has the full table.The change
src/AgentMode.ts: newAgentMode.AskAlways("ask-always", "Ask every time", kindstandard, approval policyuntrusted, revieweruser, aworkspaceWritesandbox identical toWorkspaceWrite, sandbox modeworkspace-write).AgentMode.all()lists it last, afterAgentFullAccess, so existing mode positions don't change.workspace-write, through the existingaddAdditionalDirectoriesToSandboxPolicy.README.mdandreadme-dev.md:INITIAL_AGENT_MODElistsask-always.DEFAULT_AGENT_MODE, toCodexAcpClient.sendPrompt(it already sends the mode's policies on everyturn/start), or to/status, which printsApproval: untrusted.Tests
session-config-options.test.ts:ask-alwaysadded to the expectedmodeconfig options andavailableModes, and seven rows added to theapplies $modeId permissions after $selection from $initialModematrix (selection throughINITIAL_AGENT_MODE,session/set_modeandsession/set_config_option, into and out ofask-always). The new snapshotdata/ask-always-mode-policy.jsonpins the outgoingturn/startpolicies:untrusted,user, andworkspaceWritewith the extra root writable and no network.RUN_E2E_TESTS=true), newask-alwayssuites:catof a workspace file requests permission; an in-workspace write requests permission and is applied afterallow_once; a cancelled request leaves the file unwritten.allow_once; a cancelled request leaves the file unwritten.Local results:
npm run typecheckCI=true npm test: 60 files passed, 786 tests passed, 37 skipped (the e2e suites)npm run buildnpm run bundle:all: not run locally (no bun installed); the change adds no dependencies or build inputsnpm run test:e2e: not run (needs an OpenAI API key); the manual probe above covers the same casesCompatibility
availableModesor themodeconfig option show it automatically; clients that hard-code the four ids are unaffected. It is appended at the end of the list, so clients that pick modes by index are unaffected.approvalPolicy: "untrusted"onturn/start. If a later Codex removes it,turn/startwould fail in this mode only, and the snapshot plus the e2e cases would flag it on the nextcodex-updatePR. The issue discusses the alternative (not marking session roots trusted).untrusted, Codex offerscancelas the only reject option, so rejecting ends the turn. The PR for Rejecting a command or file edit can only end the turn when Codex doesn't offerdecline#556 adds an opt-in continue-on-reject option. The two PRs are independent and merge cleanly in either order.🤖 Generated with Claude Code