[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

Status Open
Reported on v2.1.239
Maintainer reply None cached
Activity 0 comments · opened Aug 22, 2026

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:

  1. a plain-text /compact user record, materialized from the message queue right after dequeue (isMeta absent)
  2. the <local-command-caveat> wrapper (isMeta: true)
  3. the <command-name>/compact</command-name> tag block (isMeta absent)
  4. 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?

  1. 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).
  2. 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

  1. Start a local interactive session, enable Remote Control, connect from the Claude iOS app.
  2. 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.
  3. Observe two identical /compact pills.
  4. 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).

View original on GitHub ↗