// vscode extension in daily use

Fulltrace Dashboard

Watch and run all of Fulltrace from inside the editor

The window onto Fulltrace, built into my code editor: a VSCode extension that shows everything the system is doing without leaving it. A sidebar tree gives status at a glance; a seven-tab panel goes deeper, headlined by Studio. I pick a job, see the price before it runs, approve the spend, and watch it work live through to the finished report.

07 dashboard tabs 05 studio views 03 clients tracked 0 runtime dependencies
the_tour [01]

The Dashboard, Toured

The dashboard, walked live: the sidebar rail, the seven tabs, a workflow taken from the catalogue through to what it cost, and then a finished run opened up to its per-stage verdicts and findings. Hover to hold a step, or drive with the dots.

The Fulltrace sidebar, toured in five steps. One, STATUS: gateway health, uptime, memory and process controls. Two, Open Dashboard opens the workspace and fills the main area with the workflow catalogue. Three, USAGE: Claude, Codex and OpenRouter budget windows with reset timers. Four, TOOL USE: session and all-time counters and a per-model token breakdown. Five, MCP SERVER: Context, Commands, Memory and Hooks as live resource trees.
1 · Runtime health The status rail: online state and uptime, memory, restarts and uptime percentage, with start, restart and stop. Open Dashboard opens the workspace.
2 · Open the workspace Open Dashboard launches the full panel: Studio and its five views, live and ready to drive. The main area fills in with the workflow catalogue.
3 · Budget windows Live usage against every limit at once: Claude's 5h and 7d windows, Codex's 30d window, and the OpenRouter credit balance, each with its reset time. A run is never launched into an exhausted quota.
4 · Session telemetry Session and all-time counters (requests, context reads, commands, tokens), plus a per-model token breakdown, so spend is attributable model by model.
5 · MCP surface The extension's own MCP server, exposing Context, Commands, Memory and Hooks as live resource trees the assistants read from and write to.
The sidebar rail, toured. Each section expands as it is explained, and Open Dashboard reveals the workspace; hover to hold a step, or jump straight to one with the dots.
  1. 1Runtime health. Online state, uptime, memory and restarts, with start, restart and stop controls.
  2. 2Open the workspace. Open Dashboard opens the full panel and fills the main area with the workflow catalogue.
  3. 3Budget windows. Live usage against Claude's 5h and 7d windows, Codex's 30d window, and OpenRouter credits, each with its reset timer.
  4. 4Session telemetry. Session and all-time counters, plus a per-model token breakdown for attributable spend.
  5. 5MCP surface. The extension's own MCP server: Context, Commands, Memory and Hooks as live resource trees.
studio [02]

One Hub for the Whole Run Lifecycle

Studio consolidates workflows, runs, audits, models, and agents into one screen organised around the life of a run. I choose the work, check the price, confirm the spend, and watch it happen live through to the result, without touching a terminal. Watching is always read-only; anything that acts, launching a run, editing a workflow's saved default models, warming or evicting a local model, running or removing a sub-agent, recording a disposition against a finding, is a deliberate, confirmed press, and every one of those acts is ledgered.

