Skip to content

Mirror sidebar activity shimmer on terminal tabs #697

Description

@adamgall

What problem does this solve?

Supacode's sidebar title is a workspace-level activity aggregate, but the terminal tab titles do not consistently expose the tab that contributes that activity. In a workspace with multiple tabs—or a tab with multiple split panes—the sidebar can shimmer while no corresponding tab title identifies where the work is happening.

This is broader than agent presence. The sidebar currently shimmers for:

  • actively working agents (.busy or .compacting),
  • terminal activity that reports running progress through Ghostty, and
  • workspace lifecycle activity such as setup, archive, or delete operations.

Tab titles currently shimmer from TerminalTabItem.isDirty, which already covers per-tab Ghostty progress/blocking scripts, but they do not receive the sidebar's independent agent-working aggregate. The result is two related shimmer decisions that can drift.

Split panes must also be handled correctly. Each pane is a terminal surface (a leaf in the tab's split tree), each tab already projects the IDs of all its surfaces, and the sidebar projects the surface IDs across every tab. The desired hierarchy is therefore:

pane/surface activity → tab activity → workspace/sidebar activity

Proposed solution

Make terminal tab-title shimmer mirror the sidebar's activity decision, using the same underlying activity semantics and preserving the existing per-surface ownership:

  • A tab shimmers when any pane/surface in that tab contributes activity that would make the workspace's sidebar title shimmer.
  • Agent activity uses the same sidebar semantics: .busy and .compacting shimmer; .idle, .awaitingInput, and .error do not.
  • Ghostty progress/blocking-script activity continues to shimmer the owning tab.
  • If multiple panes in one tab are active, the tab remains shimmering until all contributing panes become inactive.
  • If panes in multiple tabs are active, every contributing tab shimmers; unrelated sibling tabs do not.
  • The workspace's surface-derived shimmer should be the rollup/OR of its tab shimmer states rather than a separate decision that can diverge.
  • Keep agent-driven shimmer independent of the agent-presence badge visibility setting, matching the sidebar.
  • Reuse the existing ShimmerModifier, including its Reduce Motion behavior.
  • While a tab is in inline rename mode, shimmer only the normal title label—not the replacement TextField. Preserve the tab's activity state and resume the title shimmer after editing ends if the tab is still active.

For workspace-only lifecycle activity that is not attributable to a terminal surface, use the selected tab as the representative when the workspace has tabs. The invariant should be:

Whenever a workspace has at least one tab and its sidebar title is shimmering, at least one tab title in that workspace is also shimmering.

The existing model already contains the required hierarchy: WorktreeTabProjection.surfaceIDs is built from every leaf in a tab's split tree, and the workspace projection aggregates leaves across every tab. Extending the per-tab activity snapshot and sharing/deriving the same predicate should not require a new agent protocol event.

The existing rename view swap already supports the intended presentation: TerminalTabView hides TerminalTabLabelView while isEditing and overlays a plain TextField. Keeping shimmer attached to the title label preserves that behavior.

Acceptance examples

  • One busy agent in one pane: its tab and the sidebar shimmer.
  • One busy pane among several splits: the containing tab and sidebar shimmer.
  • Two busy panes in different tabs: both tabs and the sidebar shimmer.
  • One pane becomes idle while another pane in the same tab remains busy: the tab keeps shimmering.
  • A non-agent process reports running progress: its tab and the sidebar shimmer.
  • Sidebar lifecycle shimmer with existing tabs but no attributable surface: the selected tab shimmers as the representative.
  • An actively shimmering tab enters inline rename mode: its TextField does not shimmer; after rename completes, the normal title resumes shimmering if activity is still present.
  • No tab belonging to the workspace contributes activity: no tab title shimmers.

Alternatives considered

  • Rely on the per-tab agent badge: it is smaller and communicates agent identity/state, but it is less scannable and can be disabled.
  • Keep independently computed sidebar and tab predicates: minimal code movement, but makes future drift likely; the desired model is one pane-to-tab-to-workspace rollup.

Supacode version

0.10.6

Are you planning to build this yourself?

  • I intend to open a pull request once this is approved and marked ready.

Before submitting

  • I searched existing issues and this is not a duplicate.
  • I understand feature pull requests are closed until the issue is marked ready.
  • I agree to follow this project's Code of Conduct.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions