Skip to content

Show running background shells above the composer - #112

Merged
eivindjonassen merged 1 commit into
mainfrom
feat/background-shells-chip
Nov 14, 2026
Merged

eivindjonassen merged 1 commit into
mainfrom
feat/background-shells-chip

Conversation

@eivindjonassen

Copy link
Copy Markdown
Member

Summary

Closes #89. On the phone there was no way to see that a background shell was still running, how long it had run, or what it printed, and no way to stop it.

  • Chip: the chip above the composer now counts running background shells next to subagents, with desktop's wording: "1 shell", "2 shells", "1 subagent · 1 shell". It hides when nothing runs. Shells come from transcript shell calls that started in the background (input.background or metadata.background) or were moved there, and recorded a metadata.shellID. GET /api/shell/{id} decides whether each one still runs. Foreground shells stay in the transcript, as on desktop and in the OpenCode iOS app.
  • Sheet: "Background work" lists Needs you, Subagents and Shells. Subagent rows still open the child session.
  • Shell page: a shell row opens a page inside the sheet. It shows the command (capped, scrollable), the run time, and the last 40 lines of live output with escape codes stripped. It says "No output yet" while the shell is empty. A confirmed Stop calls DELETE /api/shell/{id}. After the shell ends, Stop gives way to "Exited", "Exited with code N", "Timed out" or "Stopped", and the run time freezes. The page stays open until Back or until the sheet closes.
  • Back: the Back button, Android hardware back and the VoiceOver escape gesture all return to the list. An iOS swipe closes the sheet.
  • Uncertain states: when the connection is stale, or a status or output refresh fails, the page shows "Last known: Running" with a frozen timer and no Stop. The chip's spoken label then says "status unavailable", its count is dimmed, and its indicator stays still.
  • Screen readers:
    • The ticking run time sits outside every live region, so it is never re-read each second.
    • iOS announces when a shell ends and when a Stop fails.
    • Focus moves to the page heading on open, back to the row (or the next thing on the list) after Back, and to the end state after Stop.
    • Commands are read as one short line.
  • Transcript, matching the OpenCode iOS app:
    • A collapsed tool group reads "Used N tools", with no Running/Finished label and no chevron. Failures stay as a caption inside the button and in its spoken name.
    • Background subagent launches fold into that group. Blocking subagents keep their card.
    • The chip announces background subagent changes, so an expanded card does not announce them a second time.
    • Expanded shell rows set the command in monospace.
  • Motion: only the Working line and the chip animate. Subagent and shell glyphs elsewhere stay still (WorkingIndicator animated={false}).
  • Contract: adds removeOpenCodeShell to the adapter. The fake API now removes configured shells on DELETE, and later reads return not found.

Earlier revisions of this change were published as EAS Updates to preview (runtime 0.1.6). No changed file is a native fingerprint source. The final revision is published from this branch's commit.

Known limits:

  • Shells launched before the loaded transcript pages are not found until those pages load. This follows the issue's transcript-sourced contract.
  • When the last running item ends while the sheet is open, closing the sheet has no chip to return focus to.

Verification

  • pnpm check (1566 mobile tests, adapter tests, both Hermes exports)
  • pnpm native:doctor (18/18)
  • pnpm crap --threshold 30
  • Tests cover the changed behavior: which shells count, chip wording and uncertainty, the sheet sections, the shell page (output tail, empty and error text, Stop, Stop of an already-ended shell, end labels, frozen run time), Android back versus iOS swipe, stale and failed-refresh states, short spoken labels, folded background subagents, one announcement per change, and the quiet tool group.
  • Platform behavior is verified on the affected targets, or the gap is documented. On an iPhone the chip showed a running background shell and "Used N tools" groups. Still unverified on devices: VoiceOver and TalkBack focus moves, TalkBack speaking dock announcements on Android 16, the final revision's appearance, Android, and large text. The gap is recorded in docs/COMPATIBILITY.md.
  • No credentials, addresses, identifiers, user content, private paths, or deployment files are included.
  • Documentation and TODO.md reflect the resulting behavior.

Council review

Rounds: 4

Delegate Round 1 Round 2 Round 3 Round 4
Claude Opus 7/10 9/10 10/10 10/10
GPT Sol 7/10 9/10 9.5/10 10/10
Gemini 7/10 8/10 10/10 10/10

Two small fixes the reviewers suggested in round 4 were applied afterwards and not re-reviewed: background rows in the sheet have no Android live region, and the chip's count is dimmed when its status is uncertain.

The composer chip now counts running background shells next to
subagents, with desktop's wording ("1 shell", "1 subagent · 2 shells").
Shells come from transcript shell calls that started in, or moved to,
the background; the server's shell status decides whether each still
runs. Foreground shells stay in the transcript.

A shell row opens a page in the sheet with its command, run time, the
last 40 lines of output, and a confirmed Stop that removes the shell on
the server. Once it ends, Stop gives way to how it ended. Android back
returns to the list; an iOS swipe closes the sheet. Stale connections
and failed refreshes read as last known, without Stop.

To match the OpenCode iOS app, collapsed tool groups read "Used N
tools" with no status or chevron, background subagent launches fold
into them, and only the Working line and the chip animate. The chip
announces background subagent changes once, and the ticking run time
stays outside every live region.
@eivindjonassen
eivindjonassen merged commit 5d81361 into main Nov 14, 2026
4 checks passed
@eivindjonassen
eivindjonassen deleted the feat/background-shells-chip branch November 14, 2026 10:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Show running background shells above the composer, as on desktop

1 participant