flowchart LR
    D["Discover
workflow catalogue"] --> C["Configure
choose options
and targets"] C --> E["Estimate
cost priced from
run history"] E --> L["Launch
explicit spend
confirmation"] L --> O["Observe
live runs +
graph view"] O --> U["Understand
results and
findings"] %% Blueprint tokens as literal hex (Mermaid cannot parse CSS vars or color-mix) classDef step fill:#62d99a1f,stroke:#62d99a,stroke-width:1.5px; classDef spend fill:#e0be621f,stroke:#e0be62,stroke-width:1.5px; class D,C,E,O,U step; class L spend;
Live without a reload

The screen updates itself every 4 seconds while a job runs, advancing node statuses and moving finished runs from Active to Completed. An idle tick never redraws the page or closes something I have open.

Outcomes, not just statuses

Graph nodes badge whether their newest stage was approved or rejected, not just whether it ran. Finished runs carry their cost, tokens, and models, and by-model donut charts break spend down per model for a workflow or a single run.

Drill through to the evidence

Clicking any fan-out node opens its detail: the findings report it produced, a clear passed-or-failed verdict, the models and tokens each stage used, and a jump straight into the Audits view with that target already selected.

apply [03]

Approving a Fix, Without Trusting It

The audit does not just find problems, it offers to fix them, and this is the one place in Fulltrace where an AI can actually change my code. So it is the part I was most careful with. The flow is four steps: review, dry-run, approve, apply, and what makes it safe is what sits between them. I see the exact change first, the project's own build has to accept it before I am even asked, and what I approve is that one specific change, not a standing permission.

A code audit findings report, toured in six steps. One, the report opened from a run's audit node: seven findings, each its own card. Two, every finding graded before it is read, by severity, model confidence and the risk of its fix, then located to a file, line and function. Three, why it matters kept separate from the suggested change, with a jump straight to the source. Four, a structural finding refused an automatic fix and offered a plan instead. Five, a safe finding offered Prepare fix, which drafts a change and freezes it as a hashed artefact without applying anything. Six, the decision row: accept, reject, defer or ask for evidence, recorded against this report only and with no effect on future audits. 1 2 3 4 5 6
1 · Seven findings, one report What Open full report opens: the audit node's own findings, each one a card carrying what it found, why that matters, what it would change, and what you are allowed to do about it. The count sits in the editor tab.
2 · Graded before it is read Every finding arrives pre-sorted: how serious it is, how confident the model is that it is real, and how risky its fix would be. Then exactly where, down to the file, the line and the function.
3 · Reasoning, then remedy Why it matters and Suggested change are kept apart on purpose, so the argument can be judged separately from the patch. Open source jumps straight to the line being argued about.
4 · Not every finding gets a fix button This one is structural, and a structural fix rarely fits in one self-contained edit. So the system does not offer to make it: it refuses itself the option and offers to plan the work instead. The finding still stands, it just does not come with a patch.
5 · The safe ones get a dry-run The finding below is flagged safe, so it earns a Prepare fix. That drafts the change and freezes it as a hashed artefact, and applies nothing: a separate simulation has to put it through the project's own build first, and an approval binds to that exact hash.
6 · My call, and it stays mine Accept, reject, defer, or ask for more evidence, with a note. The interface says what that does and does not do, in the label itself: no effect on future audits. Nothing recorded here trains anything.
A code audit findings report, toured. Two findings from the same run, treated differently: the structural one is refused an automatic fix, the safe one is offered a dry-run, and the last word on both is mine. Hover to hold a step, or jump straight to one with the dots.
  1. 1Seven findings, one report. What a run's audit node produced, each finding its own card.
  2. 2Graded before it is read. Severity, model confidence, and the risk of the fix, then the file, line and function.
  3. 3Reasoning, then remedy. The argument is kept separate from the patch, with a jump to the source.
  4. 4Not every finding gets a fix button. Structural findings are refused an automatic fix and offered a plan instead.
  5. 5The safe ones get a dry-run. Prepare fix drafts a change and freezes it as a hashed artefact, applying nothing.
  6. 6My call, and it stays mine. Accept, reject, defer or ask for evidence, recorded with no effect on future audits.
Frozen, then fingerprinted

The proposed diff is frozen as an immutable artefact and hashed the moment I see it, and my approval binds to that exact hash. If anything about it shifts afterwards, a newer dry-run supersedes the old approval rather than inheriting it, and any drift refuses fail-closed. Grants carry a short TTL, and I can withdraw one at any time.

Simulated before it is offered

Before I am asked anything, the fix is applied for real against the project, run through that project's own build gate, and always reverted. Only a fix that passes this simulation ever reaches an approval prompt, so I am never asked to approve something that would immediately fail. Nothing unapproved is ever kept.

Stricter from Studio than from the CLI

The easy button is the safe one: a write triggered from Studio always runs with approvalRequired switched on, stricter than the command line's own default. The surface with the friendliest buttons is the one with the tightest gates, not the other way around, and every attempt is ledgered, kept or reverted.

It has already earned its keep

A fix the AI proposed once referenced a class that did not exist. The target's own compile rejected it, the change auto-reverted, and I was shown the verbatim error. Once simulation shipped, that entire class of fix stopped reaching approval at all. Real fixes have been applied and kept through the full path since, the milestone being the first artefact-bound, human-approved write driven end to end from Studio.

architecture [04]

Single Poller, Two Surfaces

One StatusPoller polls the gateway's GET /status every 4 seconds and scans the filesystem for skills, commands, memory files, and agents. The sidebar and the full panel both read from that same poller, so the two surfaces never drift out of sync with each other.

Sidebar TreeView

Always visible in the VSCode activity bar. Shows server status, uptime, last memory sync time, and the portfolio file list, and opens any portfolio file straight into the editor. No interaction needed to keep it current: the poller drives updates automatically.

WebviewPanel

Opens on demand from the activity bar or command palette into the full seven-tab interface. It is a passive consumer of the same poller state, so opening it triggers no extra requests. The layout fills the editor window and scrolls within the active tab only; the status card and tab nav stay fixed.

status_poller_scanwhat one poller reads, every 4s
StatusPoller (4s interval)
├── polls GET /status ──▶ server metrics, token counts, logs
├── scans ~/.claude/commands/ ──▶ skills list
├── scans ~/.claude/projects/*/memory/ ──▶ memory entries
├── scans ~/.codex/memories/ ──▶ Codex memory entries
└── scans ~/.claude/agents/ ──▶ agents list
├── DashboardTreeProvider (sidebar) ── always visible
└── DashboardPanel (webview) ── on demand
technical [05]

Implementation Notes

01
Zero runtime dependencies

The extension runs on only the VSCode extension API, Node's own built-ins (http, child_process, fs), and the TypeScript compiler at dev time only. No npm packages ship at runtime, no bundler: just a VSIX installed via code.cmd --install-extension.

02
Theme-aware, colour-coded UI

Every colour is a var(--vscode-*) theme token, not a hardcoded hex value, so the webview matches whatever theme the editor is in automatically, and a nonce-based CSP keeps it from running injected script. Each AI client also gets its own distinct, consistent colour across every tab and badge, so a client is recognisable at a glance.

configuration [06]

Settings

Every part of the connection is configurable under agentOsDashboard.* in VSCode settings: which host and port the gateway listens on, how often it polls, and which pm2 process the Start/Stop/Restart controls drive. Those controls call pm2 with no shell and a process-name allowlist regex, so the configured name can never break out into an arbitrary command.

dashboard_settingsevery agentOsDashboard.* key
Server connection
host: MCP server host (default: 127.0.0.1)
port: MCP server port (default: 3000)
statusPath: status endpoint path (default: /status)
pollInterval: poll frequency in ms (default: 4000)
pm2 integration
pm2ProcessName: pm2 process to control (default: agentOS-portfolio)
Start/Stop/Restart buttons in the Status tab drive pm2 via child_process.spawn with no shell, plus a process-name allowlist regex, so the configured name cannot break out into arbitrary commands