Design Approach — Argus Dark Terminal Theme

The interior theme ("Argus Dark") derives every color from the evolved palette. Orange block cursor is the brand signature — the only moment of Argus identity inside an otherwise neutral terminal canvas. ANSI semantics map directly to existing Argus tokens (red=error/dead, green=live/pass, yellow=warn/stale, blue=info) so the system is coherent without a lookup table.

Terminal background is #0D0D0D — seven points darker than the app shell (#141414). This creates a subtle inset perception: the canvas reads as slightly recessed behind the Argus chrome, without any box-shadow. Overlay bar gets a hairline orange top-border at 20% opacity — echoing the active-pane orange treatment everywhere else in the app. All animations are opacity-only (WebView-safe, no filter/blur).

Live Preview — tap dot states to switch
Overlay dot:
2:40 ▲ 85%
# genai-api · bedrock-claude-4 branch claude@argus:~/kpmg/genai-api$ git status On branch feature/bedrock-claude-4 Changes not staged for commit: (use "git add <file>..." to stage) modified: src/routes/chat.py modified: src/services/bedrock.py claude@argus:~/kpmg/genai-api$ pytest tests/ -v --tb=short ══════════════════ test session starts ══════════════════ platform linux — Python 3.12.3, pytest-8.2.0 collected 24 items tests/test_chat.py::test_stream_response PASSED [ 4%] tests/test_chat.py::test_token_count PASSED [ 8%] tests/test_bedrock.py::test_claude_invoke PASSED [ 12%] tests/test_bedrock.py::test_model_routing FAILED [ 16%] ═══════════════════ FAILURES ════════════════════════════ FAILED tests/test_bedrock.py::test_model_routing AssertionError: Expected 'claude-opus-4-7', got 'claude-sonnet-4-6' 3 passed, 1 failed in 2.34s claude@argus:~/kpmg/genai-api$
tmux new-session -A -s argus (claude-server-evo) · Running · 5m 23s
VS Code
Implementation Spec — copy-paste ready
xterm.js Theme Object — "Argus Dark"
21 keys · paste into ITerminalOptions.theme · (brief lists 22; selectionForeground is optional 22nd)
// Argus Dark — xterm.js theme object
const argusTheme = {
  // Canvas + cursor
  "background":       "#0D0D0D",  // slightly deeper than app bg — terminal feels inset
  "foreground":       "#C8C8C0",  // warm-shifted off-white — default text (no ANSI escape)
  "cursor":           "#C15F3C",  // brand orange — THE signature moment
  "cursorAccent":     "#0D0D0D",  // char under block cursor = bg color
  "selection":        "rgba(193,95,60,0.25)",  // orange tint, semi-transparent

  // ANSI base 8
  "black":            "#1E1E1E",  // warm dark — not pure black
  "red":              "#C0392B",  // argus_red — errors, dead session, stderr
  "green":            "#3FB950",  // argus_green — live, success, pass
  "yellow":           "#D29922",  // argus_yellow — warnings, stale, filenames
  "blue":             "#4D9EDA",  // argus_blue — dirs, links, info
  "magenta":          "#B06EC0",  // warm purple — docker inspect, bold contexts
  "cyan":             "#4DB8B0",  // warm teal — k8s output, env vars
  "white":            "#C8C8C0",  // same as foreground

  // ANSI bright 8
  "brightBlack":      "#4E4E4E",  // argus_dim — comments, timestamps, line numbers
  "brightRed":        "#D9534F",  // bold error emphasis
  "brightGreen":      "#56D364",  // bold success — pytest PASSED
  "brightYellow":     "#E8BB3F",  // warm gold — bold warning
  "brightBlue":       "#79B8F8",  // keyword syntax, type names, bold links
  "brightMagenta":    "#C678DD",  // bold magenta
  "brightCyan":       "#6ACFCA",  // bold teal — strings in some shell configs
  "brightWhite":      "#F0F0E8"   // near-white warm — highest contrast text
};

