[BUG] Remote Control (mobile): one slash command renders as two identical user pills; "Computing..." spinner never clears after a local command with no model turn
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (closest is #68252, which covers commands routing to the model as plain text; this report is about duplicate rendering + a stuck spinner for a command that DID execute correctly)
- [x] This is a single bug report (two symptoms, one root event, evidence shared)
- [x] I am using the latest version of Claude Code
What's Wrong?
Driving a local CLI session via Remote Control from the Claude mobile app (iOS): typing /compact ONCE in the app renders two identical right-aligned "/compact" user pills, and after the command completes, the "Computing..." spinner never stops until the next real message is sent (~11.5 minutes in my case).
<img src="https://cdn.hwpark.net/s/files/gh-issue-rc-compact-double-pill.png" width="450" alt="Two identical /compact pills followed by a persistent Computing... spinner" />
The command itself executed exactly once and correctly (compaction ran, preTokens=399439 -> postTokens=36502). Both symptoms are client-side rendering/state issues, not double delivery. I verified this against the session JSONL:
Symptom 1: duplicate pills. The session transcript (~/.claude/projects/<dir>/<uuid>.jsonl) shows a queue-routed local slash command persists four user-type records:
- a plain-text
/compactuser record, materialized from the message queue right after dequeue (isMetaabsent) - the
<local-command-caveat>wrapper (isMeta: true) - the
<command-name>/compact</command-name>tag block (isMetaabsent) - the
<local-command-stdout>result block
Records 1 and 3 are both role: user, both isMeta-falsy, and both canonically display as exactly /compact. The terminal UI merges these into a single > /compact line, but the mobile Remote Control renderer apparently renders both without dedup, producing the two identical pills. (The caveat record is hidden, consistent with an isMeta filter.)
Supporting data from my transcript: every queue-routed /compact since 2026-07 shows a strict 1:1:1 correspondence of queue-operation enqueue : plain-text record : command-name record (43 of 43). Commands typed directly in an idle terminal produce only 3 records (no queue materialization, no enqueue) and do not double-render. Delivery was single: exactly one enqueue (dequeued 43 ms later), and one active bridge session at the time, so this is not an echo/double-send.
Symptom 2: stuck spinner. A manual /compact triggers no assistant turn at all. After the compact_boundary record and the <local-command-stdout> record were written (4 m 35 s after enqueue), the CLI sat idle at the prompt with zero further records, yet the app kept showing "Computing..." for ~7 more minutes until I sent the next message. The client appears to only end its "working" state on a visible assistant turn, and never treats local-command completion (stdout record, no model turn) as end-of-turn.
What Should Happen?
- One slash command typed in the mobile app should render as one user pill (dedup the queue-materialized plain-text record against the
<command-name>record, as the terminal renderer effectively does). - When a local command completes without producing a model turn, the app should clear the "Computing..." spinner (and ideally surface the command's stdout, e.g. the compaction confirmation).
Steps to Reproduce
- Start a local interactive session, enable Remote Control, connect from the Claude iOS app.
- With the session idle, type
/compact(or, expected, any local slash command, since the 4-record persistence is command-agnostic) in the app and send. - Observe two identical
/compactpills. - Wait for compaction to finish; observe the "Computing..." spinner persisting indefinitely until the next message is sent.
Error Messages/Logs
Session JSONL sequence for the event (UTC, sanitized):
20:19:22.835 queue-operation enqueue content="/compact"
20:19:22.878 queue-operation dequeue (+43 ms)
20:19:22.920 user "/compact" (plain text, queue materialization)
20:19:22.954 user <local-command-caveat>… isMeta=true
20:19:22.954 user <command-name>/compact</command-name>…
20:23:57.519 system compact_boundary preTokens=399439 postTokens=36502 trigger=manual
20:23:57.617 user <local-command-stdout>…
-- no further records; CLI idle; app spinner still "Computing..." --
20:31:01.411 (next real user message)
Claude Model
Sonnet 5 (claude-sonnet-5[1m])
Is this a regression?
Unknown. The 4-record persistence format predates this observation; the mobile rendering gap may have existed all along.
Last Working Version
_No response_
Claude Code Version
2.1.239 (host CLI); Claude iOS app current as of 2026-08-23
Platform
claude.ai subscription (Max)
Operating System
Host: Ubuntu Linux (6.8.0). Client: iOS (Claude app, Remote Control)
Terminal/Shell
bash + tmux (tmux verified irrelevant: Remote Control transport is the relay bridge, and the transcript shows single delivery)
Additional Information
Related but distinct: #68252 (slash commands intermittently routing to the model as plain text; false-positive toasts). In this report the command DID execute; the defects are duplicate rendering and turn-completion detection.
Predictions that would confirm the mechanism, if useful for triage: a plain text message from mobile should render one pill (single user record); any queue-routed slash command should render two; a slash command typed directly in the idle terminal should render one in the app's mirror (3-record path, no queue materialization).