Unified session sidebar · 25 designs

Drop the project switcher as a container; show every project's sessions in one sidebar with filtering and grouping. Ten designs stay inside web-interface best practice, fifteen don't. Every mockup uses the same eight sample sessions across four projects so they compare fairly.

Every design now carries t3code's settle v2 lifecycle: sessions are cards while active, park as slim rows in a collapsed Settled shelf when done (by hand, or automatically by the server), and can be snoozed. Rules and anatomy are in the first section.

Companion write-up: 2026-09-15-unified-session-sidebar-designs.md.

Approval Input Working Error Done, unread Idle = no glyph, receded Woke snooze ended ↶ un-settle · ✓ settle CO conduit DF dotfiles PE perry HK hunk
These 25 are the desktop exploration. The decision, rebuilt mobile-first with every settle, snooze, filter and search control drawn out, lives in the mobile-first page →

§0 · Settle v2 lifecycle (from t3code)

Three shelves, one overlay. Active rows are full cards; Settled rows are slim, quiet, and collapsed by default; Snoozed is an overlay on Active with a wake time. Pinned is a flag, not a shelf. The server settles work on its own while the app is closed, and the sidebar never second-guesses density: only settling or snoozing collapses a row.

§0.1

Anatomy: Pinned / Active / Snoozed / Settled + chat banner

Card rows hover to reveal ✓ settle in the time slot. Settled rows sit at 70% ink, glyph desaturated, and hover to reveal ↶ un-settle; their time is when they settled, not last activity. A woken snooze shows a Woke pill in its original slot until visited. Opening a settled session shows a banner; sending a message un-settles it.

Keys: ⌘⇧S settle / un-settle · ⌘⇧P pin · drag onto the Settled header · thread menu.

§0.2

Drag onto the Settled header

Mid-drag the row swaps its status and time for the verb the drop will perform (Pin / Unpin / Settle / Un-settle / Wake), the target section takes the accent, other rows slide aside. Dragging out of Settled un-settles; nothing can be dragged into Snoozed because snoozing needs a wake time.

Twins: every drop has a menu item and a shortcut; reduced-motion drops the slide.

§0.3

Snooze menu + woken session

