Memory
Correct crab’d on a pull request and, by default, the correction dies with the CI job. Every run starts from nothing. Memory changes that: when a human replies to one of crab’d’s comments and tells it it was wrong, crab’d can record what it learned as a markdown file in your repository, and read that file back on every future run.
The memories are plain files you own. You review them in a pull request, edit them, and delete the ones you disagree with. There is no hidden state and no database.
Memory is off by default. A memory file becomes standing instruction to the agent, so it only appears once you ask for it.
Turning it on
Section titled “Turning it on”memory: enabled: trueThat is enough. Memories are read from .crabd/memory/ and, when crab’d learns something, recorded
on the branch of the pull request where the correction happened.
What a memory looks like
Section titled “What a memory looks like”---name: no-barrel-filessource: https://github.com/acme/app/pull/812#discussion_r123456recorded: 2026-08-12---
Don't flag missing `index.ts` barrel exports. This repo imports by full path on purpose.nameis the identifier, also used as the filename. Recording a memory with an existing name replaces it, so a refined correction supersedes the old one instead of accumulating a near-duplicate.sourceis a permalink to the comment that taught it, so anyone reading the file can see the argument behind it.recordedis when it was written. Used for ordering when the caps below apply.- The body is the instruction itself, addressed to crab’d’s future self.
Everything except the body is optional. You can write these by hand, and nothing about the format requires crab’d to have created it.
How it is used
Section titled “How it is used”Every run loads the memory directory and includes it in the system prompt, alongside your
AGENTS.md and skills. They are framed as settled rulings for the
repository: crab’d is told not to re-raise a finding a memory rules out, and not to re-argue the
decision. If a memory genuinely contradicts what it sees in the code, it is told to say so rather
than silently ignore it.
Two caps keep the directory from crowding out the diff, since this text is re-sent on every turn of the agent loop:
memory.max_entries(default50), newest first.- A total budget of 20,000 characters, applied after that.
When crab’d records one
Section titled “When crab’d records one”crab’d does not record memories at its own discretion on every run. Two things must both hold:
- The run is a human replying to crab’d. Either a reply in an inline review thread that crab’d started, or a comment on an issue or pull request where crab’d has already spoken.
- The correction generalizes. crab’d is instructed to record only a durable fact about the repository, such as a deliberate convention, an intentional pattern, or a project fact that made its finding wrong. It is told explicitly not to record anything about the pull request in front of it.
The first condition is enforced mechanically. The second is a judgement crab’d makes, which is exactly why the default is to commit memories somewhere you review them.
Where memories are written
Section titled “Where memories are written”memory: enabled: true write: branchwrite |
Behavior |
|---|---|
branch |
Default. Commits to the pull request’s own branch, so the memory is reviewed with the code that provoked it. |
pr |
Commits to a crabd/memory branch and opens a dedicated pull request. Each memory is approved on its own. |
main |
Commits straight to the default branch. Takes effect immediately, everywhere, with no review in between. |
off |
Read-only. You author the files, and crab’d only reads them. |
Two cases resolve differently under branch, and crab’d tells you in its comment when they do:
- No pull request (a mention on an issue): there is no branch to target, so it falls back to the
prbehavior. It never falls back to the default branch. - A fork pull request: crab’d’s token is scoped to your repository and cannot push to a
contributor’s fork, so the memory is skipped with an explanation. Use
write: prif you want corrections from fork contributors recorded.
Managing memories
Section titled “Managing memories”They are files in git, so the usual tools work:
- Edit one to sharpen it. crab’d reads whatever is there.
- Delete one to make crab’d forget. The next run will raise the finding again.
- Revert the commit that added a bad one.
- Write your own without waiting for a correction. A hand-authored memory is indistinguishable
from a recorded one. With
write: offthis is the only way they appear, which is a reasonable setup for a repo that wants curated memory and no agent writes.
If nothing is being recorded
Section titled “If nothing is being recorded”crab’d posts a warning on its tracking comment from the moment it starts, not at the end, when memory is on but it cannot write. The common causes:
permissions.writeisfalse. Memory needs to commit.- crab’d’s token or GitHub App installation lacks
contents: writefor the repository. - The trigger was a fork pull request under
write: branch.
When any of these apply, crab’d does not attempt the write at all: it finishes the review normally and simply doesn’t record. No memory is silently lost to a failed commit.
If there’s no warning and still nothing is recorded, the run most likely wasn’t a reply to crab’d, or it judged the correction too specific to generalize. Both are working as intended.
Governance
Section titled “Governance”memory.enabled and memory.write are both lockable from an org config, like any other key:
memory: enabled: true write: prgovernance: locked: ['memory.enabled', 'memory.write']See config layering for how that resolves.
