Operations · 5. Meters and System
Meters answers "what did that session burn, and where did it go". System is every setting, integration and developer surface. This chapter is reference. The two Meters pages share one feed and are useless without it, so §5.1 covers that first.
5.1 Where the Meters numbers come from, and why they might be absent
Both Meters pages read GET /v1/cost/report. That store is POST-fed. Nothing computes a cost report on its own: corecruxctl session cost --post parses a local agent transcript and posts the result (render.js:11162).
Two things must therefore be true before either page shows anything:
CORECRUXD_FEATURE_COST_LENSis enabled on the daemon (cost.rs:30).- At least one report has been posted for the tenant.
The empty state says both, in as many words. That is deliberate: an empty cost page that said only "no data" would be indistinguishable from a broken one.
Neither page claims a saving. The daemon measures no counterfactual, no run of the same work without it, so there is no baseline to compare against. The Usage page carries a card that says exactly that, in place of the savings figure it used to invent (pages.js:1006).
5.2 Meters › Token Burn (Session)
Open this to find the session that cost you the most, and why. One row per posted report, with filters, a totals row and a top-burn chart (render.js:11169).
The filter toolbar
| Control | Type | Default | Filters on |
|---|---|---|---|
| filter | search | empty | Session id, source, actor passport, plan slugs, and the agent-given title, summary and actor from the session store |
| passport | select | all passports | Options are the distinct actor_passport values present, excluding __anon__ |
| plan | select | all plans | The distinct execplan_slugs present |
| min burn (out) | number, step 1000 | empty | Keeps rows whose output_tokens is at least this |
| from | date | empty | Session start, UTC midnight |
| to | date | empty | Session start, UTC end-of-day |
| sort | select | total burn (ctx+out) | See below |
Both selects are populated from the data, not hardcoded, so an empty dropdown means no report carries that field.
Sorting: magnitude versus rate
The sort control switches between two readings of the same rows (render.js:11415):
| Sort | Reads | Use it to find |
|---|---|---|
| total burn (ctx+out) | Magnitude | The sessions that cost most |
| output tokens | Magnitude | The sessions that produced most |
| output / turn | Rate | Verbose turns |
| context / turn | Rate | Sessions re-reading a large prefix |
| context : output | Rate | Sessions that read far more than they wrote |
| most recent | Time | What just happened |
A row with no value for the chosen metric sinks to the bottom rather than sorting as zero (render.js:11425). The comment in the source puts it well: "unavailable" is not "cheap".
The totals row and the count line
Under the chart, a TOTALS strip with the summed context, summed output and the number of sessions currently visible; it re-computes as you filter. The count line above adds how many reports are posted in total and how many carry an agent-given title.
A row
Each row shows the session, its window, burn figures and its plan attribution. The plan chip is the honest part:
| Chip | Means |
|---|---|
<slug> · <state> | The report carries execplan_slugs from the producer. This is a link, precise |
window-inferred | No producer link. Burn attributes to plans by window-overlap on the board (render.js:11506) |
Never read a window-inferred attribution as precise. It means "these plans were open at the same time", not "this session worked on them".
The advice thresholds
The page will attach an advice line to a session that trips one of five named gates, and it publishes the thresholds rather than hiding them (render.js:11400):
| Gate | Trips when |
|---|---|
| context-heavy | context ÷ output ≥ the ratio threshold |
| replay | context per turn ≥ the per-turn threshold |
| long session | assistant turns ≥ the turns threshold |
| verbose turns | output per turn ≥ the per-turn threshold |
| over scale | context + output exceeds the scale threshold |
A session that trips none gets no advice line. Every recommendation names a feature the daemon actually ships, token_budget, query_scan / query_expand, save_session / get_session, store_fact / query_facts, and no savings percentage is claimed.
The section-model variant
Routing to this page through the section model rather than the custom renderer gives you the same feed shaped as four cards: a session select, a Headline card (context per turn, cache replay multiple, turns and tasks, the fixed-prefix share), a Where it goes bar chart of carried-cost buckets, and a What you can do to reduce burn card of grounded levers (pages.js:811). A Spend over time chart sits at the bottom and is honest about itself: the cost lens has no bucketed series endpoint, so it renders an empty state unless demo mode is on (pages.js:805).
5.3 Meters › Average Token Usage
Open this for per-period and per-turn averages. Everything on it is computed from the same posted reports; there are no controls beyond the page itself (pages.js:958).
Four cards:
Measured usage, reports counted and the days they span; last 7 days; last 30 days; all reports; a daily average; an average per session; and an average per turn.
That last line is the careful one. Per-turn averages accumulate only over reports that carry a turn count, so like divides by like; folding turn-less reports' tokens into the numerator would deflate it silently. The line states how many of how many reports contributed and that the rest are excluded rather than counted as zero (pages.js:990).
Output per session on the token-burn scale, three bars (median, mean, largest) on the same fixed 2,000,000-token ceiling and gradient the Token Burn chart uses, so a bar length means one thing console-wide.
The bars measure output, not total, and the card explains why: on the measured corpus, context is around 99% of all tokens, so a context+output bar pins at the ceiling for nearly every session and conveys nothing. Context is not dropped; it is stated as a share, in numbers, in the row beneath (pages.js:944).
Output tokens over time, a real day/week/month series, bucketed from the session windows in the reports. When no report carries a usable window timestamp, the chart says so.
Savings, a card whose entire content is that no saving is measured, and why.
5.4 System: where it lives and what is in it
System has no rail row. Its pages hang off the account badge at the bottom of the rail (shell.html:4764).
| Page | Posture / mode | What it is |
|---|---|---|
| Settings | All | Daemon configuration and console preferences |
| Integrations | All | Installed packs and their grants, read |
| Extensions | All | Signed third-party manifests, read |
| Workbench | All | Operator tooling over /v1/workbench/* |
| Raw · JSON-RPC | Operator only | The MCP plane, by hand |
| Infra | Professional mode only | Machines, auth rails, config and session sync |
| Docs | Professional mode only | Bundled daemon reference |
5.5 System › Settings
Open this to see how the daemon is configured, and to change the two things the console actually owns.
Read the next paragraph before you touch anything on this page.
Almost every control on Settings is read-only, deliberately. Every mutating control here carries an honest, page-specific reason instead of a generic "coming soon": read-only in the console, set on the daemon host (pages.js:792). Daemon configuration is environment, not a form. The selects and toggles show you the running value; they do not write it. Four buttons are exceptions and are called out below.
The page also injects two console-preference cards above the daemon sections: Command density and Theme, both covered in chapter 2 §2.7 and §2.9 (shell.html:5266).
Runtime capabilities (top card)
Injected before everything else, only on this page (render.js:584). Eight rows, each reading <availability>, <reason> verbatim from the daemon's capability plan:
| Capability | What it gates |
|---|---|
| Dataplane append | The append path |
| Local embedders | On-box embedding |
| Embedding delegation | Delegated embedding |
| GPU rerank | Reranking |
| Hosted sync | Hosted synchronisation |
| Projection queries | The living-document projection reads |
| Graph expansion | POST /v1/query/graph-expand |
| Link graph (CoreCrux proxy) | The Link graph destination's visibility |
The validation is strict and fails closed. A descriptor with the wrong schema version, a missing capability, a missing reason code, a non-boolean stage flag, or a self-contradicting state (available while degraded) all resolve to unavailable with a stated reason code (render.js:531). This card is the first place to look when a console pane is missing.
Node
| Row | Source |
|---|---|
| origin | The browser's own origin |
| node id | node_id from the settings read |
| build | The daemon build version |
Access posture
| Control | Type | Default | Notes |
|---|---|---|---|
| auth mode | select | The running mode | Options come from the daemon's supported_modes when it reports them, else off / dev_scopes / jwt_hs256 / jwt_jwks. Read-only |
| require passport binding | toggle | on | Read-only |
Embedding (semantic retrieval)
Crux ships no embedding model; you point it at your endpoint.
| Control | Type | Default | Notes |
|---|---|---|---|
| enable embedding retrieval | toggle | The daemon's intent or active state | Read-only |
| endpoint URL | text, mono | The chosen or active URL | Read-only |
| Probe endpoint | button | - | SHIPPED, live. POST /v1/console/embedding/probe, SSRF-guarded, fetches available models. No confirmation |
| model | select | The chosen or active model | Options -, bge-m3, nomic-embed-text, e5-large-v2. Read-only |
Memory and freshness
The decay engine's horizons. All four are read-only.
| Control | Default | Options |
|---|---|---|
| decay engine | on | - |
| volatile horizon | 24h | 12h, 24h, 48h |
| medium horizon | 35d | 7d, 35d, 90d |
| stable horizon | 365d | 180d, 365d |
| Run sweep now | - | STUBBED |
Run sweep now is gated with a reason: there is no HTTP route. memory_sweep_candidates is an MCP tool and a dry run; the real sweep is a background timer with no daemon endpoint (pages.js:1673).
Coordination and leases
All three are read-only mirrors of the daemon's environment.
| Control | Default shown | Options | Real flag |
|---|---|---|---|
| punchcards | advisory | off, advisory, enforce | CORECRUXD_PUNCHCARD, daemon default off |
| coordination plane | on | - | CORECRUXD_COORD, daemon default on |
| observe / audit trail | off | - | CORECRUXD_OBSERVE, daemon default off |
Note the mismatch: the punchcards select displays advisory while the daemon's own default is off (agentgraph_kinds.rs:162). Read the daemon's environment, not this control, for the truth.
Retention
| Control | Default | Notes |
|---|---|---|
| receipts (days) | 90 | Read-only |
| execplan facts | indefinite, operator delete only | Info row |
| Export audit bundle | - | STUBBED |
Export audit bundle is gated with a reason: the real route is a read that needs a session id and CORECRUXD_OBSERVE, and there is no unparameterised console trigger for it (pages.js:1674).
Onboarding
| Control | Status |
|---|---|
| Re-run onboarding | SHIPPED, live, destructive. Confirms: Resets onboarding, the first-run wizard shows again on next load and the recorded completion is cleared for this node. Proceed? (render.js:769) |
Daemon
| Control | Status |
|---|---|
| build | Info row: version and port |
| Restart daemon | SHIPPED, live, destructive |
The restart confirmation is the most explicit in the console, and worth quoting because operators reach for this button expecting a graceful reload (render.js:766):
This RESTARTS THE DAEMON PROCESS, the daemon exits immediately (POST /v1/admin/restart) and relies on the service/container restart policy to come back. All in-flight requests drop and the console briefly disconnects. Proceed?
If your process manager has no restart policy, this button stops the daemon and nothing brings it back. The shipped root compose file sets restart: unless-stopped specifically so this works.
What Settings deliberately does not have
There is no Appearance section. The theme has its own card, and the old "canvas 2D | 3D toolbar switch" row was removed because no such control exists (pages.js:781).
5.6 System › Integrations (read)
This page reads the integration plane. It does not operate it. The first card says so and links straight through to Studio › Integrations, which is where connect, install, grant, invoke and revoke actually live (pages.js:543).
That link-through is on the page three times, deliberately. Before it existed, this page described flows that had no home.
| Card | Contents |
|---|---|
| Where integrations are set up | Two info rows and the Studio link |
| Catalog | A search box, one expander per pack (id, description, version, status, capabilities), and a header line reading enabled/disabled plus safe mode where set |
| Source connectors | Two expanders: GitHub and OpenAI-compatible LLM |
| Grants | Active grant count, a Review grants button, and the Studio link |
The two connector expanders carry live controls:
| Connector | Fields | Buttons |
|---|---|---|
| GitHub | personal access token (masked), skip TLS verify (dev only), default off | Verify connection: SHIPPED, live, POST /v1/integrations/github/connect |
| OpenAI-compatible | default model select (none default), API key (masked), organisation | Test call: SHIPPED, live, confirms first |
The Test call confirmation is the only spend warning in the console (render.js:751):
This makes an OUTBOUND request to the connected LLM and MAY SPEND TOKENS on your account. Proceed?
Both pages state the credential posture plainly: the token or key is held encrypted by the daemon and never in browser storage.
5.7 System › Extensions (read)
Same split as Integrations: read here, operate in the Studio (pages.js:593).
| Card | Contents |
|---|---|
| Where extensions are managed | The Studio link-through |
| Installed | Count in the heading; one expander per manifest with kind, version and capabilities. When empty it says whether unsigned dev installs are allowed |
| Trusted signing keys | passport fingerprint, trust tier select (unknown, community_reviewed default, locally_signed, first_party), public key. Add key is SHIPPED and live |
| Install manifest | manifest URL/path and an Install button |
Install is STUBBED here, with a precise reason: the registration route wants a full manifest object and this form supplies only a URL, so there is no groundable body. Installing from the signed catalog by id is wired, in the Studio, where the entry id and its curator-pinned sha256 are known (pages.js:1671). The card's own sub-line says the same thing.
5.8 System › Workbench
Operator deep machinery. Read tools run live; write tools are wired with confirmations (pages.js:1176).
Live read tools
Five self-loading panels, each firing a GET through the read client on open (pages.js:1186):
| Panel | Endpoint |
|---|---|
| API drift | GET /v1/workbench/api-drift |
| Command ledger | GET /v1/workbench/command-ledger |
| Reasoning timeline | GET /v1/workbench/reasoning-timeline |
| Audit triage | GET /v1/workbench/audit-triage |
| Agent brief | GET /v1/workbench/brief |
All five default to tenant_id=default. A pro-gated payload returns an entitlement note rather than an error.
The contract card
GET /v1/workbench/contract enumerates every workbench surface with its method, path and live entitlement. Each row's badge is one of enabled, pro, entitled or the raw status (pages.js:1170). A GET row is labelled read; anything else write · gated.
The write tools
Five, all SHIPPED and live, all additive, none confirming (render.js:740):
| Button | Fields | Writes |
|---|---|---|
| Build context pack | pack tenant (default), pack query | A receipted pack fact |
| Run impact preflight | impact target, comma or space separated changed paths | A preflight fact |
| Simulate policy | policy profile (eu-ai-act default, workspace, none), action to simulate | A simulation fact |
| Probe route | route to probe | Admin-scoped route probe |
| Record capability audit | capability id, audit status (pass default, partial, fail), audit notes | A capability audit |
The query workbench
A read-only card of /v1/query/* lanes, text search, graph expand, time range, plus a tenant and a time-window select. Its buttons are inert here by design; the live search surface is Explorer (chapter 6 §6.4).
The legacy-console notice
The last card states that the legacy console has been fully removed and /console/legacy now 404s. The workbench is native; there is no fallback surface (pages.js:1331).
5.9 System › Raw · JSON-RPC (operator only)
The MCP plane, by hand (pages.js:1359).
| Control | Default |
|---|---|
| method | select: tools/list, tools/call · query, tools/call · store_fact, resources/list |
| params | textarea, 4 rows, pre-filled { "token_budget": 500 } |
| Send | STUBBED |
| Response | An output pane |
X-Corecrux-Scopes | text, mono, read |
Send is gated and will stay gated. The reason given is a design position, not a milestone: the underlying route dispatches an arbitrary MCP tools/call, and a live console control there would be an arbitrary-write surface, breaking the curated no-arbitrary-mutation invariant the whole console rests on (pages.js:1675).
The transport card is still useful: it tells you the MCP endpoint is POST /mcp on port 14801, not on the HTTP port.
5.10 System › Infra (Professional mode only)
Five panels from one endpoint, GET /v1/console/infra/summary (pages.js:1027).
| Panel | Shows |
|---|---|
| Onboarding checklist | Login auth (tick plus the mode), MCP enabled, machines registered and how many have hooks |
| Auth rails | Tailscale identity, device grant, agent-token-over-HTTP, each enabled or disabled |
| Machines | One expander per machine: tailnet IP, OS/arch, rail, hooks, CLI version. Empty state: run corecruxctl login |
| Config bundles | Saved ~/.claude configs with file counts and source host, secrets redacted. Empty state names corecruxctl config push <name> |
| Session sync | Shared session snapshots across machines, with byte sizes and source host |
Every empty state names the command that would populate it. There are no write controls.
5.11 System › Docs (Professional mode only)
Static reference bundled with the build: three doc expanders (mcp-system-prompt.md, PLANS.md, agent-guide.md), a README card, and a card of external doc surfaces (pages.js:1339). There is no live docs endpoint on this build, and the page says so.
5.12 Failure states across Meters and System
| What you see | What it is |
|---|---|
| Meters: "cost lens off or unreachable" | CORECRUXD_FEATURE_COST_LENS is off |
| Meters: reachable but empty | The flag is on; no report has been posted. Run corecruxctl session cost --post |
A cost row's plan chip says window-inferred | The report carries no producer link. Do not read the attribution as precise |
| Settings: everything greyed with "set on the daemon host" | Working as designed. Daemon config is environment |
Settings: a Runtime capability says unavailable with a reason code | That is the daemon's answer. It is why a pane elsewhere is missing |
| Integrations/Extensions: a control is absent | Customer posture, or the control is one of the four gated with a stated reason |
| Workbench read panel: an entitlement note | A pro capability gates the payload; the surface is present |
| Raw: Send disabled | Permanent, by design |
Sources
- crates/corecruxd/console/v2/render.js:11169,
renderCostBrowser - crates/corecruxd/console/v2/render.js:11415, the six cost sorts
- crates/corecruxd/console/v2/render.js:531,
runtimeCapabilityStateand its fail-closed validation - crates/corecruxd/console/v2/render.js:724, the wired-write registry and every confirmation string
- crates/corecruxd/console/v2/pages.js:731,
buildSettings - crates/corecruxd/console/v2/pages.js:792, the Settings read-only gate reason
- crates/corecruxd/console/v2/pages.js:958,
buildUsageLive - crates/corecruxd/src/cost.rs:30, the cost-lens feature flag

