Every chat you've had with an AI lives in someone else's database, in a format you'll never see, behind an export button that flattens it. That never sat right with me. So I built the thing I wanted to exist: .curt — one UTF-8 file, one conversation, everything intact. Images, tool calls, the weird stuff — verbatim.
Spec v1 is frozen. curt-format@1.2.0 is on npm, MIT. Twenty-seven conformance vectors run in CI so “compatible” means something.
Full disclosure: I built this in a vacuum. No consumers yet — that's not a humblebrag, it's the current score. If you build software where conversations matter, the format is free and the door's open.
What a .curt file is
A UTF-8 JSON envelope. Magic string, version, who wrote it, which extensions it uses, and the conversation: id, title, timestamps, messages — each with a role, content, and a time. Anything an app adds that the spec doesn't know about rides along untouched on re-save. That last part is a promise, not a courtesy.
{
"curt": "curtis-conversation",
"version": 1,
"generator": "your-app@1.2.3",
"extensions": ["images-inline"],
"conversation": { "id": "conv_001", "messages": [ … ] }
}
What shipped
- The spec — frozen core, v1. New capability never means editing it; it means a registry entry.
curt-format@1.2.0— reference implementation on npm. MIT: spec, code, schema, fixtures.- Twenty-seven conformance vectors — L1 CORE through L4 per-extension — executed in CI. Claiming support is testable.
- Five extensions:
images-inlineandusage-metadatastable;tool-linkage,agent-context,consensus-receiptdraft.
The rules
The core doesn't move. If something's missing, it becomes a named extension — versioned, optional, and rejected cleanly by readers that don't know it. An extension goes draft → stable only when two independent implementations round-trip it. One author stamping their own work “stable” is how formats rot; I'm not doing that.
Where you come in
If you write software where conversations matter — a chat app, an agent runtime, an archive tool — make it speak .curt. It's an afternoon, the library handles the envelope, and the conformance vectors tell you when you're done. The path is on the adopt page. When you ship, you go in the registry — capabilities.json, public, checkable.
The format is free. The file is yours.