Skip to content
Fredrin

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.

FIG 0.7 · Where memory lives
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.

FIG 0.8 · Read, build, write back

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.

FIG 0.9 · Seed, then walk
  1. 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.

  2. 02

    Widen

    Glossary synonyms widen the query. File paths and identifiers the ticket names are matched to the docs that cite them.

  3. 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.

  4. 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.

FIG 0.10 · Superseded, not served

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.

FIG 0.11 · Three checkpoints
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.

FIG 0.12 · Served against read

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.

  • 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.