--- created: '2026-07-09' path: Sources/Homelab project: tokened tags: - homelab - podman - traefik - observability - claude-code - tokens type: project-plan --- ## Goal Visualize where the context window goes across Lovebug (herbyadmin) Claude Code sessions — turn the raw JSONL we've been hand-grepping into a standing, glanceable dashboard. Born from a session that hit 708k/1M and the question "where did it all go?" ## Success criteria 1. **Up and reachable** — `tokened.herbylab.dev` resolves through Traefik, loads, no auth wall; container runs rootless as herbyadmin reading `~/.claude/projects` read-only. 2. **Sees the real data** — herbyadmin's sessions appear across all project folders (not just lovebug-instructions), including the 3-day marathons; session list populated and browsable. 3. **Numbers are trustworthy** — dashboard's total for at least one known session roughly matches that session's `/context` reading, validating the message.id dedup. Separates "pretty" from "true." 4. **Answers the founding question** — for any session, see token breakdown by category and spot heavy hitters (e.g. read_worker_transcript-heavy, Bash-heavy patterns) without touching a terminal. 5. **Cool graphs.** Non-negotiable. Heatmaps and per-prompt cost charts render and are nice to look at. An unopened dashboard is a failed dashboard. ## Build shape - **Source:** fork upstream `nateherkai/token-dashboard` into Gitea petal-power org; build from the fork, pinned commit. Fork is load-bearing (expect local patches), not cosmetic. - **Runtime:** rootless Podman, run as herbyadmin on herbys-dev. `--userns=keep-id` → container is herbyadmin, reads own files natively. - **Mounts:** `~/.claude/projects` → `:ro`. SQLite cache → named volume, writable, herbyadmin-owned. - **Lifecycle:** manual `podman start` (fish abbr for convenience). No systemd. Dies on reboot until poked — accepted for v1. - **Ingress:** Traefik file-provider route → `tokened.herbylab.dev`. Wildcard cert. No auth (private VLAN, behind server). - **Container build:** Lovebug writes the Containerfile — `python:3.12-slim`, stdlib-only app, no build step. - **Deploy tree:** `/opt/projects/homelab/tokened/`. - **Stack fit:** first Podman tool on herbys-dev (rest is Docker) — deliberate low-stakes sandbox for the rootless model. ## Open questions — Lovebug resolves via survey before building 1. **Config surface** — does the app take `CLAUDE_PROJECTS_DIR` / a cache-path / `PORT` / `HOST` via env, or are paths hardcoded to `~/.claude/projects/`? Read the scanner source. Determines whether the mount path must match the app's expectation or can be redirected. Biggest "won't-just-work" risk. 2. **Bind address** — app defaults to `127.0.0.1`; inside the container it must bind `0.0.0.0` (container netns is the boundary) so Traefik can reach it. Confirm PORT/HOST are settable. 3. **Source-tagging** — deferred to build time by design. Goal is to tag each session by source-agent (orchestrator / worker / interactive) using JSONL fields (agentType, parentToolUseId) — richer than folder-tagging. Survey whether upstream exposes this as a dimension or flattens it; if flattened, this is fork-patch #1. Work out during build. ## Design principle Static, on-demand tool — read when opened, no live streaming. Upstream's 30-second re-scan is unwanted; disable or ignore. Keep as many axes in the data as possible (source-agent, project-folder, tool-type, per-prompt cost, cache-hit, time) — slicing them is the point. ## Validation checkpoint Once up, sanity-check dashboard total vs `/context` for a known session (criterion 3). Rough agreement = dedup works, numbers trustworthy. Divergence = don't trust it, investigate. This is the fun part. ## Out of scope / v2 negative-space - Reboot persistence (Quadlet / systemd-user lingering) — accepted manual for now, explore later. - Deep axis-slicing / custom graphs beyond upstream defaults — the fork roadmap, not v1.