assistant-logA self-hosted, single-user log aggregator for CLI AI assistants (Claude Code, opencode, crush, pi, kimi). Server runs on a home server (phoebe) behind Tailscale; collectors run as systemd user units on each machine and POST normalized turns to SQLite + FTS5. Server-rendered HTML UI, no SPA. Single user. Full transcripts of every session across every tool across every machine, searchable in one place.
GitHub/Linear-style dense data UI for power scanning. Built on the assumption the user lives in terminals all day and wants information density, not chrome.
#1c1a17), monospace, contains breadcrumb (assistant-log / scarlet), an always-visible search input that responds to ⌘K, and tab nav (Recent / Projects / Stats / Health / Settings).#fdfcf8), Inter for prose, JetBrains Mono for all data (timestamps, paths, tokens, IDs).#c96442, used sparingly — selected tab, primary chip, sparkline highlight, FTS hit highlight, "stale" warnings.var(--ink-3) color.--rule-2 dividers, hover #f3f0e7.#ebe7d8, host-green #d9e6dd, accent terracotta. Per-tool a 8 px square color dot (claude-code terracotta, opencode green, crush purple, pi ochre, kimi blue).display: grid; grid-template-columns: …, mono in time/path/numeric columns, sans in prose columns.Home (Recent) — Reverse-chronological feed of sessions across all tools/hosts. Columns: when · tool tag · host tag · session question + cwd · turns · tok · turns/h sparkline. Top sub-bar carries tool: any · host: any · since: 30d chips and a global turns/day sparkline.
Search results — Results are a flat table of turns (not sessions), one match per row, with the snippet truncated and FTS hits wrapped in a terracotta <mark>. Filters in chips above. Save-search action lives next to the chip row.
Session view — Two-column. Left aside (240 px) is a turn list with # · role glyph · preview · token count, current turn highlighted with a left accent border. Right pane is the linear transcript: each turn is a row separated by 1 px rules, role label is mono uppercase color-coded (USER neutral, ASSISTANT accent, TOOL muted), tool calls render as monospace cards with a faint background tint. Sticky header carries cwd · title · tool tag · host tag · model · turn count · tokens · open dot.
Project view (cwd) — Header shows ~/code/ breadcrumb + tt-bundle in mono, count chips, and a sparkline of activity. Saved-search chips below. Then the same dense session table filtered to that cwd.
Stats — Top sub-bar has range pills (7d / 30d / 90d / all) and group-by pills (tool / host / project / model). Content is a grid of cards: per-tool stat strip (turns / tokens / cost / sparkline / share %), a stacked turns/day chart (60 days), a 12-week activity heatmap, and a top-cwd bar list.
Ingestion health — Status pills in sub-bar (● 7 ok · ● 1 warn). Table of every (host, tool, source) row with: status dot · host · tool · source path · lag · outbox depth · last-OK · events 24h. Stale rows get accent-colored lag, non-empty outboxes get accent-colored count. Footer strip: backfill progress bar + last parser error inline.
Settings — Sidebar nav (Sources / Display / Auth / Backup / Export / Tags / Saved searches). Sources page is the dense source table with status dot, tool tag, path, poll interval, event count, last-OK, edit. Display has compact tag-pair toggles (density, tool calls, accent).
j/k move row, ↵ open, g h/s/p/i jump to home / stats / projects / health.Sample sessions (across claude-code, opencode, crush, pi, kimi on laptop and workpc):
| time | tool | host | cwd | first prompt | turns | tok | model |
|---|---|---|---|---|---|---|---|
| 14:22 | claude-code | laptop | ~/code/tt-bundle | lockfile design for the tt bundle — should we hash inputs or outputs? | 84 | 12.4k | claude-opus-4-7 |
| 11:08 | opencode | workpc | ~/work/atelier/migrations | why does the v3 migration drop the partial index on (org, ts) | 12 | 2.1k | gpt-5-mini |
| 10:52 | claude-code | workpc | ~/work/scarlet-svc | is there a way to make this retry loop tolerate 429s without a sleep | 41 | 7.7k | claude-opus-4-7 |
| 09:14 | crush | laptop | ~/code/dotfiles | rewrite this zsh prompt to show ssh host only when on a remote | 6 | 0.9k | gemini-2-flash |
| Yest | pi | laptop | ~/notes | help me draft a one-pager for the offsite session on incident response | 19 | 4.0k | inflection-3 |
| Yest | claude-code | laptop | ~/code/tt-bundle | when do we need to re-resolve transitive deps after a lock bump | 28 | 5.3k | claude-opus-4-7 |
| Yest | kimi | workpc | ~/work/atelier | translate these comments to english but keep the tone | 4 | 0.7k | kimi-k2 |
Ingestion health — 8 collector rows (one per host × tool):
| host | tool | source | lag | outbox | last ok | status |
|---|---|---|---|---|---|---|
| laptop | claude-code | ~/.claude/projects | 4s | 0 | now | ok |
| laptop | opencode | ~/.local/share/opencode | 12s | 0 | 12s | ok |
| laptop | crush | ~/.cache/crush | 28s | 0 | 28s | ok |
| laptop | pi | ~/.config/pi/history | 1m | 0 | 1m | ok |
| workpc | claude-code | ~/.claude/projects | 7s | 0 | now | ok |
| workpc | opencode | ~/.local/share/opencode | 18s | 0 | 18s | ok |
| workpc | kimi | ~/.kimi-cli/history.jsonl | 2m | 127 | 2m | warn |
| workpc | crush | ~/.cache/crush | 8m | 0 | 8m | stale |
Per-tool 30-day rollups:
Build a hi-fi clickable prototype of a personal CLI AI assistant log aggregator UI in the Dense Data UI style described in the attached spec. One HTML file. Real navigation between screens (top-bar tabs, row clicks, ⌘K search focus, filter chips). Cover Home / Search / Session / Project / Stats / Health / Settings. Use the mock data shape and visual system specified.