SuperBased Observer
Integrates with GitHub Copilot to capture token usage and cost data from coding sessions.
Captures token usage from Gemini CLI, Google Antigravity, and other Google AI tools for cost tracking.
Captures token usage from Hermes Agent coding sessions for cost tracking.
Captures token usage from ChatGPT and other OpenAI products for cost tracking.
Captures OpenTelemetry traces and spans from LLM applications for observability and cost attribution.
Captures token usage from Perplexity browser sessions for cost tracking.
SuperBased Observer
The exact tokens your AI provider billed you — cache splits, reasoning tokens, long-context surcharges — reconciled across 26 coding tools, entirely on your own machine. Nothing you build here ever leaves your machine unless you opt a node into it.
Table of contents
Related MCP server: knitbrain
What it is in 30 seconds
A single local Go binary built on three things a hosted usage console can't give you, in order of how much they matter:
Proxy-accurate, cross-vendor cost attribution. An optional API reverse proxy reads the token counts your provider actually billed — net input, 5m/1h cache read/write splits, reasoning tokens, long-context repricing — the same math your invoice uses, not a JSONL-derived estimate. It's accurate enough that it caught its own bug: a Codex reasoning-token double-billing regression Observer found and back-corrected months of history for (migration 058, shipped v1.18.0) — the kind of self-audit a vendor console has no incentive to run against itself.
Local-first, by construction. The watcher, proxy, dashboard, MCP server, and CLI make zero outbound calls on your behalf — no telemetry, no analytics, no remote reporting. An optional team rollup server ships only hashed metadata by default; raw content ships only when the node opts in, never a remote admin toggle. Full details:
PRIVACY.md.One capture layer, every tool you actually use. 26 adapters — Claude Code, Codex, Cursor, Cline + Cline CLI, GitHub Copilot + Copilot CLI, Gemini CLI, OpenCode, Google Antigravity, Cowork, Hermes Agent, Kilo Code, Aider, Goose, Devin, Qoder, Crush, Grok, Kiro CLI, Kimi Code, Qwen Code, OpenClaw, Pi, and more — parsed into one normalized schema, queryable from a local dashboard, an MCP server (so the tools themselves can query it), and a CLI. (Five of the 26 are
*-webadapters for ChatGPT/Claude.ai/Gemini/ Copilot/Perplexity in the browser — those need the browser-capture extension, which today only installs unpacked; every tool listed above works out of the box.)
Raw token counting across tools is table stakes here — it's the substrate the accurate-cost layer above is built on, not the pitch.
Two planes, one binary. Plane B is coding-agent observability — desktop-first: capture, proxy-accurate cost, compression, cache tracking, and session handoff for every AI coding tool on your machine, with an optional team rollup server for org-wide spend. Plane A is general LLM-app observability — admin-server-first: OTLP trace/span capture, evals, and an LLM-as-judge input-admission guardrail for an application you host, whose end users route through Observer. Most solo developers only ever touch Plane B; teams add Plane A when they're also running an LLM-powered product. Full explainer: superbased.app/docs/getting-started/two-planes (or docs/deployment-models.md if you're reading this in the repo).
It answers questions like:
Where did this week's $147 Claude bill come from — which projects, models, sessions, tool calls? And is that number the same one my provider's invoice would show?
Did I spend more on Opus or Sonnet? Are my Sonnet sessions hitting the long-context tier and getting repriced at 2×?
How much did I waste re-reading files that hadn't changed since the last read in the same session?
Could that trivial Opus session have been done by Sonnet for 1/5 the cost?
Across Claude Code, Cursor, and Codex working in the same repo, what files are touched by all three? Where are they stepping on each other?
What will my next message roughly cost — and how much of my 5-hour and weekly subscription limit is left before I hit it?
Where did my own OpenTelemetry-instrumented agent spend its tokens — with the proxy's exact per-span cost where it routed through the proxy?
Install
Pick whichever package manager fits your environment — npm and PyPI
ship the same prebuilt binary from the same v* tag, version
numbers kept in lock-step.
Via VS Code (Marketplace or Open VSX)
code --install-extension superbased.superbased-observerThe VS Code extension bundles the observer binary, lifts the dashboard / sidebar / status bar / file decorations into the editor, and contributes a terminal profile that pre-exports the proxy env vars so AI CLIs launched from it route through observer automatically. Cursor, VSCodium, and Windsurf install the same VSIX via Open VSX.
After install, VS Code's Get Started page surfaces an in-editor
walkthrough; the long-form user guide lives at
docs/vscode-extension-user-guide.md
and the command + settings reference is at
docs/vscode-extension.md.
Via npm (recommended for Node users)
npm install -g @superbased/observer
observer --versionVia pip / uv / pipx (recommended for Python users)
pip install superbased-observer # plain pip
uv tool install superbased-observer # uv (isolated env, fastest)
pipx install superbased-observer # pipx (isolated env)
observer --versionWheels ship for manylinux2014_{x86_64,aarch64},
macosx_*_{x86_64,arm64}, and win_amd64. uv tool and pipx
keep the install isolated from your project's Python env — generally
what you want for a CLI tool.
Via go install (latest main, builds locally)
go install github.com/marmutapp/superbased-observer/cmd/observer@latest
observer --versionVia direct download (pre-built per-platform archive)
Each tagged release attaches per-platform archives to the
Releases page,
verifiable against the published SHA256SUMS:
Asset | Platform | Contents |
| Linux x86_64 |
|
| Linux arm64 |
|
| macOS Intel |
|
| macOS Apple Silicon |
|
| Windows x86_64 |
|
| — | sha256 of all five archives |
# Linux x64 example — substitute your platform + version.
VERSION=v1.6.21
PLAT=linux-x64
curl -L -O https://github.com/marmutapp/superbased-observer/releases/download/$VERSION/observer-$VERSION-$PLAT.tar.gz
curl -L -O https://github.com/marmutapp/superbased-observer/releases/download/$VERSION/SHA256SUMS
shasum -a 256 -c SHA256SUMS --ignore-missing
tar -xzf observer-$VERSION-$PLAT.tar.gz
./observer --versionThe binary is pure Go — no CGO, no external runtime dependencies.
SQLite storage is pure-Go via modernc.org/sqlite. Single static
binary; scp it anywhere it runs. Same artifacts ship to npm and to
the Releases page (build-once-ship-everywhere CI), so the npm and
direct-download paths produce byte-identical binaries.
First-run walkthrough
# 1. Start everything: proxy + watcher + dashboard in one foreground
# process (ctrl-c to stop). Hooks auto-register for every detected
# AI tool, and the dashboard opens in your browser
# (http://localhost:8081; suppress with --no-open).
observer start
# 2. (another shell) Backfill from existing session logs so the
# dashboard has history immediately rather than starting empty.
observer scanFrom here the dashboard drives. On an empty database the Overview tab
leads with a three-step onboarding checklist — and a demo mode
offer if you'd rather look around first: one click seeds a temporary
synthetic dataset so every chart renders with realistic data (your
real observer.db is never read or written; a persistent banner marks
demo state and one click clears it). The two checklist steps that
matter:
Route your AI tool through the proxy — accurate token counts and conversation compression both need it. On the Compression tab's Proxy banner, click your tool's status pill, then Route through the observer proxy…: the button previews the exact file change (Claude Code: an
env.ANTHROPIC_BASE_URLentry in~/.claude/settings.json; Codex: anobservermodel provider in~/.codex/config.toml) and writes only on confirm. Durable — every later session routes automatically. The same section of the Settings → Connected tools panel offers a per-tool setup wizard (hooks / MCP / routing, one consent click per write) and a Launch button. Prefer the terminal? The same routing ships asobserver init, as session-scoped wrappers (observer claude/observer codex— no config writes), or as a plainexport ANTHROPIC_BASE_URL=http://localhost:8820/OPENAI_BASE_URL=http://localhost:8820/v1.Use your AI tool as normal. The checklist tracks the first captured session; cost, compression, and cache numbers populate within minutes of real activity.
Optional — MCP registration. observer init additionally writes
MCP server entries (and hook entries) into each AI tool's own config
files (~/.claude/settings.json, ~/.claude.json,
~/.cursor/mcp.json, ~/.codex/config.toml, …). Hooks default ON,
MCP defaults ON; opt out per-side with --skip-hooks / --skip-mcp.
Idempotent. observer start alone never registers the MCP server —
MCP wiring is explicit-only, because it costs ~1,800 schema tokens
per AI-client turn.
If you route Claude Code while MCP servers are registered, set
ENABLE_TOOL_SEARCH=true in the same environment. Claude Code's
SDK disables ToolSearch:optimistic deferred MCP loading whenever
ANTHROPIC_BASE_URL is set, eagerly inlining all 17 observer MCP
tool schemas (plus any Google MCPs) into every request prefix —
~+21K tokens/turn. The override re-enables lazy loading; observer's
proxy forwards tool_reference blocks byte-identically, satisfying
the SDK's documented safety condition. Empirical: with the override +
v1.7.23 defaults, the proxy is −6.9% mean cost vs no-proxy on
Claude Code's reference rig (n=8 lumen refactor task, V7-22 binary).
Without it, ~+9% per-turn overhead. See
superbased.app/docs/connect/claude-code
for the full picture.
The proxy logs every turn with the exact token counts the provider returned, including cache-tier breakdowns (5m vs 1h ephemeral) and 1h surcharges that JSONL adapters can't always disambiguate.
Verifying the install
observer doctor # health checks: DB integrity, hook
# registration, MCP entries, pid bridge
observer status # row counts + recent activity
observer tail # live-stream captured actionsDashboard tour
observer start opens the dashboard automatically on interactive
launches (suppress with --no-open; default URL
http://localhost:8081). Eighteen tabs in four nav groups (Monitor /
Analyze / Optimize / Configure), each designed around one question —
the tour below covers the core surfaces; Live (recent sessions with a
real-time action feed), Search (full-text over captured tool outputs),
and Privacy (capture map + scrub tester) are self-explanatory once
you're in, and the Suggestions tab's advisor
nudges and the Patterns tab's derived habits are covered in their own
docs. Evaluating without data? Start demo mode from the empty
Overview — synthetic dataset in a temp DB, real observer.db
untouched, one click to clear.
Overview — what's been happening?
Four headline KPI tiles (sessions, API turns, token rows, stale re-reads — each filterable by the global Window / Tool / Project chips), cost-over-time stacked area split by billable token bucket, actions-over-time stacked by tool, top models by token volume, top tools by action count.
Sessions — what did each run actually do?
One row per session with cost, token totals (input / cache R /
cache W / output), elapsed time, action count, and a model badge.
Quality / Errors / Redundancy scoring columns light up once
observer score has run. Click a row to open the per-session
slide-over (shown below in Session detail).
Actions — the firehose, filtered
Every recorded tool call, normalized across adapters. Filter by
action type (28 categories), tool, effort, permission. Each row
exposes its target + status + raw-tool source + truncated content
preview; click to expand to the full event with error context.
Cost — per-model breakdown with the right math
Eight KPI tiles across the billable token buckets (Net Input, Cache Read, Cache Write 5m, Cache Write 1h, Output, Reasoning, plus total USD and turn count). Per-model table shows the full breakdown including reasoning tokens (billed at output rate) and long-context surcharges (Sonnet 1M, gpt-5 >272K, Gemini 2.5 Pro >200K). Hover any column header for its definition + formula.
Analysis — spending insights & efficiency signals
Twelve KPI tiles comparing this period to prior: spend Δ%, MTD vs budget with projection bar, $/M output rate, cache savings + cache efficacy %, high-context turn count, $/turn, burn rate ($/active hour), top model concentration %, Discovery waste $, sessions total. Daily-spend stacked bars with Model / Project / Tool dimension toggle, hour-of-day heatmap, period-over-period movers (top increases / decreases / new entrants), and model right-sizing hints (trivial Opus sessions that could have used Sonnet).
Tools — per-AI-client breakdown
Four KPIs (total actions, distinct tools, overall success rate, busiest tool), activity-over-time stacked area, and per-tool action-type-mix horizontal bars (100% normalized, colored by action category). Surfaces which AI client owned which kind of work.
Compression — what the proxy saved
Five KPIs: total $ saved (priced at your input rate), tokens saved, bytes trimmed, turns compressed. Savings-per-day stacked bar by mechanism (drop, trim, summary), savings-by-mechanism donut, recent events table with original→compressed→saved + dollar impact per event.
Cache — prompt-cache observation & forecasting
Headline cache-ratio hero (cache_read ÷ cache_write tokens) and three sibling KPIs: Cache read, Cache write, and Avoidable spend / Event count. Avoidable spend renders in warn tone — it's the dollar overhead of rewrites that wouldn't have happened on a perfectly cache-friendly session. By-model and By-project tables with R%/W% mix bars + absolute Read/Write/Events + cache Ratio + Avoidable $. Proportional Top causes histogram (suffix_growth + hit dominate a healthy session; real invalidations render in warn tone; tools_changed on MCP toggles renders neutral). Worst sessions table sorted by rewrite count; click-through opens the per-turn Cache panel.
How it's captured. Two paths feed the same engine, both writing
to NODE-LOCAL cache_segments / cache_entries / cache_events
tables (migrations 036+037, never pushed to a Teams org server):
Tier-1 (proxy) — point your AI client at
127.0.0.1:8820and the cachetrack engine reads each turn'scache_read_input_tokens+cache_creation_input_tokensenvelope live. Default capture path for Claude Code.Tier-2 (transcript watcher) — feeds the same engine from on-disk claude-code JSONL transcripts for sessions that didn't route through the proxy. Run
observer backfill --cache-rescanto retrofit history.
Enable / disable. Default-on per spec §11 (the loader merges
[cachetrack].enabled = true if the section is absent). To turn off:
[cachetrack].enabled = false in ~/.observer/config.toml, then
restart observer start. Inspect engine health with
observer cache-health --json. Operator reference:
superbased.app/docs/guides/cache-tracking
(or docs/cache-tracking.md in the repo).
Suggestions — the advisor's quantified nudges
Default-on, fully local suggestions engine (zero LLM cost, zero
network): 19 detectors turn the window's captured activity into
ranked, dollar- or minute-quantified recommendations — session
balloons, idle re-cache, long-context tier crossings, trivial
sessions on expensive models, cache hit-rate / cache-write waste /
prefix thrash, read-heavy expensive-model sessions, effort
overprovisioning, fast-tier premium, unrecovered failures, quality
regressions, MCP schema overhead, compression off, capture without
proxy routing, cross-session stale reads, web-search spend, spend
spikes, plus a posture nudge (guard observing idle, pointing at the
surface that owns the workflow). Every
card carries its arithmetic ("show math"), a confidence score,
snooze/dismiss with a 7-day cooldown, and — where a dashboard
control can fix the finding — a one-click action that navigates to
the right surface (writes stay behind that surface's own consent
flow). CLI twin: observer advise. Config: Settings → Advisor
([advisor] — evidence window, confidence/savings floors, opt-in
≤400-token session-start digest).
Discovery — the waste detector
Waste $ hero (stale-read tokens × your blended input rate). Four KPIs: stale re-reads count, tokens wasted, affected files, repeated commands. Top files re-read table with cross-thread highlighting (when the same file was re-read from a subagent that didn't see the parent's read). Repeated-commands table with no-change-rerun detection.
Security — the guard, operable end to end
Posture tiles + a filterable verdict timeline (rule IDs resolve to
their full definitions), then the routine workflows: a consent-gated
mode control that shows the simulate evidence before you flip
enforce, the enforce-readiness replay over your real history, the
approvals register (scoped, expiring — live immediately), a
lint-gated user-policy editor with .bak undo, budget guardrails
suggested from your own observed spend with a daily burn-down meter,
MCP pin approvals, and one-click compliance evidence downloads.
Settings — every config knob, editable
Schema-driven forms for every config section — Watcher, Freshness,
Retention, Hooks, Proxy, Compression, Intelligence, Advisor, Cache
tracking, Secrets scrubbing, MCP, Profiles, Org share, OTel — with
honest reload semantics per section: pricing and profile changes
apply hot, MCP applies to the next AI session, restart-gated
sections raise a persistent restart-pending banner that names the
exact command and clears only when the daemon actually restarts.
Alongside the forms: a Connected tools panel (per-tool status
matrix, consent-gated setup wizard, Launch button), a Health
panel (the observer doctor checks + recent failures), the
Backfill panel (every mode click-to-run with streamed output +
full rescan), a Storage panel (per-table DB size breakdown with
index/FTS bytes folded in, vacuum + online backup as click-to-run
jobs, documented manual restore — CLI twin observer db stats|vacuum|backup), and a config-file card with one-click .bak
restore.
182 baked-in default models; pricing "Override" prompts auto-fill
from the default.
Live — what's running right now
Every session with activity in the last 15 minutes, refreshing on a 5-second tick: lifetime cost, tokens, turns, and a streaming action feed per session. The fastest way to confirm the proxy is capturing while you work.
Trajectories & Evals — observe an LLM app you host
General observability — Plane A. Distinct from the coding-agent usage above: this observes an LLM application you run at the admin level, whose end-users route through Observer.
Point any OpenTelemetry-instrumented app or agent at the local OTLP
endpoint (or route it through the proxy) and its trace/span graph is
captured into node-local obs_* tables — enriched with the proxy's
exact cost and cache numbers wherever a span matches a proxied turn
(the join no external observability tool can make). You view
trajectories and eval-run health on the admin dashboard (web2, the
Trajectories nav group) — the node/developer dashboard stays focused on
your own coding-agent activity. Capture is local and node-opt-in, and
the same plane adds per-end-user budgets + an input-admission guardrail
judged by a local, custom-remote, or gateway LLM (see
superbased.app/docs/getting-started/two-planes
for the Plane A guardrail model).
Session detail — drill into one session
Click any session row → slide-over with an action-type breakdown donut, a token-bucket bar (net input / cache R / cache W / output), and the models used. It also carries the next-message cost predictor (a low / typical / high band over the session's likely turn fan-out) and, for proxied subscription sessions, the 5-hour / weekly limit gauge read from the provider's own rate-limit headers.
Scroll down for the full per-message timeline — every upstream API turn with its model, token buckets, per-turn cost, and the tool calls nested inside it, each row expandable. The same panel surfaces from Actions when you click a session pill.
MCP server — 25 cross-tool intelligence calls
Opt-in. The MCP server is not active until you run
observer init (or observer init --claude-code / --cursor /
--codex). That command writes entries pointing at the observer
binary into each AI tool's own MCP config file
(~/.claude.json, ~/.cursor/mcp.json, ~/.codex/config.toml).
The MCP server then runs as a stdio subprocess spawned by your AI
tool — its lifecycle matches the AI tool's, and it never opens a
network port. observer start alone does NOT register or launch
the MCP server; it can be skipped entirely via
observer init --skip-mcp if you want hooks-only capture.
Once registered, every connected AI tool can query the observer over MCP/stdio: 21 tools are always registered, and 4 more register conditionally (only when the capability they depend on — the proxy stash, or the codeintel index — is actually configured):
MCP tool | What it answers |
| Has this file changed since I last read it? |
| Did this exact command already run? With what result? |
| Every read/edit of this file across every tool + session (with codeintel enrichment when available). |
| What did session X actually do? AI-generated 2–4 sentence summaries. |
| For resuming an interrupted session. |
| Derived behaviours: hot files, co-changes, edit→test pairs. |
| Without re-running. |
| Error correlation + retry detection. |
| The raw row, scrubbed of secrets. |
| Per-window spend rollup. |
| What would Discovery flag for this project? |
| Fuzzy symbol search across the project's codeintel index (Tier-C). |
| Chronological ±N actions around an |
| Full-text search of past tool-call outputs (FTS5 over excerpts). |
| Code vs. explanation split of a session's output, by bytes, with the code:explanation ratio and languages used. |
| Top dollar/time-quantified cost & quality suggestions from the local advisor. |
| Live prompt-cache health: which caches are warm, expiring, or cold, with value-at-risk. |
| Evidence-backed model suggestion per turn-kind, from the local Model Value Report. |
| Model-routing layer state: phase, available policy templates, tier-table size, decision-log counters. |
| A distilled, scrubbed handover of a session from another AI tool, so you can continue its work here. |
| One full, un-excerpted message from a session's transcript — pulls the complete body a handover excerpt truncated. |
| The file's current bytes (or at a given commit), with path-safety gate + audit. |
| Resolve symbol name + range to file path + body (codeintel-backed). |
| Codeintel BFS — who calls / is called by this symbol. |
| Pulls original bytes of a tool_result the proxy stashed (only registered when CCR is enabled). |
Operator note for Claude Code via observer's proxy. When you set
ANTHROPIC_BASE_URL=http://localhost:8820, Claude Code's SDK
disables ToolSearch:optimistic deferred MCP loading — observer's
tool schemas (plus any Google MCPs you've registered) end up
eagerly inlined into every request prefix, ~+21K tokens/turn. Set
ENABLE_TOOL_SEARCH=true in the same shell to recover lazy
loading; observer's proxy forwards tool_reference blocks
byte-identically, satisfying the SDK's documented safety condition
for the override. See
superbased.app/docs/connect/claude-code
for the full picture.
Knowledge captured from one tool benefits all the others working on the same project — data is organized by git root, not by tool. A read by Claude Code becomes a freshness signal for Codex; a Cursor compaction is visible from Cline.
API proxy — accurate tokens, compression, stash
The proxy is the home of three features that only exist when your AI
client routes through it. None of them run on the watcher / observer start ingestion path — compression and stash live in the request
path because that's the only place where bytes can be rewritten
before they reach the upstream provider.
When you point your AI tool at http://localhost:8820, the proxy:
Forwards your request to your chosen upstream (Anthropic or OpenAI). The destination is the same provider URL your AI client would have called directly; no data leaves your machine that wasn't already going to that provider. Your API key is yours — the proxy reads it from the inflight headers, never stores it.
Records the exact token counts the provider returned (cache 5m vs 1h split, long-context tier triggers, reasoning tokens) into the
api_turnstable — more accurate than parsing the JSONL the AI tool wrote.Compresses the conversation before forwarding (importance-scored, prefix-stable for cache alignment) — the biggest lever for keeping long sessions inside rate-limit windows. Opt-in: flip
[compression.conversation].enabled = true(or the Settings → Compression toggle); once enabled, tuned per-tool profiles apply automatically (see below), with the safe per-type set (compress_types = ["json","logs","code"]) on Anthropic traffic. Compressed events land in thecompression_eventstable and surface on the Compression dashboard tab. Empirical on Claude Code lumen rig (n=8, V7-22): −6.9% mean cost vs no-proxy, CV 7.6%, zero tail outliers.Stashes large tool outputs the compressor hides, so the originals stay retrievable via the
retrieve_stashedMCP tool (only registered when stash is configured). Off by default — stash markers break Anthropic's prefix cache (V7-25 n=1 measurement: +25% cost,cache_creation_input_tokensdoubled). Operators who want stash on a workload should A/B before committing.
Three compression layers, each independently toggleable:
Shell output filters — RTK-style truncation of large
bash/git/go test/docker/kubectl/cargo/pytestoutputs inline before they hit the LLM context. Runs on hook /observer runpaths; does not require the proxy.Tool output indexing — every tool call's output indexed into FTS5; large outputs trimmed to a 2KB excerpt cap so the index stays compact and
search_past_outputsstays fast. Runs on the watcher path; does not require the proxy.Conversation compression — proxy rewrites large
tool_resultblocks before forwarding upstream. Proxy-only — there is no non-proxy path for this layer, and the stash that backsretrieve_stashedis wired here too.
Trade-off if you skip the proxy: you still get full hook + JSONL ingestion, the dashboard, MCP (if registered), and shell+indexing compression. You lose proxy-grade token accuracy, conversation compression, and the stash. For rate-limited plans (Claude Teams 5h/7d windows), conversation compression is usually the difference between "finishes the task" and "hits the limit."
Choosing a compression mode (Anthropic vs Codex)
mode is a profile parameter — each shipped profile (next section)
already pins the right one, so most users never set it by hand; the
matrix below is the why. It behaves differently per provider. Per-type
tool_result compression runs in every mode; mode only changes how messages
are dropped and whether an Anthropic cache_control marker is injected.
| What it does | Claude Code (Anthropic) | Codex / OpenAI |
| Per-type compress, then drop lowest-scored messages to hit | ✅ Works. | ✅ Clearest choice for Codex/OpenAI. |
| Restrict drops to the tail half + inject a | ✅ Anthropic-specific. | ⚠️ No effect beyond |
| Skip drops, narrow compression to | ✅ Recommended for Anthropic Pro/Max — and the shipped default. | ⚠️ No effect beyond |
The shipped default is cache_aware (token is just the internal fallback when
mode is empty). The cache/cache_aware strategies exist for Anthropic's
content-hash prefix cache (cache_control is an Anthropic Messages API
concept). OpenAI/Codex prompt caching is automatic and server-side — there
is nothing to mark or tune, so the proxy's OpenAI path is mode-agnostic (the
default cache_aware simply behaves like token there).
Profiles — the right parameters per tool, automatically
Compression parameters ship as profiles: named parameter sets resolved per traffic class at the proxy boundary (formerly "recipes", which had to be hand-picked per daemon — and applied to all traffic, mis-tuning whichever tool the recipe wasn't written for). Enable compression once and the tuned parameters apply per tool simultaneously:
Profile | Auto-assigned to | Headline params | Measured |
| Anthropic-path traffic ( |
| −6.9% mean cost vs OFF (n=8 lumen refactor, CV 7.6%, zero tail outliers; requires |
| OpenAI-path traffic (plain GPT under the codex CLI: |
| −22% to −56% on gpt-5.4-mini (V7-21, n=10); inconclusive on an |
| manual — | ratio 0.99, preserve 50, no per-type compression (V7-2: | −10% ($0.270 vs $0.300, n=10, gpt-5.3-codex) |
| escape hatch | master-config | — |
"variant" in codex-variant means the -codex model variant
(gpt-5.3-codex, anything *-codex*), not a variant of the codex
CLI — both codex profiles are for the codex CLI.
Working with profiles:
Inspect:
observer profile list(assignments + sources),observer profile show codex-safe(the resolved TOML).Reassign per traffic class or per tool:
observer profile assign openai codex-variant,observer profile assign tool:cline codex-safe— or Settings → Profiles in the dashboard.Custom profiles:
observer profile create mine --from claude-code, thenobserver profile set mine compression.conversation.target_ratio 0.9— or the Settings → Profiles editor.Per-project overrides: a repo-level
.observer/config.toml([profiles]+[compression]keys only) picks different profiles or turns compression OFF for that repo's traffic — never on (untrusted-repo guard).Hot for new sessions: profile edits and assignment changes apply without a daemon restart. The master
enabledswitch itself is restart-gated — the dashboard banner says so honestly.observer start --recipe <name>survives as a deprecated alias that pins one profile for all traffic.
Measured effects vary by traffic shape and workload — from the
double-digit savings above to a since-fixed configuration that once
regressed cost on a different binary. Historic marketing claims of a
flat savings percentage are retracted; compression ships opt-in and
default-off precisely because the right call depends on your own
traffic — A/B it before relying on any number here. Full knob
reference (stash, rolling-summary's per-provider model
split, compaction):
docs/compression-modes.md. Then route
your client through the proxy — the one-click button path in the
First-run walkthrough — and restart it.
Architecture
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Claude Code │ │ Cursor │ │ Codex │ ... 26 adapters total
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ JSONL │ hook events │ rollout files
▼ ▼ ▼
┌────────────────────────────────────────────────────────┐
│ fsnotify Watcher + Adapters │
│ (one parser per platform, normalized output) │
└───────────────────────────┬────────────────────────────┘
│ ToolEvent / Action / Session
▼
┌────────────────────────────────────────────────────────┐
│ SQLite (WAL, pure-Go via modernc.org/sqlite) │
│ actions · sessions · projects · file_state · │
│ api_turns · token_usage · failure_context · │
│ compaction_events · action_excerpts (FTS5) │
└───────────────────────────┬────────────────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Dashboard │ │ MCP Server │ │ API Proxy │
│ HTTP+/api/* │ │ stdio · 25 │ │ Anthropic + │
│ 18 tabs │ │ tools │ │ OpenAI │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
▼
upstream API
(traffic passes
through verbatim,
with token tracking
+ optional compression)Adapters parse each platform's session format into a unified
Action row. The cost engine reads api_turns (proxy, accurate)
and token_usage (JSONL adapters, approximate) and deduplicates
per-turn via the upstream request_id ↔ source_event_id match.
The MCP server exposes the same database. The dashboard pulls JSON
from the same /api/* endpoints the MCP tools use.
Teams & Org Visibility
For teams, an optional observer-org server gives admins org-wide
visibility — per-developer and per-team spend, project rollups, and budgets —
without changing the solo-local experience at all. It is purely additive: a
developer who never enrols sees a byte-identical local tool. Developers opt in
with observer enroll --link <magic-link>, after which the agent pushes
hash/metadata-only rollup rows (signed, gzipped, deduplicated) to the
server. The default v1.8.0+ posture ships sha256 hashes of command targets,
filesystem paths, and git remotes — never the raw values; a per-node opt-in
([org_client.share].full_content = true) lets a developer choose to share
full content, but the org admin cannot flip this remotely.
Authentication is SAML SSO for humans, SCIM 2.0 for provisioning, and Ed25519
bearers for agents; no prompts, command bodies, full assistant responses, or
file contents ever leave the machine — even in the opt-in full-content mode,
only the small set of fields the agent already stores in metadata-only mode
gets expanded. The server ships as a signed Docker image
(ghcr.io/marmutapp/observer-org) and a Helm chart (charts/observer-org/).
Local-in-5-minutes: observer-org quickstart brings up a dev compose stack,
provisions an admin, mints an enrolment token, and prints a ready-to-share
magic link. observer org status / preview / backfill give the developer
full visibility into what their agent is shipping.
Independently, each agent can export per-turn LLM spans to your own
OpenTelemetry collector (gen_ai.* + sbo.* attributes, off by default).
Getting started —
observer-org quickstartfor local-in-5-minutes; production SAML/SCIM bring-up.Architecture — components, runtime data flow, the v1.8.0 privacy posture, source map.
Operations — backup/restore, key rotation, upgrades, troubleshooting,
scrub-contentfor legacy DBs.Local test plan — an internal 7-phase evaluator plan covering local bring-up end to end in ~15 minutes (source-repo reference, not shipped in this distribution).
Security & control layer (guard)
The guard evaluates every captured agent action against a table-driven policy
— built-in rules (destructive commands, project boundaries, secrets egress,
MCP pinning, taint/dataflow, budgets) plus your own TOML rules — records each
verdict in a hash-chained tamper-evident audit table, and blocks
pre-execution on the channels that support it (Claude Code and Cursor hooks,
the proxy egress path, plus native permission rules it compiles into each
client's own config). It ships observe-only by default: nothing blocks
until you flip enforce, and observer guard simulate --since 168h replays
your real history against current policy first so you know exactly what
enforce would have done.
Teams installs can distribute an Ed25519-signed org policy bundle that merges
as a strictness floor (escalate-only — the server can never weaken node
policy), with fleet rollups and RBAC on the org dashboard. Audit rows export
as JSONL/CEF for SIEM ingestion, and observer guard report renders a
compliance evidence pack mapped to SOC 2 / NIST 800-53. The no-network
invariant holds: nothing leaves the machine unless you opt into Teams push,
the OTel feed, or the cloud alerting tier individually.
Optional process observability ([observer.process], opt-in, off by
default) attaches the OS-level process tree — Linux eBPF or Windows ETW —
beneath each captured session, for the runtime side effects hooks alone
can't see (a spawned binary, an unexpected child process).
Alerting. Guard verdicts and budget/obs-alert crossings can push out
through desktop toast notifications ([guard.alerts] desktop = true) and
outbound webhooks — generic, Slack, Discord, or PagerDuty
([[guard.cloud.webhooks]] for guard events; the org server's per-budget
and per-obs-alert-rule webhook columns for spend/eval alerts) — each behind
its own opt-in, routed through one egress worker with an endpoint allowlist
and a payload cap. Nothing fires until you configure it.
Every routine guard workflow also runs from the dashboard's Security page (mode control with simulate evidence, enforce-readiness replay, approvals, lint-gated policy editor, budget guardrails, evidence downloads) — see the Dashboard tour above.
Operator guide — concepts, modes, the observe→enforce path, Teams policy merge, and the honest "what guard does NOT do" list.
Rule catalog, policy authoring, compliance mapping — every built-in rule ID, the TOML matcher vocabulary with a worked 7-recipe cookbook, and the SOC 2 CC-series + NIST 800-53 AU-2/AU-3/AU-9/AC-6 evidence-pack mapping ship as
docs/guard-rules.md,docs/guard-policy-authoring.md, anddocs/guard-compliance.mdfor anyone building from source.
CLI reference
Command | Purpose |
| Register hooks + MCP server + durable proxy routes with every detected AI tool (each side defaults on; |
| Reverse of |
| One-time backfill — parse all known session files into the DB. |
| Live fsnotify-based watcher daemon. |
| Proxy + watcher + dashboard in one foreground process. Auto-opens the dashboard on interactive launches ( |
| Launch Claude Code routed through the proxy for that session only — no config writes; re-exports a fresh Pro/Max OAuth token so the SDK can't bypass the proxy. |
| Launch Codex routed through the proxy for that session only (argv |
| Compression profiles: inspect, reassign per traffic class / per tool, create + edit custom ones. Hot for new sessions. |
| Dotted-key config setter through the shared validated write path; |
| Run only the API reverse proxy. |
| Embedded dashboard + |
| Token + USD rollup from the CLI. |
| Stale re-reads + redundant-commands report. |
| Derive hot files, co-changes, common commands, edit→test pairs. |
| Derive correction rules from failure→recovery pairs. |
| Compose patterns + corrections into CLAUDE.md / AGENTS.md / .cursorrules. |
| Generate AI session summaries (uses Anthropic Haiku). |
| Session quality scoring (error rate, redundancy, onboarding cost, retry cost). |
| Row counts + recent activity. |
| Live-stream captured actions. |
| Prescriptive cost/quality suggestions (the Suggestions tab, in the CLI). |
| Prompt-cache engine health: grading gate, read:write consistency, cause concentration. |
| Health checks: DB integrity, hook checksums, MCP drift, pid bridge, proxy routing gaps. |
| Run retention now. |
| Storage manager: per-table size breakdown (index + FTS5 shadow bytes folded in), reclaim free pages with bytes-freed report, online snapshot via |
| Merge another |
| Prometheus |
| Dump tables for external analysis. |
| Re-populate columns added by later migrations. |
| Run a command with its stdout streamed through the shell filter. |
| Hook entrypoint (called by the AI tools after |
| MCP stdio server (spawned by AI tools). |
| Shell completions (bash / zsh / fish / powershell), e.g. |
observer <command> --help for full flag listings. Bare observer
prints a status welcome (daemon up? dashboard URL? next step) instead
of the help wall; observer --help keeps the complete list.
Configuration
Default location: ~/.observer/config.toml. Override with
--config. A minimal config:
[observer]
db_path = "~/.observer/observer.db"
log_level = "info"
[proxy]
enabled = true
port = 8820
anthropic_upstream = "https://api.anthropic.com"
openai_upstream = "https://api.openai.com"
[intelligence]
monthly_budget_usd = 100 # surfaces on Analysis tab; 0 hides
[compression.shell]
enabled = true
exclude_commands = ["curl", "playwright"]
[compression.indexing]
enabled = true
max_excerpt_bytes = 2048
[compression.conversation]
enabled = false # opt-in; modifies request bodies in flight
mode = "cache_aware" # "token" | "cache" | "cache_aware" — see "Choosing a compression mode" below
target_ratio = 0.85
preserve_last_n = 5
compress_types = ["json", "logs", "code"]
# Per-model pricing overrides. Only specify what differs from baked-in.
[intelligence.pricing.models."claude-sonnet-4-6"]
input = 3.0
output = 15.0
cache_read = 0.30
cache_creation = 3.75
cache_creation_1h = 6.00
# Long-context tier example (Anthropic Sonnet 1M, gpt-5 >272K,
# Gemini 2.5 Pro >200K). When prompt exceeds the threshold, every
# rate is replaced with its long_context_* counterpart for that turn.
[intelligence.pricing.models."claude-sonnet-4-5"]
input = 3.0
output = 15.0
cache_read = 0.30
cache_creation = 3.75
cache_creation_1h = 6.00
long_context_threshold = 200000
long_context_input = 6.0
long_context_output = 22.50
long_context_cache_read = 0.60
long_context_cache_creation = 7.50
long_context_cache_creation_1h = 12.00Every key has a TOML environment-variable override:
OBSERVER_<SECTION>_<KEY> (uppercased, underscores). Nested
sections join with extra underscores:
OBSERVER_COMPRESSION_CONVERSATION_ENABLED=true.
The Settings tab in the dashboard provides a fully-editable visual
editor for everything in config.toml — pricing and profile changes
apply hot, MCP settings apply to the next AI session, and
restart-gated sections raise a persistent banner that names the
exact restart command and clears itself once the daemon actually
restarts (the daemon never restarts itself).
Post-upgrade hygiene + recovery
After upgrading the binary, or whenever the Actions tab looks gappy (watcher fell behind, daemon restart with stale state, fsnotify event drops):
observer backfill --allRe-walks every JSONL the adapters know about from offset 0, then
runs the surgical column-update backfills (cache-tier, message-id,
etc.) on top. The (source_file, source_event_id) UNIQUE index
keeps the pass idempotent.
The dashboard surfaces a top-of-page banner whenever the watcher's
parse cursor for any session file is more than 10 KB behind the
on-disk size, so silent data loss has a visible signal.
observer backfill --help lists every supported flag.
Build from source
git clone https://github.com/marmutapp/superbased-observer
cd superbased-observer
make build # builds bin/observer + bin/antigravity-bridge.exe
make test # full test suite (race detector enabled)
make all # fmt + vet + lint + test + buildRequirements: Go 1.22+. No CGO. SQLite via modernc.org/sqlite
(pure Go). golangci-lint optional for make lint. Dashboard
source under web/ (React + TypeScript + Vite + Tailwind); the
compiled bundle is committed to
internal/intelligence/dashboard/webapp/dist/ so a contributor
who only touches Go can make build without Node.
If you edit web/src/:
# Hot-reload dev loop (Vite serves :5173, proxies /api/* to observer)
./bin/observer dashboard --addr 127.0.0.1:8081 &
cd web && npm install && npm run dev
# When done, rebuild the embedded bundle and commit
make web-build
git add internal/intelligence/dashboard/webapp/dist web/distmake web-build regenerates both web/dist and the embedded copy.
Requires Node 22 LTS.
CI gates
Every PR + push to main runs .github/workflows/ci.yml:
frontend—npm ci→ typecheck → build → dist-consistency check (asserts the committed embedded bundle matches a fresh build).go—go vet→go test -race→ cross-compile.
Tag pushes (v*) trigger .github/workflows/npm-release.yml:
builds the frontend once, cross-compiles five platform binaries,
ships them to npm, and creates a GitHub Release.
Contributing
PRs welcome. Table-driven tests in every package; >80% coverage on
core packages (cost, freshness, adapters, store). Run make test
before submitting; make all locally to catch fmt/vet/lint issues.
Conventional commits (feat: / fix: / chore: / docs: /
test: / refactor: / perf:).
For larger changes, open an issue first to align on scope. Adapter
contributions (a new AI coding tool to support) are particularly
welcome — see existing adapters in internal/adapter/ for the
pattern.
License
Apache 2.0 — see LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/marmutapp/superbased-observer'
If you have feedback or need assistance with the MCP directory API, please join our Discord server