// xterm.js config
const termOptions = {
  theme: argusTheme,
  fontFamily: "'JetBrains Mono', ui-monospace, Menlo, monospace",
  cursorStyle: "block",
  cursorBlink: true
};
Overlay Bar CSS
Exact IDs · 40px · no blur · perf-safe anims
/* ── Argus Overlay Bar ─────────────────────────── */
/* NOTE: use position:fixed in prod (this preview  */
/* uses position:absolute). All else copy-paste.   */

#argus-overlay {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 9999;
  height: 40px;
  background: rgba(12, 10, 8, 0.94);
  border-top: 1px solid rgba(193, 95, 60, 0.20);
  display: flex;
  align-items: center;
  padding: 0 12px 0 10px;
  gap: 10px;
  user-select: none;
}

#argus-dot {
  width: 7px; height: 7px;
  border-radius: 50%; flex-shrink: 0;
  background: #3FB950;
  animation: argus-pulse 2s ease-in-out infinite;
}
#argus-dot.detached {
  background: #D29922;
  animation: none; opacity: 0.75;
}
#argus-dot.dead {
  background: #4E4E4E;
  animation: none; opacity: 0.50;
}
@keyframes argus-pulse {
  0%,100% { opacity: 1; }
  50%     { opacity: 0.3; }
}

#argus-status {
  flex: 1; min-width: 0;
  font-family: 'JetBrains Mono', ui-monospace, Menlo, monospace;
  font-size: 11px;
  color: rgba(200, 200, 192, 0.65);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: 0.01em;
}
/* Kotlin innerHTML: <strong>name</strong> · uptime */
#argus-status strong {
  color: #C15F3C; font-weight: 600;
}

#argus-morph {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 0 10px; height: 32px;  /* > 30px tap-target floor */
  background: rgba(193, 95, 60, 0.10);
  border: 1px solid rgba(193, 95, 60, 0.28);
  border-radius: 3px;
  color: #C15F3C;
  font-family: 'JetBrains Mono', ui-monospace, Menlo, monospace;
  font-size: 11px; font-weight: 500;
  text-decoration: none;
  cursor: pointer; flex-shrink: 0; white-space: nowrap;
  transition: background 0.15s, border-color 0.15s;
}
#argus-morph:active {
  background: rgba(193, 95, 60, 0.20);
  border-color: rgba(193, 95, 60, 0.45);
}

/* REQUIRED: clear xterm canvas for overlay */
.xterm-screen { padding-bottom: 40px; }
Page CSS
html/body required · vignette + scanlines optional
/* REQUIRED — stops page competing with xterm scroll */
html, body {
  background: #0D0D0D;
  margin: 0;
  overflow: hidden;
}

/* OPTIONAL — warm vignette. pointer-events:none,
   no blur, no box-shadow — perf-safe in WebView. */
.argus-vignette {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 9998;
  background: radial-gradient(
    ellipse 90% 80% at 50% 50%,
    transparent 55%,
    rgba(6, 4, 3, 0.50) 100%
  );
}

/* OPTIONAL — scanlines at 3.5% opacity.
   Set opacity:0 to disable.
   background-attachment:fixed OMITTED — buggy WebView. */
.argus-scanlines {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 9997;
  background-image: repeating-linear-gradient(
    0deg,
    transparent 0px, transparent 3px,
    rgba(0,0,0,0.035) 3px, rgba(0,0,0,0.035) 4px
  );
}

/* Add before </body>:
   <div class="argus-vignette"></div>
   <div class="argus-scanlines"></div> */
Details
Font
JetBrains Mono — keep it
No change needed. Already in use, great legibility at small sizes. Fallback: ui-monospace, Menlo, monospace
fonts.google.com/specimen/JetBrains+Mono
Cursor
block · blink: true
Orange block cursor is the brand's terminal signature. Blink on — makes it feel alive. xterm config: cursorStyle:"block", cursorBlink:true
BG depth rationale
#0D0D0D vs #141414
Terminal canvas is 7 points darker than app shell. Creates a subtle inset perception — terminal reads as slightly recessed behind the Argus chrome — with zero box-shadow required.
All 21 swatches
Hover swatches for key name. No cool grays anywhere.
Pane Header — Active Type Indicator NEW v0.19
How terminal panes identify themselves

