@superbased/observer 1.8.2 → 1.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,6 +3,9 @@
3
3
  [![npm](https://img.shields.io/npm/v/@superbased/observer.svg)](https://www.npmjs.com/package/@superbased/observer)
4
4
  [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
5
5
  [![Platforms: Linux • macOS • Windows](https://img.shields.io/badge/platforms-linux%20%7C%20macos%20%7C%20windows-blue.svg)](https://github.com/marmutapp/superbased-observer)
6
+ [![Website](https://img.shields.io/badge/homepage-superbased.app-2EC4B6.svg)](https://superbased.app/)
7
+
8
+ **Homepage:** [https://superbased.app/](https://superbased.app/)
6
9
 
7
10
  **Capture, normalize, compress, and analyze every AI coding tool call you
8
11
  run** — across Claude Code, Codex, Cursor, Cline / Roo Code, GitHub
@@ -82,30 +85,33 @@ the [main repo](https://github.com/marmutapp/superbased-observer).
82
85
  ## Five-minute quickstart
83
86
 
84
87
  ```bash
85
- # 1) Install. `observer init` is OPTIONAL — only run it if you want
86
- # the MCP server registered with your AI clients (gives them
87
- # on-demand tools like check_file_freshness / get_cost_summary
88
- # at the cost of ~1,800 tokens of schema per turn).
88
+ # 1) Install.
89
89
  npm install -g @superbased/observer
90
- observer init # OPTIONAL — interactive: pick clients;
91
- # writes MCP + codex proxy-route into AI client configs.
92
- # Skip this step for an MCP-free install.
93
-
94
- # 2) Start the long-running services (proxy + watcher + dashboard).
95
- # Auto-registers HOOKS for every detected AI tool on first launch.
96
- observer start &
97
-
98
- # 3) Engage the proxy by pointing your AI client at the local URL.
99
- # See "Per-AI-client setup" for the matching env var.
100
- export ANTHROPIC_BASE_URL=http://127.0.0.1:8820 # Claude Code
101
- export OPENAI_BASE_URL=http://127.0.0.1:8820/v1 # Codex / OpenAI
102
-
103
- # 4) Open the dashboard.
104
- open http://127.0.0.1:8081/ # macOS
105
- xdg-open http://127.0.0.1:8081/ # Linux
106
- start http://127.0.0.1:8081/ # Windows
90
+
91
+ # 2) Start everything: proxy + watcher + dashboard in one process.
92
+ # Hooks auto-register for every detected AI tool, and the
93
+ # dashboard opens in your browser (suppress with --no-open).
94
+ observer start
107
95
  ```
108
96
 
97
+ From here the dashboard drives:
98
+
99
+ 3. **Route your AI client through the proxy** — on the Compression
100
+ tab's **Proxy** banner, click your tool's status pill, then
101
+ **Route through the observer proxy…**. The button previews the
102
+ exact file change and writes only on confirm. (Every other
103
+ routing mechanism — `observer init`, the `observer claude` /
104
+ `observer codex` wrappers, plain env vars — is listed in
105
+ [Per-AI-client setup](#per-ai-client-setup).)
106
+ 4. **Use your AI tool as normal.** The Overview tab's onboarding
107
+ checklist tracks your first captured session; cost, compression,
108
+ and cache numbers populate within minutes of real activity.
109
+
110
+ `observer init` is OPTIONAL — run it only if you want the MCP server
111
+ registered with your AI clients (gives them on-demand tools like
112
+ `check_file_freshness` / `get_cost_summary`, at the cost of ~1,800
113
+ tokens of schema per turn). Skip it for an MCP-free install.
114
+
109
115
  **What `start` does vs what `init` adds:**
110
116
 
111
117
  | Step | Hooks | Proxy listening | Watcher | Dashboard | MCP in AI clients | Codex proxy route |
@@ -117,16 +123,46 @@ start http://127.0.0.1:8081/ # Windows
117
123
  MCP and codex routing are explicit-only because both write per-client
118
124
  config files. Hooks self-heal on every `start`.
119
125
 
120
- After ten minutes of normal AI-coding usage, the dashboard will be
121
- populated with cost over time, per-tool activity, compression
122
- savings, and stale-reread waste signals.
123
-
124
126
 
125
127
  ## Per-AI-client setup
126
128
 
127
- Different clients send to different upstreams. The local proxy on
128
- `127.0.0.1:8820` handles all of them — routes by URL path. Set the
129
- env var that matches your client(s); both can coexist on one machine.
129
+ ### Routing through the proxy the canonical section
130
+
131
+ Accurate token counts, conversation compression, and cache tracking
132
+ all require your AI client to send its API traffic through the local
133
+ proxy on `127.0.0.1:8820`. There is one decision to make — *how* to
134
+ route — and four mechanisms that all end at the same proxy. Pick the
135
+ first one that fits:
136
+
137
+ | Mechanism | What it does | Use it when |
138
+ |---|---|---|
139
+ | **Dashboard button** *(recommended)* | On the Compression tab's **Proxy** banner, click your tool's status pill, then **Route through the observer proxy…**. It previews the exact file change and writes only on confirm: Claude Code gets `"env": { "ANTHROPIC_BASE_URL": … }` in `~/.claude/settings.json`; Codex gets an `observer` model provider in `~/.codex/config.toml`. Durable — every later session routes automatically, no wrapper, no env vars. Undo: remove the entry, or `observer uninstall --claude-code` / `--codex`. | You have a browser open. This is the default path. |
140
+ | **`observer init`** | Writes the same durable routing from the CLI, alongside hooks + MCP registration (each side defaults on; opt out with `--skip-hooks` / `--skip-mcp` / `--skip-proxy-route`). | Headless machines, scripted setups. |
141
+ | **Wrapper commands** — `observer claude` / `observer codex` | Launch the tool with routing injected for that session only; nothing is written to any config file. The claude wrapper also re-exports a fresh Pro/Max OAuth token so the SDK's OAuth path can't bypass the proxy (an expired stored token is left alone — Claude Code then refreshes natively). `observer claude --verify` runs the pre-flight checks without launching. | Trying the proxy out, or you don't want config writes. |
142
+ | **Env var export** | `export ANTHROPIC_BASE_URL=http://127.0.0.1:8820` (Anthropic clients) or `export OPENAI_BASE_URL=http://127.0.0.1:8820/v1` (OpenAI clients — note the `/v1`) in the shell that launches the tool. | One-off shells; clients without a button or wrapper. |
143
+
144
+ Routing is per-tool, not global: route Claude Code and Codex
145
+ independently, and both can coexist on one machine — the proxy
146
+ routes by URL path.
147
+
148
+ > **Claude Code + MCP servers**: set `ENABLE_TOOL_SEARCH=true` in the
149
+ > same environment. Claude Code's SDK disables deferred MCP schema
150
+ > loading whenever `ANTHROPIC_BASE_URL` is set and eager-inlines every
151
+ > registered MCP schema (~+21K tokens/turn) — enough to turn the proxy
152
+ > into a net cost. The override restores lazy loading; the proxy
153
+ > forwards `tool_reference` blocks byte-identically.
154
+
155
+ > **If the daemon is down while a tool is routed**, Claude Code does
156
+ > not silently bypass to the real API — it retries the dead port
157
+ > (verified live: it hangs rather than failing over). `observer
158
+ > doctor` and the dashboard's Health panel flag this state as a
159
+ > "proxy routing gap"; bring the daemon back with `observer start`.
160
+
161
+ ### Capture modes per client
162
+
163
+ The proxy covers the clients that speak the Anthropic / OpenAI wire
164
+ APIs. Everything else is captured passively from session logs. The
165
+ table below is the full per-client reference.
130
166
 
131
167
  | AI client | Env var | Capture mode |
132
168
  |---------------------------------|-------------------------------------------------------|--------------|
@@ -134,15 +170,17 @@ env var that matches your client(s); both can coexist on one machine.
134
170
  | **Cursor** (Anthropic mode) | `ANTHROPIC_BASE_URL=http://127.0.0.1:8820` | proxy + JSONL |
135
171
  | **Codex** | `OPENAI_BASE_URL=http://127.0.0.1:8820/v1` (note `/v1`) | proxy + JSONL with API-key auth; ChatGPT-plan login currently behaves as JSONL only |
136
172
  | **Cursor** (OpenAI mode) | `OPENAI_BASE_URL=http://127.0.0.1:8820/v1` | proxy + JSONL |
137
- | **Cline / Roo Code** | `ANTHROPIC_BASE_URL=...` or `OPENAI_BASE_URL=...` per provider | proxy + JSONL |
173
+ | **Cline (VS Code) / Roo Code** | `ANTHROPIC_BASE_URL=...` or `OPENAI_BASE_URL=...` per provider | proxy + JSONL |
174
+ | **Cline CLI** (npm `cline` 3.0.20+) | (no proxy route yet — the CLI ignores base-URL env vars; per-provider `baseUrl` overrides live in `~/.cline/data/settings/providers.json`, a credentials file only the operator should edit) | JSONL — SQLite session metadata at `~/.cline/data/db/sessions.db` (schema v1, 28 columns) plus per-session `<id>.messages.json` content blocks. Captures `user_prompt` / `assistant_text` / `tool_use` / paired `tool_result` rows + Tier 2 per-API-call token usage from `modelInfo` overrides. Subagent + team linkage via 5 new `ActionMetadata` fields (`ParentSessionID`, `ParentAgentID`, `AgentID`, `IsSubagent`, `TeamName`). 28-tool taxonomy (10 core + 18 `team_*` coordination primitives). WSL2 over `/mnt/c` uses the same `stageMirror` pattern as opencode/kilocode. Tagged `Source=jsonl, Reliability=approximate`. |
138
175
  | **GitHub Copilot** | (no proxy yet) | JSONL only |
139
176
  | **OpenCode** ([opencode.ai](https://opencode.ai/)) | (no proxy yet) | SQLite — actual install path is `~/.local/share/opencode/opencode.db` (XDG). Captures **token counts + model + cost** per assistant message from OpenCode's InfoData (`tokens.input/output/reasoning/cache.{read,write}` + `cost`); **subtask** parts → `spawn_subagent` actions; **todo** table → `todo_update` actions; tool-name coverage extended to webfetch/websearch/task/todowrite/todoread/multiedit. Tagged `Source=jsonl, Reliability=approximate`. |
140
177
  | **OpenClaw** ([openclaw.ai](https://openclaw.ai/)) | (no proxy yet) | JSONL + sqlite — `~/.openclaw/tasks/runs.sqlite` + `~/.openclaw/agents/<agent>/sessions/sessions.json` |
141
178
  | **Pi** ([pi.dev](https://pi.dev/)) | (no proxy yet) | JSONL — `~/.pi/agent/sessions/--<path>--/*.jsonl` (per upstream `docs/session-format.md` v3). Captures user / assistant / toolResult / `bashExecution` message roles; `usage.cost.total` → per-message USD; terminal `stopReason` (stop/length/error/aborted) → `task_complete` with `success=false` for failures (mid-turn `toolUse` is correctly skipped); `thinking` blocks surface as preceding reasoning. Tagged `Source=jsonl, Reliability=approximate`. |
142
179
  | **Google Antigravity** | (no proxy yet) | Encrypted protobuf — `~/.gemini/antigravity/conversations/*.pb` (Linux-native) and the matching Windows-side path on WSL2. Observer ships a per-OS Chromium-pattern `oscrypt` key fetcher (macOS Keychain / libsecret / DPAPI / WSL2-via-PowerShell helper) and a multi-cipher try-loop for local decryption. Sessions whose ciphers don't validate locally fall back to the language_server's `GetCascadeTrajectory` gRPC endpoint via a built-in helper (`antigravity-bridge.exe` on WSL2 / native gRPC elsewhere) — extracts model + per-turn token counts + Tier 0–6 ToolEvents (file views, artifact edits/writes, user prompts, assistant text, run_command terminal snapshots, structured plan steps, final summaries). State index + per-conversation title/workspace URI read from `state.vscdb` + `state.vscdb.backup`. Tagged `Source=jsonl, Reliability=approximate`. |
143
180
  | **Kilo Code IDE extension (legacy)** | (no proxy yet) | JSON — `<vsCodeGlobalStorage>/kilocode.kilo-code/tasks/<taskId>/api_conversation_history.json`. The legacy Kilo extension is a Cline + Roo Code fork and shares the Cline parser; emitted rows are re-tagged `Tool="kilo-code"` so dashboard rollups don't blur Kilo activity into Cline. Tagged `Source=jsonl, Reliability=approximate`. |
144
- | **Kilo Code CLI (current)** | Optional: `OPENAI_BASE_URL=http://127.0.0.1:8820/v1` (Kilo Gateway is OpenAI-compatible at the wire) | SQLite — `~/.local/share/kilo/kilo.db` on every OS (Kilo intentionally mirrors XDG; Windows does NOT use `%APPDATA%`). The new `@kilocode/cli` (npm) is a fork of sst/opencode and uses the same `message`/`part`/`todo` tables shape with Kilo additions (`project`, `workspace`, `event`, `session_message`, `account`, `permission`, `session_share`). Captures **token counts + model + cost** per assistant message from `message.data.tokens = {total, input, output, reasoning, cache: {read, write}}`. Tool name coverage inherits OpenCode's surface (`read` → `read_file`, `bash` → `run_command`, `websearch` → `web_search`, etc.). Tagged `Source=jsonl, Reliability=approximate`. |
181
+ | **Kilo Code CLI (current)** | (no proxy route yet — base-URL env vars are not honored; a project-scoped `kilo.json` provider `baseURL` override reaches the proxy, but the Gateway provider's model-catalog calls share that base URL and have no upstream there — see `docs/kilo-code-adapter.md`) | SQLite — `~/.local/share/kilo/kilo.db` on every OS (Kilo intentionally mirrors XDG; Windows does NOT use `%APPDATA%`). The new `@kilocode/cli` (npm) is a fork of sst/opencode and uses the same `message`/`part`/`todo` tables shape with Kilo additions (`project`, `workspace`, `event`, `session_message`, `account`, `permission`, `session_share`). Captures **token counts + model + cost** per assistant message from `message.data.tokens = {total, input, output, reasoning, cache: {read, write}}`. Tool name coverage inherits OpenCode's surface (`read` → `read_file`, `bash` → `run_command`, `websearch` → `web_search`, etc.). Tagged `Source=jsonl, Reliability=approximate`. |
145
182
  | **Gemini CLI** | (no proxy yet) | JSONL or single-object JSON — `~/.gemini/tmp/<hash>/chats/session-*.{json,jsonl}`. Dual-format dispatch: legacy single-object JSON (size-based cursor, cline-style) and proposed JSONL event records (byte-offset cursor, issue [#15292](https://github.com/google-gemini/gemini-cli/issues/15292)). Action mapping covers `read_file` / `write_file` / `edit_file` / `run_command` / `search_files` / `web_fetch` and arbitrary MCP tool calls. Project root falls back through tool-call `cwd` → `~/.gemini/history/<hash>/.git/config` worktree pointer → synthetic `[gemini-cli:<hash>]` key (promoted via ON CONFLICT DO UPDATE on `sessions.project_id` once a future scan supplies a real cwd). Tagged `Source=jsonl, Reliability=approximate`. |
183
+ | **Hermes Agent** ([Nous Research](https://github.com/NousResearch/hermes-agent)) | (provider-routed; uses your existing `ANTHROPIC_BASE_URL` / `OPENAI_BASE_URL` when set) | Hooks + SQLite — Python plugin at `~/.hermes/plugins/superbased-observer/` registers `post_tool_call` / `post_api_request` / `on_session_start` / `on_session_end` / `subagent_stop` callbacks (fire-and-forget via `observer hook hermes`); the watcher walks `~/.hermes/state.db` (schema v14, `messages.active = 1` filter) and emits `ToolEvent` + `TokenEvent` rows via `modernc.org/sqlite`. 70+ Hermes tools fold into the normalized action set (`read_file` / `write_file` / `patch` / `terminal` / `search_files` / `web_search` / `web_extract` / `browser_*` / `delegate_task` / `todo` / `clarify` / `memory` + `mcp_call` fall-through). Token bundles lifted from `post_api_request.usage{input/output/cache/reasoning_tokens}`; OpenRouter `:suffix` tails (`:free`, `:beta`, `:fast`) preserved so the dashboard distinguishes paid vs free tiers. Install via `observer init --hermes`; backfill via `observer backfill --hermes-rescan`. Tagged `Source=jsonl, Reliability=approximate`. |
146
184
 
147
185
  **JSONL-only** clients are captured passively by the watcher whenever
148
186
  `observer start` is running. Hooks self-heal on every `start`, so a
@@ -151,8 +189,8 @@ for them on the Compression tab (those need the proxy), but every tool
151
189
  call shows up on Sessions / Actions / Discovery / Tools / Patterns and
152
190
  the JSONL-derived token counts feed the Cost tab. Reliability tagging
153
191
  is per-adapter: Claude Code emits `unreliable` (the JSONL stream uses
154
- streaming-time placeholder counts per spec §24); Codex / Cline / Pi /
155
- OpenCode / OpenClaw / Antigravity / Gemini CLI / Kilo Code / Kilo Code CLI emit `approximate`
192
+ streaming-time placeholder counts per spec §24); Codex / Cline / Cline CLI /
193
+ Pi / OpenCode / OpenClaw / Antigravity / Gemini CLI / Hermes / Kilo Code / Kilo Code CLI emit `approximate`
156
194
  (provider-reported usage that hasn't been reconciled against an
157
195
  upstream invoice).
158
196
 
@@ -161,32 +199,6 @@ For **Codex specifically**, Observer currently has two practical support modes:
161
199
  - `Proxy + JSONL`: Codex is routed through `OPENAI_BASE_URL=http://127.0.0.1:8820/v1` and Observer can link proxy turns to the session, so live compression metrics are available.
162
200
  - `JSONL only`: Observer can still recover sessions, actions, and approximate token counts from `~/.codex/sessions`, but live proxy compression is currently not available when Codex is logged in with a ChatGPT plan on the local machine.
163
201
 
164
- ### Persistent setups
165
-
166
- **Claude Code** (`~/.claude/settings.json`):
167
-
168
- ```json
169
- {
170
- "env": { "ANTHROPIC_BASE_URL": "http://127.0.0.1:8820" },
171
- "hooks": { /* `observer init` writes these */ }
172
- }
173
- ```
174
-
175
- **Codex** (`~/.codex/config.toml`):
176
-
177
- ```toml
178
- [env]
179
- OPENAI_BASE_URL = "http://127.0.0.1:8820/v1"
180
- ```
181
-
182
- **Shell rc** (`~/.bashrc` / `~/.zshrc`) — affects every program:
183
-
184
- ```bash
185
- export ANTHROPIC_BASE_URL=http://127.0.0.1:8820
186
- export OPENAI_BASE_URL=http://127.0.0.1:8820/v1
187
- ```
188
-
189
-
190
202
  ## Architecture in detail
191
203
 
192
204
  <p align="center">
@@ -252,8 +264,10 @@ Pure-Go via `modernc.org/sqlite`, no CGO. WAL mode by default.
252
264
 
253
265
  ### 4. Local dashboard (`:8081`)
254
266
 
255
- Eight tabs covering: Overview, Cost, Sessions, Actions, Tools,
256
- Compression, Discovery, Patterns. See [Dashboard tour](#dashboard-tour).
267
+ Fifteen tabs in four groups — Monitor (Overview, Live, Sessions,
268
+ Actions, Search), Analyze (Cost, Analysis, Tools), Optimize
269
+ (Compression, Cache, Suggestions, Discovery, Patterns), Configure
270
+ (Privacy, Settings). See [Dashboard tour](#dashboard-tour).
257
271
 
258
272
  Static HTML + Chart.js. No analytics, no external requests.
259
273
 
@@ -277,7 +291,24 @@ running `init`.
277
291
 
278
292
  ## Dashboard tour
279
293
 
280
- Open `http://127.0.0.1:8081/` after `observer start`. Ten tabs.
294
+ `observer start` opens the dashboard automatically on interactive
295
+ launches (suppress with `--no-open`; the URL is also printed —
296
+ `http://127.0.0.1:8081/` by default). Fifteen tabs in four nav groups
297
+ (Monitor / Analyze / Optimize / Configure) — the tour below covers the
298
+ core surfaces; Live (recent sessions with a real-time action feed),
299
+ Search (full-text over captured tool outputs), and Privacy (capture
300
+ map + scrub tester) are self-explanatory once you're in. On an empty
301
+ database the Overview tab leads with a three-step onboarding
302
+ checklist that takes you from zero to your first captured session
303
+ without leaving the browser.
304
+
305
+ **Just looking?** The empty-database Overview also offers **demo
306
+ mode**: one click seeds a temporary synthetic dataset so every chart
307
+ and table renders with realistic data — parsed through the real
308
+ ingest pipeline into a temp DB; your real `observer.db` is never read
309
+ or written. A persistent banner marks demo state, and one click
310
+ clears it again. The fastest way to evaluate the dashboard before
311
+ routing any real traffic.
281
312
 
282
313
  ### Overview tab
283
314
 
@@ -355,7 +386,7 @@ was tier-fallback rather than billing-grade ("accurate" reliability).
355
386
  Click a row to open the session-detail panel:
356
387
 
357
388
  <p align="center">
358
- <img src="https://github.com/marmutapp/superbased-observer/raw/main/docs/assets/screenshots/10-session-detail.png" alt="Session detail slide-over" width="900">
389
+ <img src="https://github.com/marmutapp/superbased-observer/raw/main/docs/assets/screenshots/11-session-detail.png" alt="Session detail slide-over" width="900">
359
390
  </p>
360
391
 
361
392
 
@@ -435,10 +466,119 @@ saved by trimming requests before forwarding upstream:
435
466
  score (for drops), and a **Source** column showing whether the
436
467
  event came from a main-thread or sub-agent runtime call
437
468
 
469
+ ### Cache tab
470
+
471
+ <p align="center">
472
+ <img src="https://github.com/marmutapp/superbased-observer/raw/main/docs/assets/screenshots/08-cache.png" alt="Cache tab" width="900">
473
+ </p>
474
+
475
+ Anthropic prompt-cache observation, attribution, and forecasting —
476
+ how well your sessions are reusing provider-cached prefixes.
477
+
478
+ - **KPI tiles**: Cache ratio (cache_read ÷ cache_write tokens; the
479
+ headline cache-payback signal), Cache read, Cache write, and
480
+ Avoidable spend / Event count. The avoidable-spend tile is the
481
+ dollar overhead of cache rewrites that wouldn't have happened on
482
+ a perfectly cache-friendly session — it surfaces in warn tone when
483
+ non-zero.
484
+ - **By model + By project tables** — for each rollup dimension: R%/W%
485
+ mix bars + absolute Read / Write / Events + cache Ratio + Avoidable
486
+ $. Identifies the model or repo that's pulling the most overhead.
487
+ - **Top causes histogram** — proportional bar list of `cache_events.cause`
488
+ values. Healthy baseline is `suffix_growth` + `hit` dominating
489
+ (info-toned warm prefix growth). Real invalidations (`system_changed`,
490
+ `expiry_rewrite`, `model_switch_rewrite`) render in warn tone. Causes
491
+ that legitimately fire on real operator toggles — currently
492
+ `tools_changed` on MCP server connect/disconnect — render with a
493
+ neutral "flagged" pill rather than alarm-red.
494
+ - **Worst sessions table** — ranked by rewrite count; click a row to
495
+ open the session's Cache panel with the full per-turn timeline.
496
+
497
+ #### How the cache data gets captured
498
+
499
+ Two capture paths feed the same engine; both write the same three
500
+ local-only tables (`cache_segments`, `cache_entries`, `cache_events`;
501
+ migrations 036 + 037 — never pushed to a Teams org server, pinned by
502
+ `tests/invariant/privacy_test.go::TestSelectUnpushedSinceExcludesCacheTables`):
503
+
504
+ 1. **Tier-1 (proxy)** — point your AI client at the local proxy
505
+ (`ANTHROPIC_BASE_URL=http://127.0.0.1:8820` for Claude Code;
506
+ `OPENAI_BASE_URL=http://127.0.0.1:8820/v1` for codex and
507
+ copilot-cli). The proxy reads the upstream usage envelope
508
+ (`cache_read_input_tokens` + `cache_creation_input_tokens`) and the
509
+ cachetrack engine attributes each turn live as it streams. Every
510
+ claude-code prompt-cache event surfaces here in real time.
511
+ 2. **Tier-2 (transcript watcher)** — the watcher tails claude-code
512
+ JSONL transcripts and feeds the same engine retroactively for
513
+ sessions that didn't route through the proxy. Run
514
+ `observer backfill --cache-rescan` to retrofit pre-cachetrack
515
+ history.
516
+
517
+ #### How to enable / disable
518
+
519
+ - **Default-on.** Per spec §11, the loader merges `[cachetrack].enabled = true`
520
+ if the section is absent. No action needed for a fresh install.
521
+ - To disable: set `[cachetrack].enabled = false` in
522
+ `~/.observer/config.toml` and restart `observer start`.
523
+ - Inspect engine health: `observer cache-health --json` — §10 grading
524
+ gate + read:write consistency + cause-concentration WARNs.
525
+ - 90-day retention is on by default
526
+ (`[cachetrack].retention_days = 90`); the maintenance tick prunes
527
+ stale `cache_*` rows alongside the existing retention pass.
528
+
529
+ Operator reference: [`docs/cache-tracking.md`](https://github.com/marmutapp/superbased-observer/blob/main/docs/cache-tracking.md).
530
+
531
+ ### Suggestions tab
532
+
533
+ The **advisor** — a prescriptive suggestions engine that turns the
534
+ window's captured activity into ranked, dollar- or minute-quantified
535
+ recommendations. **On by default** and entirely local: detectors are
536
+ pure reads over data the observer already stores, recomputed fresh on
537
+ every view — zero LLM calls, zero network.
538
+
539
+ Twenty detectors across four categories:
540
+
541
+ - **cost** — session balloons (one session's context growth dominating
542
+ spend), idle re-cache (cache rewrites after idle gaps), long-context
543
+ tier crossings, trivial sessions on expensive models, cache hit-rate,
544
+ cache-write waste, prefix thrash, read-heavy sessions on expensive
545
+ models, effort overprovisioning, cross-session stale reads,
546
+ web-search spend, spend spikes ("today is 3× your daily average" —
547
+ the while-it's-still-happening check, linking to the Live view),
548
+ routing evidence ready (the advise shadow met its promotion gate
549
+ with routing still not enforcing — linking to the Shadow card,
550
+ which owns the evidence and the consent-gated promote).
551
+ - **latency** — fast-tier premium (sessions that paid the 2× fast-tier
552
+ rate without needing it).
553
+ - **quality** — unrecovered failures, quality regressions.
554
+ - **hygiene** — MCP schema overhead vs. actual MCP calls, compression
555
+ off while proxied traffic flows, capture running without proxy
556
+ routing, guard observing idle (recurring high-severity verdicts
557
+ with zero approvals or tuning — linking to the Security page).
558
+
559
+ Each card carries the quantified claim ($ or minutes, with a
560
+ **show math** toggle exposing the arithmetic), a confidence score, a
561
+ scope chip (window / project / session — session scopes deep-link to
562
+ the session detail), and — when a dashboard control can fix the
563
+ finding — an action button that navigates to the right surface
564
+ (writes only ever happen behind that surface's own consent flow).
565
+ `snooze 7d` quiets a card temporarily; `dismiss` retires it, with a
566
+ 7-day cooldown so the same finding doesn't re-nag. The all-clear
567
+ state means exactly what it says: nothing worth nagging about in
568
+ this window.
569
+
570
+ Tune it under Settings → Advisor (`[advisor]` in config.toml):
571
+ evidence window (default 14 days), confidence floor (0.5), minimum
572
+ claimed savings ($1), and the opt-in **session digest** — when
573
+ `session_digest = true`, the Claude Code session-start hook injects a
574
+ ≤400-token digest of the top suggestions into new sessions (off by
575
+ default; the hook only reads a pre-computed snapshot, refreshed every
576
+ 30 minutes). CLI twin: `observer advise`.
577
+
438
578
  ### Discovery tab
439
579
 
440
580
  <p align="center">
441
- <img src="https://github.com/marmutapp/superbased-observer/raw/main/docs/assets/screenshots/08-discovery.png" alt="Discovery tab" width="900">
581
+ <img src="https://github.com/marmutapp/superbased-observer/raw/main/docs/assets/screenshots/09-discovery.png" alt="Discovery tab" width="900">
442
582
  </p>
443
583
 
444
584
  Wasted-effort signals:
@@ -469,21 +609,73 @@ observations push it higher) and an observation count.
469
609
  high-confidence ones into `CLAUDE.md` / `AGENTS.md` / `.cursorrules`
470
610
  so new sessions inherit your habits.
471
611
 
612
+ ### Security tab
613
+
614
+ The guard layer's operating surface — not just a verdict viewer.
615
+ Posture tiles (mode, verdict counts, audit-chain check) over a
616
+ filterable verdict timeline (rule / severity / decision / session,
617
+ with rule IDs resolved to their full definitions), then the routine
618
+ workflows end to end: a consent-gated **mode control** that shows the
619
+ simulate evidence before you flip enforce, the **enforce-readiness
620
+ card** (a replay of your real history under the enforce projection,
621
+ with per-rule blocking concentration), the **approvals register**
622
+ (scoped, expiring exceptions — DB writes, live immediately), a
623
+ **lint-gated policy editor** for your user rules (malformed files are
624
+ refused with the problems listed; `.bak` undo), **budget guardrails**
625
+ suggested from your own observed spend with a daily burn-down meter,
626
+ MCP pin approvals, and one-click **compliance evidence** downloads
627
+ (report / JSONL / CEF / audit verification).
628
+
629
+ ### Routing tab
630
+
631
+ Model routing's transparency + adoption surface. While routing is
632
+ off, a **Preview savings** card replays your last 30 days under any
633
+ policy template — read-only, nothing enabled. Once advise mode runs,
634
+ the page shows the decisions feed (every decision expandable to its
635
+ matched rule, reason codes, and cache economics), savings with CI95
636
+ error bars, the expanded policy rule table (never a black box,
637
+ demoted rules marked), the tier map with calibration overlays, the
638
+ model health board, and the **advise-shadow readiness ladder** with
639
+ its consent-gated promote control. The **Apply to tools** card turns
640
+ observed sub-agent evidence into per-tool native config — dry-run
641
+ preview, one consent per file write, backups + per-file revert, and
642
+ an append-only audit ledger of everything observer changed.
643
+
472
644
  ### Settings tab
473
645
 
474
646
  <p align="center">
475
- <img src="https://github.com/marmutapp/superbased-observer/raw/main/docs/assets/screenshots/09-settings.png" alt="Settings tab" width="900">
647
+ <img src="https://github.com/marmutapp/superbased-observer/raw/main/docs/assets/screenshots/10-settings.png" alt="Settings tab" width="900">
476
648
  </p>
477
649
 
478
- Fully editable visual editor for everything in `config.toml`.
479
- Pricing overrides hot-reload (no daemon restart `cost.Engine`
480
- swaps the pricing table atomically via `atomic.Pointer.Store`).
481
- The Backfill panel surfaces every `observer backfill` mode as
482
- click-to-run buttons that spawn the CLI as a child process and
483
- stream output back live. Watcher / Freshness / Retention / Hooks /
484
- Proxy / Compression / Intelligence sections are schema-driven forms
485
- with inline help; a "Restart daemon" banner appears whenever a
486
- section is saved that consumers bind at startup.
650
+ Fully editable visual editor for everything in `config.toml`, plus
651
+ the operational panels a config file can't express:
652
+
653
+ - **Config sections** schema-driven forms for Watcher, Freshness,
654
+ Retention, Hooks, Proxy, Compression, Intelligence, Advisor, Cache
655
+ tracking, Secrets scrubbing, MCP, Profiles, Org share, and OTel.
656
+ Each section is honest about reload semantics: pricing and profile
657
+ changes apply hot, MCP settings apply to the next AI session, and
658
+ restart-gated sections raise a persistent restart-pending banner
659
+ that names the exact command and clears itself only when the
660
+ daemon actually restarts.
661
+ - **Connected tools** — one row per detected AI client (detected /
662
+ capturing / hooks / MCP / proxied), a per-tool setup wizard that
663
+ previews every config write and applies each one only on its own
664
+ consent click, and a Launch button (with a copy-paste fallback)
665
+ for opening a routed session.
666
+ - **Health** — the full `observer doctor` check set with remediation
667
+ hints, plus recent command failures (recovered vs not).
668
+ - **Backfill** — every `observer backfill` mode as a click-to-run
669
+ job with live streamed output, plus a full-rescan card with an
670
+ adapter picker.
671
+ - **Storage** — what's actually taking the space: per-table database
672
+ size breakdown (index and FTS5 shadow-table bytes folded into the
673
+ table they serve), vacuum and online backup as click-to-run jobs,
674
+ and the documented restore procedure (restore is deliberately
675
+ manual: stop the daemon, swap the file, start). CLI twin:
676
+ `observer db stats|vacuum|backup`.
677
+ - **Config file card** — view the active file; one-click restore of
678
+ the automatic `.bak` taken before every save.
487
679
 
488
680
  ### Help drawer
489
681
 
@@ -560,7 +752,7 @@ a content-aware compressor. Six compressors:
560
752
  | Mechanism | What it does | When it fires |
561
753
  |-----------|--------------|---------------|
562
754
  | **json** | Replaces every scalar value with a type sentinel (`"<string>"`, `"<number>"`, …) preserving structure (keys, arrays, nesting). Arrays of length > 1 collapse to one element with `_len: N`. | API responses, structured logs, telemetry exports. JSON tool_results are usually the biggest savings target. |
563
- | **code** | Heuristic skeleton: keeps top-of-file imports + signature lines (function / method / class / struct / interface / type), drops bodies. | Source code files. **On by default** as of v1.7.23 for the `claude-code` recipe (V7-24 empirical winner). |
755
+ | **code** | Heuristic skeleton: keeps top-of-file imports + signature lines (function / method / class / struct / interface / type), drops bodies. | Source code files. **On by default** as of v1.7.23 in the `claude-code` profile (V7-24 empirical winner). |
564
756
  | **logs** | Two-pass: collapses adjacent identical lines to `<line> [×N]`, then head+tail-truncates to 200 lines if still long. | Log-shaped output — `go test ./...`, `npm run build`, polling/retry loops. Lossless on distinct lines; only the truncate pass is lossy. |
565
757
  | **text** | Catch-all for content not classified as code/json/logs/diff/html. Head+tail truncation: keeps 40 + 40 lines on inputs over 80 lines. | Markdown bodies, README excerpts, narrative descriptions. |
566
758
  | **diff** | Strips unified-diff context beyond ±1 line of each change. Keeps every header, every `+`/`-` line, drops the rest with elision markers. | `git diff`, patch tool outputs. Lossless on changes; lossy only on the cheap-to-rebuild context. |
@@ -606,14 +798,34 @@ tab's "Recent compression events" view surfaces these with
606
798
  mechanism, original / compressed / saved bytes, message slot, and
607
799
  importance score (for drops).
608
800
 
609
- ### Tuning
610
-
611
- `observer config` settings (in `~/.observer/config.toml`). These are the only
612
- keys the conversation compressor reads:
801
+ ### Tuning — profiles pick the parameters for you
802
+
803
+ Compression parameters are supplied by **profiles**: named parameter
804
+ sets resolved per traffic class at the proxy boundary. The moment you
805
+ enable compression, Anthropic-path traffic gets the `claude-code`
806
+ profile and OpenAI-path traffic gets `codex-safe` — each tool gets
807
+ its tuned parameters simultaneously; there is no recipe-picking step.
808
+ Inspect with `observer profile list` / `observer profile show
809
+ <name>`; reassign per class or per tool (`observer profile assign
810
+ openai codex-variant`, `observer profile assign tool:kilo-code-cli
811
+ codex-safe`); build your own (`observer profile create mine --from
812
+ claude-code`, or Settings → Profiles in the dashboard). Per-tool
813
+ assignment needs the proxy to identify the connecting tool: hook-fed
814
+ identity (Claude Code) is exact, and Codex, Kilo CLI, opencode, and
815
+ Claude Code are also recognized by their request headers; clients
816
+ that send no distinctive headers (e.g. Cline CLI) fall back to the
817
+ per-provider profile. Profile
818
+ edits apply to **new sessions without a daemon restart**. A repo can
819
+ also carry `<root>/.observer/config.toml` with `[profiles]` /
820
+ `[compression]` keys to override per project — project files can turn
821
+ compression *off* for their traffic, never on.
822
+
823
+ The master config (`~/.observer/config.toml`) keeps the one on/off
824
+ switch and the fallback parameters used by the `default` profile:
613
825
 
614
826
  ```toml
615
827
  [compression.conversation]
616
- enabled = true
828
+ enabled = true # THE switch — profiles never flip this
617
829
  mode = "cache_aware" # "token" | "cache" | "cache_aware" — default cache_aware; see matrix below
618
830
  target_ratio = 0.85
619
831
  preserve_last_n = 5 # never drop the most recent N messages
@@ -651,20 +863,22 @@ reference lives in `docs/compression-modes.md`.
651
863
 
652
864
  ### Measured savings (v1.7.23)
653
865
 
654
- We A/B every shipped recipe against an OFF baseline on a real refactor
866
+ We A/B every shipped profile against an OFF baseline on a real refactor
655
867
  workload (`lumen` TypeScript codebase, 408-line Zustand store →
656
868
  4 domain sub-stores) on the v1.7.22 binary tip. The numbers below are
657
869
  the **most recent statistically-meaningful measurements**.
658
870
 
659
- **Pick a recipe based on which model you're running:**
871
+ The first two profiles are what the per-provider auto-assignment
872
+ applies (Anthropic → `claude-code`, OpenAI → `codex-safe`);
873
+ `codex-variant` is the manual pick for `-codex`-family models:
660
874
 
661
- | Recipe | Use when your model is… | Workload | n | Δ vs OFF (mean cost) | What's compressed |
875
+ | Profile | Use when your model is… | Workload | n | Δ vs OFF (mean cost) | What's compressed |
662
876
  |---|---|---|---|---|---|
663
- | **`claude-code`** *(default)* | Any Anthropic Claude model — `claude-sonnet-4-6`, `claude-opus-4-7`, `claude-haiku-4-5`, … | Refactor, Claude Sonnet 4.6 via Claude Code 2.1.158 | n=8 B vs n=4 OFF | **−6.9%** (CV 7.6%; tighter than OFF's 7.5%) | json + logs + code bodies; cache-aware; stash disabled |
877
+ | **`claude-code`** *(default)* | Any Anthropic Claude model — `claude-sonnet-4-6`, `claude-opus-4-7`, `claude-haiku-4-5`, … | Refactor, Claude Sonnet 4.6 via Claude Code 2.1.158 | n=8 B vs n=4 OFF | **−6.9%** (CV 7.6%; tighter than OFF's 7.5%) | json + logs + code bodies + tool-defs trim (A2-adopted 2026-06-11: −12.5% vs the pre-A2 set, zero `tools_changed` cache events); cache-aware; stash disabled |
664
878
  | **`codex-variant`** | OpenAI's `-codex` reasoning fork — `gpt-5.3-codex`, `gpt-5.4-codex`, `gpt-5-codex-agent`, anything matching `*-codex*` | Refactor, gpt-5.3-codex | n=10 B vs n=10 OFF | **−10%** ($0.270 vs $0.300) | Tools-defs trim; cache-aware; no per-type compression |
665
- | **`codex-safe`** | Plain OpenAI GPT under the codex CLI — `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.5`, `gpt-4o`, any non-`-codex` | Refactor, gpt-5.4 + `apply_patch` | n=3 B vs n=4 OFF | not statistically distinguishable on this workload | logs only; cache-aware |
879
+ | **`codex-safe`** | Plain OpenAI GPT under the codex CLI — `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.5`, `gpt-4o`, any non-`-codex` | Refactor, gpt-5.4 + `apply_patch` | n=3 B vs n=4 OFF | not statistically distinguishable on this workload | logs + tools-defs trim (A6-adopted 2026-06-11: fired on 117/117 candidate requests, ~0.8KB/request of definition prose, task-completion parity + no cache degradation at n=9 vs n=7; effect scales with envelope bulk — MCP-registered installs save more); token mode |
666
880
 
667
- The word **"variant"** in `codex-variant` refers to the *model variant* (the `-codex` reasoning fork of GPT), NOT a variant of the codex CLI. Both codex recipes are for the codex CLI; they differ only in which model family they assume. `codex-safe` is so named because plain GPT models tolerate logs trimming safely — it's not "safer than codex-variant."
881
+ The word **"variant"** in `codex-variant` refers to the *model variant* (the `-codex` reasoning fork of GPT), NOT a variant of the codex CLI. Both codex profiles are for the codex CLI; they differ only in which model family they assume. `codex-safe` is so named because plain GPT models tolerate logs trimming safely — it's not "safer than codex-variant."
668
882
 
669
883
  **Honest caveats:**
670
884
 
@@ -749,6 +963,126 @@ counts one API call 2-4×. Two layers of dedup catch this:
749
963
  Migration 007 ran a one-time pass collapsing pre-fix duplicates.
750
964
 
751
965
 
966
+ ## Security & control layer (guard)
967
+
968
+ The guard evaluates every captured agent action against a
969
+ table-driven policy — built-in rules (destructive commands, project
970
+ boundaries, secrets egress, MCP pinning, taint/dataflow, budgets)
971
+ plus your own TOML rules — records each verdict in a hash-chained,
972
+ tamper-evident audit table, and on the channels that support it can
973
+ block before execution. It ships **observe-only by default**: a fresh
974
+ install records and alerts, and never blocks anything until you
975
+ explicitly flip enforce.
976
+
977
+ What makes it different from standalone command-guards:
978
+
979
+ - **One policy, every tool.** The same rules evaluate Claude Code,
980
+ Codex, Cursor, Cline and the rest through one engine — and
981
+ `observer init --guard` additionally *compiles* the policy into
982
+ each client's own native permission dialect, so the client itself
983
+ enforces even when the observer daemon is down.
984
+ - **Replay before you enforce.** `observer guard simulate --since 168h`
985
+ replays your real captured history against current policy and shows
986
+ what last week WOULD have flagged or blocked — a confidence check
987
+ only a tool that already has your history can run.
988
+ - **Proxy-level secrets egress scanning.** Clients routed through the
989
+ observer proxy get outbound API bodies scanned for credentials,
990
+ with mask/deny enforcement — an egress point no other local-first
991
+ tool sits on.
992
+ - **Auditable, honestly.** Verdicts are hash-chained
993
+ (tamper-EVIDENT, not tamper-proof — the docs say exactly what that
994
+ means), exportable as JSONL/CEF for your SIEM, and summarized by
995
+ `observer guard report` into a compliance evidence pack mapped to
996
+ SOC 2 / NIST 800-53.
997
+ - **Operable from the dashboard, not just the CLI.** The Security
998
+ page runs the routine workflows end to end: a consent-gated mode
999
+ control that shows the simulate evidence before you flip enforce,
1000
+ an Enforce-readiness replay over your real history, the approvals
1001
+ register (scoped, expiring exceptions — live immediately), a
1002
+ lint-gated policy editor for your user rules (malformed files are
1003
+ refused before they touch disk, with `.bak` undo), budget
1004
+ guardrails suggested from your own observed spend (p95 + headroom)
1005
+ with a daily burn-down meter, MCP pin approvals, and one-click
1006
+ compliance evidence downloads.
1007
+
1008
+ Honest scope: hooks see declared commands, not side effects (use OS
1009
+ sandboxes for containment — the guard detects and recommends them);
1010
+ most adapters are watcher-channel and can only flag post-hoc; the
1011
+ proxy scan only covers proxy-routed clients. The full capability
1012
+ matrix is on the dashboard's Security page, and the no-network
1013
+ invariant holds — nothing leaves your machine unless you opt into
1014
+ Teams push, OTel export, or the cloud alerting tier, each
1015
+ individually.
1016
+
1017
+ Quick start:
1018
+
1019
+ ```
1020
+ observer guard status # mode, rules, recent verdicts, chain check
1021
+ observer guard test "rm -rf ./build" # would this block?
1022
+ observer guard simulate --since 168h # what would last week have flagged?
1023
+ observer guard enable --enforce # flip to enforce when ready
1024
+ ```
1025
+
1026
+ Full references:
1027
+ [guard.md](https://github.com/marmutapp/superbased-observer/blob/main/docs/guard.md)
1028
+ (operator guide + getting started),
1029
+ [guard-rules.md](https://github.com/marmutapp/superbased-observer/blob/main/docs/guard-rules.md)
1030
+ (rule catalog),
1031
+ [guard-policy-authoring.md](https://github.com/marmutapp/superbased-observer/blob/main/docs/guard-policy-authoring.md)
1032
+ (writing rules + cookbook),
1033
+ [guard-enforce-runbook.md](https://github.com/marmutapp/superbased-observer/blob/main/docs/guard-enforce-runbook.md)
1034
+ (the observe→enforce migration),
1035
+ [guard-compliance.md](https://github.com/marmutapp/superbased-observer/blob/main/docs/guard-compliance.md)
1036
+ (SOC 2 / NIST mapping).
1037
+
1038
+ ## Model routing
1039
+
1040
+ The routing layer selects the right model for each KIND of work —
1041
+ from your own observed evidence, never a brochure — through two
1042
+ channels: **A** writes each AI tool's own config (claude-code
1043
+ per-subagent `model:` frontmatter — dry-run first, backed up,
1044
+ revertable, audit-ledgered; other tools get exact paste-able
1045
+ snippets), and **B** rewrites the `model` field on requests already
1046
+ transiting the proxy. It is **opt-in, advise-first, and fail-open
1047
+ everywhere**: a routing failure can never break a turn that would
1048
+ have succeeded.
1049
+
1050
+ The adoption ladder is deliberate, and every step has a dashboard
1051
+ surface: **preview** what a policy would have saved over your last 30
1052
+ days while routing is still off (a read-only replay of recorded
1053
+ turns) → enable **advise** (decision rows accrue; requests untouched)
1054
+ → read the **shadow** (the §R22 readiness ladder: enough decisions,
1055
+ real net savings after cache forfeits, zero quality flags) →
1056
+ **promote** to enforce through a consent dialog that restates the
1057
+ evidence — and warns loudly when the gate is not met. Enforce
1058
+ rewrites within the same provider shape only, holds switches that
1059
+ would forfeit a warm prompt cache worth more than they save, and
1060
+ auto-demotes any rule whose downshifts grade as regressing
1061
+ (loudly, never silently). Custom `[[routing.rules]]` are editable in
1062
+ a lint-gated dashboard editor with a worked recipe gallery in the
1063
+ docs.
1064
+
1065
+ Privacy posture: decision rows and calibration are **node-local**
1066
+ (never pushed to an org server); org-distributed policy fragments are
1067
+ signed and structurally cannot flip your enforce switch — **no remote
1068
+ enforce toggle exists, by design**.
1069
+
1070
+ Quick start:
1071
+
1072
+ ```
1073
+ # Preview before enabling anything (CLI twin of the dashboard card):
1074
+ observer routing simulate --policy value --days 30
1075
+ # Then: dashboard → Routing → Preview savings → Enable advise mode.
1076
+ observer routing shadow # the promotion evidence, any time
1077
+ observer routing apply --tool claude-code # Channel A, dry-run default
1078
+ ```
1079
+
1080
+ Full reference:
1081
+ [model-routing.md](https://github.com/marmutapp/superbased-observer/blob/main/docs/model-routing.md)
1082
+ (operator guide + the first-30-days runbook + the rules recipe
1083
+ gallery).
1084
+
1085
+
752
1086
  ## Terminology and glossary
753
1087
 
754
1088
  Quick reference; the in-platform help drawer (press `?` on the
@@ -836,9 +1170,11 @@ Every command supports `--help` for the full surface.
836
1170
 
837
1171
  | Subcommand | Purpose |
838
1172
  |------------------------------------|---------|
839
- | `observer init` | Register hooks + MCP server with installed AI clients |
1173
+ | `observer init` | Register hooks + MCP server + durable proxy routes with installed AI clients (each side defaults on; opt out with `--skip-hooks` / `--skip-mcp` / `--skip-proxy-route`). With **zero flags on a terminal** it runs an interactive checklist instead: detects your tools, previews each pending config write, and asks consent one write at a time (MCP never pre-selected). Any flag or redirected stdio keeps the batch behaviour. |
840
1174
  | `observer uninstall` | Reverse `observer init` |
841
- | `observer start` | Run watcher + dashboard + proxy in one process (recommended). Flags: `--dashboard-addr ADDR` (default `127.0.0.1:8081`), `--no-dashboard` to skip the HTTP UI. |
1175
+ | `observer start` | Run watcher + dashboard + proxy in one process (recommended). Auto-opens the dashboard on interactive launches. Flags: `--dashboard-addr ADDR` (default `127.0.0.1:8081`), `--no-dashboard` to skip the HTTP UI, `--no-open` to skip the browser. |
1176
+ | `observer claude [-- args…]` | Launch Claude Code routed through the proxy for that session only (no config writes; fresh Pro/Max OAuth token re-exported so the SDK can't bypass). `--verify` runs pre-flight checks without launching. |
1177
+ | `observer codex [-- args…]` | Launch Codex routed through the proxy for that session only (injects `openai_base_url` via argv; no config writes). |
842
1178
  | `observer watch` | Long-running JSONL watcher only |
843
1179
  | `observer dashboard --addr ADDR` | HTTP dashboard only |
844
1180
  | `observer proxy start` | Reverse proxy only |
@@ -855,13 +1191,19 @@ Every command supports `--help` for the full surface.
855
1191
  | `observer summarize` | Roll-up summary across sessions |
856
1192
  | `observer export` | Export DB to xlsx / json |
857
1193
  | `observer prune` | Manual retention pass (delete old data) |
1194
+ | `observer db stats\|vacuum\|backup` | Storage manager. `stats`: per-table size breakdown (index + FTS5 shadow bytes folded into the table they serve). `vacuum`: reclaim free pages, reports bytes freed (can report SQLITE_BUSY against a busy daemon — re-run in a quiet moment). `backup <path>`: online snapshot via SQLite `VACUUM INTO` — safe while the daemon runs, refuses to overwrite. Restore is manual by design: stop daemon, swap file, start. |
1195
+ | `observer db import <path>` | Merge another `observer.db` into this node's (a stranded install from another OS or home directory). Set-based, single-transaction, idempotent — re-running adds nothing twice; project identities remap by root path. `--dry-run` executes the same transaction and rolls it back, so its per-table counts are exact. Migrates the source schema first — point it at a copy. Node-local state (cache tracking, watcher cursors, advisor state) doesn't transfer. |
858
1196
  | `observer backfill --is-sidechain` | Re-walk JSONL to populate `actions.is_sidechain` (added by migration 010) on pre-migration rows. |
859
1197
  | `observer backfill --cache-tier` | Re-walk JSONL to populate `cache_creation_1h_tokens` (added by migration 008) on pre-migration rows. Run once after upgrading to v1.4.16+ to correct historical 1h-tier cache writes that were silently billed at the cheaper 5m rate. |
860
1198
  | `observer backfill --message-id` | Re-walk JSONL to populate `message_id` on `actions` and `token_usage` (added by migration 012). Required by the per-message timeline view in the Sessions modal. |
861
1199
  | `observer backfill --all` | Run every supported backfill in one invocation. Idempotent — safe to re-run. |
1200
+ | `observer profile list\|show\|assign\|create\|delete\|set` | Compression profiles: inspect built-ins, reassign per traffic class or per tool (`assign tool:cline codex-safe`), create/edit custom profiles. Edits apply to new sessions hot. |
1201
+ | `observer config set <key> <value>` | Dotted-key config setter (`compression.conversation.enabled true`). `--project <root>` writes a per-repo override file instead. |
1202
+ | `observer advise` | Prescriptive cost/quality suggestions from captured activity (the Suggestions tab, in the CLI) |
1203
+ | `observer cache-health` | Prompt-cache engine health: grading gate, read:write consistency, cause concentration |
862
1204
  | `observer metrics` | Prometheus-format metrics endpoint |
863
1205
  | `observer serve` | MCP server (stdio JSON-RPC) — usually invoked by `observer init` registration |
864
- | `observer tail` | Live event stream |
1206
+ | `observer completion <shell>` | Generate shell completions (bash / zsh / fish / powershell) — e.g. `observer completion zsh > "${fpath[1]}/_observer"` |
865
1207
 
866
1208
 
867
1209
  ## Configuration
@@ -965,11 +1307,13 @@ its dirs get created and the watcher picks them up.
965
1307
 
966
1308
  ### Empty dashboard / "No proxy traffic"
967
1309
 
968
- The JSONL adapter populates passively after `observer init`, but
969
- ground-truth cost / compression numbers require the proxy. Set
970
- `ANTHROPIC_BASE_URL=http://127.0.0.1:8820` (Claude Code) or
971
- `OPENAI_BASE_URL=http://127.0.0.1:8820/v1` (Codex) in the shell
972
- that launches your AI client.
1310
+ Session/action data populates passively whenever `observer start` is
1311
+ running, but ground-truth cost / compression numbers require the
1312
+ proxy. Route your tool through it — the quickest way is the
1313
+ dashboard's Compression tab → **Proxy** banner → **Route through the
1314
+ observer proxy…** button; every other mechanism (wrappers, env vars,
1315
+ `observer init`) is listed under
1316
+ [Per-AI-client setup](#per-ai-client-setup).
973
1317
 
974
1318
  Verify with `observer status | grep api_turns` — count should
975
1319
  climb during AI-client activity.
@@ -3,6 +3,9 @@
3
3
  [![npm](https://img.shields.io/npm/v/@superbased/observer.svg)](https://www.npmjs.com/package/@superbased/observer)
4
4
  [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
5
5
  [![Platforms: Linux • macOS • Windows](https://img.shields.io/badge/platforms-linux%20%7C%20macos%20%7C%20windows-blue.svg)](https://github.com/marmutapp/superbased-observer)
6
+ [![Website](https://img.shields.io/badge/homepage-superbased.app-2EC4B6.svg)](https://superbased.app/)
7
+
8
+ **Homepage:** [https://superbased.app/](https://superbased.app/)
6
9
 
7
10
  **Capture, normalize, compress, and analyze every AI coding tool call you
8
11
  run** — across Claude Code, Codex, Cursor, Cline / Roo Code, GitHub
@@ -82,30 +85,33 @@ the [main repo](https://github.com/marmutapp/superbased-observer).
82
85
  ## Five-minute quickstart
83
86
 
84
87
  ```bash
85
- # 1) Install. `observer init` is OPTIONAL — only run it if you want
86
- # the MCP server registered with your AI clients (gives them
87
- # on-demand tools like check_file_freshness / get_cost_summary
88
- # at the cost of ~1,800 tokens of schema per turn).
88
+ # 1) Install.
89
89
  npm install -g @superbased/observer
90
- observer init # OPTIONAL — interactive: pick clients;
91
- # writes MCP + codex proxy-route into AI client configs.
92
- # Skip this step for an MCP-free install.
93
-
94
- # 2) Start the long-running services (proxy + watcher + dashboard).
95
- # Auto-registers HOOKS for every detected AI tool on first launch.
96
- observer start &
97
-
98
- # 3) Engage the proxy by pointing your AI client at the local URL.
99
- # See "Per-AI-client setup" for the matching env var.
100
- export ANTHROPIC_BASE_URL=http://127.0.0.1:8820 # Claude Code
101
- export OPENAI_BASE_URL=http://127.0.0.1:8820/v1 # Codex / OpenAI
102
-
103
- # 4) Open the dashboard.
104
- open http://127.0.0.1:8081/ # macOS
105
- xdg-open http://127.0.0.1:8081/ # Linux
106
- start http://127.0.0.1:8081/ # Windows
90
+
91
+ # 2) Start everything: proxy + watcher + dashboard in one process.
92
+ # Hooks auto-register for every detected AI tool, and the
93
+ # dashboard opens in your browser (suppress with --no-open).
94
+ observer start
107
95
  ```
108
96
 
97
+ From here the dashboard drives:
98
+
99
+ 3. **Route your AI client through the proxy** — on the Compression
100
+ tab's **Proxy** banner, click your tool's status pill, then
101
+ **Route through the observer proxy…**. The button previews the
102
+ exact file change and writes only on confirm. (Every other
103
+ routing mechanism — `observer init`, the `observer claude` /
104
+ `observer codex` wrappers, plain env vars — is listed in
105
+ [Per-AI-client setup](#per-ai-client-setup).)
106
+ 4. **Use your AI tool as normal.** The Overview tab's onboarding
107
+ checklist tracks your first captured session; cost, compression,
108
+ and cache numbers populate within minutes of real activity.
109
+
110
+ `observer init` is OPTIONAL — run it only if you want the MCP server
111
+ registered with your AI clients (gives them on-demand tools like
112
+ `check_file_freshness` / `get_cost_summary`, at the cost of ~1,800
113
+ tokens of schema per turn). Skip it for an MCP-free install.
114
+
109
115
  **What `start` does vs what `init` adds:**
110
116
 
111
117
  | Step | Hooks | Proxy listening | Watcher | Dashboard | MCP in AI clients | Codex proxy route |
@@ -117,10 +123,6 @@ start http://127.0.0.1:8081/ # Windows
117
123
  MCP and codex routing are explicit-only because both write per-client
118
124
  config files. Hooks self-heal on every `start`.
119
125
 
120
- After ten minutes of normal AI-coding usage, the dashboard will be
121
- populated with cost over time, per-tool activity, compression
122
- savings, and stale-reread waste signals.
123
-
124
126
 
125
127
  <!-- @@INCLUDE:docs/distribution/README-body.md@@ -->
126
128
 
@@ -181,11 +183,13 @@ its dirs get created and the watcher picks them up.
181
183
 
182
184
  ### Empty dashboard / "No proxy traffic"
183
185
 
184
- The JSONL adapter populates passively after `observer init`, but
185
- ground-truth cost / compression numbers require the proxy. Set
186
- `ANTHROPIC_BASE_URL=http://127.0.0.1:8820` (Claude Code) or
187
- `OPENAI_BASE_URL=http://127.0.0.1:8820/v1` (Codex) in the shell
188
- that launches your AI client.
186
+ Session/action data populates passively whenever `observer start` is
187
+ running, but ground-truth cost / compression numbers require the
188
+ proxy. Route your tool through it — the quickest way is the
189
+ dashboard's Compression tab → **Proxy** banner → **Route through the
190
+ observer proxy…** button; every other mechanism (wrappers, env vars,
191
+ `observer init`) is listed under
192
+ [Per-AI-client setup](#per-ai-client-setup).
189
193
 
190
194
  Verify with `observer status | grep api_turns` — count should
191
195
  climb during AI-client activity.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superbased/observer",
3
- "version": "1.8.2",
3
+ "version": "1.8.4",
4
4
  "description": "SuperBased Observer — capture, normalize, compress, and analyze AI coding tool activity across Claude Code, Codex, Cursor, Cline/Roo, and Copilot.",
5
5
  "keywords": [
6
6
  "ai",
@@ -14,7 +14,7 @@
14
14
  "tokens",
15
15
  "cost"
16
16
  ],
17
- "homepage": "https://github.com/marmutapp/superbased-observer",
17
+ "homepage": "https://superbased.app/",
18
18
  "repository": {
19
19
  "type": "git",
20
20
  "url": "git+https://github.com/marmutapp/superbased-observer.git"
@@ -36,11 +36,11 @@
36
36
  "LICENSE"
37
37
  ],
38
38
  "optionalDependencies": {
39
- "@superbased/observer-linux-x64": "1.8.2",
40
- "@superbased/observer-linux-arm64": "1.8.2",
41
- "@superbased/observer-darwin-x64": "1.8.2",
42
- "@superbased/observer-darwin-arm64": "1.8.2",
43
- "@superbased/observer-win32-x64": "1.8.2"
39
+ "@superbased/observer-linux-x64": "1.8.4",
40
+ "@superbased/observer-linux-arm64": "1.8.4",
41
+ "@superbased/observer-darwin-x64": "1.8.4",
42
+ "@superbased/observer-darwin-arm64": "1.8.4",
43
+ "@superbased/observer-win32-x64": "1.8.4"
44
44
  },
45
45
  "scripts": {
46
46
  "test": "node bin/observer.js --version"