CClawMetryDocs

Runtimes

How detection works#

Detection is a filesystem question, not a PATH question. ClawMetry asks "did this runtime write a store here?", because a binary on your path that you have never run tells you nothing, and a runtime you uninstalled last month may still have a year of history worth reading.

The order#

Every adapter resolves its data location the same way, most specific first:

  1. An explicit ClawMetry overrideCLAWMETRY_<RUNTIME>_DIR,

CLAWMETRY_<RUNTIME>_DB or similar. This exists so you can point ClawMetry at a relocated store without touching the runtime's own configuration.

  1. The runtime's own environment variableCODEX_HOME, KIMI_SHARE_DIR,

OPENHANDS_PERSISTENCE_DIR, CLINE_DATA_DIR, and so on. If you already moved the runtime, ClawMetry follows.

  1. Platform conventions — XDG on Linux and, for some runtimes, macOS;

%APPDATA% on Windows.

  1. The documented default~/.codex, ~/.claude, ~/.grok, and so on.

The exact chain per runtime is on that runtime's reference page.

Platform assumptions bite

Goose uses XDG paths on macOS, not ~/Library/Application Support — it follows the CLI convention rather than the app convention. Cline's data lives under ~/.cline/**data**, not ~/.cline. GEMINI_CLI_HOME points at the directory that contains .gemini, while QWEN_HOME points at the data directory itself. Each of these has silently returned "no sessions" for somebody.

Two runtimes are not on the filesystem#

  • QM persists to PostgreSQL. ClawMetry reads whatever DATABASE_URL (or

CLAWMETRY_QM_DATABASE_URL, for a read replica) points at, using short-lived read-only connections. With no Postgres driver installed, detection reports not-detected with a note rather than failing.

  • Exo anchors its state to the workspace, not the home directory — it is

the only runtime in the matrix that does. Discovery scans a bounded set of likely parent directories for */.exo/exoharness/agents, honours CLAWMETRY_EXO_ROOTS, and caches the result so a page load does not rescan your disk.

Aider has a related constraint: its transcript is written into each project, and there is no central store and no home-anchored environment variable. ClawMetry scans a bounded set of likely roots plus AIDER_HISTORY_DIRS. It deliberately does not walk your entire home directory.

Reading is always read-only#

Every adapter opens files read-only and never writes into an agent's directory. For SQLite stores this matters more than it sounds:

  • A runtime that is running keeps recent writes in a -wal sidecar.

Opening with immutable=1 ignores the WAL and returns a stale or empty view. Cursor, Devin, n8n, Copilot and Hermes are all read WAL-aware (mode=ro) for exactly this reason.

  • A runtime that owns its files exclusively — NanoClaw's per-session

databases — is opened mode=ro&immutable=1 so ClawMetry can never take a writer lock on them.

Getting this backwards is the difference between "my live session is invisible" and "my agent hung on a locked database". Both have happened; both are why the per-runtime pages call it out.

How much history gets ingested#

CLAWMETRY_FAMILY_SESSION_LIMIT (default 50) caps how many recent sessions each runtime contributes on a pass. Sessions are ranked newest-first by file mtime, so you always get the current work; raise it for deeper backfill.

bash
CLAWMETRY_FAMILY_SESSION_LIMIT=500 clawmetry sync --restart

CLAWMETRY_FAMILY_EVENT_CAP bounds the events pulled per session, which is what keeps one enormous session from starving a sync cycle.

Detected but empty#

This is a real state and it usually means one of four things:

SymptomLikely cause
Detected, zero sessionsThe runtime has a store but has not written anything yet
Detected, only old sessionsCLAWMETRY_FAMILY_SESSION_LIMIT is hiding newer ones, or the daemon has not run a full cycle
Not detected, but installedStore relocated — set the override on the runtime's page
Qwen Code detected, nothing recordedChat recording is opt-in upstream (--chat-recording); nothing exists to read
Check it
clawmetry runtimes --json | jq '.runtimes[] | {id, detected, meta}'
clawmetry status --json    | jq '{daemon, last_sync, store_bytes}'

Deduplication#

Some work is visible from two places, and counting it twice would be worse than missing it:

  • Claude Code sessions spawned by OpenClaw are recorded under the OpenClaw

session UUID. The standalone Claude Code adapter reads OpenClaw's index and skips those ids.

  • OpenHands stores a copy of each child conversation's metrics under a

delegate:* key on the parent. Summing every key and listing the child would double-count, so those keys are excluded from the parent row.

  • Copilot stamps sub-agent API calls with initiator='sub-agent', so child

spend is split out of the parent rollup rather than added to it.

  • Gemini CLI re-appends a turn under the same message id once its tool calls

resolve, with the same token block both times. Events are de-duplicated by message id, last write wins.

Adding a runtime to the loader#

For contributors: an adapter module is inert until it is named in the daemon's adapter spec tuple and in the entitlement runtime list. There is no dynamic discovery — a module sitting in the adapters package that nobody registered will never be imported, and a runtime missing from the entitlement list is invisible to the UI even when its adapter runs.

Cookie preferences