Terminal panes carry three visual identifiers: (1) a 3dp green left-edge stripe on the pane container, (2) a [TERMINAL] monospace badge in the header, and (3) an orange page-count chip showing open pane count. The stripe color tracks the session dot — green = live · yellow = detached · gray = dead. Code-server panes use a blue [CODE] badge; no stripe.

claude-server-evo CODE
argus TERMINAL 2
Green left stripe
border-left: 3dp solid #3FB950 On pane container. Tracks dot color: #3FB950 = live · #D29922 = detached · #4E4E4E = dead
[TERMINAL] badge
bg: rgba(63,185,80, 0.10) border: rgba(63,185,80, 0.30) Page count badge: orange tint — rgba(193,95,60,.12)
Keybar — Terminal Shortcut Strip tmux chips NEW
Standard keys + new tmux argument chips

The keybar provides one-tap terminal keys above the system nav bar. Standard key chips (esc through slash) existed in v0.8. The new tmux argument chips (-s · -t · new-session · -A) insert tmux flags into the active pane. They use a lighter orange tint to signal "smart argument" vs plain key-send. Chips are horizontally scrollable on smaller form factors. Tap any chip below to preview the press state.

Keybar strip — 34dp height · horizontally scrollable
tmux
Standard Keys
Keycode sent to active xterm pane
// Standard key → xterm.js action
// esc   → term.write('\x1b')
// tab   → term.write('\t')
// ctrl  → modifier latch (combinator)
// alt   → modifier latch
// ↑↓←→  → '\x1b[A' '\x1b[B' '\x1b[D' '\x1b[C'
// home  → term.write('\x1b[H')
// end   → term.write('\x1b[F')
// |     → term.write('|')
// -     → term.write('-')
// /     → term.write('/')

// Combinator (ctrl latch example)
if (ctrlLatched) {
  const code = key.charCodeAt(0) - 64;
  term.write(String.fromCharCode(code));
  ctrlLatched = false;
}
Tmux Argument Chips NEW
Insert tmux flags · orange-tint variant
// Tmux chips insert argument text + trailing space
// -s          → term.write('-s ')
// -t          → term.write('-t ')
// new-session → term.write('new-session ')
// -A          → term.write('-A ')

// Common build with chips:
// [new-session] [-A] [-s] name
// → "tmux new-session -A -s argus"

/* Orange-tint visual diff from standard key: */
.kc-tmux {
  background: rgba(193, 95, 60, 0.07);
  border-color: rgba(193, 95, 60, 0.22);
  color: rgba(193, 95, 60, 0.85);
  font-size: 11sp;
}
Add Pane — Terminal Dialog + AI Agent Spawning NEW v0.19
Bottom sheet — Terminal tab with agent launcher

Tapping "+" opens the Add Pane bottom sheet. The Terminal tab shows a command/session field followed by the "SPAWN NEW AI AGENT SESSION" section — four agent archetype chips (radio-select) and four capability toggles. Leaving all chips deselected opens a plain terminal. Allow Write is the most consequential toggle and renders first. Tap the chips and switches below to interact.

Command / Session
tmux new-session -A -s argus
Spawn new AI agent session
Allow Write
Deep Search
Skip Perms
Background
Add Pane Terminal — Component Spec
Tokens · layout · interaction rules
// Bottom sheet — slides up from bottom edge
// Corner radius: 8dp top-left + top-right only
// Background:  --panel  (#1C1C1C)
// Border:      1px solid --border (#272727)
// Max-width:   420dp on tablet, full-width phone

// ── Tab row ──────────────────────────────────
// Active tab:    color orange, border-bottom 2px orange
// Inactive tab:  color --muted, no underline
// Font:          JetBrains Mono 11sp, uppercase

// ── Command/Session input ─────────────────────
// Background:  --panel2 (#242424)
// Border:      1px solid --border
// Border-radius: 4dp
// Placeholder: "--muted" color, JetBrains Mono 12sp

