Skip to content

tui: session tab shows no spinner while background shell still running #62505

Closed as duplicate

Description

@naihongzhou1029

Summary

Session tab shows no spinner while a background shell in that session is still running, even though the shell row itself shows a spinner and a Background badge.

Environment

  • opencode version: 2.1.3
  • OS: Darwin MacBook-Pro-2.local 27.2.0 Darwin Kernel Version 27.2.0: Wed Oct 14 23:46:57 PDT 2026; root:xnu-13432.41.4~25/RELEASE_ARM64_T8103 arm64
  • Terminal: TERM=xterm-256color, TERM_PROGRAM=Apple_Terminal, COLORTERM=truecolor (macOS Terminal.app, see screenshot)
  • Shell: /bin/bash
  • Install/channel: Homebrew anomalyco/tap/opencode-v2, latest
  • Active plugins: None found in config (~/.config/opencode/opencode.json has only $schema, autoupdate, permission, agent.build.prompt)

Reproduction

  1. Open opencode TUI with tabs enabled and open two sessions (two tabs).
  2. In one session, run a long shell command in the background, e.g. via shell tool with run_in_background=true, or via the wrapper from the screenshot:
    SKILL=~/.config/opencode/skills/bg-task; "$SKILL/task_run.sh" run --title "test" -- python3 -c "import time; time.sleep(60)" &
  3. Wait for the session execution to go idle while the shell keeps running. Observe the session transcript row vs. the tab strip at the top.

Expected Behavior

The tab for the session with the still-running background shell should keep animating (spinner / working state), same as the shell row does, so background work is visible while looking at another tab.

Actual Behavior

The shell row in the transcript keeps animating and shows a Background badge, but the corresponding session tab shows no spinner and looks idle. In the screenshot: bottom row shows : spinner + command + Background, top tab Downloading YouTube Music pl... shows no animation.

Additional Context

  • Frequency: consistently reproducible.
  • Workaround tried: none; have to switch back into the session to see the shell row spinner.
  • Screenshot: macOS Terminal window opencode — 315x69, top red box = tab strip without animation, bottom red box = : spinner + SKILL=... task_run.sh run ... + Background badge. Text below screenshot says the tab position was just corrected, so annotation arrows are accurate.

Root-cause hypothesis from dev source inspection:

  • packages/tui/src/routes/session/index.tsx ShellDisplay: isRunning = props.status === "running" || backgroundRunning() where backgroundRunning = Boolean(id && data.shell.get(id)). So a backgrounded shell (status === "completed" && metadata.status === "running") still renders <Spinner> and <StatusBadge>Background</StatusBadge>.
  • packages/tui/src/context/session-tabs.tsx status(): busy = members.some((id) => data.session.status(id) === "running" || data.session.pending.list(id).some((item) => item.type !== "synthetic")). This only looks at session active + inbox pending, never at data.shell.listBySession(id).
  • Once the execution goes idle after backgrounding, busy becomes false, so packages/tui/src/component/session-tabs.tsx TabIndicator takes the non-runs() path and shows no spinner, while the shell row still spins.

Suggested fix: include running shells in the tab busy check, e.g. data.shell.listBySession(id).length > 0 for each family member (same data.shell store already used by ShellDisplay). Background subagents are already covered via family active, only background shells are missed. Same status() also feeds createProgramStatus, so terminal title / program status would be fixed together.

Activity

  1. opencodejr commented on Nov 7, 2026

    @opencodejr
    Contributor

    Thanks for the detailed report and the root-cause analysis, @naihongzhou1029!

    I think this is a duplicate of #51810. That issue covers TUI activity indicators ignoring running background shells once the turn has ended. It was filed for the /sessions list, but the reply there notes that the session tabs' busy indicator has the same gap: status() in context/session-tabs.tsx checks session status and pending items but never data.shell, which matches what you found.

    Possible duplicates and related issues, ordered by likelihood:

    Your suggested fix (counting data.shell.listBySession(id) for each family member) would be a useful addition on #51810.

    The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.

  2. naihongzhou1029 commented on Nov 7, 2026

    @naihongzhou1029
    Author

    Illustration note (reporter confirmed screenshot may be used):

    Screenshot shows macOS Terminal running opencode TUI:

    • Top tab strip: Downloading YouTube Music pl... and Google OAuth login error in g + — no spinner/activity on the active tab.
    • Transcript middle: shell tool code lines + Edit yt-dlp-test/.normalize_to_minus14.py.
    • Bottom tool row: : spinner frame + SKILL=.../bg-task / "$SKILL/task_run.sh" run --title "..." -- python3 yt-dlp-test/.normalize_to_minus14.py + Background badge.

    So the same background shell animates in the transcript row but not in the tab strip.

    Reporter will attach the original PNG if needed; keeping this textual illustration until the file is uploaded via web UI.

  3. naihongzhou1029 commented on Nov 7, 2026

    @naihongzhou1029
    Author

    Agree this is a duplicate of #51810 — same root cause.

    My tab-strip case matches the session-list gap described there: status() in context/session-tabs.tsx only checks session active + non-synthetic pending, never data.shell. The transcript shell row keeps spinning via data.shell.get(id) while the tab goes idle.

    Happy to close this in favor of #51810. I’ll add the tab-specific reproduction there so list + tabs can be fixed together.

  4. opencodejr commented on Nov 7, 2026

    @opencodejr
    Contributor

    Thanks for confirming, @naihongzhou1029. Adding the tab-strip reproduction to #51810 is a good idea: that way the fix can cover the session list, the tabs and the terminal title together, since they all get their state from status(). This issue will be closed as a duplicate of #51810 as planned.

  5. opencodejr commented on Nov 8, 2026

    @opencodejr
    Contributor

    Closing this as a duplicate of #51810, as agreed above. Thanks again, @naihongzhou1029, for the clear report and root-cause analysis. Please keep following #51810, where adding your tab-strip reproduction will help the session list, tabs and terminal title get fixed together. Related: #56660 (the same gap in the web app) and #62365 (Subagents tab).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions