fix(desktop): Full Access by default, matching the CLI (tools no longer time out) - #819
Merged
Merged
Conversation
…er time out) Every Write/Bash in the desktop app raised a permission prompt the user never saw, then failed with "permission request timed out" — six Write attempts and two Bash in one turn, so the agent gave up and pasted the file contents into chat instead of creating them. Cause: `clawcodex serve` hardcoded permission_mode="default" and flags-only bypass availability. But the interactive entrypoints (src/cli.py and tui_launcher) both resolve through resolve_interactive_permission_state, whose floor is bypassPermissions — the documented "Full Access by default". The desktop is the same kind of surface (a real user at the window, its own loopback + token-gated child process), so it now uses that same resolver. That also inherits the guards which make the implicit floor safe: an operator `disableBypassPermissionsMode` lockdown and root-outside-sandbox both drop back to prompting, and a persisted `permissions.defaultMode` still wins. --permission-mode now defaults to None so the resolver's ladder applies instead of being pinned. Second bug, same area: the renderer's approval vocabulary is manual|smart|off and normalizeApprovalMode coerces anything unknown to "manual" — so sending the raw agent mode made even a Full Access session render as "ask every time". Added a mapping (bypassPermissions→off, auto→smart, everything else→manual) applied to every session.info, plus the `approvals.mode` config.get/config.set key the Safety panel and /approvals round-trip through (get returned the whole settings blob with no `value`, so the panel always showed manual; set had no handler at all). Verified against a real agent in a scratch workspace: - default: "build hello.py" → 0 approval prompts, file written, turn ok. - switch to manual via the Safety path → Write DOES prompt, approval.respond 'once' runs the tool, file written; config.get reads back "manual". 5 new pytest cases; 72 desktop tests green.
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.
The bug
Every Write/Bash in the desktop app raised a permission prompt the user never saw, then failed with "permission request timed out" — six Write attempts and two Bash in one turn, so the agent gave up and pasted the file contents into chat instead of creating them.
Cause
clawcodex servehardcodedpermission_mode="default"with flags-only bypass. But both interactive entrypoints (src/cli.py,tui_launcher.py) resolve throughresolve_interactive_permission_state, whose floor isbypassPermissions— the documented "Full Access by default". The desktop is the same kind of surface (a real user at the window; its own loopback, token-gated child process), so it now uses that same resolver.That also inherits the guards that make the implicit floor safe: an operator
disableBypassPermissionsModelockdown and root-outside-sandbox both drop back to prompting, and a persistedpermissions.defaultModestill wins.--permission-modenow defaults toNoneso the ladder applies instead of being pinned.Second bug, same area
The renderer's approval vocabulary is
manual|smart|off, andnormalizeApprovalModecoerces anything unknown to "manual" — so even a Full Access session rendered as "ask every time". Added the mapping (bypassPermissions→off,auto→smart, elsemanual) on everysession.info, plus theapprovals.modekey the Safety panel and/approvalsround-trip through (config.getreturned the whole settings blob with novalue, so the panel always showed manual;config.sethad no handler at all).Verified against a real agent (scratch workspace)
approval.respond 'once'runs the tool; file written;config.getreads backmanual5 new pytest cases; 72 desktop tests green.
🤖 Generated with Claude Code