// ── Agent archetype chips — radio group ───────
// Options: Investigator · Developer · Generalist · Mechanic
// Deselected:
  background: --panel2;
  border: 1px solid --border;
  color: --muted;
// Selected (one at a time):
  background: rgba(193, 95, 60, 0.10);
  border-color: rgba(193, 95, 60, 0.40);
  color: --orange;

// ── Capability toggles ────────────────────────
// Track ON:   background --orange; border --orange
// Thumb ON:   #ffffff
// Track OFF:  background --panel3; border --border
// Thumb OFF:  --muted
// Defaults:   Allow Write = ON · rest = OFF
// Row divider: 1px rgba(255,255,255,0.04)

// ── Action buttons ────────────────────────────
// Cancel: ghost — border --border, color --muted
// Open:   filled — background --orange #C15F3C
//         text #fff, weight 600, border-radius 4dp
Morph Button Icon — proposed replacement for current ↩ chevron-left
/* Drop inside your existing button/anchor element. Renders at currentColor — inherits orange from #argus-morph. */ <svg width="13" height="12" viewBox="0 0 13 12" fill="none"> <path d="M4.5 2L1 6l3.5 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8.5 2L12 6l-3.5 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg>
Code-brackets icon — universally reads as "source editor / VS Code". Renders at currentColor so it inherits orange from the parent without a fill attribute. If you prefer the current ↩ glyph, ignore this card entirely.
Dense Mode — 3-Pane Compact Headers v0.19
At 3+ panes, the tab bar collapses to 28dp

When pane count reaches 3, the header bar enters dense mode: row height drops from 44dp to 28dp, the [TERMINAL]/[CODE] type badge is hidden to save space, the session label truncates to folder name only, and the page-count chip shrinks to 18dp. The 3dp left-edge stripe remains the sole session-state signal in dense mode.

arena
argus 3
kpmg
Dense mode triggers at 3 panes
Row height: 28dp (was 44dp)
Label: folder name only, truncated
Type badge [TERMINAL]/[CODE]: hidden
Page-count chip: 18dp diameter
Stripe still tracks session state
Green stripe = live session
Yellow stripe = detached
Gray stripe = dead
No stripe = code-server pane
Dense Mode — Token Diff
Only the values that change vs normal mode
// Dense mode activates when paneCount >= 3
paneTabRow.height:    28dp    /* was 44dp */
sessionLabel.textSize: 10sp   /* was 11sp */
sessionLabel.truncate: END    /* folder name only */
typeBadge.visibility:  GONE   /* [TERMINAL]/[CODE] hidden */
pageChip.minSize:      18dp   /* was 20dp */
pageChip.textSize:     8sp    /* was 9sp */
// Unchanged in dense mode:
stripe.width:           3dp    /* live: #3FB950 · detached: #D29922 · dead: #4E4E4E */
paneIcon.size:          10dp   /* down from 12dp for visual balance */
Pane Interactions — Swap & Close v0.19
Long-press tab → context menu · × button to close

Two pane management gestures: (1) Long-press any pane tab → context menu anchored below the tab with Swap and Close options. (2) × button appears on the active pane tab and closes immediately. Swap reorders pane positions without touching the underlying tmux sessions — sessions stay alive, only the ViewPager order changes.

Active pane — × appears on tab
argus TERMINAL
× button: 18dp · red tint
Only on active/focused pane tab
Tap confirms close — no second dialog
Long-press tab → context menu
arena
argus
Swap with arena →
Close pane
Long-press: 400ms · haptic feedback
Menu anchors below the pressed tab
Dismiss: tap outside or back
Swap + Close — Implementation Notes
Gesture timings · layout swap · session lifecycle
// ── Close pane ─────────────────────────────────
// × button visible only on the ACTIVE (selected) pane tab
// Tap × → immediate close, no confirmation dialog
// Session stays alive in tmux — only the WebView detaches
// If closing last pane → show empty-state dashboard

