Browser operations surface

Web Dashboard and Workspace

A Nord-styled browser control plane for Cacophony operators.

The caco-web service serves the overview dashboard and the /workspace MVP. Both are daemon clients: they load snapshots from the local daemon, subscribe to SSE updates, and open terminal panes through first-party agent PTY endpoints rather than talking directly to tmux or remote daemons.

caco ui launches the same dashboard in a co-installed Tauri desktop shell on Linux and macOS. The native app owns a loopback dashboard process for its lifetime, adds native window and keyboard integration, and does not require a separately launched caco web.

Visual changes are reviewed against deterministic fixture captures: scripts/caco-web-ui-capture.sh renders every view at desktop, tablet, ultrawide and phone sizes and in each theme, without contacting a live daemon.

Screenshots

The dashboard

Captured from a synthetic three-node demo fleet.

caco-web Status view with fleet health, running agents, open beads and recent activity
StatusFleet health, active work and recent activity on one screen.
caco-web Agents view listing agents across three nodes with state filters
AgentsEvery agent across the mesh, filterable by state, node and project.
caco-web Beads board with in-progress, open and blocked beads
BeadsThe task board, with priorities, labels and assignees.
caco-web Flows view showing a running feature.ship flow graph
FlowsTyped flow graphs with live node state for each run.
caco-web project chat between the operator and agents
ChatProject, group and direct chat with batched or immediate delivery.
caco-web command palette filtering commands for beads
Command paletteEvery view and action from the keyboard.
caco-web chat on a 390 px phone screen caco-web inbox on a phone with a pending choice caco-web agent list on a phone
The same dashboard at 390 px: navigation collapses and every view stays usable.

Entrypoints

RoutePurpose
/Dashboard overview, release/status cards, project and fleet summaries, plus top-level Inbox, Links, and other operational views.
/workspacePane-based browser workspace for agents, beads, summaries, logs, source views, chat, and terminal slices.
#tui / TUI navigation itemPersistent browser-hosted terminal for an operator-supplied agent running caco tui --project caco-web.
/terminal.htmlStandalone terminal surface used by legacy/detail flows.
/notifications.htmlFocused notification list for operator triage.

Native desktop shell

Run caco ui for the native Linux or macOS application. It starts an app-owned dashboard on 127.0.0.1:11801, selects a free loopback port if that port is occupied, disables redundant browser authentication only for that private child, and terminates the owned server when the window exits. Existing dashboards selected with --web-server retain their normal authentication contract.

Use caco ui --serve to print the app-owned local URL for concurrent browser inspection. Use caco ui --web-server workstation:11180 or a complete HTTP(S) URL to skip local server startup and connect the native shell to an existing dashboard. Native shortcuts add Cmd/Ctrl+1…7 for the primary destinations, Cmd/Ctrl+L for project scope, and Cmd/Ctrl+, for theme selection without replacing the dashboard’s accessible browser shortcuts.

The Tauri binary is built as a separate Rust derivation, keeping GTK/WebKit build dependencies out of ordinary workspace checks. Linux packages install a freedesktop Caco UI launcher and icon. Darwin exports an ad-hoc-signed Caco UI.app with bundle identifier dev.cacophony.ui, a native ICNS icon, and the Mach-O caco-ui executable as its bundle entry point. The shell resolves caco from an explicit argument, a sibling executable, the nix-darwin system profile, the user Nix profile, the Cargo profile, or PATH. Its distinct identity does not overlap the native SwiftUI Cacophony.app. The manual-only Tauri desktop manual build workflow serializes Linux Nix build and headless lifecycle validation and never runs on pushes or pull requests.

Dashboard authentication

The dashboard authenticates with an httpOnly session cookie, not a bearer token embedded in the page. When the session is missing or expired (a 401 from the API), caco-web shows a Sign in overlay where the operator pastes the caco-web access token — the contents of $CACOPHONY_DIR/tokens/caco-web.token. That posts to POST /api/web/session, which sets the httpOnly cookie, and subsequent /api calls carry it.

For zero-config loopback launches, caco web prints a launch URL carrying a single-use ?token=<bootstrap>. The page strips that token from the URL synchronously before any network request (no Referer leak, no lingering in browser history) and exchanges it for the session cookie through the same /api/web/session endpoint, so the durable dashboard token never travels in a URL. A consumed, expired, or wrong bootstrap token falls through to the same Sign-in overlay.

Enforcement is default-on once the dashboard token and cookie-signing key are configured: an explicit CACO_WEB_ENFORCE_AUTH env wins (1/true enforces, anything else disables), otherwise the gate enforces whenever those credentials are present and stays inert when they are unset, so unconfigured/dev setups are unchanged. When enforcement is active, the daemon-proxy API surface (/api/*, except the /api/web/session login endpoint) and /metrics require a valid session cookie or the dashboard bearer and otherwise return 401; static pages, /health, and the login endpoint stay open. The dashboard surfaces that 401 as a distinct login-required connection state (the Sign-in overlay) rather than a generic disconnected/backend-unavailable banner, so an auth gap is not mistaken for a backend outage.

Dashboard Shell Controls

Nodes View

The dashboard Nodes section is the browser member of the shared caco-web, TUI, Android, and native macOS Nodes contract. It exposes top-level cluster navigation, keeps node selection in the URL hash, orders the local node first when known, and opens a node detail panel without leaving the dashboard shell. The daemon snapshot now includes a bounded topology projection derived from config, peer reachability, relay state, and beads-primary routing, so browser/TUI/mobile/macOS clients can share direct/relay edge data, active-primary markers, dynamic-node metadata, and truncation status without inventing separate topology models.

Stats View

The dashboard Stats section renders the unified fleet stats aggregate from /api/v1/stats (the same endpoint the CLI, TUI, macOS, Android, and iOS surfaces consume) as raw figures plus charts. It shows the cluster compute/storage rollup with per-node CPU/memory/disk utilization bars and a sortable per-node table, fleet token usage by project with cached-versus-fresh input/output cards and composition, and bead throughput — closed-rate totals plus a closed-bead time-series trend (sparkline). A project filter narrows the throughput/token sections and a node filter narrows the per-node rows while the fleet compute rollup stays whole, and the window/bucket selection drives the throughput series. Filter and sort state is reflected in the URL hash so refreshes and shared links restore the same view. Operators can also export the current stats payload as a JSON download or the per-node compute table as a CSV download.

Workspace Contract

Chat Composer Loops

The dashboard chat composer uses the live agent list for @ agent-username suggestions; workspace chat panes request include_body=true for reader views and render message/file attachments as chips; selecting a suggestion inserts the mention token while send/routing semantics remain part of normal chat submission. It also shows local send-state feedback: an in-flight send remains visible as pending, successful acceptance is replaced by the canonical message row, and pre-accept failures remain visible with manual retry/failure affordances instead of vanishing. It also understands /loop <interval> <message>, /loop status, and /loop off as first-class slash commands. A browser loop captures the currently selected project, channel, and speak/broadcast/direct target at creation time, then repeats through the same message endpoints as ordinary chat sends. Project chat sends, retries, and loop creation treat the visible project channel as authoritative, so a channel such as #kittui cannot fall back to a stale default-project filter and broadcast to unrelated agents.

Use browser loops for operator-visible recurring nudges from the current chat context. Use the CLI caco loop surface for terminal-driven narration loops, and the Pi-native /loop mixin inside managed Pi runtimes.

Backend Health Semantics

caco-web and the daemon behind it can be healthy at different times: while a restart converges, the shell and /health answer but proxied daemon APIs fail. The dashboard says which situation it is in rather than showing healthy-looking zeros.

You seeWhenBehind it
Backend unavailabledaemon APIs fail during restart convergence, or the snapshot upstream returns 500, 502 or 504a 200 OK sentinel with error:"daemon_proxy_upstream_error" and X-Caco-Upstream-Status
Snapshot delayed/api/v1/ui/snapshot exceeds caco-web's short backpressure budgeta 200 OK sentinel with error:"daemon_proxy_timeout", backend_unavailable:true, upstream_status:504; it retries
Cached state · reconnecting, with a stale badgethe live stream has failed for longer than a 15-second gracethe last known rows stay visible; pages with nothing cached fall back to disconnected
Agents delayed, Beads unavailable …the same states, inside workspace panesnever shown as an empty search result
Loaded Beads, in warning coloursthe snapshot has no bead_statsthe count is rows loaded, not the board total; caco bd status is authoritative
Summaries unavailable, retryablea summaries read takes longer than 12 secondsthe proxy gives up rather than holding a daemon handler open

Persistent caco-web Development Loop

The shipped caco-web persistent profile is intentionally active rather than idle. On each wake it should inspect inbox and ready browser-dashboard beads, coordinate ownership of any existing local dashboard listener, run a real browser audit, file or claim focused defects from evidence, validate targeted fixes, commit all bounded artefacts, and reintegrate with caco agent reintegrate --mode direct without terminating the persistent agent.

  1. Scan and scope. Check assigned work plus ready/open beads mentioning caco-web, caco web, browser, dashboard, workspace, summaries, visual-polish, or playwright. Claim exactly one clear caco-web implementation bead, or continue the observation loop when no suitable bead exists.
  2. Own one dashboard instance. Inspect caco web status, listening processes, and recent handoffs before launching anything. A healthy listener without a managed PID is evidence for the lifecycle tracker, not a reason for this agent to kill or restart services.
  3. Allocate artefacts first. Create a stable pending directory such as .cacophony/agent/<agent-id>/summary/pending/web/ before driving the browser; direct reintegration assigns the final summary/<NNNN>/ state-branch path. Store the observation log, server log, audit markdown, screenshots, console logs, network evidence, and notes there.
  4. Drive the real UI. Prefer cargo run -p caco-web --bin caco-web-observe -- --url http://127.0.0.1:11180 --comprehensive --out ... --server-log ... --audit-md .... The comprehensive pass visits Status, Agents, Beads, Feed, Chat, Nodes, Services, Projects, Choices, Notifications, Actions, Logs, Timeline, Summaries, Workspace, narrow and wide layouts, and every Workspace pane type. The observation log records served web /health version, proxied daemon /api/v1/node version, and daemon URL; if it prints a version-skew warning, interpret failures as live-daemon/served-asset evidence rather than checkout source proof until the runtime is refreshed.
  5. Show what changed. Post the screenshot set to the kitty preview area for operator review, then summarize console/network status, served version, daemon version, PID ownership, Workspace copy, and whether the pass exposed a source defect or only operational/restart-window evidence.
  6. Fix only focused browser-dashboard defects. File one bead per distinct issue with reproduction steps and artifact paths, claim it, implement a small source fix, run targeted validation such as cargo check -p caco-web --all-targets and cargo test -p caco-web --lib, rerun the focused Playwright proof, and close only after reintegration lands.
  7. Land every cycle. Observation-only cycles still write summary.md, commit the summary directory and curated artefacts, rebase if main advanced, and reintegrate directly. The persistent agent then returns to the web loop unless the operator explicitly asks it to pause.

Live-DOM Validation Tooling

The browser dashboard is a single-page app with an open Server-Sent-Events stream, which gives the live-DOM validation tooling a few sharp edges worth documenting so caco-web specialists do not re-derive them each session.

Service Management

Use caco web status for the dashboard service itself. It checks the configured dashboard ownership mode, standalone PID when applicable, local /health, and served-version drift from the current CLI/package version.

Visual Design

The Pages docs mirror caco-web's visual language: dark Nord tokens, the same semantic CSS variables, 8px card radii, subtle borders, and short hover transitions. The webapp stylesheet remains the source of truth for tokens; the docs site keeps a lightweight curated stylesheet rather than copying the full dashboard CSS bundle.