#1. What failed
Every iteration of the HAAK browser has built good data plumbing and bad UX. The symptoms are consistent: the user opens the browser and cannot answer "what is happening right now?" within five seconds.
Root causes: (a) sessions displayed by UUID, not by what they are doing; (b) engagement IDs shown raw instead of named; (c) flat lists of 500 items with no hierarchy; (d) no search over content; (e) dotted-line bars for sessions without transcripts; (f) no control surface -- can look but cannot act.
The deeper problem: the user works in Zed with named sessions as tabs. Bouncing between them is instant. The browser should work the same way. The tab IS the session manager.
#2. The five-second rule
When the user opens the browser, within five seconds they must know:
- How many agents are alive and what they are doing (names, not UUIDs)
- Whether any agent is in danger (context > 75%)
- What work is active (engagement names, not IDs)
- Whether anything needs attention (stuck agents, failed obligations)
Everything else is drill-down.
#3. Layout
+-------------------------------------------------------------------+
| [* Reed .|] [* haak-simons .|] [* orchest .|] [+] | <- tab bar
+-------------------------------------------------------------------+
| search... [Engagements] | <- utility bar
+-------------------------------------------------------------------+
| |
| (main area -- changes based on what's selected) |
| |
+-------------------------------------------------------------------+
Three horizontal zones, top to bottom: tab bar, utility bar, main area. The tab bar is the primary navigation. The utility bar provides search and the engagement axis. The main area renders content for the selected tab or mode.
#4. Tab bar
The tab bar shows all LIVING agents/sessions. It is the session manager.
#Tab anatomy
Each tab shows:
- Colored dot: green = active, amber = frozen
- Label:
[agentname]: [sessionname]or just[session_name]if agent is "claude" - Context bar: thin colored stripe under the label (green < 50%, amber 50-75%, red > 75%, pulsing red > 90%)
- Dropdown arrow (
.|): opens session management menu
No UUIDs shown anywhere in the UI. Ever.
#Tab dropdown actions
Right of each tab label, a dropdown menu with:
| Action | Effect |
|---|---|
| Rename | Inline edit of session name |
| Chat | Open chat with this agent (main area switches to chat mode) |
| Terminal | Open terminal to tmux pane (desktop only, xterm.js) |
| Freeze | Pause agent, keep context |
| Revive | Inscribe + start new session with compressed context |
| Split into... | Select rounds by engagement, fork into new agents |
| Merge with... | Combine with another session |
| Kill | Bury agent, archive session |
| Dispatch | Send message to agent mailbox |
#[+] button
Creates a new agent/session. Dialog: name, role, model selection. New tab appears on creation.
#Tab behavior
- Click tab -> switch main area to that session's rounds (session mode)
- Tab names are editable inline (double-click to rename)
- Renaming syncs to inscription database
- Sessions get named on first inscription (from first user message) or via
/renamein Claude Code - Frozen agents shown with amber dot, active with green dot
- Dead agents do not appear as tabs (findable via search or "All agents" in engagement mode)
- Draggable tab reordering (future enhancement, not v1)
#5. Main area modes
The main area has four modes. These are not separate pages -- they are modes within the same window, all sharing the tab bar.
#5.1. Home mode (no tab selected)
What you see on first open, or when no tab is active.
+-------------------------------------------------------------------+
| [* Reed .|] [* haak-simons .|] [* orchest .|] [+] |
+-------------------------------------------------------------------+
| search... [Engagements] |
+-------------------------------------------------------------------+
| |
| ACTIVE WORK |
| +---------------------------------------------------------------+|
| | Session inscription system Reed, Sill 3h ago ||
| | 12 rounds across 4 sessions phase: build ||
| +---------------------------------------------------------------+|
| | ASC manuscript review Veda 1d ago ||
| | 8 rounds across 2 sessions phase: collect ||
| +---------------------------------------------------------------+|
| |
| RECENT ROUNDS |
| R14 Reed 3m ago "write the UX spec" -> "Here's the..." |
| R13 Reed 8m ago "read the engagement viewer" -> "I see..." |
| R12 Veda 1h ago "check ASC references" -> "Found 3..." |
| ... |
+-------------------------------------------------------------------+
Engagement cards show: name (human-readable), contributing agents, recency, round count, phase. Sorted by most recent activity. Max 10 shown; "Show all N engagements" link if more. Click a card to enter engagement mode.
Recent rounds: reverse-chronological feed of last ~20 rounds across all agents. Click a round to expand. Click agent name to activate that agent's tab.
#5.2. Session mode (tab clicked)
Default when clicking a tab. Shows that session's rounds with collapsible drill-down.
+-------------------------------------------------------------------+
| [* Reed .|] [* haak-simons .|] [* orchest .|] [+] |
+-------------------------------------------------------------------+
| search... [Engagements] |
+-------------------------------------------------------------------+
| Reed: browser-ux | opus-4-6 | 42% [========== ] | R14 |
+-------------------------------------------------------------------+
| [user] [assistant] [thinking] [tools] filter toggles |
+-------------------------------------------------------------------+
| |
| R14 3m ago "write the UX spec" |
| -> "Here's the revised spec with tab-based navigation..." |
| [4 tools] |
| |
| R13 8m ago "read the engagement viewer" |
| -> "I see the current implementation..." |
| [2 tools] |
| |
| ... |
+-------------------------------------------------------------------+
Session metadata bar: name, agent, model, context %, round count. Filter toggles for thinking/tools (carried forward from current viewer). Rounds expand/collapse on click. Tool calls and thinking blocks are nested collapsibles within expanded rounds.
#5.3. Chat mode (from tab dropdown "Chat")
Full-width conversation with the selected agent. Streaming responses.
+-------------------------------------------------------------------+
| [* Reed .|] [* haak-simons .|] [* orchest .|] [+] |
+-------------------------------------------------------------------+
| |
| [conversation history scrolls here] |
| |
| Reed: I've written the UX spec at patterns/architecture/41-... |
| |
| You: Can you also add mobile considerations? |
| |
| Reed: [streaming response...] |
| |
+-------------------------------------------------------------------+
| [Type a message... ] [Send] [+File] |
+-------------------------------------------------------------------+
Message input pinned to bottom. Send button + file upload. WebSocket connection to router or agent session. Drag-drop for files.
#5.4. Engagement mode (from utility bar "Engagements" button)
Engagements cross-cut sessions -- they are a different navigation axis, not a tab. Accessed from the utility bar, not from the tab bar.
+-------------------------------------------------------------------+
| [* Reed .|] [* haak-simons .|] [* orchest .|] [+] |
+-------------------------------------------------------------------+
| search... [Engagements *] |
+-------------------------------------------------------------------+
| ENGAGEMENTS | |
| +------------------+ | |
| | Session inscrip. | | phase: build | Mar 19 | 12 rounds |
| | ASC manuscript | | Reed, Sill |
| | Browser redesign | | obligations: implement round writer, ... |
| | Face decoding | | +-----------------------------------------+ |
| +------------------+ | | R12 Reed Mar 21 "implement writer" | |
| | | -> "I'll create the round file..." | |
| [Show dead] | | R11 Sill Mar 21 "check store struct" | |
| | | -> "The store follows the spec..." | |
| | | R10 Reed Mar 20 "design SQL schema" | |
| | | -> "Here's the schema..." | |
| | +-----------------------------------------+ |
+-------------------------------------------------------------------+
Left sidebar lists engagements (name, phase, contributor count). Click an engagement to load its cross-agent round stream in the main panel. Engagement metadata at top of stream: phase, start date, round count, participating agents, current obligations.
Rounds from all contributing agents, chronological. Agent names color-coded (hash-to-hue). Left-border color distinguishes agents. Same filter bar for thinking/tools.
#5.5. Search mode (from search box)
+-------------------------------------------------------------------+
| [* Reed .|] [* haak-simons .|] [* orchest .|] [+] |
+-------------------------------------------------------------------+
| [round model_____] [Engagements] |
+-------------------------------------------------------------------+
| 7 results across 3 sessions |
+-------------------------------------------------------------------+
| |
| R8 Reed Mar 20 [Session inscription system] |
| "...the round model stores each turn as a JSON file..." |
| |
| R5 Sill Mar 19 [Session inscription system] |
| "...round model needs to support retroactive tagging..." |
| |
| R22 Reed Mar 18 [Architecture review] |
| "...decided the round is the atomic unit, not the message..." |
| |
+-------------------------------------------------------------------+
FTS5 over rounds_fts table in sessions.db. Results ranked by relevance. Each result shows: round number, agent name, date, engagement badge, matching text with highlights. Click result to expand full round. Click engagement badge to enter engagement mode. Click agent name to activate tab. 20 results shown, "Load more" for pagination.
#6. Naming conventions
- Sessions get named on first inscription (derived from first user message)
/renamein Claude Code syncs to inscription database- Tab names editable inline (double-click)
- Agent name (Reed, Kavi) is primary identifier
- Session name is subtitle/qualifier
- Tab label:
[agentname]: [sessionname]or just[session_name]if agent is "claude" - Engagement names: transform
infra-session-inscriptionto "Session inscription system" by stripping known prefixes (infra-,lab-,ops-), replacing hyphens with spaces, title-casing. Override viadisplay_namefield in engagement data. - NO UUIDs shown anywhere in the UI. Ever.
#7. URL structure
| URL | Mode |
|---|---|
/ | Home mode (no tab active) |
/session/<name> | Session mode (tab active) |
/session/<name>/chat | Chat mode |
/session/<name>/terminal | Terminal mode |
/engagement/<id> | Engagement mode with engagement selected |
/search?q=<query> | Search mode |
All URLs served by the same index.html. pushState on every navigation. Back/forward works. Bookmarkable. Every entity on screen is a link: engagement name -> engagement mode, agent name -> session tab, round number -> expand in place.
#8. Mobile design
Phone is a real use case -- the user checks "what's happening" from their phone.
#Tab bar
Becomes a horizontal scrollable strip. Dropdown becomes long-press on a tab. Tabs show dot + name only (no context bar -- too small).
#Mode behavior on mobile
- Home mode: engagement cards and recent rounds stack vertically. Single column.
- Session mode: full width, rounds stack naturally. Filter bar wraps.
- Chat mode: works well (standard mobile messaging layout). Input pinned to bottom.
- Engagement mode: sidebar collapses to a top dropdown selector. Rounds full width.
- Search mode: full width, results stack.
- Terminal mode: hidden on mobile (not usable). Button not shown.
#Breakpoints
- > 900px: full layout as designed
- 600-900px: single column, engagement cards 2-up
- < 600px: single column, everything stacked, tab bar scrollable
#Minimum viable mobile
The phone user must be able to: (1) see which agents are alive and their context %; (2) see active engagements; (3) search for content; (4) read rounds. Chat is a stretch goal. Terminal is desktop-only.
#9. Visual design decisions
Dark theme. --bg: #0d1117, --surface: #161b22, existing palette. No changes.
No timeline canvas. The previous implementation's timeline canvas is removed. Engagement card list with recency labels does the same job in less space and works on mobile.
No dotted lines. Sessions without transcripts are not shown unless explicitly requested.
Agent colors. Hash-to-hue for round streams. Named colors for known agents (Reed=green, Sill=purple, Veda=amber).
Typography. 13px body, system font stack. Monospace for round numbers, tool names. No UUIDs to render.
Tab bar styling. Tabs have a 2px bottom border in the agent's color when active. Context bar is a 3px stripe under the tab label, width proportional to usage, colored by threshold. Inactive tabs have muted text. Hover shows full session name if truncated.
#10. Component inventory
| Component | Data source | Interactions |
|---|---|---|
| Tab bar | Agent roster, session DB | Click tab, dropdown actions, [+] create |
| Tab dropdown | Agent roster, session state | Rename, Chat, Terminal, Freeze, Revive, Split, Merge, Kill, Dispatch |
| Utility bar | -- | Search submit, Engagements toggle |
| Engagement card | engagement.md + session DB | Click to enter engagement mode |
| Round row (collapsed) | rounds table | Click to expand |
| Round row (expanded) | Round JSON files | Collapse, nested tool/thinking collapsers |
| Filter bar | Derived from round content types | Toggle type visibility |
| Context bar | Agent roster (context_pct) | Visual only, color thresholds |
| Search results | FTS5 on rounds_fts | Click to expand, click badges |
| Chat panel | WebSocket to router/agent | Send message, upload file |
| Terminal panel | WebSocket PTY bridge (xterm.js) | Full terminal emulation |
| Engagement sidebar | Engagement state files | Click to select engagement |
#11. Testing plan
#Tab lifecycle tests
| Test | Verify |
|---|---|
| Create via [+] | Tab appears in bar with name, dot, context bar |
| Rename tab | Inline edit works, inscription database updated |
| Click tab | Main area switches to session mode, rounds load |
| Chat from dropdown | Main area switches to chat mode, WebSocket connects |
| Kill from dropdown | Tab disappears, session archived in DB |
| Freeze from dropdown | Dot changes to amber, agent paused |
| Revive from dropdown | New tab appears with fresh session, old tab removed |
#Mode tests
| Test | Verify |
|---|---|
| Home mode (no tab) | Engagement cards + recent rounds visible |
| Session mode | Rounds load for selected session, filter toggles work |
| Chat mode | WebSocket streaming works, messages render incrementally |
| Engagement mode | Cross-agent rounds load, sidebar lists engagements |
| Search mode | FTS5 returns results, clicking jumps to round in context |
#Integration tests
| Scenario | Steps |
|---|---|
| Full navigation loop | Home -> click engagement -> click agent name -> tab activates -> chat -> home |
| Search to context | Search "round model" -> click result -> verify engagement badge links |
| Tab management | Create -> rename -> freeze -> revive -> kill |
| Mobile flow | Viewport 375x812 -> tab bar scrolls -> search -> read rounds -> chat |
| Live update | Inscribe a session while browser open, verify tab appears without refresh |
#Edge cases
| Case | Expected behavior |
|---|---|
| Agent with 0 rounds | Tab shows, session mode says "No activity yet" |
| Engagement with 1 session | Card shows "1 session" (not "1 sessions") |
| Dead agent | No tab, findable via search or "All agents" |
| Session without engagement | Rounds appear in "Untagged" in recent rounds |
| 500+ engagements | 10 shown on home, "Show all" link |
| Tab name collision | Append round count or model as disambiguator |
architecture . 41 . browser ux design . 2026-03-21 . zach + claude
Architecture 41 — Browser UX Design — 2026 — Zachary F. Mainen / HAAK