feat(chat): show why Claude asks for approval in Full access
HA
1h ago+606+606+012345678901234567890123456789-93-93-01234567890123456789
Links
- Before/after mock-up: https://app.superset.sh/page/approval-card-before-and-after-3mrko9 (an HTML copy of the card's styles, not a screenshot)
Summary
- The approval card now shows the reason Claude Code gives for a prompt, and says when it asked even though the chat is in Full access.
- The native
claude-codeharness now showsAskUserQuestionas a question form instead of a yes/no "Allow this tool call?" prompt. - The Full access mode description changes from "Never asks before acting" to "Rarely asks before acting".
Why / Context
Claude Code still asks before some actions in bypassPermissions mode (safety checks, ask rules). It sends a reason, but we dropped it, so a prompt in Full access looked like the mode had failed. The mode picker also promised it would never ask.
How It Works
- Protocol:
approvalRequestSchemagets an optionalreason. It is alooseObject, so released clients ignore it. - ACP (
claude-acp): claude-agent-acp sends the reason only to JetBrains AIR clients, at_meta.jetbrains.air.permission.description(prefixed withReason:). We already advertise AIR ininitialize, soairPermissionReason()reads it from there. codex-acp sends the same field without the prefix. - Native (
claude-code):canUseToolpassesdecisionReasonthrough, trimmed.AskUserQuestionnow becomes a form with one field per question plus a<id>_custom"Other" field, the same shape claude-agent-acp builds, soQuestionFormrenders it. Answers fold back into the tool input the way Claude Code'scall()reads them: multi-select picks are comma-joined and quoted, and text typed beside a single-select pick goes intoannotations[question].notes. Skip lets the tool run with no answers; cancel interrupts the turn. - Desktop: a new
SessionModeProvidergivesApprovalRowthe chat's mode. A newApprovalReasonbox shows the reason. In an unrestricted mode it adds the heading "Still asks in Full access mode", and falls back to a generic note when there is no reason. It shows only on pending option cards, never on forms or answered cards.
Manual QA Checklist
Not done yet: this was written in a cloud workspace that can't run Electron.
- Full access Claude chat: a prompt Claude still raises (for example a long
$(...)chain that sends a login code) shows the reason box with "Still asks in Full access mode" - "Ask for approval" mode: a prompt shows the reason without the heading, and looks the same as before when there is no reason
- Old
claude-codechat:AskUserQuestionrenders as a question form; picks, "Other" text and Skip all reach Claude - Mode picker shows "Rarely asks before acting" for Full access
- Answered and expired approval cards look the same as before
Testing
bun testinpackages/chat-runtime(506 pass, 2 skip),packages/chat(120),apps/desktopsrc/renderer/routes/_authenticated(2536),packages/host-servicesrc/chat-v3(100)- New tests: AIR reason parsing, ACP approval
reason, nativedecisionReason, nativeAskUserQuestionform round trip, answer folding (multi-select quoting, single-select notes) bunx tsc --noEmitinpackages/chat-runtimeandapps/desktopbunx biome check,bun run check:i18n(2 new strings plus the changed mode description, translated in all 17 locales)- Not run locally: the repo-wide
bun run typecheck/bun run lint/sherif; CI covers those.
Known Limitations
- claude-agent-acp's code calls the reason field temporary diagnostic text, so an adapter bump may change or drop it. The card then falls back to the generic note.
- Mobile (
ChatRowView) does not show the reason yet. - The note follows the chat's current mode, not the mode when Claude asked.
- Agents other than Claude that ask a question as an options prompt, rather than a form, still get the generic Full access note.
Summary by cubic
Shows the reason Claude Code gives when it asks for approval, so prompts in Full access no longer look like the mode failed. Claude Code still asks before some actions in bypassPermissions mode (safety checks, ask rules), and the card previously dropped the reason. The native claude-code harness now renders AskUserQuestion as a question form instead of a yes/no "Allow this tool call?" prompt.
- Approval items carry an optional
reason: the ACP adapter reads it from_meta.jetbrains.air.permission.description, and the native harness passesdecisionReasonthrough. - The desktop approval card shows the reason with a "Still asks in Full access mode" heading in unrestricted modes, or a generic note when no reason was sent.
- The Full access mode description now reads "Rarely asks before acting".
AskUserQuestionforms get one field per question plus an "Other" text field; answers fold back into the tool input, and Skip lets the tool run with no answers.
Summary by CodeRabbit
- New Features
- Approval prompts can now explain why an action needs permission, including prompts that remain in Full access mode.
- Claude’s question requests are presented as interactive forms, with submitted answers passed back to the agent.
- Updates
- Full access is now described as rarely asking before acting, rather than never asking. Approval guidance is available in supported languages.