Skip to content

feat(claude): Reflect Claude’s autonomous plan transitions to the UI#1452

Open
AbdulelahHajjar wants to merge 1 commit intopingdotgg:mainfrom
AbdulelahHajjar:feat/reflect-claude-auto-initiated-plan-mode-ui
Open

feat(claude): Reflect Claude’s autonomous plan transitions to the UI#1452
AbdulelahHajjar wants to merge 1 commit intopingdotgg:mainfrom
AbdulelahHajjar:feat/reflect-claude-auto-initiated-plan-mode-ui

Conversation

@AbdulelahHajjar
Copy link
Copy Markdown
Contributor

@AbdulelahHajjar AbdulelahHajjar commented Mar 26, 2026

What Changed

  • Added interaction.mode.changed runtime event to the shared contracts layer (ProviderRuntimeEvent)
  • Claude adapter now detects EnterPlanMode and ExitPlanMode tool calls in stream events (content_block_start) and emits interaction.mode.changed to propagate the mode transition
  • Orchestration ingestion layer handles the new event and dispatches thread.interaction-mode.set to update the thread's read model, which the UI observes
  • Added 4 tests: 2 in ClaudeAdapter (emit on enter/exit) and 2 in ProviderRuntimeIngestion (dispatch on change, dedup on same mode)

Why

When the Claude agent autonomously decides to enter plan mode (i.e., the agent calls EnterPlanMode on its own without the user toggling it from the UI), the T3 Code UI didn't reflect the mode change. The user would remain in "default" mode visually while the agent was already operating in plan mode internally.

Approach and Certain Trade-off's I faced

1- Manual tool mapping required. Due to the Claude SDK only exposing setPermissionMode() with no getter, we detect mode changes by intercepting tool names in stream events. If Claude adds new interaction modes in the future, the mapping in interactionModeForTool() must be updated manually.

2- Codex does not support this behavior. I realized that Codex has no mechanism for the agent to autonomously enter plan mode from a message, therefore, I intended to keep this PR as Claude-only for now.

UI Changes

Before

CleanShot.2026-03-27.at.01.21.37.mp4

Notice "Chat" incorrectly persisted despite Claude entering plan mode.

After

CleanShot.2026-03-27.at.01.29.28.mp4

Notice "Chat => Plan" transition upon Claude entering plan mode.
... and "Plan => Chat" transition upon Claude exiting plan mode.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included a video for animation/interaction changes

Note

Medium Risk
Introduces a new cross-layer runtime event and updates orchestration ingestion to mutate thread interaction mode, which could affect UI state for all providers if mis-emitted or mis-handled. Scope is contained and covered by new adapter/ingestion tests, lowering regression risk.

Overview
Adds a new runtime event interaction.mode.changed to shared provider-runtime contracts, carrying the current interactionMode.

Updates the Claude provider adapter to detect EnterPlanMode/ExitPlanMode tool-use starts in the stream and emit interaction.mode.changed accordingly.

Extends ProviderRuntimeIngestion to translate interaction.mode.changed into a thread.interaction-mode.set command only when the mode differs, with tests covering both mode updates and deduping duplicate mode events.

Written by Cursor Bugbot for commit e21c2d7. This will update automatically on new commits. Configure here.

Note

[!NOTE]

Reflect Claude's autonomous plan mode transitions to thread interaction mode

  • Adds EnterPlanMode and ExitPlanMode tool-use detection in ClaudeAdapter.ts, emitting interaction.mode.changed runtime events with the corresponding mode (plan or default).
  • Adds a new interaction.mode.changed handler in ProviderRuntimeIngestion.ts that dispatches a thread.interaction-mode.set command when the incoming mode differs from the thread's current mode.
  • Extends the ProviderRuntimeEventV2 union in providerRuntime.ts with the new interaction.mode.changed event type and its interactionMode payload.

Macroscope summarized e21c2d7.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 26, 2026

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

Run ID: 5b0607eb-d693-4864-af18-0a69b754ea25

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@github-actions github-actions bot added size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 26, 2026
@AbdulelahHajjar AbdulelahHajjar changed the title feat(claude): Reflect Claude’s autonomous plan mode transitions to th… feat(claude): Reflect Claude’s autonomous plan transitions to the UI Mar 26, 2026
…e UI

Signed-off-by: Abdulelah Hajjar <aab.hajjar@gmail.com>
@AbdulelahHajjar AbdulelahHajjar force-pushed the feat/reflect-claude-auto-initiated-plan-mode-ui branch from 3db4f34 to e21c2d7 Compare March 26, 2026 22:27
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.

1 participant