Observe the agents you run
Install the gjalla plugin in Claude Code, Codex or Hermes Agent, backfill 14 days from your existing transcripts, and see what the agents you run cost by kind of work.
Claude Code, Codex and Hermes Agent. Two parts, and you can do them in either order. The backfill gives you a report today from the sessions already on your disk. The plugin keeps it current from here on.
1. Install the CLI and log in
pip install gjalla
gjalla auth login
The CLI is the collector: the plugin’s hooks call it, and gjalla scan is it. gjalla auth login sends a 6-digit code to your email, which you enter in the terminal, and stores a key in ~/.gjalla/config.yaml; every upload from this machine uses it. Sessions land in your personal team unless you pick a team:
gjalla auth team <team-id> # optional; `--clear` goes back to personal
To open your dashboard in a browser later, sign in on /login with “Email me a code”: same email, new 6-digit code.
2. Backfill from the transcripts you already have
gjalla scan # finds sessions, logs in if needed, posts them (last 14 days; `--days 90` to go further back)
Claude Code and Codex CLI transcripts are found where each harness keeps them. The scan is idempotent: run it again and every session it already posted is skipped, so it is safe to run whenever you like. When it finishes it prints the Sessions URL. Open it: one row per session with tokens, cost, and the commits it found in the transcript. Task type is empty until the weekly analysis fills it in for full teams with transcript analysis on.
3. Install the plugin
Claude Code
In Claude Code:
/plugin marketplace add gjalla/gjalla-plugin
/plugin install gjalla@gjalla-plugin
Four hooks are wired: session start, end of each turn, session end, and commit capture. From the next session on, each turn is posted as it finishes and the row on Sessions updates within seconds. No per-repo setup.
Codex CLI
Install the plugin’s codex/ directory the way its README describes, then run /hooks in Codex and trust the four gjalla entries. Codex does not auto-trust plugin hooks and skips them silently until you do, so if a Codex session is not showing up, /hooks is the first thing to check.
Hermes Agent
Hermes is a self-hosted agent with a Python plugin system, so the same install shape applies: a plugin, no code. From the gjalla/gjalla-plugin repo:
hermes plugins install gjalla/gjalla-plugin/hermes
hermes plugins enable gjalla
The plugin calls the gjalla-observe package from inside Hermes’ own Python environment; if hermes plugins enable does not install it for you, pip install gjalla-observe into that environment once.
Hermes calls the plugin on session start and end, on each model call and on each tool call, so the trajectory on Sessions has the same shape as a Claude Code session, with harness hermes. There is no backfill for Hermes; sessions are recorded from the moment the plugin is enabled. One caveat: Hermes’ tool hooks do not say which session they belong to, so tool calls are attributed to the most recently started open session, which is exact for one person at a CLI and approximate for a gateway serving several conversations at once.
4. Let the agent classify its commits
Nothing to do here except notice it. When the agent commits, the commit-capture hook records the commit against the session and tells the agent:
gjalla recorded commit 3f2a9c1 from this session. Classify it:
gjalla attest add --commit 3f2a9c1 --session <id> --task-type <feature|bug-fix|refactor|docs|test|chore> [--summary "..."]
The agent fills in the type and runs the line; the CLI prints Classified 3f2a9c1 as bug-fix. That attestation is what Measure uses to say where tokens go. If an agent skips it, the session simply stays unclassified.
5. Read the report
Open Measure. After the backfill you have the last 14 days: session count, tokens, cost with the cache-read share, and the by-model table. As plugin sessions accumulate, “where tokens go” fills in by task type and the “spent on bug-fixes” tile becomes the number to watch week over week. Observe › Sessions is the row-level view; open any session for its full trajectory.
A team's report
Each engineer installs the plugin and runs gjalla auth team <team-id> once. Their sessions then land in the team’s Observe, and Measure is the team’s number. Individual backfills stay personal unless the team id is set before the scan.
What is collected
Every full team with transcript analysis on is analysed once a week, per session: how much of the session was productive work versus overhead, rediscovery, rework or a dead end, and why. Preview teams default to transcript analysis off and are not analysed. The CLI strips prompt and response text before sending when transcript analysis is off; the server strips as a backstop.
| Kept | Stripped | |
|---|---|---|
| Always | Timestamps, event types, tool names, labels, token usage, models, commits, durations, the session’s judgement and token breakdown | Nothing |
| Transcript analysis on (default for full teams) | Prompt and response text, tool inputs, and error excerpts (kept for 30 days); the session’s analysis and its trajectory summary (one line per step block, no quoted code) | Transcript text only, automatically, once a session is 30 days old |
| Transcript analysis off (default for preview teams) | Everything in “Always” only | Prompt and response text, tool inputs, and error excerpts (at the moment each session is received) |
A team admin turns transcript analysis off in Team Settings. Turning it off does not retroactively delete anything already stored; it stops new content from being stored and excludes the team from the weekly analysis run going forward. The transcript text itself is deleted after 30 days; the resulting judgement and token breakdown are kept.
If a session is missing
gjalla auth loginagain if the CLI says the key is invalid (401); a 403 means the key cannot write sessions, which a fresh login fixes.- Claude Code:
claude --debugshows hook invocations; the collector’s own logs are under~/.gjalla/collect/. - Codex:
/hooks, then check the four entries are trusted. - Re-run
gjalla scan: the session-start hook also sweeps for deltas that a crashed session never posted, and the scan does the same for everything on disk.
