Anatoli Kot

Anatoli Kot

Software Engineer · Cybersecurity

softwaresecurityhigh

Agent Dashboard

Real-time monitoring and control plane for locally running Claude Code agents — a Go and Vue dashboard that discovers agents by scanning processes, streams tokens, cost and status over SSE, and drives a multi-stage task pipeline in isolated git worktrees. I'm not its author — my work extends it in my own fork.

Role

Open-source contributor — 24 commits (+5,900 lines across 86 files) in my fork of lx-wnk/Agent-Dashboard, not yet merged upstream

Problem

Running several agents at once leaves you with no shared view of what they are doing, what they cost, or which one is waiting on an answer. The upstream project solves that by reading what Claude Code already writes to disk, with no per-project hooks. My work went into the surfaces that make it legible: the workspace an agent is inspected in, the machine context around it, and a set of performance and correctness faults underneath both.

Tech Stack

GoVue 3TypeScriptTailwind CSSViteServer-Sent EventsSQLiteMCP

How It Works

Discover AgentsLocalScope CollectorAllow-List ProxyLive Roster (SSE)Agent Workspace
  1. 01The dashboard finds agents with no setup per project — scanning processes and reading each one's CLAUDE_CONFIG_DIR to tell profiles apart — then streams the roster to the browser over SSE with live tokens, cost, status and uptime.
  2. 02I replaced the fixed details drawer with an agent workspace that makes the conversation the primary surface and puts the intelligence column beside it rather than behind a tab, and rebuilt Overview as a command center: metric row, system map, and an activity feed read from the audit log.
  3. 03LocalScope — a separate read-only collector for the machine's listening services and processes — is consumed rather than reimplemented. It binds loopback and answers Access-Control-Allow-Origin: null, so a browser cannot call it directly; the Go server proxies an allow-list of GET paths same-origin instead of opening a general route into loopback.
  4. 04Those services are correlated to agents by segment-safe path containment in both directions, so a card shows the ports running inside the project that agent is editing — and a chip only becomes a link when the collector reported a real URL, never one composed from a port.
  5. 05Throughout, unavailable and zero stay different claims: a null count renders as "not collected" rather than 0, and every panel separates loading, empty, unavailable and failed.

What I Learned

  • Working inside someone else's large codebase is its own skill. The fastest way in was to find the rule that already existed — the correlation logic the workspace diagram used — and move it somewhere shared, rather than write a second copy that could drift out of agreement with the first.
  • A bug's reported symptom is rarely its cause. An intermittent 429 on one endpoint turned out to be a per-IP rate limiter sized for auth probing but applied to every read the page makes, quietly killing all four SSE streams on each cold load and dropping live updates to a 3-second poll.
  • Caching a resolved value deduplicates sequential callers but not simultaneous ones. Caching the in-flight promise instead was the whole difference between one request and one per mounted component.
  • "Unavailable" and "zero" are different claims, and merging them makes a dashboard lie quietly — a count of null shown as 0 tells you the system looked and found nothing, when it never looked at all.
System Status
>_anatoli@portfolio|OS: PortfolioOS (Next.js 16.3.4)Kernel: React 19.2.8CPU: TurbopackProjects: 14Languages: TypeScript, JavaScript, Python, Java