second-brain
CLAUDE.md16 starsChanged 21 days agoMITView on GitHub
IMPORTANT: 1. You must write automated tests for all code (pytest). Aim for both unit tests and integration tests against a real Postgres test database. 2. You must pass ALL tests before committing. 3. Maintain a minimum test coverage threshold of 85%. Per-module targets: pure logic (chunker, search, format) 95%, ingest pipeline 90%, CLI commands 85%. 4. NEVER commit or push without explicit user permission. No exceptions — even in bypass permissions mode. 5. USE Team mode (native agent teams…
- Reads credentials
- Deletes or force-pushes
- Installs packages
In this repository12 other files it gives its agents.
- AGENTS.mdAGENTS.md
- brain-askSkill
- brain-authoringSkill
- brain-captureSkill
- brain-graphSkill
- brain-maintenanceSkill
- brain-memorySkill
- brain-proactivitySkill
- brain-todoSkill
- consult-brainSkill
- elicit-brainSkill
- ingest-brainSkill
The file
Show its rules and text
We split this CLAUDE.md into the rules it gives an agent
23 rules. About 0 are common, 11 are distinctive, and 12 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈11
Distinctive · estimate
This author's own choices. Worth a look.
12
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Distinctive: line 7
NEVER commit or push without explicit user permission: No exceptions — even in bypass permissions mode.
- Distinctive: line 8
USE Team mode (native agent teams — dispatch Agent teammates.
- Very specific: line 9
After edits, run the full test suite (pytest) and lint (ruff check).
- Distinctive: line 10
NEVER jump straight to code.
- Distinctive: line 11
When referencing existing modules/functions, READ the actual source file first.
- Very specific: line 12
All Python code MUST pass ruff check with zero warnings AND mypy src/ with zero errors.
- Very specific: line 13
Pre-commit check: Run ruff check && mypy src/ && pytest before committing.
- Very specific: line 14
Memory updates: After completing a task that adds/changes any of the following, update the corresponding memory file in the auto-memory …
- Distinctive: line 17
MANDATORY regression tests for bug fixes: Every bug fix MUST include a test that reproduces the original bug and verifies the fix.
- Distinctive: line 23
Post-phase code review + completion audit LOOP (MANDATORY): After completing each phase/wave of a plan, run a review + audit loop that …
- Distinctive: line 26
THE LOOP: If EITHER review finds issues → fix ALL issues → re-run BOTH → repeat.
- Very specific: line 47
Plan header override: When writing plan documents, use > For agentic workers: REQUIRED SUB-SKILL: Use team-driven-development to implement …
- Distinctive: line 52
Search for existing shared code before creating new modules/utilities.
- Distinctive: line 54
Prefer composition over copy-paste.
- Very specific: line 59
Liskov Substitution: All extractors return ExtractedDoc.
- Very specific: line 90
Every file over 800 has a row in the table in docs/ceiling-table.md.
- Very specific: line 107
Every documents read that filters draft is a read of the browseable corpus, and almost every one is a place a *confidential* row could …
- Very specific: line 117
Run after every change: ruff check (lint) or ruff check --fix (auto-fix), then mypy src/.
- Very specific: line 157
Never hardcode secrets — VOYAGE_API_KEY and DATABASE_URL come from .env (gitignored).
- Distinctive: line 158
Never log full document content at INFO level — it can contain sensitive transcripts/emails.
- Distinctive: line 169
Use teammates for: parallel test creation, codebase exploration, tasks consuming >30% of context window, implementation when plan is …
- Very specific: line 189
Default arctic (Snowflake Arctic Embed v2 over local Ollama, 1024-dim).
- Very specific: line 329
Pluggable embedders behind one Protocol: All three backends conform to brain.ingest.Embedder (dim: int, embed(texts, *, input_type), …
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CLAUDE.md
IMPORTANT:
- You must write automated tests for all code (pytest). Aim for both unit tests and integration tests against a real Postgres test database.
- You must pass ALL tests before committing.
- Maintain a minimum test coverage threshold of 85%. Per-module targets: pure logic (chunker, search, format) 95%, ingest pipeline 90%, CLI commands 85%.
- NEVER commit or push without explicit user permission. No exceptions — even in bypass permissions mode.
- USE Team mode (native agent teams — dispatch Agent teammates; the team auto-forms, no TeamCreate/TeamDelete needed) for any multi-task work to keep the main context window clear. Always use team-driven execution (not inline) when executing implementation plans. See "Team Mode Override" section below.
- After edits, run the full test suite (
pytest) and lint (ruff check). Fix bugs and update tests before claiming work complete. - NEVER jump straight to code. Produce a written plan FIRST for any multi-file task. Get explicit approval before writing code.
- When referencing existing modules/functions, READ the actual source file first. Never guess field names, import paths, or function signatures.
- All Python code MUST pass
ruff checkwith zero warnings ANDmypy src/with zero errors. See "Linting" below. - Pre-commit check: Run
ruff check && mypy src/ && pytestbefore committing. - Memory updates: After completing a task that adds/changes any of the following, update the corresponding memory file in the auto-memory directory: CLI commands →
cli.md, database schema →schema.md, Python types/dataclasses →types.md, ingest extractors →extractors.md, search algorithm changes →search.md. 11a. Memory audits: When asked to "update memory", audit ALL memory files against the current codebase using parallel Explore agents (one per file). Update any drifted content and the MEMORY.md index. 11b. Plans, specs & docs: ALL plans, specs, design docs, and any.mdfiles created as part of work MUST be stored underdocs/— specs indocs/specs/YYYY-MM-DD-<topic>-design.md, plans indocs/plans/YYYY-MM-DD-<topic>.md. Never leave planning/spec documents in the repo root. - MANDATORY regression tests for bug fixes: Every bug fix MUST include a test that reproduces the original bug and verifies the fix. No bug fix is complete without a regression test.
- NO monkey-patching in tests. NO EXCEPTIONS.
- BANNED: Reopening production modules/classes to inject constants, methods, or attributes.
- BANNED: Direct attribute assignment on imported modules without restoration.
- If a test needs monkey-patching to pass, the production code has a bug. Fix the production code, not the test.
monkeypatch(pytest),unittest.mock.patch, andmocker.patch(pytest-mock) are NOT monkey-patching — they are standard test doubles with automatic cleanup. These are fine.
- Post-phase code review + completion audit LOOP (MANDATORY): After completing each phase/wave of a plan, run a review + audit loop that repeats until BOTH pass with zero issues:
- Code review: Dispatch
superpowers:code-revieweron ALL changes in the phase against the plan spec. - Completion audit: Dispatch a separate completion auditor checking: (a) every task implemented — nothing skipped, (b) every fix matches spec exactly, (c) every required test exists and passes, (d) no regressions, (e) no dead code — no orphaned modules, unused functions, or untested branches.
- THE LOOP: If EITHER review finds issues → fix ALL issues → re-run BOTH → repeat. Exit condition: code reviewer says "APPROVED" AND auditor says "AUDIT PASSED". No phase is complete until the loop exits clean.
- Code review: Dispatch
- No PII in checked-in code. NO EXCEPTIONS. The repo has been explicitly PII-scrubbed across tests, fixtures, docs, and comments — never reintroduce real personal data. Use synthetic / redacted values for names, email addresses, phone numbers, postal addresses, meeting attendees, calendar specifics, company names, customer references, and internal project codenames. When fixing or extending tests, copy the existing synthetic pattern; never paste production data (e.g. real meeting transcripts, real email bodies, real chat threads, employer / coworker names) even temporarily. If a real value seems required for a test to be meaningful, the test is wrong — parameterize the fixture or refactor the production code so it's testable with synthetic data. This rule covers commit messages and PR descriptions too.
Team Mode Override (MANDATORY — overrides superpowers skill routing)
ALL agent dispatching MUST use Team mode (native agent teams — dispatch Agent teammates; the team auto-forms and is torn down automatically, so there is no TeamCreate/TeamDelete and no team_name to pass) instead of standalone Agent subagents. This applies to every superpowers skill that spawns agents:
| Superpowers skill | Use instead | What changes |
superpowers:subagent-driven-development | team-driven-development skill | Teammates with worktree isolation, SendMessage for coordination (team auto-forms — no TeamCreate) |
superpowers:dispatching-parallel-agents | team-parallel-dispatch skill | Parallel teammates with worktree isolation (team auto-forms — no TeamCreate) |
superpowers:requesting-code-review | Dispatch reviewer as a teammate (it auto-joins the active team), otherwise standalone Agent | No team_name needed |
superpowers:executing-plans | Use team-driven-development instead of subagent-driven-development when it suggests subagents | Same redirect |
superpowers:writing-plans execution handoff | NEVER offer a choice. Skip the two-option prompt and proceed directly with team-driven-development. | No "Inline Execution" option, no question asked |
Non-agent superpowers skills are unchanged: brainstorming, verification-before-completion, using-git-worktrees, finishing-a-development-branch, test-driven-development, systematic-debugging, receiving-code-review, writing-skills.
Why: Team mode provides shared task lists, inter-teammate communication via SendMessage, and better coordination visibility than isolated subagents.
NEVER fall back to standalone Agent subagents for execution or parallel dispatch.
Plan header override: When writing plan documents, use > **For agentic workers:** REQUIRED SUB-SKILL: Use team-driven-development to implement this plan task-by-task.
Architecture Principles
DRY
- Search for existing shared code before creating new modules/utilities.
- Reusable patterns:
src/brain/for shared utilities. Extract anything used in 2+ places. - Prefer composition over copy-paste.
SOLID Principles (MANDATORY)
- Single Responsibility: Each module has ONE reason to change. Extractors only extract. The chunker only chunks. The embedder only embeds. The search module only searches. The CLI only orchestrates.
- Open/Closed: Open for extension, closed for modification — adding a new ingest source (e.g.,
notion.py) means adding a new extractor module + dispatcher entry, not editing existing extractors. - Liskov Substitution: All extractors return
ExtractedDoc. All search backends conform to the same result shape. Callers don't care which subclass. - Interface Segregation: Modules expose narrow, focused public APIs. Don't force a consumer to import a kitchen-sink module to get one helper.
- Dependency Inversion: High-level modules accept dependencies via constructor / function args (e.g.,
count_tokenscallable on the chunker,clienton the embedder). Tests pass fakes; production passes real ones.
Coding Conventions
- PEP 8,
snake_caseeverywhere. - Type hints on every function signature.
mypy src/must pass. - f-strings for string formatting (no
%or.format()). pathlib.Pathfor filesystem paths, never raw strings.- Dataclasses for value objects (
ExtractedDoc,Chunk,SearchResult). - Custom exceptions inherit from a project-specific base (
BrainErrorif needed); neverraise Exception(...). - Every module has a one-line docstring at the top describing its purpose.
- Use parameterized SQL (
%splaceholders + tuple). NEVER concatenate user input into SQL strings. - Every external HTTP/DB client MUST have explicit timeouts. The Voyage client gets an explicit
timeout; it does not retry (voyageai.Client'smax_retriesdefaults to0andembeddings.pyleaves it there — corrected 2026-10-16, this line used to say retries were handled). Postgres connections setconnect_timeout. - No bare
except:— always catch specific exceptions (psycopg.OperationalError,voyageai.error.RateLimitError, etc.).
File-size ceiling — 800 lines
The global rules set an 800-line ceiling per file (200–400 typical). It binds new modules and new growth. It is not a mandate to split the files that are already over it.
- A new module lands under 800. No exceptions.
- An existing file under 800 stays under it. Extract rather than grow past it
(
brain/backup/db_names.py,brain/format_search.pyandbrain/snippet_context.pyall exist for that reason). - A file already over may grow only for a written reason, recorded in both places: (1) an inline comment at the point of growth, for the reviewer reading the diff; (2) a one-line pointer in the module docstring, for the reader who opens the file. "It was already over" is not a reason. A change that leaves the file the same size or shrinks it owes no growth record.
- Every file over 800 has a row in the table in
docs/ceiling-table.md. A file that crosses 800 gets its row in the same change. A file that drops back under loses its row and gets a "deliberately absent" note below the table. - Rows carry no live line counts. The Lines cell holds the command
(
wc -l src/brain/<path>); the Why cell holds a trail of SHA-bound counts and the recorded reason. When you touch a file in the table, first promote its trailing descriptive hop to a real SHA and count, then add a descriptive hop for your own change. Read the trail rules indocs/ceiling-table.mdbefore editing a row. scripts/check_ceiling_table.pyparses that table and runs in CI'slintjob and inbin/brain-ci. It fails when the row set and the tree disagree. It does not check what a row says; that is still a review.
Re-derive the over-800 set with
find src/brain -name '*.py' | xargs wc -l | sort -rn. Never count it from memory.
The F6 draft/sensitivity residue audit
Every documents read that filters draft is a read of the browseable corpus, and
almost every one is a place a confidential row could travel. Judge each
statement, not each file: it must either carry a sensitivity predicate or
carry a written reason it does not. An ungated statement with no recorded reason is
the defect. Re-derive the set, never inherit it:
grep -rn "draft = FALSE\|draft=FALSE\|draft IS FALSE\|NOT d.draft" src/brain/.
The full audit and the known, judged residue are in
docs/audits/f6-residue-audit.md.
Linting — Ruff + mypy
Run after every change: ruff check (lint) or ruff check --fix (auto-fix), then mypy src/. Config in pyproject.toml under [tool.ruff] and [tool.mypy].
Key rules: Line length 100, target Python 3.11, from __future__ import annotations not needed (3.11+ has native PEP 604 union syntax). Sort imports with ruff check --select I --fix.
Eval gate (CI)
- The
evalpytest marker is off in the defaultpytestrun (addopts = "... -m 'not eval'"). The harness needs a live Postgres and Ollama. .github/workflows/eval.ymlchecks harness health only. The retrieval-quality regression gate is a local pre-merge check. On 2026-10-12 the user decided there will be no hermetic CI gate. The gate step self-arms only when bothtests/eval/baselines/ci.jsonand the gitignoredtests/eval/golden_corpus.yamlexist.brain eval --baseline ci --diff --fail-belowexits3when any mean metric (nDCG@5, MRR, Recall@20) regresses by more than1e-4. It exits1on an error or when a query the baseline also has is degraded (a transiently failed embed), and2on bad flags. A spurious exit 3 almost always means the document set moved, not that search got worse: checkbrain statusfirst.ci.jsonis keyed to one machine's document set. Whoever makes a change that invalidates it re-records it (brain eval --record-baseline ci) in the same PR and names the trigger in the commit message. Triggers: an ingest or deletion that changes the document set, a re-embed or embedder swap, a change to aconfig_signaturekey, a ranking-code change, an edit togolden_corpus.yaml, or recency-window drift (since_daysqueries only).- A new committed baseline is allowlisted by name in
tests/eval/baselines/.gitignore. Never blanket-allow.
Full detail (workflow steps, the three ways ci.json bites, recency pinning, the
re-judging history, the degraded-run rules) is in docs/eval-gate.md and
tests/eval/baselines/README.md.
Migration Safety
- Migrations are raw SQL files in
src/brain/migrations/(shipped inside thebrainpackage so wheel/pip installs bundle them), applied in name order bybrain initviadb.migrations_dir(). - Never reference Python code in migrations — they are pure SQL, frozen in time.
- Every migration must be idempotent or applied to a fresh schema. During development,
docker compose down && rm -rf data/postgres && docker compose up -d && brain initresets cleanly. (docker compose down -valone won't wipe the data — Postgres is mounted from a host bind-mount at./data/postgres, not a Docker-managed volume.) - Schema changes = new numbered migration file. Never edit
001_init.sqlonce shipped.
Security Standards
- UUID primary keys everywhere.
- Parameterized SQL queries only.
- Never hardcode secrets —
VOYAGE_API_KEYandDATABASE_URLcome from.env(gitignored). Never commit.env. - Never log full document content at INFO level — it can contain sensitive transcripts/emails. Log titles + IDs only.
Workflow
Plan → Approve → Implement → Verify
- Plan — List affected files, modules, tests, risks.
- Approve — Present plan to user. Do NOT write code until approved.
- Implement — File by file. Use teammates for large tasks (per Team Mode Override above).
- Verify — Run
ruff check && mypy src/ && pytest. Then exercise the CLI end-to-end (brain doctor,brain status, a samplebrain search).
Teammate Usage
Use teammates for: parallel test creation, codebase exploration, tasks consuming >30% of context window, implementation when plan is approved. See "Team Mode Override" — always Team mode, never standalone subagents.
Project Overview
Local personal knowledge base ("second brain") with hybrid search, designed to be queried by Claude from any conversation. Stores career documents, interview prep, Krisp call transcripts, Slack threads, and selected Gmail in Postgres + pgvector. Searches use Reciprocal Rank Fusion of FTS rank + vector cosine similarity.
Embeddings: Pluggable via the BRAIN_EMBEDDER env var. Default arctic =
Snowflake Arctic Embed v2 (1024-dim, local Ollama, free, Apache 2.0).
Alternatives: voyage (Voyage AI voyage-3.5 SaaS, paid, 1024-dim) and
qwen3 (Qwen3-Embedding-8B, local Ollama, free, China-origin, 4096-dim — no
HNSW index because pgvector caps at 2000 dims for vector).
Full design in docs/specs/2026-04-24-second-brain-design.md. Implementation plan in docs/plans/2026-04-24-second-brain.md. Pluggable-embedder retrofit plan in docs/plans/2026-04-28-local-embeddings-qwen3-8b.md.
Tech Stack
- Language: Python 3.11+
- CLI framework: Typer
- Database: PostgreSQL 16 + pgvector (Docker, port 55432)
- Embeddings: Pluggable backends behind a single
EmbedderProtocol. Defaultarctic(Snowflake Arctic Embed v2 over local Ollama, 1024-dim). Alternates:voyage(Voyage AI SaaS, 1024-dim) andqwen3(Qwen3-Embedding-8B over local Ollama, 4096-dim). Selected at setup time viaBRAIN_EMBEDDER. - PDF/DOCX: pypdf, pdfplumber, python-docx
- Markdown: markdown-it-py
- Tokenization: tiktoken (offline
cl100k_base, used by every backend for chunker budgeting) - Output: Rich (colored tables, JSON)
- Graph retrieval (experimental): Apache AGE (openCypher graph in-Postgres) +
networkx (Louvain community detection). Entity-centric GraphRAG alongside the
vector/FTS search. Needs the custom AGE Postgres image; default-OFF via
BRAIN_GRAPH_ENABLED. - Tests: pytest, real Postgres test DB, fake embedder fixture
- Lint/Type: ruff, mypy
Build & Run Commands
# Setup (default arctic backend — local Ollama, free, no API key)
brew install ollama # macOS; on Linux follow ollama.com/install
brew services start ollama
ollama pull snowflake-arctic-embed2
cp .env.example .env # BRAIN_EMBEDDER=arctic by default
python3.11 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
docker compose up -d # Postgres + pgvector on port 55432
brain init # applies migrations + aligns chunks.embedding dim
brain reembed # backfill any NULL embeddings + finalize column
brain doctor # health check (env, Postgres, embedder, gws CLI)
# Daily use
brain ingest <file> # ingest a single file
brain ingest-dir <dir> # recursive ingest
brain search "..." # hybrid search
brain show <id-prefix> # full document
brain reembed # backfill missing embeddings; idempotent
# Switching backends (destructive — requires data wipe + re-ingest)
docker compose down && rm -rf data/postgres
# edit .env (BRAIN_EMBEDDER=qwen3 / voyage / arctic)
docker compose up -d && brain init && brain ingest-dir <…> && brain reembed
# GraphRAG (experimental — entity graph alongside vector/FTS search)
# Requires the custom Apache AGE Postgres image
# (second-brain-age:pg16-v1.5.0-rc0-pgv0.8.6), NOT the stock pgvector prod
# image. `pip install -e ".[dev]"` pulls the networkx dep. Set
# BRAIN_GRAPH_ENABLED=true in .env to enable the ingest-time graph sync.
brain init # also bootstraps AGE + applies graph migrations when the image ships AGE
brain graphrag build --backfill # backfill the people graph from existing docs
brain graphrag communities build # detect + summarize communities (needed for --mode global)
brain graphrag search "..." # graph retrieval (modes: auto|local|themes|global|fuse)
brain graphrag themes --person "Jane Doe" # "themes in my conversations with X"
brain graphrag search "..." --mode fuse # RRF of the graph leg + vector/FTS hybrid leg
brain graphrag communities list # admin view of materialized communities
brain doctor # also reports AGE + graph health (soft check)
# Usage skill (Claude Code): skills/brain-graph/SKILL.md (brain-graph) — graph
# retrieval for themes / patterns / connections across interactions (themes
# with a person, what connects A and B, recurring themes), alongside plain
# hybrid search.
# Testing
pytest # full suite
pytest --cov=brain --cov-report=term # with coverage
pytest tests/test_chunker.py -v # single file
# Linting
ruff check # lint
ruff check --fix # auto-fix
mypy src/ # type checkArchitecture
Layout
src/brain/
cli.py — Typer app, all commands (init / doctor / status /
ingest* / search / show / list / tag / edit / rm / reembed)
config.py — env loading; selects BRAIN_EMBEDDER ∈ {arctic, voyage, qwen3}
db.py — psycopg connection + migration runner;
ensure_embedding_column() reconciles chunks.embedding
dim against the active embedder
embeddings.py — `_OllamaEmbedderBase` shared transport; concrete
`ArcticEmbedder`, `Qwen3Embedder`, `VoyageEmbedder`;
`make_embedder(cfg)` factory dispatched on cfg.embedder
errors.py — BrainError base + id-prefix exceptions, OllamaEmbedError
queries.py — read helpers (resolve_document_prefix, fetch_document,
list_documents, summary_counts) + reembed helpers
(iter_chunks_missing_embedding, finalize_embedding_index,
embedding_column_state)
search.py — hybrid FTS + vector via RRF
format.py — human + JSON output
edit_session.py — JSON-header + body editor flow used by `brain edit`
mcp_server.py — stdio MCP server (brain-mcp entry point)
chat.py — shared public chat_json() Ollama call (brief / ask / audio)
ollama_budget.py — leaf: BRAIN_OLLAMA_NUM_CTX default + the per-call token
budgets validated against it at config load; the
BRAIN_OLLAMA_EMBED_NUM_CTX default + floor (chunker
ceiling the chunker binds); the shared overflow regex
activity.py — shared time-windowed activity reader (brief + weekly review)
resurface.py — `brain resurface` spaced-repetition scoring core
brief.py — `brain brief` daily-digest assembly + next-step suggestions
review/ — `brain review` package: scans (contradiction/staleness),
weekly synthesis, queue queries, emit/render
timeline.py — `brain timeline` temporal bucketing over graph entities
connect.py — `brain connect` auto-link scoring core
cli_connect.py — `brain connect` CLI sub-app (list/refresh/accept/reject/stats)
ask.py — `brain ask` agentic plan/reflect/synthesize loop
audio.py — `brain audio` two-host script generation + TTS Protocol
gaps.py — `brain gaps` search-failure clustering + detector
eval/ — retrieval + answer eval harness; answer_eval.py backs
`brain eval --answer`
ingest/
__init__.py — Embedder Protocol (declares `dim`);
ingest_document() / update_document() pipelines
dispatch.py — extractor registry: extension → ExtractorSpec (RM-07)
chunker.py — paragraph-aware chunking (uses embedder.count_tokens)
text.py / markdown.py / pdf.py / docx.py — file extractors
gmail.py — shells out to gws CLI
stdin.py — generic stdin ingester (Krisp, Slack)
src/brain/migrations/ — numbered SQL files (packaged inside the brain package; applied by brain init)
001_init.sql — base schema (chunks.embedding starts as vector(1024))
002_qwen3_embedding.sql — drops + re-adds chunks.embedding as vector(4096), nullable
(ensure_embedding_column then resizes for the active backend)
scripts/embedding_smoke.py — retrieval sanity check for a corpus +
seeded queries (used during backend swaps)
tests/ — real-DB fixture, fake embedder, one test file per module
docs/specs/ — design specs
docs/plans/ — implementation plansKey Patterns
- Idempotent ingest:
documents.content_hashis UNIQUE ondocuments. Re-ingesting the same file is a no-op unless--force. - Source dedup:
sources(kind, external_id)is UNIQUE. Re-ingesting the same Krisp/Gmail message updates the existing row instead of duplicating. - Hybrid search: Reciprocal Rank Fusion (k=60) combines FTS rank and vector cosine similarity. Ranks chunks; groups by document; returns top N docs with best matching chunk as snippet.
- Claude-orchestrated ingestion: Krisp and Slack don't have CLIs. Claude calls the MCP, then pipes content into
brain ingest-stdin --source krisp/slack .... - Pluggable embedders behind one Protocol. All three backends conform to
brain.ingest.Embedder(dim: int,embed(texts, *, input_type),count_tokens). The factorymake_embedder(cfg)is the only place that knows about concrete backends; ingest, search, and reembed depend only on the Protocol. - Dim-aware finalize.
queries.finalize_embedding_indexappliesNOT NULLonchunks.embeddingfor every backend, then conditionally creates an HNSW cosine index whenembedder.dim ≤ 2000(arctic, voyage). For Qwen3 (4096) the index is skipped — pgvector 0.8.x caps HNSW/IVFFlat at 2000 forvector; sequential cosine scan is acceptable at personal-corpus scale. - Backend-aware
brain init.initruns migrations, thendb.ensure_embedding_columnreconcileschunks.embedding's declared dim againstembedder.dim— drop + re-add on a fresh DB, error with a destructive-reset hint if chunks already exist at a different dim. - Switching backends is destructive. Embeddings cannot be re-projected across models; switching requires
docker compose down && rm -rf data/postgres && brain init && brain ingest-dir … && brain reembed. Postgres data is a host bind-mount (./data/postgres), not a Docker volume —docker compose down -valone is not sufficient.
Lessons Learned
These are universal mistakes — never repeat them.
- Never guess fields/paths — Read the actual source file before referencing any field, function, or import path.
- Never declare "done" without running it — Run the CLI command end-to-end before claiming a task complete. Tests passing ≠ feature working.
- Never copy-paste code — Extract shared patterns into reusable functions. If you write something twice, refactor on the third write.
- Test mocks must match signatures — After changing a function's signature, grep ALL call sites and update them. Run
mypy src/to catch drift. - Four Phase Tests — Every test follows setup → exercise → verify → teardown. Clear separation between phases. No mystery guests — make test data explicit, don't rely on invisible factory defaults.
- No test failures are pre-existing — Every failure is a regression until proven otherwise. Investigate immediately, never dismiss as "pre-existing" or "flaky" without evidence.
- The Scout Law — leave the code better than you found it — Before completing any task, ALL tests in the suite must pass — not just the ones related to your changes. If you encounter broken tests from other areas, fix them.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

