Supported read access to historical session data for third-party tools #3740
LarsArtmann
started this conversation in
Ideas
Replies: 1 comment
|
Three things from the other side of this — I maintain a tool that writes agent state to disk rather than reading Crush's, so I've paid the opposite set of costs.
For what it's worth, the tool I work on went the other way and stores everything as plain markdown committed into the repository — no database, no format to reverse-engineer, readable in a diff. That has its own bill: it's slower, it's in code review whether you wanted it there or not, and it can't answer aggregate questions the way a SQLite file can. Not a recommendation, just the trade sitting on the other end of this one. |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
What I'm asking about
A supported, documented way for third-party tools to read historical
session data (workspaces, sessions, messages, todos, cost stats). Mainly
three questions at the bottom — the server API looks like it already covers
most of this, so this is partly "please consider analytics consumers in the
upcoming docs/release" and partly "what should on-disk readers do meanwhile".
Context: the read-only consumer ecosystem
There is a real ecosystem of open-source tools that read Crush's local
data — Go, Rust, TypeScript; all currently built on the
undocumented on-disk format (the Go six reviewed source-level on
2026-09-07, see
the review):
crush.db<project>/.crush/crush.dbcrush.db.crush/crush.dbper projectcrushadapter (deepest parser in the ecosystem)crush.dbscanscrush.dbprobing (#3531)projects.json+crush.db(mine; verified against v0.92.0 / 559ec80), plus crush-daily (private, mine) building daily per-project summaries on itAdjacent: perplexityai/numbat
integrates via the hooks surface. vshulcz/deja-vu
merged a Crush parser (#2949 →
PR #3158, 2026-09-07)
shortly after this inventory was compiled — another JSON-parts reader
(7th Go reader).
When even motivated third parties get misled — deja-vu's Crush parser
notes: "It keeps sessions in SQLite, not in the JSON state file the
README talks about" — that's a docs gap, not a tooling gap.
What these tools all currently reverse-engineer (no upstream docs):
<global>/projects.jsonregistry shape and location resolutioncrush.db:sessions/messages/read_filestables (goosemigrations evolve these — fine, but changes are invisible to readers)
[{"type":…, "data":{…}}], 8 discriminators)messageID$$toolCallID)are not; comment fix pending in docs(db): fix timestamp unit comments in initial migration #3576). The comment has real victims:
2 of the 6 Go readers shipped date bugs from converting with
time.UnixMilli— their sessions landed in January 1970. Both are nowfixed: openusage#357,
mnemo#22 — the fixes took
one line each; the diagnosis took reverse-engineering
This works, but breaks silently on migrations. For example, #3580
(compressing message parts) would break every JSON-parsing reader. As #2707's
author put it: "Schema isn't a public API, breaks on migrations." We know —
that's exactly why we're asking.
What I found in the repo (v0.92.0)
The server API already looks like the answer for most of this.
internal/swagger/swagger.jsonincludes:GET /workspaces— would replaceprojects.jsondiscoveryGET /workspaces/{id}/sessions+/sessions/{sid}—proto.Sessioneven carries
parent_session_id(agent subtrees),todos,cost,token counts, timestamps
GET /workspaces/{id}/sessions/{sid}/messages(+/history)and per @meowgorithm in #3531: "Server-client is still not officially
released, but usable and hopefully not too far off. Part of that work will
definitely be docs."
Questions
Backend.ListWorkspacesreturnsthe running server's in-memory workspaces (populated via
CreateWorkspace; I couldn't find hydration from theprojects.jsonregistry at startup). For analytics tools the make-or-break operation is
"enumerate every project I have ever used, offline ones included, and
read its full history." Could
GET /workspaces(or a sibling endpoint)cover the registry, or is that intentionally out of scope?
intend to treat it as a compatibility surface (semver-ish pinning), or
best-effort/may-change for a while? Even a rough answer lets downstream
tools decide how much to lean on it versus the DB.
migrations under
internal/db/migrationsas the de-facto changelog forread-only consumers ("watch this dir"), or a short docs note stating the
on-disk format is unsupported and will keep changing? Either is cheap
and removes the guesswork.
An offer, in case it's useful
If Crush ever wants an official read surface — an SDK, a docs page, or
an in-process package — I'd be glad to contribute the basis:
go-crush-data is MIT,
resolves the
projects.jsonregistry, opens everycrush.dbread-only,probes schema capabilities so migrations degrade gracefully instead of
breaking, and decodes the parts envelope and todos shape, tested against
v0.92.0 plus a census of 287 real databases (71,747 todo items). It
would of course need to become a module Crush controls; the logic and
census-verified fixtures are simply there if useful. No strings
attached either way — the questions above matter more than the offer.
Happy to share what we learned from real-world data (e.g. that todos
census) if that's useful for the docs work.
Related
historical reads)
All reactions