Brain · Brain reflection

Review what your brain learned overnight

At 02:00 local RepoOps reads the last week of commits and session entries for each tracked repository, asks Claude for entries worth adding to five knowledge files, and writes them as proposals. It never edits those files itself. You accept, edit or reject each card, and what you accept is appended to the file your next session reads.

For: the engineer who owns a repository's brain, and anyone deciding how much the nightly pass may accept without them

What it does, and why it helps

One pass makes one model call per knowledge file: errors, decisions, open questions, patterns and glossary. Each call gets the existing file, the commits since the cutoff and up to eight recent session entries, and is told to return an empty list when nothing belongs. The tier follows the work: glossary is term extraction on Haiku, errors, decisions and open questions are synthesis on Sonnet, patterns is the cross-cutting one on Opus. The result is written to .claude/brain/proposed/, one file per knowledge file per day, and a fresh run for the same day replaces it.

Every card carries a band the model assigned itself, high, medium or low, and a one-line signal naming what triggered it. That band is a claim, not a measurement, which is why the bulk accept asks you to type the repository id first: accepted text is appended to files your agents read as instructions. Accept appends. Edit lets you add the boundary the model left out. Reject writes the body to proposed/rejected/ and stamps a ledger, so the card keeps a rejected badge and the text survives. Overnight, a separate drain accepts typed high and medium cards through the same path your click uses, capped and stamped, and a stale sweep bulk-rejects what nobody read for fourteen days.

The pain. The same fix gets rediscovered every few weeks. The knowledge is in the session log and the commit messages, and nothing moves it into the files the next session reads.

The point of view. A machine may propose into your knowledge base and may never write into it unasked. So the pass produces cards in a separate directory, each naming the signal that produced it, and the canonical file changes only when someone accepts. A confidence band is the model's own claim about itself, so it is a sort order, not a verdict.

What gets easier. Deciding in the morning. Five sections, newest and unreviewed first, each card showing its band, its signal, the body it would append, and the file it would append to.

When it helps. A repository with a .claude/brain/ directory and session entries, on a machine that has an Anthropic key. It pays off most on a repository worked on by several sessions a week, because that is where the same lesson gets relearned.

Its limits. It proposes; it does not verify. Nothing here checks that an accepted entry is true or that it prevents anything. An accepted entry cannot be un-appended from inside the app, and rejecting a card you already accepted changes the badge, not the file. Without an Anthropic key there are no proposals at all, though the rest of the nightly pass still runs. The hosted tab of the same name reads your published lessons store, not this queue.

Understand it in 30 seconds

30.1 s, captions on. Narration: Microsoft Zira Desktop (provisional voice; an approved narration source is pending).Transcript
Read the narration
  1. 0:00 Your agent relearns the same lesson every week.
  2. 0:03 Nothing wrote it down.
  3. 0:06 Each night RepoOps proposes entries from the week's work.
  4. 0:09 Confidence is the model's own claim.
  5. 0:13 Each card names the signal that triggered it and the file it would join.
  6. 0:17 Accept, edit, or reject; the reject is archived.
  7. 0:23 Accepted text lands in the file your agents read next session.
  8. 0:27 Set the caps.

Synthetic example. Read the guide

Where to find it

Where to find it

  • Desktop: localhost:4000. It has no sidebar row: open it from the palette, or go straight to its address.
  • Hosted: repoops.ai/team/brain-reflection. It has no sidebar row: open it from the search box, or go straight to its address.
  • Keyboard: ⌘ K, then type “Brain reflection”.

When to use it

The morning after a heavy week

Situation. Four sessions shipped in five days. The nightly pass ran, and the tab shows cards across errors, decisions and patterns, newest and unreviewed first.

What you do. Read each card's signal line before its body. Accept the ones that capture a rule you would want a teammate to follow. Press Edit on the one that is right but unbounded, add the boundary, then Accept. Reject the rest.

What you see. The status pill on each card flips in place to Accepted or Rejected with a relative timestamp. The status bar names the file the entry landed in, and says so again if the repository's own brain sync script did not run there.

What it establishes. The accepted bodies are appended to errors.md, decisions.md and patterns.md, which the next session reads. Nothing was verified by accepting it; the file now says what you agreed it should say.

You disagree with what the drain accepted overnight

Situation. A high-band entry you would not have accepted is already in patterns.md, because the nightly drain accepts typed high and medium cards on its own by default.

What you do. Read the accepted ledger for that file under proposed/accepted/, where a machine accept carries auto true and a reason naming the tier, and the per-run rows in proposed/drain-runs.jsonl. Then edit or remove the entry in the knowledge file itself, and set REPOOPS_BRAIN_AUTO_DRAIN_OFF=1 if you want every card by hand.

What you see. The ledger separates a machine decision from yours. drain-runs.jsonl has a row for every run, including the runs that accepted nothing, so a drain that found nothing is distinguishable from a drain the pass never reached.

