Why .dai · three parts · about 15 min

The case, the mechanism,
and the file itself.

Everything about the format in one place: why a folder of text files beats a bigger context window and a vector database, how saving and recalling actually work, and what is inside a .dai file. Read it in order, or jump to the part you came for.

Part one of three · Why .dai
In plain words

How it actually works

When you save a conversation, Kerneta converts it into a .dai document with three zones: an identity header, an understanding section holding machine-parseable facts, events and entities with their dates, and the cleaned original content. The untouched original is also kept byte-exact in _raw/, forever.

When you ask a question, your whole history is not fed into the model's window. Retrieval code, not a model, scans the index and picks only the relevant pieces: a mean of 10,065 tokens per question on the benchmark run. Your model reads that small, dated, pre-digested context and answers. That is the entire trick, and it is why retrieval itself makes no model call and stays fast at any history size.

Building the store is a one-time, cheap pass: about $0.0009 per 1,000 tokens with the GPT-4.1-mini observer that produced every published number here, or nothing at all on a Claude subscription, where the assistant writes each memory itself.

one question, two ways · LongMemEval-S, GPT-4o answering both arms
WITHOUT .dai
  [the benchmark's full-context arm]
  → feed the whole history into the window
  → model hunts for one detail in a haystack
  → 60.60%, the benchmark authors' own baseline

WITH .dai
  recall_memory("the aquarium question")
  → retrieval code picks the relevant facts
  → feed 10,065 tokens (measured mean)
  → model reads a page, not a library
  → 83.00% on the same questions, same judge

  +22.4 points, same answering model, measured
The uncomfortable truth about long context

Bigger windows don't remember better.

As you stuff more history into a context window, the model's attention spreads thinner: details drown, dates blur, and it loses the thread silently. It does not say "my context is too full", it says "I don't have that information" while the answer sits right there in its window. We measured exactly that.

It drowns, and it is measurable

On LongMemEval, the benchmark authors' own full-context GPT-4o baseline scores 60.60%. The same model answering from a .dai store scores 83.00%. That is +22.4 points, on the same questions and the same official judge. The information was in the window either way, so what improves is not what the model was told but how much it had to wade through to find it.

And it bills you for the privilege

Mastra's published run averages about 30k tokens of context per question; ours averages 10,065. That is 3.0× cheaper per answer, $0.025 against $0.075 at GPT-4o input pricing, and it is a per-question cost you pay again on every question. Theirs is their own published figure; ours comes off the release run.

And eventually it stops working

Attention thinning is the gentle failure. The hard one is the ceiling: at 1M tokens of history, pasting does not fit on any model we price, the million-token ones included, once you leave room for the question and the answer. Recall reads a bounded slice instead, about 40,000 tokens at that size, so the wall never arrives.

So on the chat-history benchmark accuracy is higher than feeding the raw text (83.00% against 60.60% on LongMemEval, GPT-4o answering in both arms, official scoring) while reading about 3.0× less context than Mastra's published run reads. At small sizes the window works fine, which is exactly why the decision layer routes small in-window jobs to the full-text default rather than retrieving. Everything above traces to the results page.

The benchmark landscape

Where .dai sits, including who is above us

LongMemEval_S, all 500 questions, GPT-4o answering in every row. Our score comes from the benchmark authors' own official script, and the others are as published by each vendor, so protocols and dates vary. The table ranks systems whose configuration is reproducible: published in enough detail that somebody else could run it. One of them publishes a higher number than ours, and it is open source. We show it anyway, because the point of this table is what column three costs you. Runs that miss the criterion are listed directly underneath, including one that scores above every row in the table.

SystemScore · GPT-4o actorWhat you must run or trust
Mastra OM (published)84.80
84.23 task-averaged
published on the same benchmark and the same GPT-4o actor
.dai (official script, v4.4n)83.00
84.02 task-averaged
a folder of text files on your disk
Supermemory (published)81.60hosted memory API, so your memories live in their cloud; cleaned-dataset variant on a custom harness
Mastra RAG topK 20 (published)81.20the same framework's plain top-k retrieval configuration, judge unnamed
TiMem (published)76.88temporal knowledge-graph service, the project's own figure, not audited by us
Zep (published)71.20graph memory server, own harness with re-implemented baselines
Feather (published)69.30vector DB plus compression service, vendor-published, not audited by us
Full-context GPT-4o (published)60.60the whole history pasted into the window on every question

Our number is reproducible from three public things: LongMemEval-S, which is a public academic benchmark; the v4.4n engine that produced the score, which is Apache 2.0 in the public repository; and the benchmark authors' own evaluate_qa.py with the gpt-4o-2024-08-06 judge snapshot, which is their scorer rather than ours. We publish no run artifacts of our own for you to re-score. Instructions here. We are second among systems whose configuration is reproducible: 1.80 points (9 questions) behind Mastra OM on the same GPT-4o actor, and 22.4 points above raw full-context, with no service, no database and no account. The gap to Mastra is inside single-run variance, p≈0.44, but the point estimate is theirs and not ours. Column two is the micro (per-question) average for every row; where a system also publishes a task-averaged figure it sits underneath, and the two aggregations must never be read across rows.

Same benchmark, different setup: not in the ranking

These runs are on LongMemEval_S too, and the first of them scores above everything in the table above. They are out of the ranking because of the criterion, not because of where they land, and the numbers stay here with the reason attached.

System · runScoreWhy it is not in the ranking
EmergenceMem Internal (published)86.00
GPT-4o actor
a closed configuration its own authors call not publicly reproducible, and the judge model is never named. This is the only run held out of the ranking that scores above us on the GPT-4o actor.
EmergenceMem Simple (published)82.40
GPT-4o actor
same family, same unnamed judge; 0.6 below our 83.00, which is three questions
EmergenceMem Simple Fast (published)79.00
GPT-4o actor
the one EmergenceMem configuration that is open-sourced, scored by the same unnamed judge

Two things worth saying plainly. All three EmergenceMem configurations are listed together, including the open-sourced one that scores below us. Splitting the family so that only the rows beneath us stayed in the ranking would be exactly the move the criterion exists to prevent. And an unnamed judge on its own is flagged in column three of the ranking rather than used to keep a row out: Mastra RAG topK 20 stays ranked on exactly that basis. The EmergenceMem family is out because its headline configuration is not publicly reproducible and no configuration in the family names its judge; the family is treated as one, which is why the open-sourced row leaves the ranking with the rest of it. Supermemory's headline 95% is in neither table because it is Recall@15, a retrieval metric rather than answer accuracy; it has its own section below.

Why every row above uses GPT-4o, an older model

Because the answering model moves the score more than the memory system does, and a table that mixes models is ranking models rather than memory.

The same .dai store that scores 83.00% with GPT-4o answering scores 92.00% with Claude Fable 5 and 91.00% with Claude Opus 5. Nothing about the memory changed between those runs: identical files, one shared set of rendered prompts, identical retrieval, only the model reading them. Other systems see the same effect, and Mastra publishes 93.27% on gemini-3-pro-preview and 94.87% on gpt-5-mini against their 84.80% on GPT-4o.

So none of those figures can be set against each other. Our 92.00 does not beat their 84.80, and their 93.27 does not beat our 83.00. They are answers from different models.

Retrieval head-to-head

Recall@k, at everyone else's metric

Supermemory headlines Recall@k=15 of 95% on LongMemEval_S. That is a retrieval metric, not answer accuracy. Fair enough. Here is the same metric for the .dai retrieval layer, taken from the v4.4n release run itself: retrieval surfaced the gold session on 94.6% of all 500 questions, session-level (the granularity the benchmark's own evidence labels use), at the depth the engine actually read, which is 5 files on 215 of the 500 questions and more where the source is larger. Theirs is a hosted pipeline; ours is deterministic code over a plain-text index.

This figure has moved, and the reconciliation that was outstanding is now done. We previously published 98.6% at k=5 from a separate retrieval-only harness on the v4.4d build, then withdrew it in favour of the 94.6% the engine's own per-question diagnostics record. A fixed-k sweep over the release run, k=1 to 15, now measures both definitions on the same build: counting only gold sessions the reader opened as documents gives 94.6%, and also counting gold sessions cited as the source of a fact or event row gives 98.0%. The gap was a difference in what counts as retrieved, not a difference in the engine. Both are published, and the stricter one stays the headline.

.dai retrieval hit rate, session-level, v4.4n release run

Every system's published k=5 figure, side by side

SystemMetricUnit retrievedAtRecall
.dai v4.4nRecallsession documents, plus facts and events cited from themk=598.0%
MemPalaceRecallraw chunks, ChromaDB defaults, palace features disabledk=596.6%
SupermemoryRecallatomic memoriesk=586%
LongMemEval paper baselineRecallsession / round / fact, measured on _Mk=564.4%
Mastra Observational Memorynone publishedno retrieval step, keeps a running compressed logn/an/a

Recall is not comparable across rows without reading the unit column. Ours admits whole session documents, Supermemory's admits atomic memories, and MemPalace's row is measured with its own architecture disabled. LongMemEval_S, 500 questions, gold sessions as annotated by the benchmark.

Sources. Supermemory's 86% at k=5, with 91% at k=10 and 95% at k=15, is from their own research page. MemPalace's 96.6% is their own published claim; the independent analysis in arXiv:2604.21284 (Dey and Viradecha, April 2026) reproduces it and attributes it to verbatim storage plus ChromaDB's default all-MiniLM-L6-v2 embedder rather than to the palace structure, and notes it is recall_any@5, the most generous variant. Mastra publishes no retrieval figure because their design has no retrieval step: they carry a running compressed log, which is also why their per-question context is around 30k rather than around 10k.

The LongMemEval baseline is Table 3 of arXiv:2410.10813, best key design (K = V + fact) at Recall@5, round granularity, measured on LongMemEvalM. The same table reports a session-granularity figure of 73.2% at k=5, and since our own recall is session-level that is arguably the fairer row to set beside ours. We show the round figure because the paper leads with it for retrieval, and state the session figure here.

Why k=5 and not deeper. Our curve is flat: 96% at k=1, 98% from k=3, and nothing above k=5 moves it at all, with every column from k=10 to k=15 identical. Reading to k=10 buys 33% more context tokens for zero additional recall, which is why the engine stops at 5. Two structural reasons, not luck. 305 of the 500 questions are answered from the global facts and events indexes rather than from opened documents, so depth never enters them and they sit at 100% at every k; and the single-document path shortlists 10 candidates before it slices to k, so no k above 10 can reach further. The one category that responds to depth is preference, and only in which document gets opened rather than in whether the evidence is reachable.

Three things that stop this table being read too kindly. Our recall is measured at session level, the unit LongMemEval's own evidence labels use, while Supermemory's k admits atomic memories, so the two are not strictly like for like. Their 95% sits in a table beside Zep's 71.20 and full-context's 60.60, but those are answer-accuracy figures, a different metric. On answer accuracy, GPT-4o answering both sides, we score 83.00 on the official script against their 81.60 on a cleaned-dataset variant with a custom harness: close enough that the harness difference matters more than the gap.

How the sweep was run. It re-runs retrieval against the stores the release run already built, with the actor replaced by a stub and the network disabled, so it spends nothing: no actor call, no observer call, no embedding call. Its control column reproduces the published run on 500 of 500 questions across reading strategy, files read, context tokens to the token, and retrieval hit. .dai answers from its top 5 files rather than 15 because we measured that feeding models more retrieval hurts answers.

What the 5.4% miss actually is. On the strict definition it is where the gold session was never opened as a document, not where its content never arrived: outright, nothing from the gold session reached the model on 2.0% of questions. That is also why the weakest question types fail on synthesis rather than on search, since the evidence was present for 98.0% of questions while the score is 83.00%.

Product comparison

How memory products differ

Most memory products are good at what they do. The question is what you give up. Hosted memory APIs keep your memories in their cloud, behind their API, in their format. Graph and vector systems store your life as embeddings or graph edges, which are machine-queryable but human-unreadable. Some open-source frameworks land in neither column, and we do not claim these properties are ours alone. Here is the picture by category.

.dai (free)Hosted memory APIsGraph / vector serversBuilt-in app memory
Where your memory livesyour disk, plain filestheir clouda database you or they runinside your account at that vendor
Can you read it?yes, open it in Notepad, grep it, diff itthrough their API or appno, embeddings and graph edges aren't prosepartially, a settings pane rather than your data as files
Works with no account, fully offlinerecall yes, zero network: it is code over an index. Conversion needs a model, on your subscription or your keyno, the service is the productself-hosting possible, database requiredno
Portable across assistantsyes, one store serves Claude, ChatGPT, Cursor, local modelsvia their integrationsvia their integrationsno, each vendor's memory stays in its walled garden
If you leaveyou keep everything, because it was always yoursyou export whatever their export gives youyou keep a database dumpit stays behind
Improves retroactively yes, originals are lossless so you re-index anytimeat their discretionre-embedding means re-running the pipelineno, you cannot re-run their pipeline on your past
Price$0 forever locally; hosted from $20/moabout $19/mo typicalvaries, plus infrastructure costbundled with the subscription

These are category descriptions rather than accusations. Hosted APIs are genuinely convenient, and if you want zero setup they are a fine choice. This table exists because most people do not realise what the trade is until they try to leave. Note what the columns do not claim: running with no account and no server is a property of .dai rather than something only we can do, and we make no claim to be the only readable format. This table carries no accuracy row: the scores live in the ranking above. Hosted pricing is as of July 2026 and typically runs from about $19/mo.

Against built-in memory

Claude and ChatGPT already have memory. Why this?

Built-in app memory is real and useful, and structurally different.

  • It's vendor-bound. Claude's memory works in Claude and ChatGPT's works in ChatGPT. Neither follows you to the other, to Cursor, to your API agents, or to a local model. One .dai store serves all of them.
  • It's not yours as files. You can view and edit entries in a settings pane, but you cannot open your memory in an editor, grep it, back it up, or take it with you.
  • You can't re-process it. Whatever their pipeline extracted is what you have. Kerneta keeps the originals, so better extraction later applies to your whole past.
Cross-window recall

Saved in one window. Available in every other.

A context window dies when the chat ends. The store does not.

  • Across chats: archive today's session and tomorrow's fresh window recalls it, in about 10k tokens.
  • Across apps: save from Claude Code in the terminal, then recall in Claude Desktop or from an API agent. Same store, same facts.
  • Across vendors: the store that serves Claude serves ChatGPT and any MCP client, so you can ask ChatGPT about something you told Claude last month.
  • Across model generations: plain text outlives every model. The same store served five answering models on one shared set of prompts, and accuracy ran from 78.00 with Claude Haiku 4.5 to 92.00 with Claude Fable 5 (460/500), a 14.0-point spread. The store is portable. The accuracy is not.
Lossless originals

Your memory gets better over time, retroactively.

Because every original is kept byte-exact in _raw/, improved conversion is not just for new saves. Re-run indexing and your entire history is upgraded. This is not hypothetical, and it is how our own benchmark score moved without re-saving a single conversation.

Method releaseSame stored history, re-scored (GPT-4o actor)
v1.973.40%
v1.9.674.00%
v2.0-sem276.20%
v3.0 (leanScan)78.60%
v3.0.179.00%
v4.279.40%
v4.3a80.60%
v4.4a82.00%
v4.4d82.60%
v4.4n (current)83.00%

Overall totals only, all on the official script with GPT-4o answering. The version numbers are internal reference points rather than public releases. v4.4n is the only version we publish a current result for.

The grep story

Early engine versions failed a synthetic planted-code test, missing the codes entirely, because summaries filter out off-topic details. The fix was pure plain-text philosophy: grep the store. A full-text search fallback finds them again (not retrieval Recall@k, and unrelated to Supermemory's 95%@15) with zero extra model calls. The data had been in the store the whole time, because nothing is ever thrown away. You cannot grep an embedding.

Part two of three · How it works
The store

One conversation, one file.

Your memory lives in ~/DaiDocs (override it with DAIDOCS_STORE). Three things live there, and you can open every one of them in a text editor:

  • *.dai documents. One per conversation, carrying an identity header, the structured understanding, then the full content. Readable top to bottom.
  • _index/ is the retrieval layer: a manifest, extracted facts, events and a profile. Plain files that the recall code scans.
  • _raw/ holds byte-exact originals of everything ever saved. Never modified, never deleted.

Because the store is plain text, every tool you already have works on it: grep, git, backup software, your file manager. On the free tier the memory browser is deliberately Explorer or Finder. Ownership is not a feature toggle here, it is the storage format.

Save path

Saving: verify first, then extract.

1

Capture, verbatim

The conversation is written byte-exact into _raw/ and verified before anything else happens. If every later step failed you would still have lost nothing. That is the verify loop, and it is why the Claude Code hook can archive sessions even with no API key configured.

2

Extract

One small model call (the observer) writes the summary and dated facts, measured at about $0.0009 per 1,000 tokens with the GPT-4.1-mini observer used for every published number, or $0 on a Claude subscription, where the assistant writes each memory itself. Un-indexed saves catch up later with npm run catch-up, a project at a time.

3

Index

Facts, events and profile entries land in _index/ as plain files. No embeddings required, no vector database to run, nothing to migrate. You can read the index in a text editor too.

Recall path

Recalling: code retrieves,
your model answers.

1

Retrieval makes no model call

When Claude calls recall_memory, retrieval runs as ordinary code over the index and the files. No model call is made to fetch your memory, so recall itself costs nothing.

2

Pack a small context

The relevant memories come back as a small block of readable text: about 8k tokens per question on the benchmark run. Date arithmetic is computed in code and handed to the model to read, which is why temporal questions hold up.

3

Your model answers

Whatever Claude you are already in (Desktop, Code, the API) answers from that context on your existing plan. Kerneta never sits between you and the model.

The decision layer

The part that tells you not to use it.

Before answering, a built-in classifier routes each question to the cheapest strategy that will actually work. That routing is what produces the recommendation against converting:

Chat history, many files, beyond window

→ .dai

Where a pasted history degrades the answer, or will not fit in the window at all, the store answers from kilobytes instead. This is the territory our measured results cover.

A history small enough to paste

→ full-text default

Below roughly 15,000 to 20,000 tokens there is nothing to gain: the whole thing already fits, so the decision layer reads your text as it is. Converting is one paid model call, and it should not be spent where plain text already works.

Why this is a feature

A memory layer you can trust is one that knows its own boundary. The same discipline governs every claim we make: each one is scoped to what was actually measured, and the arms that beat us are published too.

Losslessness

Summaries can be wrong. Originals can't.

Every compression-based memory system faces the same question: what happens when the summary missed the detail you need? The answer here is structural.

  • The content zone of every .dai document keeps the full conversation inside the memory file itself.
  • _raw/ keeps the byte-exact original of every save, written and verified before extraction runs, and never deleted.
  • Recall can always drop to the verbatim layer when the indexed facts are not enough, so nothing is ever summarised away.
Portability

The store doesn't care which model reads it.

Memory formats that only one vendor can read are lock-in with extra steps. A .dai store is plain text, so:

  • The same store serves Claude, GPT, Cursor, Windsurf and local models through the same MCP server.
  • In a cross-actor run over the same store with one shared set of prompts, accuracy ran from 78.00 (Claude Haiku 4.5, our weakest actor) to 92.00 (Claude Fable 5, 460/500), a 14.0-point spread. The format is portable across models. The accuracy is not, so which model reads the store still matters.
  • It can also back Anthropic's native memory tool (memory_20250818), where Claude manages memory autonomously and Kerneta does the storage.
Part three of three · The format
Anatomy

Three zones. One file.

A .dai document is ordinary UTF-8 text. Open it in any editor and you can read the whole thing top to bottom. The zones are ordered so the cheap, structured part comes first and the full record is always underneath it.

1 · IdentityA YAML header naming the document, its source, and the date range it covers. This is what a file browser and a search index read first.
2 · UnderstandingMachine-parseable JSON holding dated facts, typed events and entities. Retrieval reads this zone alone for most questions, which is why recall costs no model call.
3 · ContentThe cleaned original, segmented but complete. When the structured zone is not enough, retrieval drops down here, so no detail is ever lost to summarisation.

Alongside the documents, a store keeps _index/ (the retrieval layer), _raw/ (byte-exact originals, written and verified before extraction runs, never deleted) and _unconverted/ (what is captured but not yet converted, small, read by the next session and gone once it converts).

YYYY-MM-DD_bug-investigation.dai
---
title: Investigating intermittent build failures
source: claude-code
dates: YYYY-MM-DD
---

# Understanding
{
  "facts": [
    { "date": "YYYY-MM-DD",
      "fact": "deploy flakiness traced to cache step" },
    { "date": "YYYY-MM-DD",
      "fact": "decision: pin builder image at v2.4" }
  ],
  "open": [ "rollback alias not yet created" ]
}

# Content
[USER] our deploys keep failing about 1 in 5 times…
[ASSISTANT] Let's look at the pipeline definition…
…full conversation, unabridged…
Why a format, not a product

Formats outlive companies.

The documents you can still open from twenty years ago are the ones written in formats somebody published. The ones you have lost were in a database owned by a company that changed its mind. AI memory is heading the same way, and it is early enough to choose differently.

Open by construction

The container is plain text, the spec is public, and the reference implementation is Apache 2.0. Nothing about reading a .dai file requires our software, our servers or our permission.

Improves retroactively

Because _raw/ keeps every original, better extraction upgrades your whole history. Our own benchmark score moved from 73.40 to 83.00 with GPT-4o answering, on already-stored data, with nothing re-saved.

Model-portable

The same store answered through five models on one shared set of prompts, from 78.00 with Claude Haiku 4.5 to 92.00 with Claude Fable 5 (460/500), a 14.0-point spread. The format travels. The accuracy still depends on the model.

Greppable

Plain text means grep works. A code-only full-text search fallback recovers planted codes that summarisation had dropped (not retrieval Recall@k, and unrelated to Supermemory's 95%@15) with no model call involved. You cannot grep an embedding.

Yours to fork

Write your own reader, ship your own tools, or extend the spec. Adoption is the point, so the licence gets out of the way.

Adopt it

Deploying .dai takes minutes.

One install and one setup command puts it on every surface you already use. If you build an assistant, an agent framework or a note tool, emitting .dai means your users' memory is portable the day you ship it. Three ways in, all free:

Use the reference implementation

The daidocs-mcp package reads and writes the format, runs as an MCP server, and works with any MCP-capable client. Install it

Back the native memory tool

Point Anthropic's memory_20250818 tool at a .dai store and the model manages memory while Kerneta handles storage and retrieval. API guide

Write your own reader

It is YAML, JSON and text. Parse the zones you need and ignore the rest. The spec, the engine and a reference reader ship together in one public repository, github.com/Kerneta/daidocs. Open source

Now that you have the whole picture

Read the measured results: every number of ours traces to a run you can reproduce.