Threads & handoff
A chat history belongs to one provider. A thread belongs to you: a durable identity (“Q3 campaign”, “billing bug”) that sessions from any client surface attach to, so work started in one tool resumes in another. Threads are free core and fully local; Sync replicates them later without changing the model.
The model
thread { id, title, status, tags, created_at, last_active }
session { ..., thread_id, continues_from } // an ingested digestSessions attach to threads by thread title on save. Lineage runs through continues_from (the predecessor's session id), which also inherits the thread when the reporting agent never names one. The result is a provenance chain across providers: a ChatGPT digest, a Claude continuation, a local Cursor session, one timeline. Everything lives in the same local SQLite as session ingest.
Saving: save_session
"Save this session to ctxfile, thread Q3 campaign."
The agent summarizes the conversation and calls save_session with the digest and the thread name. No envelope, no harness enum to memorize: the client surface is inferred from the MCP client info (declare harness to override). Records are redacted at write, provenance-stamped (reported_by: agent, the door, revision history), and reviewable with ctxfile ingest list.
Resuming: continue_thread
"Pick up my Q3 campaign thread. What were we doing?"
The resolution rules are built for “you know what I mean”:
- A named thread is fuzzy-matched against titles and tags (exact, containment, token overlap).
- No name defaults to the most recently active thread, and the result says so: Resuming “Q3 campaign” (assumed: most recently active thread).
- Genuine ambiguity returns a shortlist so the agent can ask the user instead of guessing.
The result is the merged, chronological history: every entry labeled with its harness, its door, and its timestamp; token budgeting keeps the newest sessions detailed and summarizes the older ones; the latest open items ride on top. The whole payload is marked agent-reported untrusted data, and it ends by pointing the model at get_context for the full project snapshot.
The handoff package
“Hand this off so someone else can take over” has a defined meaning here. When the agent sets handoff: true, validation enforces everything a cold takeover needs, and rejects anything less with per-section errors the agent self-corrects from:
| Section | What it must contain |
|---|---|
| state | What is done, what is in progress, what is not started. |
| key_decisions | The choices made and the rationale, the part chat history loses first. |
| open_items | Next actions, ordered, with blockers named. |
| gotchas | Quirks, constraints, dead ends already tried. |
| artifacts | Files/docs/links that matter, each with a one-line role. |
| suggested_first_prompt | The prompt the next agent should receive to resume cold. |
Because the contract lives in the tool description and the validator, any agent on any harness produces the same artifact without per-agent training. That is the point: the intelligence lives in the MCP surface. A handoff is presented with priority when the thread is resumed, suggested first prompt included.
Person-to-person takeover
A thread will be shareable via a handoff grant: a scoped, revocable, read-only token for one thread. The recipient adds the ctxfile connector, redeems the grant, and their agent calls continue_thread on it. Grants respect redaction profiles, expire by default, and every redemption is audit-logged. Grants ship with the Sync relay (the second beat of this launch); the provenance and token machinery they build on is already in the core you're reading about. Full multi-user shared context stays the Team tier.
Seeing what you have
ctxfile threads # id, title, sessions, last active, last surface ctxfile ingest list # the sessions themselves, thread shown per record ctxfile ingest rm <id> # delete one record
Slash commands
Client surfaces that expose MCP prompts get ctx-save and ctx-continue as one-tap versions of the two verbs. See the MCP surface for the full tool contracts.