// ── Swap pane ──────────────────────────────────
// Trigger: long-press any pane tab — 400ms, haptic VIRTUAL_KEY
// Context menu anchors directly below the long-pressed tab
// "Swap with [other pane name]" → swaps visual positions only
// Sessions NOT restarted — only ViewPager item order changes
// If 3+ panes: "Swap with..." submenu lists all other panes

// ── Context menu tokens ────────────────────────
menu.background:    --panel2 (#242424)
menu.topBorder:     2px solid --orange (#C15F3C)
menu.borderRadius:  0 0 5dp 5dp   /* flat top, rounded bottom */
swapItem.color:     --orange (#C15F3C)
closeItem.color:    #D9534F        /* red — destructive action */
row.padding:        9dp vertical · 14dp horizontal
Drag Handle — Pane Resize v0.19
4dp strip between panes — 3 visual states

When two panes share the screen in split layout, a 4dp invisible drag handle sits between them. Touch-and-hold activates after the Drag Activation Delay (Settings → Behavior, default 300ms). While dragging: the handle glows orange, a width-percentage tooltip tracks your finger, and both panes resize live. Release snaps to the nearest 5% increment. Minimum pane width: 30%.

Idle
Transparent · 4dp wide
dim hairline only
Touch Hold
Orange tint bg
activates after delay
Dragging
38%
Orange glow · % tooltip
snaps to 5% on release
Drag Handle — Token + Behavior Spec
3 visual states · snap grid · min width
// ── Handle dimensions ──────────────────────────
handle.width:        4dp
handle.touchTarget:  20dp   /* expanded touch zone, centered on handle */

// ── Idle (default) ────────────────────────────
handle.bg:           transparent
hairline.size:        2dp × 24dp, color --border (#272727)

// ── Touch-hold (after activation delay) ───────
handle.bg:           rgba(193, 95, 60, 0.15)
hairline.color:       rgba(193, 95, 60, 0.50)
activation.delay:    Settings → Drag Activation Delay (default 300ms)
activation.haptic:   VIRTUAL_KEY (short tick)

// ── Active drag ───────────────────────────────
handle.bg:           rgba(193, 95, 60, 0.25)
handle.bar:          3dp × 30dp, color --orange, border-radius 1.5dp
handle.glow:         box-shadow 0 0 6dp rgba(193,95,60,0.30)
tooltip.text:        "38%" (left pane width as integer %)
tooltip.bg:          --orange, text #fff, 9sp mono 700
tooltip.offset:      8dp above touch point, horizontally centered on handle

// ── Snap + constraints ────────────────────────
snap.increment:      5%
pane.minWidth:       30%    /* hard stop — refuse to drag below 30% */
release.haptic:      CLOCK_TICK (snap confirmation)
Alternate Terminal Themes — xterm.js Objects v0.19
Solarized Dark · Dracula · Catppuccin Mocha — copy-paste ready

The app UI theme (see 08-theme-architecture.html) switches colors.xml tokens. The terminal canvas uses a separate 21-key xterm.js theme object — two independent systems. Paste the active theme's object into ITerminalOptions.theme when the user changes app theme. No page reload required — xterm.js applies the palette on the next render cycle.

Solarized Dark
cursor: #CB4B16 (Solarized orange)
const solarizedDarkTheme = {
  "background":    "#002B36",
  "foreground":    "#839496",
  "cursor":        "#CB4B16",  // Solarized orange — brand signature
  "cursorAccent":  "#002B36",
  "selection":     "rgba(203, 75, 22, 0.25)",
  "black":         "#073642",
  "red":           "#DC322F",
  "green":         "#859900",
  "yellow":        "#B58900",
  "blue":          "#268BD2",
  "magenta":       "#D33682",
  "cyan":          "#2AA198",
  "white":         "#EEE8D5",
  "brightBlack":   "#002B36",
  "brightRed":     "#CB4B16",
  "brightGreen":   "#586E75",
  "brightYellow":  "#657B83",
  "brightBlue":    "#839496",
  "brightMagenta": "#6C71C4",
  "brightCyan":    "#93A1A1",
  "brightWhite":   "#FDF6E3"
};
Dracula
cursor: #FF79C6 (Dracula pink)
const draculaTheme = {
  "background":    "#282A36",
  "foreground":    "#F8F8F2",
  "cursor":        "#FF79C6",  // Dracula pink — accent signature
  "cursorAccent":  "#282A36",
  "selection":     "rgba(255, 121, 198, 0.25)",
  "black":         "#21222C",
  "red":           "#FF5555",
  "green":         "#50FA7B",
  "yellow":        "#F1FA8C",
  "blue":          "#BD93F9",
  "magenta":       "#FF79C6",
  "cyan":          "#8BE9FD",
  "white":         "#F8F8F2",
  "brightBlack":   "#6272A4",
  "brightRed":     "#FF6E6E",
  "brightGreen":   "#69FF94",
  "brightYellow":  "#FFFFA5",
  "brightBlue":    "#D6ACFF",
  "brightMagenta": "#FF92DF",
  "brightCyan":    "#A4FFFF",
  "brightWhite":   "#FFFFFF"
};
Catppuccin Mocha
cursor: #CBA6F7 (Mocha Mauve)
const catppuccinMochaTheme = {
  "background":    "#1E1E2E",
  "foreground":    "#CDD6F4",
  "cursor":        "#CBA6F7",  // Mocha Mauve — accent signature
  "cursorAccent":  "#1E1E2E",
  "selection":     "rgba(203, 166, 247, 0.25)",
  "black":         "#45475A",
  "red":           "#F38BA8",
  "green":         "#A6E3A1",
  "yellow":        "#F9E2AF",
  "blue":          "#89B4FA",
  "magenta":       "#F5C2E7",
  "cyan":          "#94E2D5",
  "white":         "#BAC2DE",
  "brightBlack":   "#585B70",
  "brightRed":     "#F38BA8",
  "brightGreen":   "#A6E3A1",
  "brightYellow":  "#F9E2AF",
  "brightBlue":    "#89B4FA",
  "brightMagenta": "#F5C2E7",
  "brightCyan":    "#94E2D5",
  "brightWhite":   "#A6ADC8"
};
Theme Switching — runtime pattern
term.options.theme = solarizedDarkTheme;
Call this via the WebView JavascriptInterface when the user selects a theme in Settings. No page reload needed — xterm.js repaints on the next render cycle. App UI theme (colors.xml) and terminal theme (xterm.js object) must be switched together in a single coordinated call.

Note: these are the terminal canvas ANSI palettes — separate from the app UI CSS tokens in 08-theme-architecture.html.
Extended Overlay Bar — Attach Status + Quick Actions v0.21
What's new in the overlay

The existing overlay shows: dot · session name · morph-to-VS-Code button. The extended overlay adds: client-count badge ("0 attached"), tmux window name chip, a Detach action, a Notify toggle, and a Kill action with confirm. All crammed into the same 40px bar — so layout must be deliberate: left = status cluster, right = action cluster.

Terminal canvas (content above)
argus silent-river-c1f0 1 client VS Code
Layout (L→R): dot · session-name · window-name-chip · client-count · [spacer] · Notify · Detach · VS Code · Kill(✕)
Notify: green tint — toggles per-session server-side idle watcher (global default from Settings)
Detach: yellow tint — drops current WebView client; tmux session keeps running
Kill ✕: red tint — triggers confirm dialog before tmux kill-session
Add Pane — Terminal: Redesigned 3-Section Layout v0.21
Why the redesign

Current modal has one text field that ambiguously doubles as URL / window-name / discovery-target. Three intents (pick existing window, override URL, spawn agent) need three distinct zones. Solution: sub-tabs within the Terminal tab body — "Windows" / "URL" / "Spawn" — keeping one clear action per section.

Folder
URL
Terminal
Browser
WINDOWS
URL
SPAWN
1 silent-river-c1f0 LIVE
2 stormy-peak-d3f1 IDLE
3 bright-fog-a9c2 DEAD
WINDOWS tab: live-fetched list from GET /argus-api/windows
Active indicator: orange left-border + green LIVE badge = ttyd currently attached here
IDLE: process alive, no writes 30+min · DEAD: no process, grayed + strikethrough
Button label adapts: "Attach" (Windows tab) → "Open" (URL tab) → "Spawn" (Spawn tab)
New Session — Full-Screen Creation Flow v0.22
Dedicated screen, not a modal

New Session is the highest-value action in Argus. It deserves a full screen — room for the name field, model picker, working-dir picker, kickoff message, and the full toggle catalog without cramming. Opened from: drawer "+ New Session" button, or main FAB long-press.

2:40▲ 85%
New Session
✏️
Auto-generated · tap ✏️ to override
Sonnet 4.6
None
/home/claude
Options
Skip Permissions
Allow Write
Deep Search
Open in pane after create
Notify on completion
Notify when idle 30 min
POST /argus-api/spawn — full body with model, cwd, toggles, kickoff
Last-used persistence — toggles restore from preferences.json
Resume toggle — appears when prior JSONL detected for working dir
Session Cards — Lifecycle + Attachment Badges v0.23
Two-axis badge system

Each session card has two independent state axes: Lifecycle (what the Claude process is doing) and Attachment (whether a tmux client is watching). They're independent — a session can be Active + Detached (process running, nobody watching) which is the normal auto-build state.

silent-river-c1f0
/home/claude/kpmg/genai-api
ACTIVE 📺 WATCHED
Sonnet 4.6·Developer·14m ago·~2.1M tokens
foundation-bigrun-v2
/home/claude
IDLE 🪟 DETACHED
Opus 4.7·Generalist·38m ago·~8.4M tokens
stormy-peak-d3f1
/home/claude/argus
⚠ STUCK 📺 WATCHED
Waiting on permission prompt — 4m 12s
Left stripe color = lifecycle: green=Active · yellow=Idle · red=Stuck · gray=Dead
Right badge = attachment: 📺 Watched=≥1 client · 🪟 Detached=0 clients · ⚠ Raw=no tmux wrap
STUCK = tool_use without matching tool_result for >2min (permission prompt)
Tap card body → Status Detail Screen (§ below)
Terminal-Mode Keybar — 3-Row Layout + Tmux Popover v0.21
Hybrid C — always-on swap + expandable tmux popover

When a TERMINAL pane has focus, the Keybar auto-swaps to terminal mode. Row 1 is always-on: Esc, arrows, Ctrl+C/D/R/L. Row 2 is collapsible: tmux prefix combos (Detach, Copy mode, New/Next/Prev win, Split). Row 3 is user snippets. "More tmux…" opens a full popover with Session/Window/Pane/Copy/Misc tabs. Control codes are yellow-tinted, tmux-prefix chips are orange-tinted (existing .kc-tmux class), snippet chips are blue-tinted.

F-KEYS
F1
F2
F3
… F12
▲ hide
TERM
Esc
Tab
^C
^D
^R
^L
TMUX
Detach
Copy ⬛
New win
Next →
← Prev
Split ⬌
Split ⬍
Zoom
More tmux…
SNIPPETS
git status
git pull
tmux ls
claude /clear
+ snippet
Yellow tint: control codes (^C/^D etc.) — single byte sent to foreground process
Orange tint: tmux prefix combos — 2 keystrokes with 50ms delay
Blue tint: snippets — typed string + Enter (configurable)
"More tmux…" opens popover below the keybar with Session/Window/Pane/Copy/Misc tabs
Tap the button above to toggle popover demo ↑
Confirm Dialogs — Destructive Actions v0.21
Kill Window — tmux kill-window
Kill Window?
stormy-peak-d3f1
This will kill the tmux window and end all processes in it. The session cannot be recovered.
Kill Session — tmux kill-session
🗑
Kill Session?
foundation-bigrun-v2
All windows and panes will be destroyed. Any running Claude agents will be terminated. JSONL output is preserved.
Trigger surface: Kill button on session card, Kill button in window list, Keybar Kill win chip, overlay Kill ✕
Escape / back: dismiss dialog, no action taken
JSONL preserved: session data survives; only the tmux process is killed
Status Detail Screen — Tap Card to Drill In v0.23
Full session introspection

Tapping a session card body (not the action buttons) opens the status detail screen. It shows: tmux state, JSONL preview (last few tool calls), model/token breakdown, and action history. Primarily for diagnosing stuck sessions and understanding what a background agent is actually doing.

2:40▲ 85%
silent-river-c1f0
/home/claude/kpmg/genai-api
ACTIVE
2.1M
TOKENS
14m
RUNTIME
23
TOOL CALLS
tmux State
session: argus
window: 0:silent-river-c1f0
clients: 1 attached
status: running (pid 48291)
Recent Activity
14:22:01 tool_use Read src/routes/chat.py
14:22:02 tool_result ✓ 248 lines
14:22:04 tool_use Edit src/routes/chat.py:142
14:22:05 tool_result ✓ applied
14:22:08 tool_use Bash pytest tests/ -v
14:22:12 tool_result 3 passed, 1 failed…
Multi-Terminal Pool — 2-Pane Independent Terminals v0.21 blocker
Option B — per-pane ttyd instance pool

Each terminal pane triggers a POST /argus-api/ttyd/spawn to fork a dedicated ttyd on an ephemeral path (/terminal/p1/, /terminal/p2/). Each pane has a window-picker dropdown in its header to choose which tmux window to attach. Max 4 simultaneous. Pool-full error shown inline. Status: live · loading · dead.

1
silent-river-c1f0
1/2 LIVE
claude@argus:~/kpmg$ pytest
3 passed, 1 failed
in 2.34s
claude@argus:~/kpmg$
Running · 5m VS Code
2
stormy-peak-d3f1
2/2 LOADING
Spawning ttyd…
Connecting…
Terminal pool exhausted (4/4) — close a terminal pane to open another
Window picker: dropdown in each pane header — pulls from GET /argus-api/windows
Sibling badge "1/2": shows how many terminal panes are open (each pane shows its own index)
LIVE: ttyd running, WebSocket connected · LOADING: ttyd spawning · DEAD: tap to respawn
Pool max: 4 concurrent ttyd instances — soft cap matches maxPanes budget
Keybar Architecture — Spanning vs Per-Pane v0.21 decision
Recommendation: Spanning (B) — one bar, follows focus

With two terminal panes open, only one can be actively typed-into at a time. A single spanning keybar at the bottom that follows focus is cleaner than duplicating chip strips inside each pane footer. Orange left-border glow on the focused pane header is the visual indicator of where keystrokes go. Per-pane mode is a Settings option for users who prefer it.

RECOMMENDED Spanning — one bar, follows focused pane
1 TERMINAL ▶ focused
$ claude
2 TERMINAL
$ git status
→ PANE 1
Esc
^C
Detach
Copy ⬛
More tmux…
Per-Pane — chip strip inside each terminal footer (Settings option)
1 TERMINAL
$ claude
Esc
^C
Detach
2 TERMINAL
$ git status
Esc
^C
Detach
Focus routing indicator: "→ PANE 1" label at left of spanning bar · orange left-border glow on focused pane
Focus change animation: chip strip fades out → fades in with new pane's context (100ms)
No terminal focused: keybar falls back to standard Quick Actions 9-chip row
Settings: Settings > Keybar > Layout Mode — Span (default) / Per-pane / Floating
Error States — Auth Failure · Spawn Failure · Empty List v0.21
AUTH FAILURE
🔐
Authentication Failed
401 — Bearer token rejected by argus-sessions-api. Check your token in Settings > Connection.
SPAWN FAILURE
Agent Spawn Failed
Server returned 500. tmux may be unavailable or claude binary not found in PATH.
EMPTY WINDOW LIST
📋
No Sessions Found
No tmux windows in the argus session. Use Spawn to start a new agent, or check the connection.