What it establishes. You know which decision was yours. Removing the text is a file edit and a git commit, not a button; the ledger keeps the record that it was accepted.

Before you start

Supported versions
RepoOps desktop v0.3.1, the release this guide was read against. The 02:00 pass runs in the dashboard process, so the machine has to be awake and the app running, or the capture daemon installed as an OS service.
Where it runs
Local: Memory, then Review proposals, which opens Brain reflection with Auto-memory as its subtab. Hosted: repoops.ai/team/brain-reflection is a read of the published lessons store (active lessons, auto-memory writes, human-curated counts and recurrences prevented). The proposal queue, the accept and reject controls and the cleanup scans are desktop only.
Permissions
No role gate on the desktop tab. The bulk accept refuses unless the request carries the repository id you typed, because it writes an unbounded number of entries into files agents read as instructions. The hosted read is session authed, scoped to your team membership and your per-member repository allow-list.
Connections
ANTHROPIC_API_KEY on this machine for the proposals and for a plan draft. Git, because the pass reads commits since the cutoff. A .claude/brain/ directory in the repository. For the hosted read, a published brain snapshot that includes the lessons store.
Plan
The local loop is on the free rung: the pricing capability map lists a flat-markdown brain with lessons written back to CLAUDE.md under solo, and states that you never pay for the brain itself. Seeing the hosted read follows the hosted dashboard tiers.

Configure it

  1. Check the nightly pass is on.

    Settings, the Brain & sync group, the Nightly brain dreaming card: the checkbox reads Run the nightly dream pass and is on unless you turned it off. The card also lists each repository's last run and flags one that has not run in 48 hours as stale. If REPOOPS_BRAIN_DREAM=0 is set in the environment the checkbox is disabled and the card says which switch is deciding.

  2. Add your Anthropic key.

    ANTHROPIC_API_KEY in the data directory's .env. Without it the nightly pass still runs its deterministic half and records the night as deterministic-only, but writes no proposals, and Reflect now returns Reflection needs your ANTHROPIC_API_KEY (BYOK). Add it in Settings.

  3. Read the queue.

    Memory, then Review proposals. Cards are grouped by knowledge file in the order errors, decisions, open questions, patterns, glossary, and inside each group unreviewed cards lead, then high, medium, low. The date picker covers every day on disk, and when the page is not the whole list it says Showing N of M proposal files. Pick a date to see the rest.

  4. Decide each card.

    Accept appends the body to that knowledge file. Edit turns the body into a text area so you can add the boundary before accepting. Reject asks for confirmation, then writes the body to proposed/rejected/ with a timestamped filename and stamps the rejected ledger. A duplicate title is reported as skipped rather than appended twice.

  5. Use Accept all high-confidence only when you mean it.

    The button asks you to type the repository id, and the route refuses the request without a matching confirm value. It applies to the visible date, or to every date when the picker is on All recent dates.

  6. Set how much the nightly drain may accept without you.

    Unset, the drain is on: it accepts typed high and medium cards for that night's date through the same accept path your click uses, at most 20 high and 8 medium per run, each stamped auto with a reason. Low confidence and every untyped card stay on your queue. REPOOPS_BRAIN_AUTO_DRAIN_OFF=1 turns it off entirely.

  7. Run the LLM-free scans when the brain feels noisy.

    Cleanup proposals, Scan now finds decision headings more than 70 percent similar, always-versus-never claim pairs, and TODO items in files unchanged for 90 days. RepoOps removes a stale TODO for you; a duplicate or a contradiction is a judgement it records rather than makes, and a dismissal needs a reason. Brain coherence, Check now returns four finding classes over features, roadmap, sessions and decisions, and reads No drift detected when there are none.

