How Fredrin memory works
Every Worker on your board starts from the same project memory: your decisions, your conventions, and the mistakes you already paid for. This page walks through the machinery end to end, so you can judge it on mechanics.
The short version
- Plain files in your repo
- Memory is markdown committed next to your code. Fredrin's database never stores it.
- A slice per ticket
- A local engine ranks those files against the ticket and hands the Worker a small pack. No embeddings, no vector store.
- Written back through review
- What a Worker learns ships in the same pull request as its code, so you review both in one diff.
- Checked at three moments
- When a run starts, before each file edit, and when the run finishes.
- Measured
- Recall is benchmarked against the docs themselves and scored against the files Workers actually opened.
Why parallel agents need it
One agent forgets everything between sessions. Ten agents running in parallel forget in ten directions, and each fills the gap with its own guess.
You find out in review, one diff at a time. Shared memory is how parallel work stays consistent: the same words, the same settled decisions and the same known traps, in front of every run before it writes a line.
It lives in your repo
Memory is a folder of plain markdown, versioned with your code. There is no separate knowledge service to run, sync or back up.
Fredrin adopts what you already have. An existing CONTEXT.md, AGENTS.md or docs/ bundle is read where it is. A new project gets .fredrin/memory/.
Nothing is copied into Fredrin's database. Stop using Fredrin and your memory is still in git, with its full history, readable by any agent or person.
- Glossary
CONTEXT.md. The project's words, and the synonyms to avoid.- Conventions
AGENTS.md. How code is written here.- Concept docs
concepts/. How each part works now. Edited in place; git keeps the history.- Decision records
adr/. Why a costly-to-reverse choice was made, with its status. One file per decision, so parallel tickets never edit the same file.- Traps and invariants
- Mistakes the project already made, and sets of files that must change together. Each carries a trigger, covered below.
Read, build, write back
Each ticket runs in its own branch and worktree. Before it writes code, the Worker reads the slice of memory that matches the ticket.
If the work changes how something behaves, the Worker updates the concept doc in the same pull request. A choice that is expensive to undo gets a new decision record.
You review memory the way you review code: in the diff. Once it merges, the next ticket starts from it.
How a ticket gets the right slice
Retrieval is lexical and graph-based, and deterministic: the same ticket over the same files returns the same pack.
- 01
Seed
The ticket's title, description and plan are scored against every doc with BM25. Long docs are scored in windows of about 750 characters, so one relevant section is not diluted by the rest of the file.
- 02
Widen
Glossary synonyms widen the query. File paths and identifiers the ticket names are matched to the docs that cite them.
- 03
Walk
From up to twelve seeds, the engine follows the links between docs one and two hops out, at half the weight per hop. Files every Worker reads anyway, like AGENTS.md, link to everything, so the walk never passes through them.
- 04
Fit
Near-duplicate decisions collapse to one entry, and the ranked list is packed into about 2,000 tokens. Every item is admitted at its one-line cost first, then upgraded to full text, so a bigger budget can add a doc but never swap one out.
The top five pointers ride on the ticket itself, for about 200 tokens, so every run sees them. The full pack is one command away.
All of it runs inside the ticket's worktree, on whichever machine runs the Worker. The docs are read straight from git; only the ticket's own text comes over the network.
Reversed decisions stay reversed
Decisions get reversed. The old record still uses the words people search with, so a plain search keeps serving it as if it were current.
Fredrin never starts a pack from a superseded, deprecated or rejected decision. A match on one is credited to the decision that replaced it, so a ticket written in yesterday's words lands on today's call.
The old record can still appear, labelled historical. And nothing decays with age: an old decision that still holds keeps its full weight.
Checked at three moments
Reading memory is not enough if a run can still walk past it. Three checks fire at the points where a mistake is cheapest to catch.
- When a build starts
- The ticket is scored against accepted decisions, at a stricter bar than retrieval. A strong match adds a heads-up to the Worker's brief: this was decided, here is why, confirm you mean to change it. It never blocks the run.
- Before each file edit
- A trap is a mistake the project already made, stored with a path pattern and optional code terms. A hook checks each edit a Worker is about to make and prints the matching rule into that turn, once per file. An invariant names files that must change together; editing one prints the others.
- When the run finishes
- Before the pull request opens, the diff is classified. A routine change that adds a decision record is stopped until the Worker folds it into a concept doc or states why it is costly to reverse. That reason is written into the record.
Measured, not assumed
Every run leaves a free relevance label: the memory files the Worker actually opened. Fredrin compares them with what it served.
Files that were read but not served are the useful signal. Each one points at a link or a synonym the docs are probably missing.
An offline benchmark needs no run history. Each decision's own links are the answer key, and the decision is held out while its prose is used as the query.
On Fredrin's own repository (2,207 docs, September 2026), the pack recovers 87% of the live docs a decision cites, and the first relevant doc usually ranks first (MRR 0.845).
The Memory tab rolls this into one health score and names the single biggest fix. When the docs drift, one click files a cleanup ticket that merges near-duplicate decisions. It is told to consolidate, never delete, and you review it like any pull request.
What leaves your machine
- Memory contents
- Stay in your repo. Fredrin keeps no copy in its database.
- Retrieval
- Runs in the ticket's worktree and works offline. Only the ticket's own text is fetched.
- Scoring signal
- File paths only, filtered to memory files on the device before anything is sent. Never file contents.
- Finish check
- The diff's changed paths and the header of any new decision record are sent to classify the change. They are not stored.
- Embeddings
- None. No vector database and no third-party embedding call. A check in the build fails if one is added to the retrieval code.
- Scope
- One project, shared by every Worker on it. There is no hidden per-user memory.
Known limits
What it does not do yet, stated plainly so you can plan around it.
- Words and links, not meaning
- Retrieval matches vocabulary and follows links. A doc that uses different words and links to nothing can be missed. Glossary synonyms and the missed-file report are how you close that gap.
- Only as good as what gets written
- Memory improves when Workers write back. The checks keep it tidy; they don't write your conventions for you.
- Some checks are narrower today
- The build-start heads-up runs on desktop builds that use a workflow; a run with no workflow gets the five pointers instead. Edit-time traps and the read-based score come from Claude Code Workers. The finish check's sense of a significant change is tuned to Fredrin's own repository, so in other repos most new decision records need a stated reason.
Why not a rules file, or your own retrieval?
Most teams start with one of two things: a rules file every agent reads in full, or a retrieval service they build themselves. Here is where each lands.
| Rules fileread in full, every run | Your own retrievalvector store and glue | Fredrin memoryfiles and a local engine | |
|---|---|---|---|
| Lives in git, reviewed in pull requests | Yes | index lives elsewhere (partial) | Yes |
| Scoped to each ticket | No | Yes | Yes |
| Tells a reversed decision from a live one | No | you build it (partial) | Yes |
| Flags a ticket that fights a settled decision | No | you build it (partial) | Yes |
| Shows a rule at the moment of the edit | No | you build it (partial) | Yes |
| Write-back built into every ticket | by hand (partial) | reindex job (partial) | Yes |
| Recall measured on your own docs | No | you build it (partial) | Yes |
| No embedding service to run | Yes | No | Yes |
Lives in git, reviewed in pull requests
- Rules file
- Yes
- Your own retrieval
- index lives elsewhere (partial)
- Fredrin memory
- Yes
Scoped to each ticket
- Rules file
- No
- Your own retrieval
- Yes
- Fredrin memory
- Yes
Tells a reversed decision from a live one
- Rules file
- No
- Your own retrieval
- you build it (partial)
- Fredrin memory
- Yes
Flags a ticket that fights a settled decision
- Rules file
- No
- Your own retrieval
- you build it (partial)
- Fredrin memory
- Yes
Shows a rule at the moment of the edit
- Rules file
- No
- Your own retrieval
- you build it (partial)
- Fredrin memory
- Yes
Write-back built into every ticket
- Rules file
- by hand (partial)
- Your own retrieval
- reindex job (partial)
- Fredrin memory
- Yes
Recall measured on your own docs
- Rules file
- No
- Your own retrieval
- you build it (partial)
- Fredrin memory
- Yes
No embedding service to run
- Rules file
- Yes
- Your own retrieval
- No
- Fredrin memory
- Yes
A note means possible, by hand or with work you would own.
The files are the easy part. What turns them into memory is everything around them:
- A ranking engine that understands supersession and stays inside a token budget.
- Checks wired into dispatch, the edit, and the finish.
- A write-back path that goes through code review, not around it.
- A scorecard that tells you when recall slips, and a cleanup pass for when it does.
Each piece is small. Together they are a system your team would have to own, tune and keep working while it ships product. With Fredrin it is there from the first ticket, and it stays plain files if you ever leave.
Point it at your repo, and every ticket starts from what your team already knows.