fix: permission mode switching not detected by remote session#1402
Open
zz327455573 wants to merge 1 commit into
Open
fix: permission mode switching not detected by remote session#1402zz327455573 wants to merge 1 commit into
zz327455573 wants to merge 1 commit into
Conversation
When switching permission modes (e.g. default → bypassPermissions) in the mobile app, the Claude remote session failed to detect the change because: 1. The MessageQueue2 hash function used `isPlan: mode.permissionMode === 'plan'` instead of `permissionMode: mode.permissionMode`. This made all non-plan modes produce identical hashes, so the nextMessage callback never detected a mode change. 2. PermissionHandler.handleModeChange() only updated internal state but never called the SDK's setPermissionMode() callback, so the running Claude query kept the old permission mode. Fix by: - Including the full permissionMode string in the hash object - Calling setPermissionModeCallback in handleModeChange to propagate mode changes to the active SDK query Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
DanielBiondi
pushed a commit
to DanielBiondi/happy
that referenced
this pull request
Jun 18, 2026
…s; eliminate silent message loss Cherry-picks slopus#1402, slopus#1157, slopus#1299 plus a broader ambient-default guard. With v1 we made 'auto' / 'dontAsk' acceptable; this makes them actually take effect. - runClaude.ts (slopus#1402): hash on full permissionMode, not just isPlan -- the old hash collapsed every non-plan mode to the same value, so default->auto was invisible to nextMessage. - permissionHandler.ts (slopus#1402 + slopus#1157): handleModeChange normalizes via mapToClaudeMode and propagates to the active SDK query via the setPermissionModeCallback. Without this, switching modes mid-session updated local state but the SDK never knew. - permissionMode.ts (broader slopus#1235): protect ANY explicit non-default mode from the ambient 'default' the mobile app sends with every message. - reducer.ts (slopus#1299): crypto.randomUUID instead of ~67-bit Math.random IDs to prevent birthday-paradox collisions silently overwriting messages.
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.
Problem
Switching permission modes (default → bypassPermissions/yolo) in the mobile app has no effect on the active Claude remote session. The session continues using the old permission mode, making mode switching appear "stuck".
Root Cause
Two bugs in the permission mode change detection pipeline:
Bug 1: Hash function doesn't capture permission mode changes
In
runClaude.ts, theMessageQueue2hash function uses:This reduces all non-plan modes to
isPlan: false, producing identical hashes. WhennextMessagecompares the incoming message's hash with the current mode hash, it never detects a change betweendefault,acceptEdits,bypassPermissions, etc.Bug 2: handleModeChange doesn't propagate to SDK
PermissionHandler.handleModeChange()only updates its internalpermissionModefield but never calls thesetPermissionModeCallbackthat propagates the change to the active Claude SDK query viaq.setPermissionMode().Fix
Replace
isPlan: mode.permissionMode === 'plan'withpermissionMode: mode.permissionModein the hash function — mode changes now produce different hashes, triggering thenextMessagemode-change detection path.Call
setPermissionModeCallbackinhandleModeChange()— the active SDK query immediately picks up the new permission mode.Testing
Verified on a live server: after applying these fixes, switching to YOLO mode in the mobile app correctly changes the Claude session's permission mode (confirmed by
--permission-mode planin the spawned process args and successful auto-approval of tool calls).