SettingWhereA sensible choiceWhy it matters
brain.dream.autoSettings, Brain & sync, Nightly brain dreaming, Run the nightly dream passon (the default when no flag is set)Turning it off stops the whole nightly pass, including the deterministic ticks that need no key. The per-repository last-dreamed stamps are kept, so turning it back on resumes.
REPOOPS_BRAIN_DREAMthe data directory's .envunset; 0 hard-disablesThe environment variable wins over the checkbox, and the Settings card names it as the switch that is deciding.
ANTHROPIC_API_KEYthe data directory's .env, or Settings BYOKset, if you want proposals at allFive calls per pass per repository, one per knowledge file. Without it the pass runs its deterministic half and writes no cards.
REPOOPS_BRAIN_AUTO_DRAIN_OFFthe data directory's .envunset to let the drain run, 1 to review every card by handUnset means typed high and medium cards can be accepted overnight without you.
REPOOPS_BRAIN_AUTO_DRAIN_CAPthe data directory's .env20 (the default)The most new entries one drain run may write, so a flooded night cannot bulk-write the brain. Idempotent no-ops do not consume it.
REPOOPS_BRAIN_MEDIUM_DRAIN_CAPthe data directory's .env8 (the default)Medium drains at a smaller cap than high on purpose: the bar is softer, so a bad night is smaller and easier to spot.
REPOOPS_BRAIN_STALE_PROPOSAL_DAYSthe data directory's .env14 (the default, lowered from 30 on 2026-08-31)How old a pending typed card must be before the nightly sweep rejects it unread. The body is archived to proposed/rejected/, so a wrong sweep is recoverable.
REPOOPS_BRAIN_STALE_REJECT_OFF, REPOOPS_BRAIN_STALE_REJECT_CAPthe data directory's .envunset, and 40 per run1 turns the stale sweep off. The cap drains a backlog over several nights rather than in one, which leaves time to notice a wrong policy.
REPOOPS_BRAIN_PRODUCE_CAPthe data directory's .env10 (the default)The most candidates one producer may write per night per kind. Keep it at or below the nightly drain rate, or the queue grows whatever the drain policy says.
brainReflect.autoMergerepos.config.json, shown read-only in Settings under Nightly reflector auto-mergeabsent or false (the default)This is the GitHub workflow's flag, not the local pass. Armed, the nightly state-doc pull request merges itself on green CI; off, it opens and waits for a person. A repository with no entry in the file gets no nightly pull request at all.
ⓘ
To stop or undo
Four levers, each independent: clear the Run the nightly dream pass checkbox, which stops the whole pass; set REPOOPS_BRAIN_DREAM=0, which overrides the checkbox; set REPOOPS_BRAIN_AUTO_DRAIN_OFF=1, which leaves the pass running but decides nothing without you; or remove ANTHROPIC_API_KEY, which leaves the deterministic ticks and produces no cards. Rejecting a card archives its body and stamps a ledger. It does not remove an entry you already accepted; that is a file edit.

What you should see

The normal night

Configuration. Dreaming on, a key set, the drain and the stale sweep at their defaults, the machine awake at 02:00 local.

Expect. One pass per repository per UTC day. Up to five proposal files under .claude/brain/proposed/ dated today, the typed high and medium cards for that date drained overnight within the 20 and 8 caps, and the rest waiting on your queue.

Verify. The tab header counts proposals across files with new, accepted and rejected pills. Each section heading shows how long ago its file was generated. proposed/drain-runs.jsonl has one row for the run, with what it scanned and what it accepted.

No Anthropic key on this machine

Configuration. Dreaming on, ANTHROPIC_API_KEY unset.

Expect. The nightly pass still runs and records the night as deterministic-only with the reason no BYOK Anthropic key configured. No proposal files are written, so the tab shows its empty state and Reflect now returns a 400 naming the key.

Verify. The empty state reads No proposals yet, and says the pass runs at 02:00 local or on the Reflect now button, and that reflection calls Claude so it needs your key. The Settings dreaming card still lists a last run per repository.

The laptop was asleep at 02:00

Configuration. Any of the above, on a machine that missed the window.

Expect. The hourly check acts outside the window only for a repository whose last pass is more than 48 hours old, and then runs it once for that UTC day. A repository that has never run is not treated as overdue, so adding a repository does not spend your key on the next boot.

Verify. The console logs catching up a missed night for that repository. The Settings dreaming card shows each repository as fresh, stale or never dreamed, with the hours since its last run.

Data and cost

What is captured
Proposals go to .claude/brain/proposed/ as one markdown file per knowledge file per day, holding the body, the band, the signal and a marker with the proposal id, the band, the model, and the actor, session and repository when a session actor is registered. Decisions go to sibling ledgers: proposed/accepted/, proposed/rejected/ and proposed/duplicate/, one ids file per knowledge file, plus a full copy of every rejected body and one row per drain run in proposed/drain-runs.jsonl. The cleanup scan appends to .claude/brain/audit/cleanup-proposals.jsonl and its dispositions to cleanup-dispositions.jsonl. A held graph proposal's decision lands in .claude/brain/graph/proposal-decisions.jsonl.
Who can see it
Local, in the repository's own working tree, so it is shared exactly as far as you push that repository. An accepted entry is appended to a knowledge file every agent session reads. The hosted Brain reflection tab reads the published lessons store and never the proposal queue, so nothing on this tab reaches repoops.ai unless you publish your brain.
How long it is kept
No automatic retention. A proposal file is replaced only by a later pass for the same day, and nothing deletes the directory on a schedule. npm run prune-proposals reports which snapshots have every card settled, and it deletes nothing until you pass the apply flag; it keeps any file holding one live card, because that file is the only copy of the card's text. The stale sweep rejects pending cards older than 14 days, which archives rather than deletes.
What leaves the machine
Five calls to Anthropic per pass per repository on your own key, one per knowledge file, bounded at 512, 1500 or 3000 output tokens by tier. Each prompt carries up to 6000 characters of the existing knowledge file, 25 commit subjects and five session entries at up to 2000 characters each. The Draft plan control adds one Haiku call. The cleanup scan and the coherence check make no model call at all. Nothing on this tab sends anything to RepoOps.
What it costs
Not metered per pass. The Settings card says so plainly and points you at the LLM calls tab, where the spend shows up like any other call made with your key. The tier split is the cost control: glossary on Haiku, errors, decisions and open questions on Sonnet, patterns on Opus.

