v0.11.0
Handing a stretch of work to something that was not there for it
Three additions that all answer the same question in different sizes, plus a fix to the
export that made it trustworthy.
A pack of several sessions, as one document
GET /export?project=&since=&until=&source= assembles several sessions into one document,
oldest first. Each entry is what was asked and what that session concluded, with the id and
time to check it against:
## 1 · 2026-09-14 08:51 · claude · a1b2c3d4
- **Project**: /repos/api-gateway · **Messages**: 1281
- **Asked**: add per-route rate limits to the gateway
- **Concluded**: done — the limits are live behind a feature flag,
config in `gateway/ratelimit.yaml`…
- **Transcript**: `/sessions/a1b2c3d4…/export?format=jsonl`
## 2 · 2026-09-15 11:55 · claude · e5f6a7b8
- **Project**: /repos/api-gateway · **Messages**: 1842
- **Asked**: the limits are too tight · loosen them to 200 rps for the read paths
- **Concluded**: adjusted and deployed; the dashboard shows no throttling…
- **Transcript**: `/sessions/e5f6a7b8…/export?format=jsonl`
Neither half of that pair is generated. The opening ask is the session's display name and
the outcome is the final result every source already computes, so a pack is deterministic
and replayable — the property a written summary lacks, since a summary decides what matters
before anyone knows what will be asked of it.
Measured on a real week: 20 sessions, 28 677 messages, six sources → 14 KB. Small
enough to hand over whole. mode=full inlines the transcripts and is off by default,
because that is the form that can be enormous.
A short opening is extended with the turns that followed — "参考评审一下" says nothing about
what is being reviewed — up to three messages or 200 characters.
What a pack does not do is say what is still true. Two sessions a week apart can
conclude opposite things and the reader has to see both, in order; the header says so
rather than the document pretending to be current.
The export covers the session, and says what it covers
Export used to inherit the message stream's page size of 200, so exporting a
16 000-message session produced its last 200 with nothing in the file to say so — it read
exactly like an export of the whole thing, and it was 1.2% of it. No limit now means
the whole session, and whatever it holds, the file states:
- **Messages**: all 16 561 messages
- **Messages**: 200 of 16 561 messages (the latest 200; the rest is not in this file)
Four export formats
format |
Served as | For |
|---|---|---|
md (default) |
text/markdown |
reading, pasting |
jsonl |
application/x-ndjson |
one tagged object per line — a jq query is a filter, not a parse |
json |
application/json |
the same data as one document |
html |
text/html |
a page that stands on its own: inline stylesheet, no scripts, no requests |
The format is now a picker on the session card as well, so none of them needs curl.
Search can be scoped, and filtered by role
search_sessions (and /search) take pattern to search inside one session and role to
keep only user or assistant hits. Without the first, "where in this session did we
discuss X" meant paging get_messages: on the largest session here that is 332 requests at
the default limit, against 1. The role filter is applied while collecting rather than to the
finished slice, so per_session counts hits that match instead of hits that came first.
Fixed
get_messagesaccepts anatargument it never declared, so no client could discover
it — the whole point ofatis landing on a search hit. A test now compares each tool's
declared properties against the arguments its implementation reads.search_sessionsstill listed six sources after the seventh was added; the list is
derived from the source registry now.- The collapsible chrome stopped bouncing at the edges of the scroll.
Full changelog: v0.10.3...v0.11.0