Brain · Patterns library
Promote a rule your repos already learned
RepoOps reads four brain files in every tracked repository, groups the entries whose titles match, and marks a title that two or more repositories carry as an established playbook. One button moves it to a repository that lacks it, as a pull request you review.
For: the engineer who keeps several repositories, and the person who decides what goes into a repository's CLAUDE.md
What it does, and why it helps
The tab reads four files in every tracked repository's brain (patterns.md, anti-patterns.md, errors.md and decisions.md), splits each into its heading-delimited entries, and groups the entries whose titles match after normalizing: lowercase, with backticks, parentheticals, dates and a short stopword list removed. A title two or more repositories carry is an established playbook. A title one repository carries is a candidate. Each card names the repositories that have it and shows each repository's own heading and the first paragraph of its entry, up to 280 characters, so you can see how the wording drifted. An established card also lists the tracked repositories that lack it and offers one button that opens a pull request appending the entry verbatim to the matching brain file there.
Above the catalog sits the Plays section. It reads the scored session outcomes for the repository you opened the tab from, keeps the ones in the good quality band that shipped clean and carry a tracked cost, and shows each with the real dollars that session spent. Adopt pins one into that repository's CLAUDE.md and AGENTS.md, inside a managed block bounded to 12 rows and 1,500 characters. Un-adopt is the exact inverse. Both write your working copy; nothing commits for you.
The pain. The same lesson gets written down twice, in two repositories, by two people who never compared notes. The entry that would have saved the second one sits in a brain file nobody opens.
The point of view. A rule two repositories wrote down on their own is stronger evidence than a rule one person liked. Count the repositories before you promote a rule, and move it as a pull request someone reads rather than a paste.
What gets easier. Seeing which brain entries recur across the portfolio, reading each repository's phrasing side by side, and getting the missing one into a third repository without opening a checkout.
When it helps. Two or more tracked repositories, each with a .claude/brain/ that carries at least one of patterns.md, anti-patterns.md, errors.md or decisions.md.
Its limits. Grouping is exact-match on the normalized title, so two repositories that phrase the same lesson differently do not group. Only those four files are read. The pull request is a proposal: RepoOps opens it and stops. Plays need scored session outcomes, so a fresh install has none.
Understand it in 30 seconds
Read the narration
- 0:00 The same mistake happens in two repositories.
- 0:03 Nobody sees the pair.
- 0:06 Count the repositories before you promote a rule.
- 0:09 Two that wrote it separately is evidence.
- 0:13 RepoOps groups brain headings across your repositories.
- 0:17 A title in two or more repos is established, and you see each repo's wording.
- 0:23 Move the lesson with a pull request you review.
- 0:26 The count is evidence.
Synthetic example. Read the guide
Where to find it
Where to find it
- Desktop:
localhost:4000, then Memory in the sidebar, then Patterns library under All tools, in the Lessons, wiki and patterns group. - Keyboard: ⌘ K, then type “Patterns library”.
When to use it
The same error, written down in two repositories
Situation. Five repositories are tracked. Two of them have an entry in errors.md whose heading normalizes to the same string. A third repository keeps hitting it.
What you do. Open the tab, press the Errors chip and the Shared only chip. Read both excerpts. In the card, pick the third repository under Install into: and press Open PR.
What you see. The card sits under the heading Established playbooks (shared across 2+ repos), open by default, with a kind tag and a badge reading the repository count. Each repository row shows that repository's own title and the first paragraph. The message after the button reads PR: followed by the URL.
What it establishes. You know how many repositories learned it and how each phrased it, and the third repository has a pull request appending the entry verbatim with a line saying where it came from. Nothing merged: you review it at your host.
An approach worth pinning into the manual
Situation. The capture pipeline has scored this repository's sessions. One shipped clean, reached the good band and carries a tracked cost.
What you do. Read the play card in the Plays section, then press Adopt. If you have set ANTHROPIC_API_KEY, press Check these with the judge first.
What you see. The card names the repository, the tool, the turn and tool-call counts, the quality score and a badge reading the measured dollars. After adopting, the message names the repository and how many plays are pinned now. A confirmed play carries a judge-confirmed mark.
What it establishes. The play is in .claude/brain/adopted-plays.json and in the managed block of CLAUDE.md and AGENTS.md, so the next agent in that repository reads it. A pinned play is a record of one cheap, clean session; it is not a claim that the next one will be.
Before you start
- Supported versions
- RepoOps desktop v0.3.1, the release this guide was read against. The catalog needs nothing else. The Plays section needs session outcomes the capture pipeline has already scored.
- Where it runs
- Local: Memory, then Patterns library under All tools, served as public/playbooks.html. Hosted: no page of its own. The Team playbooks page that hosted Memory lists under All tools is a different feature (runbooks of named steps a team shared) and the registry keeps it deliberately off this leaf, so it carries none of the cross-repo catalog.
- Permissions
- Whatever the local aggregator already has: it reads each tracked repository's mirror, with the working tree as a fallback. Open PR runs git push and gh pr create in a temporary worktree under the credential that machine already holds, so anyone who can reach the dashboard can open a pull request on your remote.
- Connections
- Two or more repositories in repos.config.json, each mirrored and ready, or the shared list stays empty by construction. The GitHub CLI installed and authenticated for Open PR. ANTHROPIC_API_KEY on this machine for the judge pass, which is the only part that calls a model.
- Plan
- No plan gate. The pricing capability map has no row for the pattern library or for Plays, and both run on the free local tier.
Configure it
- Track two or more repositories.
The scan covers every tracked mirror whose state is ready, and the Repos scanned card counts exactly those. With one, the list shows candidates only and the empty state says so. A mirror still cloning is skipped rather than reported.
- Narrow with the chips, not by reading past rows.
All, Patterns, Anti-patterns, Errors, Decisions and Shared only are server-side filters on /api/playbooks. Each chip is a new query of 20 rows with Load more, so the page you see is a page of what you chose. A value the server does not know reads as all, so a stale bookmark shows the catalog instead of an empty panel.
- Read both excerpts before you move anything.
Each repository row carries that repository's own heading and the first paragraph of its entry. Two repositories that learned the same thing rarely wrote it the same way, and the wording you promote is the one the target repository will live with.
- Open the pull request.
Install into: lists only the tracked repositories that do not already carry the pattern. Open PR copies the verbatim entry block from a repository that has it, appends it plus one attribution line to the matching brain file on a branch named playbook- and a timestamp, and returns the URL. A target that already has it is refused.
- Read the Plays section for approach, not for rules.
Plays are scoped to the repository the tab was opened from, and come from the newest 500 scored outcomes for it. A session qualifies on three counts: the good band (0.8 in config/rubrics/quality.json), not reverted, and a tracked cost above 0.0001 dollars. Sessions that describe the same win dedupe to one play and the cheapest proof wins.
- Adopt, then commit.
Adopt merges the play into .claude/brain/adopted-plays.json and re-renders the managed block between the repoops:plays markers in CLAUDE.md and AGENTS.md. Un-adopt removes it and re-renders from what remains. Both touch the working copy only, so commit all three files for a teammate to see them.
- Optionally ask the judge.
Check these with the judge re-reads the 20 most recent good-band sessions on your own key and marks the plays it confirms. A play it never read stays unmarked, which is not a rejection. Without a key the bar says so and no card can carry the mark.
| Setting | Where | A sensible choice | Why it matters |
|---|---|---|---|
repos | repos.config.json | two or more repositories, each mirrored and ready | Shared needs two, so a single tracked repository makes the established list unreachable rather than empty by accident. |
kind | the tab's chips: Patterns, Anti-patterns, Errors, Decisions | Errors first, where recurrence is cheapest to act on | It is a server-side filter, so the count and the page agree; an unrecognized value shows the whole catalog. |
group | the Shared only chip | on, once more than one repository is tracked | It asks the server for the established rows alone, instead of scrolling past candidates. |
limit | the /api/playbooks query | 20, which is what the tab asks for | Clamped at 500. The catalog measured 630,379 bytes across 898 rows, so the row count is the lever. |
ANTHROPIC_API_KEY | the data directory's .env | set it only if you want the judge pass | Without it the judge bar says the pass needs your own key, and no play can carry judge-confirmed. |
REPOOPS_PLAYS_PRODUCE_OFF | the data directory's .env | unset, or 1 to stop the nightly producer | The producer writes candidate cards to .claude/brain/proposed/ on the existing 02:00 pass. It never adopts. |
REPOOPS_BRAIN_PLAY_ADOPT_OFF | the data directory's .env | 1 if a play should only ever be pinned by hand | The nightly adoption pass is the half that writes CLAUDE.md and AGENTS.md without you. |
REPOOPS_BRAIN_PLAY_ADOPT_NIGHTS | the data directory's .env | 3 (the default) | The number of distinct nights a play must be re-proposed before it adopts itself. One night is noise. |
REPOOPS_BRAIN_PRODUCE_CAP | the data directory's .env | 10 (the default) | Candidate cards written per repository per night. What is held back is re-derived on the next run, not lost. |
What you should see
Two repositories share an error
Configuration. Two ready mirrors, each with an errors.md entry whose heading normalizes to the same string.
Expect. The Shared playbooks card counts it. The card renders under Established playbooks (shared across 2+ repos), open by default, badged with the repository count.
Verify. Both repositories appear as rows inside the card with their own headings. Install into: lists the tracked repositories that lack it, and none of the two that have it.
One repository tracked
Configuration. A single repository in repos.config.json, with patterns and errors documented.
Expect. Shared playbooks stays 0 and every row is a candidate. The empty state names how many repositories are tracked and says shared playbooks need two or more.
Verify. The Repos scanned card counts ready mirrors, not rows in repos.config.json. A mirror that has not finished cloning is the usual gap between the two numbers.
No scored sessions yet
Configuration. A fresh install, or a repository whose sessions have not been scored.
Expect. The Plays section reads No plays yet, and the hint says plays appear once a good-band, shipped-clean session with tracked cost is scored.
Verify. Nothing is pinned into CLAUDE.md by the absence, and no play is priced from an untracked session. A good-band session that spent nothing measurable never becomes a play.
Data and cost
- What is captured
- Nothing new for the catalog. It is computed per request from the four brain files of each tracked repository and memoized per repository by the newest of their modified times. Plays are projected from the agent_session_outcome rows already in the local store. Adoption writes .claude/brain/adopted-plays.json and the managed block in CLAUDE.md and AGENTS.md.
- Who can see it
- Local. The aggregator serves the catalog on this machine and publishes no snapshot; there is no hosted Patterns library page. What a teammate sees is whatever you commit: the brain files, adopted-plays.json, and the two managed blocks.
- How long it is kept
- The entries live as long as your repositories' brain files do, and the catalog keeps none of them. The nightly producer's candidate cards sit in .claude/brain/proposed/ under a dated file name, and the drain pass rejects dated proposal files older than 14 days. adopted-plays.json has no retention window.
- What leaves the machine
- Two paths, both taken only when you press something. Open PR runs git push and gh pr create against your own remote. The judge button sends a one-line summary of each candidate session (repository, tool, pull request number, CI status, turns, dollars, quality score) to Anthropic on your key, at most 20 per press. The pattern text itself never leaves the machine.
- What it costs
- The catalog and the Plays list cost local reads only. The judge pass is at most 20 model calls per press on your own key, routed through the same model lineup as every other RepoOps call. A play's dollar figure is the tracked spend of the session it describes, never an estimate.
When the result differs
| Symptom | Likely cause | Next action |
|---|---|---|
| Shared playbooks reads 0 while several repositories are tracked. | Only mirrors whose state is ready are scanned, and grouping is exact after normalizing the title. | Compare the Repos scanned card with repos.config.json, then compare the two headings character by character. |
| Two repositories clearly share a lesson and it still reads as a candidate. | Matching is normalized-title equality. Different wording does not group, and body-level or fuzzy matching is not built. | Rename one heading to match the other, or promote the candidate by hand. |
| Open PR answers Failed, with a message. | openFilePr needs origin reachable, a default branch it can detect, and an authenticated GitHub CLI in that repository. | Read the text after Failed, then check the CLI's auth status and that the target repository has a remote. |
| Open PR refuses and names the target repository. | That repository already carries the pattern, which the route answers as a conflict rather than a second copy. | Pick another repository from the list, or read the existing entry there first. |
| Every play card says Adopt after a reload, including ones you adopted. | The adopted set is only read back when the request names a repository. | Open the tab from a repository in the dashboard shell rather than by typing the bare URL. |
| The judge bar asks for a key instead of offering the button. | ANTHROPIC_API_KEY is not set on this machine. | Add it to the data directory's .env and reload. The pass is per press, never on page load. |
| A teammate's CLAUDE.md does not carry a play you adopted. | Adopt writes the working copy and nothing commits it. | Commit CLAUDE.md, AGENTS.md and .claude/brain/adopted-plays.json together. |
| The managed block shows fewer plays than the store holds. | The block is bounded to 12 rows and 1,500 characters, whichever binds first, because CLAUDE.md has its own size rule. | Read the full set in .claude/brain/adopted-plays.json. The block's own line names how many of how many it is showing. |
- Disable
- The tab itself has no switch and no background work: it reads when you open it. The two nightly halves have one each, REPOOPS_PLAYS_PRODUCE_OFF=1 and REPOOPS_BRAIN_PLAY_ADOPT_OFF=1. Removing a repository from repos.config.json takes it out of the scan.
- Roll back
- For a play, Un-adopt is the inverse and re-renders both blocks from what remains. For an installed pattern, not provided: RepoOps cannot withdraw a pull request it opened. Close or revert it at your host, and delete the playbook branch there yourself.
- Revoke access
- Not provided here. Open PR borrows the git and GitHub CLI credential the machine already holds, so revoke it with the CLI's own logout or at GitHub. Remove ANTHROPIC_API_KEY from the data directory's .env to stop the judge pass.
- Delete
- Not provided for the catalog, which owns no store: the entries are your own .claude/brain/patterns.md, anti-patterns.md, errors.md and decisions.md. Un-adopt removes a play from .claude/brain/adopted-plays.json. A nightly candidate card sits in .claude/brain/proposed/ under its dated file until the stale sweep rejects it.
Related tasks
Maintenance evidence
- Feature id
playbooks(spine leafpatterns-library)- Owner
- Memory and brain program: the cross-repo pattern library (features.md, docs/features/pattern-library.md) and Plays, positive-pattern capture (Hivemind P1.4). Guide: LDG-0717.
- Supported product version
- RepoOps v0.3.1
- Last verified
- 2026-09-15, read against origin/main at 52366bb6d; labels read from the served tab source (public/playbooks.html), and the defaults, caps and kill switches read from the route and library modules listed below rather than from the feature doc, which still places the tab under a category the registry renamed.
- Example fixtures
- No fixture file. The shapes are inline in lib/pattern-extractor.test.mjs (parsing and grouping), lib/playbooks-scope.test.mjs (the cross-repo scope regression, run against the real extractor both ways), lib/playbook-page.test.mjs (order, groups, paging), lib/plays-extractor.test.mjs (the three gates and the dedupe), lib/adopted-plays.test.mjs and lib/adopted-plays-store.test.mjs (merge and remove by slug), and lib/agent-md-blocks.plays.test.mjs (the cap, the byte budget and idempotency).
- Source references
lib/pattern-extractor.mjs,lib/playbook-page.mjs,lib/playbook-installer.mjs,lib/routes/playbooks.mjs,lib/plays-extractor.mjs,lib/routes/plays.mjs,lib/adopted-plays.mjs,lib/agent-md-blocks.mjs,lib/brain-drain-policy.mjs,lib/brain-cron.mjs,lib/routing-proposer.mjs,public/playbooks.html- Documentation review
- Independent review requested on the slice pull request; not yet recorded.
- Video review
- Narrated story rendered and published 2026-09-26 (render 7cec907fb593, LDG-1014) with the breadcrumb Memory, which lists the feature under Moved here, checked against main at 7aab4cd82 with LDG-1014 part 1. Six frames, the captions and the transcript were reviewed by the authoring agent, not an independent reviewer; the audio was not listened to by a person. Narration is the provisional Windows voice until LDG-0721.
Last updated