When the result differs

SymptomLikely causeNext action
The page says No repo selected.The tab was opened without a repo query parameter.Open it from Memory, Review proposals, rather than by its bare URL.
Reflect now fails and names your key.No ANTHROPIC_API_KEY on this machine.Add it to the data directory's .env or through Settings BYOK, then press Reflect now again.
The queue is empty the morning after a busy week.Dreaming is off, the machine was asleep and the repository is under 48 hours overdue, or the pass ran without a key and recorded a deterministic-only night.Check the Nightly brain dreaming card in Settings: it names the deciding switch and shows the last run per repository.
Accept reports that the repository's brain sync did not run.The accept appended the entry, then the repository's own sync-brain script failed or is absent.Run npm run sync-brain in that repository. The entry itself has already landed.
Accept all high-confidence returns an error about confirming.The typed value did not match the repository id.Type the repository id exactly as the prompt shows it. The route refuses any request without it.
A card you rejected comes back on a later night.The reflector does not read the rejected ledger when it proposes. The nightly drain does, and never re-accepts a rejection, but the proposer can still write a similar card.Reject it again, or prune the sources it keeps drawing from on the Patterns and Errors tabs.
The date picker is missing days you know exist.You are on an older cached response that predates the full date listing.Reload the tab. The picker is built from the whole directory, and the note beside it says how many files the page is showing.
Disable
Any of the four levers above. The checkbox and REPOOPS_BRAIN_DREAM stop the whole pass; REPOOPS_BRAIN_AUTO_DRAIN_OFF leaves the pass running and stops it deciding; removing the key leaves the deterministic ticks and produces no cards.
Roll back
Not provided. There is no route that removes an accepted entry from a knowledge file. Accept appends to the .md; undoing it means editing that file, and git holds the previous version. Rejecting a card you already accepted records the rejection and leaves the appended text where it is.
Revoke access
The proposal queue has no access control of its own; it is files in your working tree. Remove ANTHROPIC_API_KEY to stop the model half. On the hosted read, access follows team membership and the per-member repository allow-list, so removing a member or narrowing their repository scope removes their view.
Delete
Partly provided. Running scripts/prune-proposals.mjs with the apply flag deletes only the snapshot files whose every card is accepted, rejected or duplicate, and it refuses any file it cannot fully resolve. Nothing deletes the ledgers, the archived rejected bodies under proposed/rejected/, the drain-run rows, or an accepted entry in a knowledge file; those are files in the repository, removed by hand.

Maintenance evidence

Feature id
brain-reflection (spine leaf brain-reflection)
Owner
Memory OS program (M-2, Brain Dreaming, pull requests #211 to #213); the coherence panel is P9.B1. 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/brain-reflection.html and public/settings.html), defaults and caps read from the modules cited in this file's header, and the hosted half read from website/app/team/(home)/brain-reflection/page.tsx. Not checked on a running instance.
Example fixtures
No fixture file; every test builds a temporary repository inline and stubs the model call. The behaviour is exercised by lib/brain-reflector.test.mjs, lib/brain-acceptor.test.mjs, lib/brain-drain-policy.test.mjs, lib/brain-cron.dream-catchup.test.mjs, lib/brain-cron.dream-reachability.test.mjs, lib/routes/brain-dreaming.test.mjs, lib/brain-cleanup.test.mjs, lib/brain/coherence.test.mjs, lib/proposal-prune.test.mjs, test/brain-reflection-accept-and-cleanup.test.mjs and website/lib/brain-reflection.test.ts.
Source references
lib/brain-reflector.mjs, lib/brain-cron.mjs, lib/brain-acceptor.mjs, lib/brain-drain-policy.mjs, lib/brain-cleanup.mjs, lib/brain/coherence.mjs, lib/proposal-prune.mjs, lib/plan-generator.mjs, lib/llm-router.mjs, lib/brain-reflect-arm.mjs, lib/routes/brain.mjs, public/brain-reflection.html, public/settings.html, website/lib/brain-reflection.ts
Documentation review
Independent review requested on the slice pull request; not yet recorded.
Video review
Narrated story rendered and published 2026-09-26 (render f80e20ef68b9, LDG-1012) with the breadcrumb Memory, checked against main at b0bb02812. 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