Cost you can trace
Tokens and cost per session, model and subagent, summed per person, repository, model, agent or day. The agent's own recorded figure is used where there is one; an estimate is marked as an estimate.
A ledger for AI coding agents
Sessionly records every Claude Code, Cursor and Grok session: what was asked, which tools ran, which files changed and what it cost. On each developer's machine first, and for the whole team once you connect a server.
Open source under Apache-2.0. Nothing leaves a machine until you connect it to a server, and the default upload contains no text from prompts, commands or files.
$ sessionly summary --by tool --since 30d TOOL SESSIONS COST ACTIVE PROMPTS TOOLS (FAILED) FILES LINES REWRITTEN LINES KEPT Claude Code 64 $412.80 38h 12m 702 15310 (291) 348 +21480 -3112 121/344 (35%) 67% Cursor 41 $96.40 11h 05m 389 6204 (0) 183 +7498 -1431 28/178 (16%) 91% Grok 9 $18.75 4h 31m 61 1740 (22) 52 +3120 -604 17/52 (33%) 58% --------------------------------------------------------------------------------------------------------------------- total 114 $527.95 53h 48m 1152 23254 (313) 583 +32098 -5147 166/574 (29%) 72%
How it works
The sessionly binary sits beside your agents and keeps a ledger in
~/.sessionly. If your team runs a Sessionly server, the same records are
uploaded there and shown in a dashboard. What an upload may contain is on the
security page.
A hook appends each agent event to a local file in 2–4 ms. It only observes: it cannot block or change a session.
Tokens, models and cost come from the transcripts and session files the agents keep themselves.
Both become one record per session in a local SQLite ledger: prompts, tool calls, files, subagents, cost.
On every sync, the lines each session added are counted again in the files as they are now.
Only if you connect a server. Paths are made relative and the content level you chose is applied first.
agent → hook and transcripts → sessionly → ~/.sessionly, then, if
connected, upload → Sessionly server → team dashboard.
The ledger is derived data: delete it and sessionly sync --force rebuilds
it from the raw capture.
What you get
Tokens and cost per session, model and subagent, summed per person, repository, model, agent or day. The agent's own recorded figure is used where there is one; an estimate is marked as an estimate.
For every file a session changed, Sessionly keeps hashes of the lines the agent added and counts how many are still there later. Moved or re-indented code counts as kept.
sessionly list, summary and show filter by
repository, person, model, agent, file, date and cost, and search prompts and
commands. Every command takes --json.
Cost per day; totals by agent, person, repository and model; the files agents changed in each repository; and every session down to its prompts, tools and subagents.
sessionly import rebuilds sessions from the files the agents still
keep, so the ledger does not start empty. On one machine, 100 sessions in 2.5 GB
of transcripts took about a minute.
The capture hook appends one line and exits. It never prints and always exits 0, whatever its input, so a capture failure cannot block or change your session.
The default upload has counts, timings and relative paths but no text at all.
Previews are opt-in, and sessionly export shows the exact payload
before anything is sent.
Each token belongs to one person. A member sees their own sessions, an admin sees
the team, and a ci token can only report pull requests. Only a hash
of each token is stored.
One session record with a published JSON Schema is the contract between the binary and any server. A test fails if the schema in the repository is stale.
Agents
Each agent's tools are mapped to common names (Read, Edit, Write, Bash, Grep, Glob), and each agent's sessions are read from where that agent keeps them. Where an agent does not record something, Sessionly says so instead of filling it in.
| Claude Code | Cursor | Grok | |
|---|---|---|---|
| How sessions arrive | Hooks as they happen; transcripts for past sessions | Its transcript files, plus the hooks, which Cursor also runs | Its session files, plus the hooks, which Grok also runs |
| Prompts, tool calls, files and lines changed | Yes | Yes | Yes |
| Subagents | Yes | Yes | Not recorded by Grok |
| Model and tokens | Per request | Per turn, for turns the hooks saw | Yes |
| Cost | Claude Code's recorded total, with an estimate for what it leaves out | An estimate at API list prices for turns the hooks saw. Not what Cursor bills | Grok's own figure |
| Rewrite rate | Yes | Yes | Yes |
Checked with Cursor 3.27 and Grok 1.0.77. Sign-in files of either agent are never opened.
Pull requests
A GitHub Action reports each pull request to your server, which matches the lines it adds against the lines agents added in uploaded sessions. Both sides send hashes: no source code leaves GitHub or anyone's machine.
Sessionly 78% of the lines this pull request adds were written by a coding agent (1,806 of 2,315). Tool Model Lines Claude Code claude-opus-5-5 1,204 Cursor not known 602 Of the 1,790 agent lines it had when it was opened, 1,647 are still there (92%). Counts added lines that have a letter or digit. Everything not matched to an uploaded session, including agents nobody captured, counts as not an agent's.
What is uploaded
Each developer's machine decides what a server receives. There are two content levels,
and sessionly export <session> prints exactly what would be sent,
connected or not.
| On the machine | Uploaded: metadata (default) |
Uploaded: previews (opt in) |
|
|---|---|---|---|
| Full prompts, file contents, command output | In the raw capture, readable only by you | Never | Never |
| Prompts | Length, hash, first 200 characters | Length only | First 200 characters and the hash |
| Commands, search patterns, URLs, errors | One line each, up to 200 characters | No text | One line each, up to 200 characters |
| File paths | Absolute | Relative to the repository, or to ~/ |
Relative to the repository, or to ~/ |
| Counts, timings, tool names, models, tokens, cost | Yes | Yes | Yes |
| Git name, email and remote | Yes | Yes | Yes |
| Hashes of the lines an agent added | Yes | Only if switched on | Only if switched on |
A preview can contain anything that was typed or run, including a secret. Line hashes are what pull request attribution needs; a hash does not give the line back, but a short or common line can be guessed and checked against it.
Editions
Everything on this page is in the open-source edition. It never needs a license key.
Free
Apache-2.0, on your machines and your server.
sessionly binary: capture, ledger, rewrite rate, uploadBy quote
A signed license file for your self-hosted server.
Not open yet
The same server, run for you.
Sessionly is early. There are no packaged releases yet (you build the binary with Cargo), and sign-in to the dashboard is by token. The README says what works today.
Get started
Build the binary, install the hooks and import the sessions your agents still have. Listing, search, summaries and the rewrite rate all work without a server.
sessionly uninstall takes the hooks out again.
sessionly install --project DIR writes to that project's settings
only.
$ git clone https://github.com/KIvanow/sessionly && cd sessionly $ cargo install --path crates/sessionly # Rust 1.89 or later $ sessionly install # adds hooks to ~/.claude/settings.json $ sessionly import # past sessions of all three agents $ sessionly list $ sessionly summary --by tool $ sessionly show <session>
It starts the server, the dashboard and Postgres. Each developer connects their machine once; after that, sessions upload on their own when a turn ends.
http:// for
anything but a server on the same machine.
# on the server $ SESSIONLY_ADMIN_TOKEN=choose-a-long-secret \ docker compose up -d # on each developer's machine $ sessionly connect https://sessionly.example.com $ sessionly upload --dry-run # count what would be sent $ sessionly upload # optional: send previews, or the line hashes pull requests need $ sessionly settings --content previews $ sessionly settings --line-hashes on
Cost is the agent's own recorded figure where there is one and an estimate from token counts elsewhere; it is not an invoice. The rewrite rate measures whether lines survived, not whether they were good or why they changed. The agent share of a pull request is a floor. Names and emails come from git config: a label, not a verified identity.
Get started
The code, the session record's schema and the limits of every figure are in the repository.