Presets are computed from now (1h, 3h, this evening only while it's meaningfully before 6pm, tomorrow 9:00, next week, custom). You can snooze a running session, never one that's blocked on you. Anything that outranks the snooze raises its hand and wakes it early: an approval, a question, a fresh error, or a turn finishing after the snooze was set.

Sort stays static: a woken session reappears where it was, so the Woke pill carries the signal until you visit.

Manual settle

  • ✓ on card hover, ⌘⇧S, menu, or drag onto the Settled header.
  • Settling clears the pin and the manual Active slot ("done" beats "keep on top").
  • Settling an idle session dismisses unanswered questions without answering them.
  • Un-settle (↶, banner, or just send a message) returns it to the top of Active and blocks auto-settle until new activity resumes the rules.

Auto settle (server, runs while the app is closed)

  • Idle for N days, default 3, range 1–90, or off.
  • Linked PR merged (default on), or an idle session's PR closed. conduit analogue: branch merged into main / worktree removed.
  • An old merge doesn't settle work you resumed after it: the PR's terminal time must be newer than your last message.
  • Settled time is the last activity, so the shelf reads "wrapped up 3d ago".

Per project override, changing a rule never reopens already-settled sessions.

Never auto-settles while

  • Pending approval or question (hiding the request would defeat it).
  • Session starting or running, or background work alive (PTY, dev server).
  • A queued message under 2 min old that no turn has adopted yet.
  • Manually un-settled, or snoozed with time left (unless it raised its hand).

Rendering

  • Only Settled and Snoozed collapse a row to slim. Every Active row is a card; density comes from parking work, not from the sidebar guessing.
  • Settled rows: 70% ink and desaturated glyph until hover; PR number colours on hover only (open emerald, merged violet, closed red, draft grey).
  • Both shelves collapsed by default, remembered per device. Settled tail shows 10, then +25 per Show more.
  • Active order is static: activity never reorders. Settled sorts by settled time.

Best-practice designs

All ten: rows are real links, scope and group-by live in the URL, lists virtualise past 50, one polite live region for status, tabular numerals, truncation everywhere, reduced-motion honoured, archive with undo.

D1 · T3CODE BASELINE

Flat inbox, project as glyph Best practice

One recency list with a status-tier boost. Three-line 78px card; project is a glyph + name on line 1. Header holds search and a scope combobox whose trigger becomes the chosen project's glyph. Hover a card for ✓ settle; Snoozed and Settled shelves sit collapsed at the floor.

Costs: at 40+ sessions the glyph column turns to noise.

D2

Collapsible project sections Best practice

Projects are sticky headers ordered by latest activity, each with a rollup badge strip. A collapsed section still shows its strip, so no approval can hide. One-line rows because the project is already known. Settled rows live at the tail of their own project, one visible then "8 more".

Costs: cross-project triage means scanning every header.

D3 · OPENCODE / DISCORD

Icon rail + flat list Best practice

A 44px rail of project tiles with corner status badges. Click a tile to toggle it in scope, ⌘-click to solo; the top tile is All. Hover a tile to peek at its sessions. The list is a two-line row with provenance on line 2.

Costs: 44px of width; rail folds into the header when narrow.

D4

Filter chips + time buckets Best practice

Status chips (single select) over removable project chips (multi select), then the familiar Today / Yesterday / Older buckets. A segmented control swaps group-by to project or status.

Costs: ~64px of chips before the first session.

D5 · RECOMMENDED CONTAINER

Status-first triage (inbox zero) Best practice

Sections are status tiers. Needs-you rows carry the verb as their primary action; running and recent rows recede. "Recent" is what's left of Active after the auto-settle rules have swept it; Snoozed and Settled sink to the floor. Group-by-project works inside each tier.

Costs: rows move between tiers while you look; pin anything touched in the last 60s. Done-unread settles on hover ✓ or on visit + 3d idle.

D6

Colour-stripe compact rows Best practice

Project is a 3px left stripe; line 2 still names it so colour is never the only signal. Scope is a swatch legend at the top. The active row's stripe widens with the brand glow.

Costs: falls apart past four or five projects.

D7 · T3CODE SHELVES

Pinned / Active / Snoozed / Settled shelves with drag Best practice

The t3code layout verbatim: manual order in Active, fractional keys in Pinned, drag between shelves with a verb badge replacing the status slot mid-drag (shown: dragging into Pinned). Snoozed rows show their wake time. No time buckets, the auto-settle sweep is the only thing that moves rows for you.

Costs: people who never curate get one long Active list. Every drag needs a menu + shortcut twin.

D8

Table density mode Best practice

Drag the sidebar past ~380px and it becomes a sortable table with aria-sort headers; column sort is the grouping mechanism. Narrower than that, it falls back to D1 cards. Settled rows form a dimmed tail group and the Status cell explains why they settled.

Costs: two layouts to maintain.

D9

Palette-first, minimal sidebar Best practice

The sidebar shows needs-you plus the eight most recent. Everything else is ⌘K: fuzzy search over title + last message, grouped by project, ⌘1–9 jumps. "Show all" opens a full-page browser instead of growing the sidebar.

Costs: older sessions are hard to stumble on.

D10

Mobile-first tabs Best practice

Scrolling project tabs with badge dots over a segmented status control. 44px touch rows, swipe right to settle, left to snooze, long-press for the menu twins (t3code mobile uses an "Arrange" mode with drag handles instead). Same component on desktop, where the tab row wraps.

Costs: least distinctive on desktop.

Outside-the-box designs

Each one breaks at least one convention on purpose and says what it costs. Several want a full-page mode more than a 272px sidebar.

D11

Kanban swimlanes Wild

The sidebar is a three-column board. Columns are status, cards are sessions. Drop a card past Done to settle it; auto-settle clears the Done column for you after 3 days or a merge.

Costs: wants 420px+; fights the vertical scroll everything else assumes.

D12

Timeline strip Wild

Vertical time axis. Each session is a bar from creation to last activity; running bars extend to the live edge and breathe. Bar colour is project, status glyph sits at the head. You see who's been running longest and what overlapped.

Costs: lots of empty width; long-lived sessions dominate.

D13 · BLOCKGRID NATIVE

Activity heatmap per project Wild

Each project is a 24-cell sparkline built from the existing BlockGrid: one cell per hour, intensity = messages, cell pulses when live. Click a cell to filter the list to that hour; click the name to toggle scope.

Costs: the sparkline informs, the list below still navigates.

D14

Treemap Wild

Projects are rectangles sized by recent activity; sessions are tiles inside, sized by recency, tinted by status. One glance: conduit is where the action is and one tile is amber.

Costs: tiny tiles are unreadable and un-tappable; needs a list under ~40px. Settling is what keeps the map readable: settled sessions leave it entirely.

D15

Attention orbit Wild

Radial. The session that most needs you sits in the centre; needs-you ring, running ring, idle ring fading out. Angle within a ring is project (each owns a sector). Sessions drift inward the longer they wait.

Costs: hostile to screen readers and keyboard order; alternate view only.

D16 · GENUINELY USEFUL

Unified message river Wild

A feed of last assistant lines, newest first, like a Slack unified inbox. Permission prompts and questions render inline with their buttons so you approve without opening the session. Title becomes secondary. "Done" posts get a ✓ settle on hover; settled posts leave the river.

Costs: 3–4 line rows; inline actions in a nav region need careful focus management.

D17 · MISSION CONTROL

Spatial desk Wild

Freeform canvas. Sessions are draggable cards, projects are resizable zones, positions persist. Spatial memory replaces sorting ("the auth work is top-left"). New sessions spawn inside their zone.

Costs: canvases rot; needs a Tidy command and a list mode. Full-page, not a 272px sidebar.

conduit
Fix auth token refresh approve
Refactor relay stack 9m
Add session export
Wire PTY resize
dotfiles
Migrate zsh → nushell 4m
Migration strategy?
perry
Investigate flaky e2e
Visual baselines
hunk
5 idle sessions · collapsed
▸ Settled tray · 41drag a card below the line to settle it; auto-settled cards slide down here on their own
TidyList view+ New
positions persist per user · cards spawn in their zone
D18 · EASTER EGG CANDIDATE

Terminal status list (mutt / tmux) Wild

Monospace, fixed columns, zero chrome. j/k move, 1–9 jump, / search, : opens a filter mini-language. Grouping is :group project. Fits the block-grid, PTY-adjacent brand.

Costs: alienates non-terminal people; needs a palette that writes the commands for you.

D19 · USES parentID WE ALREADY HAVE

Fork graph Wild

Git-style graph: forks branch off their parent with connector lines, projects are lanes, status glyphs sit on nodes. Collapse a parent to hide its subtree. Answers "which exploration is still alive" at a glance. Settled branches stay in the tree, dimmed, so the shape of the exploration survives.

Costs: unforked sessions waste the gutter; only pays off for heavy forkers.

D20

Card stacks per project Wild

Each project is a stack, top card = most urgent session, count in the corner. Hover (or arrow key) fans the stack out; click a card to open. Scope is implicit because every stack is visible. Hover a stack below.

Costs: only the top card reads at rest, so it lives or dies on the sort.

D21

Now-playing dock Wild

Running and needs-you sessions leave the sidebar and live in a bottom dock across the whole app, each a chip with a progress ring (elapsed vs. that session's median turn). The sidebar shrinks to a plain recency list of idle sessions.

Costs: two places to look; competes with the terminal panel for the bottom edge.

Live COFix auth token refresh approve DFMigration strategy reply DFMigrate zsh 4m CORefactor relay 9m
D22

Topic clusters Wild

Group by what a session is about, not where it lives. Cluster labels come from embeddings of title + first message, recomputed nightly. Projects appear only as glyphs.

Costs: nondeterministic groups confuse spatial memory; needs an always-group-by-project escape hatch.

D23

Waiting-time queue Wild

Sessions blocked on you sort by how long they've waited, with a bar growing in real time. The top row is the agent you've neglected longest. Everything else is under a rule.

Costs: guilt-driven; the bar reads as progress (it isn't). Keep it neutral and label it.

D24 · TWEETDECK

Deck columns Wild

A rail of vertical text tabs; clicking one opens that project as a column beside whatever's already open. Independent scrolling per column. Best when you're juggling exactly two repos.

Costs: 500px+; rotated text is a readability and accessibility hit.

D25

Ambient pulse strip Wild

The sidebar collapses to an 8px strip of stacked segments, one per session, ordered like D5. Amber segments glow when they need you, blue ones breathe while working. Hover or ⌘B expands the full list (shown mid-expand).

Costs: zero information at rest; must freeze to static colour under reduced motion.

conduit
hover or ⌘B to expand · strip only shows unsettled sessions

§6 · Session row redesign

Whichever container wins, this is the thing you look at four hundred times a day. Two lines, 52px, with a one-line 36px variant that only Settled and Snoozed use. The trailing slot cross-fades between verb / time, hover actions (✓ settle, ↶ un-settle, ⏰ wake), and ⌘ jump pills so nothing ever reflows.

Working · recedes, timer is the only motion
Migrate zsh config to nushellDFdotfiles · main · opus4m
Idle · no glyph, recedes, time only
Investigate flaky e2ePEperry · main1h
Active · brand inset, project already known so glyph hidden
Refactor relay stackmain · opus9m
Hover / focus · actions swap into the trailing slot
Add session exportCOconduit · main · sonnet⇪⊟⋯
⌘ held 200ms · jump pill, absolutely positioned
Fix auth token refreshCOconduit · feat/auth · opusapprove1
Hover on a done card · ✓ settle replaces the time
Add session exportCOconduit · main · sonnetdone✓ settle
Settled slim · 36px, 70% ink, time = when it settled
COWire PTY resize#2123d↶ un-settle HKOAuth device flow2w↶ un-settle
Settled slim, hovered · full ink, PR colour, ↶ un-settle
COWire PTY resize#2123d↶ un-settle COStale socket reauth#1981w↶ un-settle
Woke · back in its original slot, pill until visited
⏰Audit brew bundleDFdotfiles · mainWoke
Mid-drag over Settled · verb badge replaces status + time
Add session exportCOconduit · main✓ Settle
Hover card after 400ms · everything we were tempted to cram into line 3
Fix auth token refreshCOconduit · feat/auth · opusapprove
Directory~/src/personal/conduitWorktree.worktrees/feat-auth · branch differs from main checkoutModelclaude-opus-5 · Claude Agent SDKLast lineMay I run pnpm test:unit? It touches 3 files.Cost$0.84 · 41k in / 6k out · 27 messagesStartedToday 15:04 · 2 forks

§7 · Recommendation

D5 as the container, D3's rail as the scope control, D1's header as search, D9's ⌘K as deep search, with the row above. Group-by (none / project / time) is a header menu; status tiers stay the outer grouping because that is what the product is for.

Settle v2 ships with it, not after it. Server-side: settledOverride · settledAt · unsettledAt · snoozedUntil · snoozedAt · pinnedAt on SessionInfo, a settlement reactor that sweeps every project on a timer (idle 3d default; branch merged into main as conduit's stand-in for "PR merged" until PR links exist), and session.settle / unsettle / snooze / unsnooze / pin RPCs. Client-side: the two shelves collapsed by default, ✓ / ↶ hover affordances, ⌘⇧S, the chat banner, and "send a message un-settles". Leave the Archived list as a Settings page; Settle is the sidebar's only parking verb.

First follow-ups once the row exists: D16's inline approve / deny, then D13's sparkline on rail tooltips as a brand flourish. Ship D18 behind ?view=tty; it's a day of work and the brand wants it.

Backend cost, plainly: listSessions spans projects, SessionInfo gains projectSlug · status · branch · model, routing moves from /p/<slug>/s/<id> to /s/<id>?p=…&g=…. Project registration is untouched; only the switcher-as-container goes.