Skip to content

feat: persistent tab strip with animated status during attach#481

Open
andreano-che wants to merge 16 commits intoasheshgoplani:mainfrom
andreano-che:feat/tab-strip-animated-progress
Open

feat: persistent tab strip with animated status during attach#481
andreano-che wants to merge 16 commits intoasheshgoplani:mainfrom
andreano-che:feat/tab-strip-animated-progress

Conversation

@andreano-che
Copy link
Copy Markdown

@andreano-che andreano-che commented Apr 2, 2026

Summary

Adds a persistent horizontal tab strip that stays visible at the top of the terminal when attached to a session. No more detaching just to see what other sessions are doing or to switch between them.

  • Horizontal tab bar with animated status indicators (braille spinner for running, static ◐ for waiting)
  • Alt+1–9 instant tab switching without leaving the current session (zero flash)
  • Read/unread tracking via existing acknowledged field — completed tasks glow until you look at them
  • Fully configurable via config.toml ([tab_strip] section)

How it works

When you press Enter to attach, agent-deck creates a narrow tmux split pane at the top running a lightweight tab-strip process. This process reads session state from SQLite and renders animated status icons. Alt+N key bindings are registered at the tmux level, so they work even while typing in the session.

Screenshots

Tab strip visible during active session:

image

Switching between tabs with Alt+N:

CleanShot 2026-04-02 at 21 59 37

New In Progress live animation

CleanShot 2026-04-02 at 21 49 14

Main screen (unchanged):

CleanShot 2026-04-02 at 22 00 33@2x

New files

File Purpose
internal/ui/tab_strip.go TabStripModel — rendering, animations, status icons, dual layout (vertical/horizontal)
internal/ui/tab_strip_test.go Unit tests (10 tests)
internal/ui/tab_strip_app.go Standalone Bubble Tea app for the tmux split pane process
cmd/agent-deck/tab_strip_cmd.go agent-deck tab-strip subcommand
cmd/agent-deck/tab_switch_cmd.go agent-deck tab-switch N subcommand (called by tmux key bindings)

Modified files

File Change
internal/ui/home.go Split-pane setup in attachSession(), switch handling, cleanup
internal/ui/hotkeys.go Tab navigation hotkey constants (tab_1–tab_9, next_tab, prev_tab)
internal/session/userconfig.go TabStripSettings struct with TOML parsing
cmd/agent-deck/main.go Register new subcommands

Configuration

[tab_strip]
enabled = true              # master switch (default: true)
layout = "horizontal"       # "horizontal" or "vertical"
width = 15                  # column width for vertical layout
show_hotkey_hints = true    # show 1, 2, 3 next to tabs

Keyboard shortcuts

Action Default Configurable
Switch to tab N Alt+1Alt+9 Yes, via [hotkeys]
Next tab Alt+] Yes
Previous tab Alt+[ Yes
Toggle unread u Already existed

Design decisions

  • Separate process for tab strip: The tab strip runs as a lightweight agent-deck tab-strip process in a tmux split pane, not inside the main Bubble Tea app. This is necessary because tea.Exec (used for tmux attach) takes over the terminal — the main app can't render during attach.
  • tmux-level key bindings: Alt+N bindings are registered via tmux bind-key -T root, so they intercept keys before they reach the application inside the pane. This means they work while typing in any session.
  • Zero-flash switching: When switching tabs, isAttaching stays true so View() returns "" throughout the transition — no flash of the main screen.
  • Read-only SQLite access: The tab strip process opens the database read-only and polls every 1 second. No write contention with the main process.
  • Non-breaking: The main screen is completely unchanged. The feature is opt-out via [tab_strip] enabled = false.

Testing

  • 10 unit tests for TabStripModel (selection, animation, rendering, transitions)
  • 2 unit tests for TabStripSettings config parsing
  • Manual testing: attach, switch tabs, detach, verify cleanup

Test plan

  • Build and run agent-deck with 3+ sessions
  • Enter a session — verify tab strip appears at top
  • Press Alt+2 — verify instant switch without flash
  • Press Ctrl+Q — verify clean return to main screen (no leftover panes)
  • Set [tab_strip] enabled = false — verify tab strip does not appear
  • Verify no impact on existing session list, preview, or hotkeys

andreano-che and others added 16 commits April 2, 2026 19:55
Add TabStripSettings struct with pointer bools for proper default
detection, integrate into UserConfig, and add TabStripConfig() method
with defaults (enabled=true, layout="vertical", width=15,
show_hotkey_hints=true). Includes TDD tests for defaults and TOML parsing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire TabStripModel into the Home struct with config-driven initialization,
80ms animation tick, instance sync on periodic tick, and alt+1-9/alt+[/]
hotkey handlers that select a tab and attach to the session.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added IsAcknowledged() on Instance (delegates to tmuxSession) and call
UpdateUnreadState on each tick so the tab strip reflects acknowledged state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant