Skip to content

fix(claude): make "Always allow for session" stick, and only for the session - #5041

Merged
juliusmarminge merged 1 commit into
pingdotgg:mainfrom
kakismash:fix/claude-accept-for-session
Aug 15, 2026
Merged

fix(claude): make "Always allow for session" stick, and only for the session#5041
juliusmarminge merged 1 commit into
pingdotgg:mainfrom
kakismash:fix/claude-accept-for-session

Conversation

@kakismash

@kakismash kakismash commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

What changed

For the Claude provider, an acceptForSession decision in canUseToolEffect no longer echoes Claude Code's permission suggestions verbatim. A small normalizer (toSessionPermissionUpdates) now:

  1. rescopes any received suggestions to destination: "session", and
  2. synthesizes a whole-tool session allow rule ({ type: "addRules", rules: [{ toolName }], behavior: "allow", destination: "session" }) when Claude Code offered no suggestions at all.

Why it should exist

Fixes #4512. T3 keeps no session-permission state of its own for Claude — "Always allow this session" worked only if Claude Code happened to attach usable suggestions to the prompt. That breaks in both directions:

  • MCP tools re-prompt forever. Claude Code sends empty or absent suggestions for MCP tools in several cases (tools flagged requiresUserInteraction, server-configured ask levels, ask-rule matches). The echo then produced no updatedPermissions, so acceptForSession silently degraded into a one-shot accept and the same tool prompted again on the next call — the exact behavior reported in [Bug]: "Always allow for session" permission is ignored for MCP tool calls (Repeatedly prompts for the same tools) #4512. Built-in tools always carry suggestions, which is why only MCP tools were affected. (The old guard also treated suggestions: [] as truthy, echoing an empty no-op array.)
  • "This session" was persisted to disk. When suggestions were present they carried destination: "localSettings", so echoing them made Claude Code write a permanent allow rule into the workspace's .claude/settings.local.json — a session-scoped consent becoming durable state without the user asking for it.

The synthesized rule uses the fully qualified tool name (e.g. mcp__server__tool), which is the exact rule shape Claude Code's own matcher generates, so subsequent calls match natively. Other providers are unaffected (they map acceptForSession to their agent's native always-allow option).

No UI change.

Testing

  • New test drives two acceptForSession round-trips through canUseTool: an MCP tool with empty suggestions (asserts the synthesized session rule) and a Bash call with a localSettings suggestion (asserts it is rescoped to session, preserving ruleContent)
  • ClaudeAdapter.test.ts: 63 tests pass; typecheck clean

🤖 Generated with Claude Code


Note

Medium Risk
Touches Claude approval/permission handling in canUseTool, which affects tool execution consent and what rules Claude Code stores; scope is limited to the Claude adapter and is covered by new tests.

Overview
Fixes Claude "Always allow for session" so it actually applies session-only rules instead of echoing Claude Code's permission suggestions verbatim.

canUseTool now routes acceptForSession through toSessionPermissionUpdates, which rescopes any SDK suggestions to destination: "session" (avoiding writes to localSettings / .claude/settings.local.json) and, when suggestions are missing or empty—typical for MCP tools—synthesizes a whole-tool session allow rule so the choice persists for the session rather than behaving like a one-shot accept.

A new test covers MCP tools with empty suggestions and Bash with localSettings suggestions, asserting the returned updatedPermissions shape.

Reviewed by Cursor Bugbot for commit 48e6245. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix 'Always allow for session' to scope permission updates to the current session only

  • In ClaudeAdapter, the acceptForSession decision now calls a new toSessionPermissionUpdates helper instead of spreading pendingApproval.suggestions directly.
  • toSessionPermissionUpdates forces destination: 'session' on all suggestions, and when no suggestions exist (e.g. MCP tools), returns a fallback addRules allow entry scoped to the session.
  • Previously, session-accept could either use wrong destination scoping from suggestions or produce no permission update at all for suggestion-less tools.

Macroscope summarized 48e6245.

…ssion

acceptForSession echoed Claude Code's permission suggestions verbatim as
updatedPermissions. That breaks in both directions:

- MCP tools frequently arrive with empty or absent suggestions, so the
  echo produced nothing and the decision silently degraded into a
  one-shot accept - the same tool prompted again on every call (pingdotgg#4512).
- When suggestions were present they carried destination localSettings,
  so a session-only choice was persisted to .claude/settings.local.json
  as a permanent allow rule.

Rescope received suggestions to destination session, and synthesize a
whole-tool session allow rule when Claude Code offered none. The rule
uses the fully qualified tool name (e.g. mcp__server__tool), which is
exactly what Claude Code's own rule matcher expects.

Fixes pingdotgg#4512

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 45dec02e-4d5c-4534-bf4e-57b12579aa3a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Jul 30, 2026
@macroscopeapp

macroscopeapp Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 48e6245

This is a targeted bug fix ensuring session-scoped tool permissions actually persist for the session and don't accidentally get written to disk. The change is limited to adding a simple helper function and includes thorough test coverage.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge
juliusmarminge enabled auto-merge (squash) August 15, 2026 10:43
@juliusmarminge
juliusmarminge merged commit e9e4697 into pingdotgg:main Aug 15, 2026
15 of 16 checks passed
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Aug 15, 2026
## What's Changed
* fix(desktop): app zoom no longer zooms the preview browser by @juliusmarminge in pingdotgg/t3code#6649
* fix(server): keep provider notification consumers alive past startSession by @tsouth89 in pingdotgg/t3code#6538
* fix(server): treat removed Bitbucket permissions endpoint as unknown, not blocking by @lnieuwenhuis in pingdotgg/t3code#6525
* fix(ssh): let cold remote servers finish starting by @gbarros-dev in pingdotgg/t3code#6168
* fix(web): preserve Claude insight line breaks by @nateEc in pingdotgg/t3code#4344
* feat(web): accept file drops across the chat workspace by @dbalders in pingdotgg/t3code#6636
* fix(web): widen ordered-list marker gutter for 3+ digit item numbers by @lnieuwenhuis in pingdotgg/t3code#6527
* fix(server): bound thread activity hydration by @t3-code[bot] in pingdotgg/t3code#6153
* fix(web): restore the Archive action in the default sidebar thread menu by @lnieuwenhuis in pingdotgg/t3code#6526
* fix(web): open diff files from nested projects by @gbarros-dev in pingdotgg/t3code#6174
* fix(mobile): use tryOpenExternalUrl for markdown links in ThreadFeed by @mohamedmastouri-hue in pingdotgg/t3code#5872
* fix(web): open the file a bare filename reference names by @Brechard in pingdotgg/t3code#6297
* fix(server): stop the provider title mirror from overwriting real thread titles by @repparw in pingdotgg/t3code#5941
* fix(shared): match source-control providers by DNS label by @gbarros-dev in pingdotgg/t3code#6175
* feat(desktop): Chrome-style hold-to-quit by @Bil0000 in pingdotgg/t3code#5508
* fix(gitlab): submit review comments on context lines by @tarik02 in pingdotgg/t3code#6348
* fix(marketing): keep Grok mark clear of mobile hero copy by @NicL9923 in pingdotgg/t3code#4542
* fix(mobile): recover the QR pairing scanner when camera access is denied by @hey-jj in pingdotgg/t3code#6487
* fix(web): keep a long path from running under the folder picker button by @Sy-D in pingdotgg/t3code#4823
* fix(terminal): right-click paste works in the terminal by @StiensWout in pingdotgg/t3code#5240
* fix(mobile): explain iOS-only settings on Android by @danvernon in pingdotgg/t3code#4981
* fix(web): stop counting a workflow coordinator as a working agent by @Rishet11 in pingdotgg/t3code#6672
* fix(web): keep floating preview anchored after panel closes by @AksharP5 in pingdotgg/t3code#6547
* fix(web): unstick /connect after in-modal sign-in by redirecting to the authorize endpoint by @TorbenWetter in pingdotgg/t3code#5133
* fix(web): keep send reachable while a turn is running on mobile by @AMohamedAakhil in pingdotgg/t3code#4781
* fix(web): reject unsupported composer image types at attach time by @mdshzb04 in pingdotgg/t3code#6574
* Make ClaudeTextGeneration tests hermetic on Windows by @mihneaptu in pingdotgg/t3code#4508
* fix(web): show command output in work log by @LikoKiko in pingdotgg/t3code#4083
* fix(web): reserve sibling column width when resizing the right panel by @Lasdw6 in pingdotgg/t3code#6279
* fix(web): replace whitespace in new ref names with dashes by @jorj-pineda in pingdotgg/t3code#6270
* fix(client-runtime): branch list no longer resets while paging through refs by @a20hek in pingdotgg/t3code#5858
* fix(web): support Shift+Insert terminal paste by @aoright in pingdotgg/t3code#5982
* fix(web): keep the composer glass aligned with the context strip at any interface font size by @Williawar in pingdotgg/t3code#5703
* fix(codex): keep background memory out of chats by @AksharP5 in pingdotgg/t3code#5468
* fix(server): treat a missing Codex rollout as a recoverable resume error by @Rishet11 in pingdotgg/t3code#6671
* fix(web): hide provider Update toast action while an update is running by @mrmg in pingdotgg/t3code#6544
* fix(desktop): agent shells inherit a UTF-8 locale on macOS by @Linus-Boehm in pingdotgg/t3code#6236
* fix(server): ignore Claude command lifecycle messages by @naveed949 in pingdotgg/t3code#6606
* docs: mention Bitbucket user read scope needed by auth probe by @thamrx in pingdotgg/t3code#6291
* fix(server): return valid preview action results by @duncan-vc in pingdotgg/t3code#5966
* fix(claude): make "Always allow for session" stick, and only for the session by @kakismash in pingdotgg/t3code#5041
* fix(ssh): surface a failed remote t3 install instead of a silent 0-byte server.log by @TorbenWetter in pingdotgg/t3code#5132
* perf(server): persist the wire projection for streaming tool.updated data by @mInrOz in pingdotgg/t3code#6675
* fix(web): stop wrapping partial code block selections in markdown fences by @JoeJoeflyn in pingdotgg/t3code#5069
* fix(web): hide T3 Connect toggle in web app settings by @JoeJoeflyn in pingdotgg/t3code#5068
* fix(web): show provider account accent badge in sidebar rows and hover card by @vitalyiegorov in pingdotgg/t3code#5980
* fix(server): wait for concurrent SQLite writers instead of failing with SQLITE_BUSY by @ostapondo in pingdotgg/t3code#5134
* fix(web): reject oversized prompts before provider turn start by @naveed949 in pingdotgg/t3code#6602
* feat(web): collapse the question prompt from its header by @Jardo-51 in pingdotgg/t3code#6773
* fix(shared): degrade an unknown system time zone to UTC in usage windows by @Rishet11 in pingdotgg/t3code#6670
* fix(claude): discover repo-local .agents/skills in skill discovery by @RoshanMhatre in pingdotgg/t3code#5488
* fix(server): let slow provider CLIs raise their discovery probe budget by @CDVolvik in pingdotgg/t3code#6223
* fix(web): retain terminal PR badges after checkout switch by @sebbonit in pingdotgg/t3code#4755
* fix(web): show selected model in context window tooltip by @nqrwhal in pingdotgg/t3code#4772
* fix(web): scale command details with code font by @Serendeep in pingdotgg/t3code#6510
* fix(web): preserve XML-like tags in user messages by @0utsights in pingdotgg/t3code#4133

## New Contributors
* @mohamedmastouri-hue made their first contribution in pingdotgg/t3code#5872
* @NicL9923 made their first contribution in pingdotgg/t3code#4542
* @hey-jj made their first contribution in pingdotgg/t3code#6487
* @danvernon made their first contribution in pingdotgg/t3code#4981
* @Rishet11 made their first contribution in pingdotgg/t3code#6672
* @AksharP5 made their first contribution in pingdotgg/t3code#6547
* @TorbenWetter made their first contribution in pingdotgg/t3code#5133
* @AMohamedAakhil made their first contribution in pingdotgg/t3code#4781
* @mdshzb04 made their first contribution in pingdotgg/t3code#6574
* @mihneaptu made their first contribution in pingdotgg/t3code#4508
* @LikoKiko made their first contribution in pingdotgg/t3code#4083
* @Lasdw6 made their first contribution in pingdotgg/t3code#6279
* @jorj-pineda made their first contribution in pingdotgg/t3code#6270
* @a20hek made their first contribution in pingdotgg/t3code#5858
* @aoright made their first contribution in pingdotgg/t3code#5982
* @Williawar made their first contribution in pingdotgg/t3code#5703
* @mrmg made their first contribution in pingdotgg/t3code#6544
* @Linus-Boehm made their first contribution in pingdotgg/t3code#6236
* @naveed949 made their first contribution in pingdotgg/t3code#6606
* @thamrx made their first contribution in pingdotgg/t3code#6291
* @duncan-vc made their first contribution in pingdotgg/t3code#5966
* @kakismash made their first contribution in pingdotgg/t3code#5041
* @mInrOz made their first contribution in pingdotgg/t3code#6675
* @JoeJoeflyn made their first contribution in pingdotgg/t3code#5069
* @vitalyiegorov made their first contribution in pingdotgg/t3code#5980
* @ostapondo made their first contribution in pingdotgg/t3code#5134
* @Jardo-51 made their first contribution in pingdotgg/t3code#6773
* @RoshanMhatre made their first contribution in pingdotgg/t3code#5488
* @CDVolvik made their first contribution in pingdotgg/t3code#6223
* @sebbonit made their first contribution in pingdotgg/t3code#4755
* @nqrwhal made their first contribution in pingdotgg/t3code#4772
* @Serendeep made their first contribution in pingdotgg/t3code#6510
* @0utsights made their first contribution in pingdotgg/t3code#4133

**Full Changelog**: pingdotgg/t3code@v0.0.34-nightly.20260815.1100...v0.0.34-nightly.20260815.1101

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.34-nightly.20260815.1101
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: "Always allow for session" permission is ignored for MCP tool calls (Repeatedly prompts for the same tools)

2 participants