* Wave A: schema + receipts foundation for v0.42 extract operator surfaces
Foundation layer for the pack-driven extractables + receipt-as-brain-memory
+ operator-discoverability cathedral. Five atomic pieces ship together
because their schema + helpers + module dependencies are tight-coupled:
A1. Widen pack manifest's `extractable` from `boolean` to
`boolean | ExtractableSpec`. ExtractableSpec carries prompt_template,
fixture_corpus, eval_dimensions, benchmark_min_recall, and reserves
verifier_path for v0.43+ pack-shipped verifier code (REFUSE at
runtime in v0.42 per plan D-EXTRACT-37). Back-compat: every pre-v0.42
pack with `extractable: true` continues parsing unchanged. Three new
helpers: extractableSpecsFromPack(), getExtractableSpec(),
refuseVerifierPathInV042().
A2. New page type `extract_receipt` in ALL_PAGE_TYPES. Source-boost map
adds `extracts/` prefix at factor 0.3 — receipts surface in search
when extraction-relevant but never dominate user content (D-EXTRACT-42).
A3. New module src/core/extract/receipt-writer.ts (~190 LOC) exporting
writeReceipt(engine, input). Canonical slug shape
extracts/{date}/{kind}/{source_id}/{run_id_short}/round-{N} per
D-EXTRACT-17. Frontmatter belt+suspenders per D-EXTRACT-19: BOTH
type:extract_receipt AND dream_generated:true stamped on every
receipt, regardless of caller, so the eligibility predicate's
anti-loop guards reject the receipt page from any future extraction
sweep (single-flag bypass requires breaking two unrelated checks).
Idempotent on resume — same run_id+round overwrites cleanly.
A4. Migration v104 creates extract_rollup_7d table (per-day rollup of
extract events keyed on kind+source_id+day). Audit JSONL stays the
SOURCE OF TRUTH per F-OUT-19; this table is a best-effort cache for
doctor's <100ms read budget. Per-day rows mean the 7-day window
auto-evicts on every read. v100 was deliberately skipped on master
(renumbered out during a prior wave); v101/v102/v103 also taken;
v104 is the next clean slot.
A5. Doctor `extract_health` check reads extract_rollup_7d for last 7
days and emits per-kind aggregates: cost_7d_usd, eval_pass_count,
eval_fail_count, halt_count, round_completed_count, halt_rate.
3-state: OK when rollup empty (pre-v0.42 brain or fresh init), WARN
when any per-kind halt rate > 10% (top-3 named in message), WARN
when rollup_write_failures > 0 (audit JSONL is SoT but operator
deserves to know the DB cache is degraded). Pre-v104 brains stay
quiet — the missing-table error path is caught and treated as
OK so doctor doesn't warn during the upgrade window.
Tests added:
- test/extractable-spec-widening.test.ts (22 cases) — back-compat with
boolean shape, new struct parsing, verifier_path REFUSE contract.
- test/extract/receipt-writer.test.ts (12 cases) — slug shape, frontmatter
belt+suspenders, idempotent resume, body human-readability.
- test/doctor-extract-health.test.ts (8 cases) — empty rollup OK, halt
rate WARN, rollup_write_failures WARN, 7-day window inclusion at
boundary, multi-kind top-3 message ordering.
Plus the canonical bootstrap-coverage test passes with the new v104
migration cleanly applied through both engines.
Plan: ~/.claude/plans/system-instruction-you-are-working-stateless-dragonfly.md
Wave A scope. Wave B (hook receipts into existing extractors) follows.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Wave B: hook receipts + rollup row into the 5 shipped extractors
Each LLM-backed extractor surface now records its run in two places when
something actually happened:
1. An extract receipt PAGE at extracts/{date}/{kind}/{source_id}/{run_id_short}/round-{N}
(queryable via gbrain search, citable, surfaces in cross-modal
contradiction probes per the Wave A foundation). Only written when
`total_rows > 0` so no-op runs don't bloat the brain.
2. An UPSERT row in extract_rollup_7d (DB-backed best-effort cache
per F-OUT-19) so the doctor extract_health check from Wave A reads
per-kind aggregates without scanning JSONL.
New module src/core/extract/rollup-writer.ts (~120 LOC) exports
upsertExtractRollup() with PostgreSQL ON CONFLICT DO UPDATE on the
(kind, source_id, day) PK. Concurrency-safe per F-OUT-14 design.
Failure path is best-effort — bumps rollup_write_failures in the
table itself, stderr-warns once per (kind, day, error-class), and
NEVER fails the parent extraction operation. JSONL remains source
of truth.
Wired into 5 extractors:
- extract-conversation-facts (kind: facts.conversation) — both
success path AND BudgetExhausted halt path write receipt+rollup
so partial runs are still observable.
- extract_atoms cycle phase (kind: atoms)
- synthesize_concepts cycle phase (kind: concepts, source_id: default
because concepts are brain-global)
- propose_takes cycle phase (kind: takes.proposed) — scope-aware
source_id from the read scope.
- extract_facts cycle phase (kind: facts.fence) — deterministic
(no LLM cost) but still records reconcile activity so doctor sees
the cycle is alive.
Receipt frontmatter belt+suspenders (D-EXTRACT-19) reused from
Wave A: every receipt stamps BOTH `type: extract_receipt` AND
`dream_generated: true` so the eligibility predicate's anti-loop
guards reject the receipt page from any future extraction sweep.
Test surgery in test/propose-takes.test.ts — one existing assertion
tightened from "no INSERTs" to "no INSERT INTO take_proposals" so
the new rollup UPSERT doesn't falsely fail the cache-hit case test.
Run regression: 85/85 tests pass across extract-conversation-facts,
extract-atoms-synthesize-concepts, extract-facts-phase, propose-takes.
Plan: ~/.claude/plans/system-instruction-you-are-working-stateless-dragonfly.md
Wave B scope. Wave C (pack-author scaffolding + benchmark) follows.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Wave C+D: pack-author scaffolding + operator surfaces for v0.42 extract
Wave C: pack-author authoring loop
- scaffold-extractable mutation primitive declares a kind as extractable
on a pack manifest in one verb (wires through updateTypeOnPack from
the v0.41 mutate library); generates 5 placeholder fixtures + a
pack-supplied prompt template stub
- schema CLI wires gbrain schema scaffold-extractable <type> --pack <pack>
- extract benchmark CLI loads a pack's fixture corpus through strict
D-EXTRACT-21 path validation (rejects absolute paths, .. traversal,
null bytes, symlinks resolving outside pack root); v0.42 ships as a
stub reporter (LLM dispatch deferred to Wave E)
Wave D: operator surfaces
- extract status CLI reads extract_rollup_7d for the last 7 days,
sorts by (halt_rate desc, cost desc); kubectl-style right-aligned
table, top-5 + "more rows" hint by default, --verbose shows all;
stable schema_version: 1 JSON envelope for monitoring pipelines
- extract --explain <kind> CLI prints the active pack's resolution
chain: declaration source (pack-declared vs built-in cycle phase),
prompt_template + fixture_corpus paths with existence checks,
eval_dimensions, benchmark_min_recall, and the last 7d rollup
- extract.ts gains a lifecycle-grouped help text (Extraction /
Inspection / Status) per the original D3 plan goal
Tests:
- test/schema-pack/scaffold-extractable.test.ts (15 cases) including
explicit privacy-rule assertions guarding against real-name leakage
- test/extract/benchmark.test.ts (17 cases) covering path validation
rejections + JSONL fixture parsing
- test/extract/status.test.ts (15 cases) over pure aggregation +
formatting
Housekeeping:
- test/extract/receipt-writer.test.ts refactored to the canonical
PGLite block (beforeAll/afterAll/resetPgliteState in beforeEach)
per CLAUDE.md test-isolation R3+R4; runtime drops from ~30s of
99-migration replay per test to <6s for all 12 cases together
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* v0.42.0.0: extract operator surfaces + pack-driven extractables
Bump VERSION + package.json to 0.42.0.0. CHANGELOG entry covers the
three-wave shipped scope (receipts + rollup + doctor check; receipts
hooked into all 5 shipped extractors; pack-author scaffolding +
benchmark stub-reporter; status + --explain dashboards + lifecycle
help). CLAUDE.md Key Files gains a v0.42 cluster annotation. llms.txt
regenerated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* v0.41.23.0: re-tag from 0.42.0.0 (patch-channel slot, no scope change)
VERSION + package.json + CHANGELOG header + CLAUDE.md cluster annotation
all moved from 0.42.0.0 to 0.41.23.0. Body text updated in-place: every
"v0.42" / "v0.43+" reference inside this entry's release notes now reads
"v0.41.23" or "follow-up release" as appropriate.
Same scope shipping — the three-wave extract operator surface stays
intact. Just lands in the patch-channel queue (.20/.21/.23 free; .22 is
PR #1542's type-unification cathedral) instead of the minor-channel bump.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: add extract_receipt to gbrain-base.yaml page_types (CI parity gate)
CI shard 5 caught the drift: test/regressions/gbrain-base-equivalence.test.ts
asserts every ALL_PAGE_TYPES seed has a matching page_type entry in the
gbrain-base.yaml pack. Wave A added `extract_receipt` to ALL_PAGE_TYPES
but didn't seed it in the base pack manifest.
Adds the entry under the `annotation` primitive with `extracts/` path
prefix (matches the source-boost demote site) and `extractable: false`
(receipts are written by the framework, never extracted from). Comment
documents the belt+suspenders D-EXTRACT-19 invariant so future readers
understand why receipts carry both `dream_generated: true` AND
`type: extract_receipt`.
Closes the CI gate without changing runtime behavior — the pack-aware
read paths already had the prefix demote wired in src/core/search/source-boost.ts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: bump gbrain-base page-type count 24→25 in schema-cli test
CI shard 4 caught the second drift from the same root cause as the
prior parity-gate fix: v0.41.23's `extract_receipt` addition bumped
gbrain-base.yaml from 24 to 25 page types. The schema-cli smoke test
was pinned at 24 (the count after v0.41.11.0 added `conversation` +
`atom`); update to 25 and note v0.41.23's contribution alongside the
prior version stamp.
Verified hermetic: running test/schema-cli.test.ts with a clean
GBRAIN_HOME tempdir produces 12/12 pass (the local-machine 'schema
active' fail is from a real ~/.gbrain pinning gbrain-base-v2; not a
shipped-code issue, doesn't repro on CI).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(test): pack-locator stub leak between shard 6 test files
CI shard 6 caught three flaky failures in test/onboard-pack-upgrade-checks.test.ts:
- checkPackUpgradeAvailable > fires on gbrain-base brain with gbrain-base-v2
- checkPackUpgradeAvailable > manual_only routing via render.ts allowlist (D17)
- checkTypeProliferation > warns when distinct types exceed declared+5
Root cause: test/schema-pack-sync.test.ts calls
`__setPackLocatorForTests(...)` to stub the disk-loader, but doesn't
restore in afterAll. Bun's CI shard 6 loads multiple test files into
one process; when sync.test.ts runs before onboard-pack-upgrade-checks.test.ts,
the stubbed locator persists at module scope. `loadActivePack` for
gbrain-base / gbrain-base-v2 then returns null and:
- findPackSuccessors returns [] → status='ok' instead of 'warn' (F1+F2)
- declared falls back to 15 → fail threshold becomes 30, 32 > 30 → 'fail'
instead of 'warn' (F3)
Local single-file runs pass because the locator starts at its default.
Two-layer fix:
1. test/schema-pack-sync.test.ts afterAll calls
`_resetPackLocatorForTests()` to undo the mutation (the canonical
fix at the source).
2. test/onboard-pack-upgrade-checks.test.ts beforeEach calls the same
reset (defense-in-depth against any future test file in the shard
that forgets to restore).
Reproduced locally: running the three shard-6 schema-pack files together
fails 3 tests pre-fix and passes 30/30 post-fix. Full shard 6 sweep
(77 files, 1232 tests) now green; bun run verify still 28/28.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(test): pglite-engine — dim-agnostic chunk-embedding test data
CI shard 6 caught two flaky failures in test/pglite-engine.test.ts:
- PGLiteEngine: Chunks > getChunksWithEmbeddings returns embedding data
- PGLiteEngine: stale chunk pagination > countStaleChunks counts chunks
with NULL embedding only
Both failed with `expected 1280 dimensions, not 1536` at the upsert site.
Root cause: pglite-engine.ts:287 initSchema() reads embedding dim from
gw.getEmbeddingDimensions() if the gateway is configured (potentially
left in that state by another shard-6 test file in the same bun process),
falling back to DEFAULT_EMBEDDING_DIMENSIONS otherwise — which is 1280
since v0.36+ when the ZE default landed (zeroentropyai:zembed-1).
Pre-v0.36 defaults were OpenAI's 1536; my test data was pinned to that
stale literal.
The two outcomes that pass:
- gateway happens to be configured for 1536-dim (e.g. master shard 6
run 26515999465 — these tests passed at 20ms + 24ms with no
"dimensions" error)
- gateway happens to be configured for 1280-dim AND test data is 1280
The outcome that fails:
- gateway configured for 1280-dim AND test data hardcoded to 1536
Fix: capture the actual column width after initSchema (probe
pg_attribute.atttypmod for content_chunks.embedding) and use that
captured `CHUNK_EMBED_DIM` constant at the three Float32Array sites.
Test data now matches whatever width the column was created at,
regardless of which shard-6 file ran first.
Local repro: full shard 6 (77 files, 1232 tests, ~6min) green; this
file standalone (100 tests) green; bun run verify 28/28.
Broader pattern: 9 other test files use the same Float32Array(1536)
literal. None land in shard 6 today (so they don't flake), but the
fix shape here can be lifted into a shared helper if the bug class
surfaces elsewhere — filed as a v0.42+ follow-up rather than a
preemptive sweep, since each file's setup shape is slightly different.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GBrain
Search gives you raw pages. GBrain gives you the answer. It's the brain layer your AI agent has been missing — the only one that does synthesis, graph traversal, and gap analysis in one box.
I'm Garry Tan, President and CEO of Y Combinator. I built GBrain to run my own AI agents. It's the production brain behind my OpenClaw and Hermes deployments: 146,646 pages, 24,585 people, 5,339 companies, 66 cron jobs running autonomously. My agent ingests meetings, emails, tweets, voice calls, and original ideas while I sleep. It enriches every person and company it encounters. It fixes its own citations and consolidates memory overnight. I wake up smarter than when I went to bed — and so will you.
And now it works as a company brain too. Each person on the team gets their own slice of the brain, scoped by login. When you query, you only see what you're allowed to see — never another person's notes, never another team's data. We fuzz-tested this across every way you can read the brain (search, list, lookup, multi-source reads) and got zero leaks. Drop GBrain in as your team's shared institutional memory — the company-brain shape YC just put on its Request for Startups. If you're building in that space, you might as well build on this. Tutorial: set up GBrain as your company brain →
Lots of personal-knowledge systems give you keyword matching and grep in a box. GBrain does that, and adds two things nobody else ships together:
- A synthesis layer that gives you the actual answer. Synthesized, well-cited prose across people, companies, deals, and ideas. Not "here are 10 chunks that mention your query"; an actual answer with citations and an explicit note on what the brain doesn't know yet. The gap analysis is the part that changes how you use the brain.
- A self-wiring knowledge graph. Every page write extracts entity refs and creates typed edges (
attended,works_at,invested_in,founded,advises) with zero LLM calls. Ask "who works at Acme AI?" or "what did Bob invest in this quarter?" and get answers vector search alone can't reach. Benchmarked: P@5 49.1%, R@5 97.9% on a 240-page Opus-generated rich-prose corpus, +31.4 points P@5 over its graph-disabled variant and over ripgrep-BM25 + vector-only RAG by a similar margin. Full BrainBench scorecards live in the sibling gbrain-evals repo.
The point of building a 100K-page brain is to use it as a strategic moat. To never lose context. To query what's in your own head without re-reading it. The brain layer is what makes the moat usable. The 24/7 dream cycle is what keeps it sharp. Both run on your hardware, your DB, your keys.
It's easier to ship a daemon that runs 24/7 to ingest, enrich, and consolidate than it is to keep an agent in chat working hard. GBrain is that daemon, generalized. Install in 30 minutes. Your agent does the work. As my personal agent gets smarter, so does yours.
~30 minutes to a fully working brain. Database ready in 2 seconds (PGLite, no server). You just answer questions about API keys.
LLMs: fetch
llms.txtfor the documentation map, orllms-full.txtfor the same map with core docs inlined in one fetch. Agents: start withAGENTS.md(orCLAUDE.mdif you're Claude Code).
What this looks like
Say you have a meeting with Alice tomorrow. You want to walk in remembering what she works on, when you last talked, and what's still open between you. Here's what you'd type, and what you'd get back.
You ask:
"What do I need to know before my meeting with Alice tomorrow?"
Most personal-knowledge tools give you back a list of pages. Something like:
1. people/alice — Alice runs engineering at Acme...
2. meetings/2026-03-15-alice-q1 — Q1 product review with Alice...
3. meetings/2026-01-08-acme-kickoff — Kickoff meeting with Acme team...
4. customers/acme — Acme is a series-B fintech we work with...
5. notes/2026-04-22 — Quick chat with Alice about pricing...
Five pages you now have to open and read yourself to actually prepare. The tool found the right material, but it didn't do the work.
GBrain gives you back the answer, with sources:
Alice runs engineering at Acme (a series-B fintech). You last spoke
on April 22 in a quick pricing chat. Three things are still open
from that conversation:
1. She owes you the security review for the new tier
(deadline was May 1; no update since).
2. You committed to pricing for a 500-seat tier
(you sent it April 25; no response yet).
3. She mentioned they're hiring a CISO; you said you'd intro
someone from your network.
Heads up: nothing's been added to the brain about Alice or Acme
since April 22, six weeks ago. She may have replied through email
or Slack DM, channels the brain doesn't see. Worth asking her to
catch up before assuming any of this is still current.
Every claim has a source page behind it. The "heads up" at the end tells you what the brain doesn't know yet, so you can ask Alice about it directly instead of being surprised. The brain just did your meeting prep.
This is the difference between a search engine and a brain. Search finds the pages. The brain reads them for you and writes the answer.
Install
GBrain is designed to be installed and operated by an AI agent. The fastest path is to have your agent do it for you. The CLI and MCP paths below are for people who want to wire it up themselves.
Have your agent install it (recommended)
If you don't already have an AI agent platform running, start with one of these. Both are designed to read GBrain's install protocol and execute it:
- OpenClaw — deploy AlphaClaw on Render (one click, 8GB+ RAM)
- Hermes — deploy on Railway (one click)
Then paste this into your agent:
Retrieve and follow the instructions at:
https://raw.githubusercontent.com/garrytan/gbrain/master/INSTALL_FOR_AGENTS.md
The agent installs GBrain, creates the brain, asks for your API keys, loads 43 skills, configures the dream cycle, and verifies the install end-to-end. ~30 minutes. You answer questions, it does the work.
Never set up an AI agent platform before? The personal-brain tutorial walks the whole path end-to-end — picking OpenClaw vs Hermes, deploying it, pointing it at INSTALL_FOR_AGENTS.md, getting the API keys, and verifying the first query. Start there if any of the above is new.
Install it into your existing agent
Already running Codex, Claude Code, Cursor, or another coding agent? Paste the same instruction in:
Retrieve and follow the instructions at:
https://raw.githubusercontent.com/garrytan/gbrain/master/INSTALL_FOR_AGENTS.md
This works in any agent that can read files over HTTPS and execute shell commands. Tested with Codex, Claude Code, Claude Cowork, Cursor, and AlphaClaw.
CLI standalone (no agent)
bun install -g github:garrytan/gbrain
gbrain init --pglite # 2 seconds; no server, no Docker
gbrain doctor # verify health
gbrain import ~/notes/ # index your markdown
gbrain query "what themes show up across my notes?"
Postgres-at-scale, Supabase, and thin-client setup paths live in docs/INSTALL.md.
Connect GBrain to your AI client (MCP)
GBrain exposes 30+ tools over MCP (stdio and HTTP). The specific snippet depends on which client you use:
- Claude Code — one command:
claude mcp add gbrain -- gbrain serve. Zero server, zero tunnel. - Cursor / Windsurf / any stdio MCP client — same shape, add
{"command": "gbrain", "args": ["serve"]}to your MCP config. - Claude Desktop (Cowork) — Settings → Integrations → add the URL of your HTTP server. Remote only; the local
claude_desktop_config.jsondoes not work for remote servers. - Claude Cowork (team plan) — org Owner adds the connector under Organization Settings → Connectors.
- Perplexity Computer — Settings → Connectors → add the URL + bearer token. Pro subscription required.
- ChatGPT — uses OAuth 2.1 with PKCE (the hard requirement). Register a
chatgptclient from the admin dashboard with grant typeauthorization_code.
For the HTTP server itself:
gbrain serve # stdio MCP (local subprocess; for Claude Code, Cursor, Windsurf)
gbrain serve --http # HTTP MCP with OAuth 2.1 + admin dashboard at /admin
# (required for Claude Desktop, Cowork, Perplexity, ChatGPT)
The HTTP server includes DCR-style client registration, scope-gated access (read / write / admin), and rate limiting. Deployment guides (ngrok, Railway, Fly.io) live under docs/mcp/.
Two ways to query your brain
Raw retrieval (what most personal-knowledge tools ship) and a synthesis layer that gives you an actual answer. They serve different jobs.
# raw retrieval: top pages by hybrid score, fast, no LLM cost
gbrain search "who's working on AI agents at portfolio companies?"
# brain layer: synthesized answer with citations and gap analysis
gbrain think "who's working on AI agents at portfolio companies?"
gbrain search returns the top retrieved pages, ranked by hybrid scoring (vector + keyword + RRF + source-tier boost + reranker). Use it when you want raw material to skim: agent context windows, citation lookups, finding a specific quote.
gbrain think runs the same retrieval, then composes a synthesized answer across the results with explicit citations to the source pages AND an honest note on what the brain doesn't know yet. The gap analysis is the differentiator: the answer tells you when a page is stale, when a claim is uncited, when two pages contradict each other, when there's a hole you should fill.
Why it compounds. Pair the brain layer with find_trajectory and you get answers like "how have the company's metrics changed AND what does the team look like right now AND what did they promise / share AND when did we last meet AND what's the value-add I can offer here": well-scored, well-cited, in one shot. That's the strategic moat. That's why building a 100K-page brain is worth the effort.
gbrain agent run "..." exposes the same surface to a sub-agent through the Minions queue, with crash-safe two-phase persistence. Same answers, durable.
How to get data in
One command, local or hosted, synchronous receipt:
gbrain capture "the thought I want to remember"
gbrain capture --file ./notes/today.md
echo "from a pipe" | gbrain capture --stdin
SLUG=$(gbrain capture "..." --quiet)
The page lands in the database and on disk in one move. Default slug inbox/YYYY-MM-DD-<hash8> so captures cluster in a predictable triage location. On thin-client installs the verb routes through MCP to the server: same command, same UX.
For webhook ingestion (Zapier / IFTTT / Apple Shortcuts):
curl -X POST https://your-brain/ingest \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: text/markdown" \
-d "# a thought from a Shortcut"
For mobile capture, the inbox folder source picks up anything dropped into
~/.gbrain/inbox/ from iOS Shortcuts / AirDrop / Drafts / Finder.
Third-party skillpacks can ship custom ingestion sources (Granola, Linear,
voice, OCR) against the versioned IngestionSource contract at
gbrain/ingestion. See docs/skillpack-anatomy.md.
Your brain's shape (schema packs)
Most personal-knowledge tools force one fixed layout: their idea of "notes" + "people" + "tags." Drop a Notion export or your own years-old Obsidian vault on top, and the agent doesn't know what a Projects/ folder means or whether Reading/ is people or sources.
gbrain doesn't have a fixed layout. It ships with bundled schema packs and lets you author your own when none fit:
gbrain-base-v2(default as of v0.41.22) — 15-type DRY/MECE canonical taxonomy (14 canonical +notecatch-all):person,company,media,tweet,social-digest,analysis,atom,concept,source,deal,email,slack,writing,project,note. Subtypes/format/origin pushed to frontmatter. The taxonomy that responds to issue #1479.gbrain-base(legacy, v0.41 and earlier brains) — the original 24-type layout. Stays bundled for back-compat; brains on it can upgrade viagbrain onboard --check --explain→gbrain jobs submit unify-types --allow-protected --params '{"target_pack":"gbrain-base-v2"}'.gbrain-recommended— extendsgbrain-basewith the 13 additional directories fromdocs/GBRAIN_RECOMMENDED_SCHEMA.md(source, place, trip, conversation, personal, civic, project, etc.). Activate withgbrain schema use gbrain-recommended.- Your own pack —
gbrain schema detectclusters your actual filesystem into proposed types,gbrain schema suggestruns an LLM pass over them, andgbrain schema review-candidates --applypromotes the ones you like. Three commands and the brain knows your shape. Authoring a successor pack (declaresmigration_from:so existing brains can opt in): seedocs/architecture/pack-upgrade-mechanism.md.
gbrain schema active # which pack is running, which tier set it
gbrain schema list # bundled + installed packs
gbrain schema detect # propose types matching your filesystem
gbrain schema suggest # LLM-refined proposals on top of detect
gbrain schema review-candidates # human gate: promote / rename / ignore
gbrain schema use my-pack # activate
The active pack threads through every read + write path: parseMarkdown infers page type from the pack's path prefixes; whoknows scopes expert routing to types declared expert_routing: true; extract_facts runs only on extractable: true types; the search cache folds the pack name + version into its key so cross-pack contamination is structurally impossible. Switch packs and the brain re-interprets itself; switch back and nothing's lost.
Seven-tier resolution chain (per-call flag → env var → per-source DB key → brain-wide DB key → gbrain.yml → ~/.gbrain/config.json → gbrain-base default). Full reference + authoring guide: docs/architecture/schema-packs.md.
Tutorials
Step-by-step walkthroughs for getting the most out of GBrain. Each one takes you from zero to a working outcome, with concrete commands and real numbers.
- Set up your personal AI agent + brain from zero — the canonical full-stack install. Two GitHub repos, a Telegram bot, AlphaClaw on Render, OpenClaw + GBrain + Supabase. End-to-end in about 2 hours.
- Set up GBrain as your company brain — federated, multi-user, OAuth-scoped institutional memory for a 10-50 person team. About 90 minutes end-to-end.
More walkthroughs in progress: connecting an existing agent (Claude Code, Cursor, OpenClaw, Hermes) to a GBrain memory layer; setting up GBrain for VC dealflow with founder scorecards and meeting prep; migrating an existing Notion or Obsidian vault; indexing a codebase as a queryable code brain. Full tutorial index: docs/tutorials/.
Want to see a tutorial that isn't here yet? Open an issue describing the workflow you want documented.
What it does (the loop)
signal → search → respond → write → auto-link → sync
(every (brain-first (informed (page + (typed edges (cron
message) retrieval) by context) timeline) + backlinks) keeps fresh)
- Signal detector runs on every message your agent receives. Captures ideas, entity mentions, time-sensitive todos, names, links.
- Brain-first lookup before any external API call. The cheapest, fastest, most personal information source you have.
- Auto-link fires on every page write. No LLM calls; pure pattern matching on
[[wiki/people/bob]]style references. New entity → new page stub → graph grows. - Cron-driven enrichment runs while you sleep: dedup people pages, fix citations, score salience, find contradictions, prep tomorrow's tasks.
The whole loop is described in docs/architecture/topologies.md with diagrams.
Capabilities
Hybrid search. Vector (HNSW on pgvector) + BM25 keyword + reciprocal-rank fusion + source-tier boost + intent-aware query rewriting. Three named search modes (conservative, balanced, tokenmax) bundle the cost/quality knobs into a single config key. Live cost/recall comparisons in docs/eval/SEARCH_MODE_METHODOLOGY.md. Default: balanced with ZeroEntropy reranker on. Per-query graph signals notice when a top result is a hub for THAT query (adjacency boost), is corroborated across team brains (cross-source boost), or is being crowded out by weak chunks from a chatty session (session demote). Run gbrain search "<query>" --explain to see per-stage attribution: base score, every boost that fired, what it multiplied. gbrain doctor ships a graph_signals_coverage check; gbrain search stats shows fire counts and failure breakdowns.
Self-wiring knowledge graph. Every put_page extracts entity refs from markdown/wikilinks/typed-link syntax and writes edges with zero LLM calls. Typed edges (attended, works_at, invested_in, founded, advises, mentions, …). Multi-hop traversal via gbrain graph-query. The graph is what produces the +31.4 P@5 lift over vector-only RAG.
Job queue (Minions). BullMQ-shaped, Postgres-native job queue. Durable subagents (LLM tool loops that survive crashes via two-phase pending→done persistence), shell jobs with audit, child jobs with cascading timeouts, rate leases for outbound providers, attachments via S3/Supabase storage. Replaces "spawn subagent as fire-and-forget Promise" with something that recovers from anything.
43 curated skills. Routing lives in skills/RESOLVER.md. Covers signal capture, ingest (idea / media / meeting), enrichment, querying, brain ops, citation fixing, daily task management, cron scheduling, reports, voice, soul audit, skill creation, eval framework, and migrations. Skills are markdown files (tool-agnostic), packaged as a single skillpack the installer drops into your agent workspace.
Eval framework. gbrain eval longmemeval runs the public LongMemEval benchmark against your hybrid retrieval. gbrain eval export + gbrain eval replay capture real queries and replay them against code changes (set GBRAIN_CONTRIBUTOR_MODE=1). gbrain eval cross-modal cross-checks an output against the task using three different-provider frontier models. Full methodology in docs/eval/SEARCH_MODE_METHODOLOGY.md.
Brain consistency. gbrain eval suspected-contradictions samples retrieval pairs, layered date pre-filter, query-conditioned LLM judge, persistent cache. Surfaces conflicts between takes + facts the agent has written. Wired into the daily dream cycle.
Agent-authored schema (v0.40.7.0). Your brain has a shape — what page types exist (person, meeting, paper, case, lab-result), what they link to (attended, authored, prescribed-by), what facts get extracted automatically. The default ships with 22 universal types, but your brain's actual shape is not the default shape. Agents can now evolve that shape on your behalf via 14 gbrain schema CLI verbs + a batched MCP op (schema_apply_mutations, admin scope, NOT localOnly so remote agents reach it over HTTPS). Atomic file locks, audit log with the agent's identity, chunked UPDATE backfill in 1000-row batches that never wedge concurrent writers. The brain stops being a pile of notes and becomes something with structure. Why it matters: docs/what-schemas-unlock.md — 7 killer use cases (4000 invisible meetings, founder ops brain, research brain, legal brain, team brain, agent-as-co-curator). 5-minute walkthrough: docs/schema-author-tutorial.md. Agent skill: skills/schema-author/SKILL.md.
Integrations
Data flowing into the brain. Each integration is a recipe — markdown + setup hints — that ships in recipes/ and is discoverable via gbrain integrations list.
- Voice: Phone calls create brain pages via Twilio + OpenAI Realtime (or DIY STT+LLM+TTS). Setup recipe:
recipes/twilio-voice-brain.md. - Email + calendar: webhook handlers that route to brain signals.
docs/integrations/meeting-webhooks.md. - Embedding providers: 16 recipes covering OpenAI (default fallback), OpenRouter, Voyage, ZeroEntropy (default), Google Gemini, Azure OpenAI, MiniMax, Alibaba DashScope, Zhipu, Ollama (local), llama.cpp llama-server (local), LiteLLM proxy. Pricing matrix + decision tree in
docs/integrations/embedding-providers.md. - Rerankers: ZeroEntropy
zerank-2hosted (default intokenmaxmode) plus the v0.40.6.1llama-server-rerankerrecipe for fully-local cross-encoder rerank via llama.cpp — runs Qwen3-Reranker or self-hosted ZeroEntropy weights against the samegateway.rerank()seam. Setup walkthrough indocs/ai-providers/llama-server-reranker.md. - Credential gateway: vault-aware secret distribution.
docs/integrations/credential-gateway.md. - MCP clients: every major MCP client is supported.
docs/mcp/per-client setup.
Architecture
Two engines, one contract. PGLite (Postgres 17 via WASM, zero-config, default) for personal brains up to ~50K pages. Postgres + pgvector (Supabase or self-hosted) for shared / large / multi-machine deployments. The contract-first BrainEngine interface in src/core/engine.ts defines ~47 operations both engines implement; CLI and MCP server are generated from one source.
Brain repo is the system of record. Your knowledge lives in a regular git repo (your "brain repo") as markdown files. GBrain syncs the repo into Postgres for retrieval; deletes in git become soft-deletes in DB. You can publish public subsets, share team mounts, run thin-client setups pointing at a colleague's brain server. Topologies in docs/architecture/topologies.md.
Two organizational axes (brain ⊥ source). A brain is a database (your personal brain, a team mount you joined). A source is a repo inside that brain (wiki, gstack, an essay, a knowledge base). Routing lives in .gbrain-source dotfiles and resolves via a documented 6-tier precedence chain. Full diagrams in docs/architecture/brains-and-sources.md.
Why the graph matters. Vector search returns chunks that are semantically close. The graph returns chunks that are factually connected. Hybrid search pulls from both; auto-linking on every write keeps the graph fresh. Deep dive: docs/architecture/RETRIEVAL.md.
Troubleshooting
gbrain import fails with expected N dimensions, not M? Run gbrain doctor. It will print the exact gbrain config set ... or gbrain retrieval-upgrade command to repair the mismatch. You should not need to delete ~/.gbrain. Fresh gbrain init --pglite auto-detects your embedding provider from API keys in your environment: set OPENAI_API_KEY (or ZEROENTROPY_API_KEY / VOYAGE_API_KEY) before running init, or pass --embedding-model <provider>:<model> explicitly. With multiple keys set, init fires an interactive picker. In non-TTY contexts (CI, Docker) with no keys, init exits 1 with a paste-ready setup hint; pass --no-embedding to defer setup until runtime. See docs/integrations/embedding-providers.md for the full provider matrix and docs/operations/headless-install.md for Docker/CI sequencing.
Hourly cron sync keeps timing out on a federated brain? v0.41.13.0 ships
two flags + a recommended pattern. Switch your cron to a per-source loop
with shell timeout(1) doing the OS-level kill and gbrain self-terminating
gracefully half-a-minute earlier:
gbrain sync --break-lock --all --max-age 1800
for src in $(gbrain sources list --json | jq -r '.[].id'); do
timeout 600 gbrain sync --source "$src" --timeout 540 || true
done
When --timeout fires mid-import, gbrain sync exits 0 with status
partial and last_commit UNCHANGED — the next run re-walks the same
diff and content_hash short-circuits already-imported files. The
--max-age 1800 first command self-heals any wedged-but-alive locks
left by a hung previous run, using the v98 last_refreshed_at semantic
(NOT acquired_at) so healthy long-running holders are safe by
construction. See the v0.41.13.0 entry in CHANGELOG.md
for the honest scope notes (extract + embed phases run to completion;
30-min rollout window for --max-age post-migration v98; full-sync
triggers deferred to v0.42+).
Dream cycle silently losing wiki links on Supabase? v0.41.19.0 fixes
the bug class structurally. The engine now self-retries every bulk batch
write (addLinksBatch / addTimelineEntriesBatch / upsertChunks) on
Supavisor pooler blips, with a 12s worst-case wait that covers the full
5-10s circuit-breaker recovery window. gbrain doctor surfaces incidents
via the new batch_retry_health check (reads the last 24h of
~/.gbrain/audit/batch-retry-YYYY-Www.jsonl). To tune for an unusually
slow pooler:
# Defaults: 3 retries, base 1s, max 10s, decorrelated jitter.
# Override per operator without a release:
export GBRAIN_BULK_MAX_RETRIES=5 # int >= 0; 0 disables retries
export GBRAIN_BULK_RETRY_BASE_MS=2000 # int > 0
export GBRAIN_BULK_RETRY_MAX_MS=15000 # int >= base
Bad values surface at gbrain doctor startup with a paste-ready fix
(not at first-retry mid-cycle). PGLite-only installs pay zero cost — the
retry wrap is engine-level, but PGLite has no pooler so retries never
fire in practice.
gbrain brainstorm returning judge_failed: true with 0 scored
ideas? v0.41.21.0 closes the two bugs that caused it. The judge
hard-coded a 4K-token output cap; for any run past ~40 ideas the call
truncated mid-JSON and the parser threw. Same release closes a slash-
form pricing miss: gbrain brainstorm --judge-model anthropic/claude-sonnet-4-6 --max-cost 5 failed with
BudgetExhausted reason=no_pricing because every pricing site only
matched the colon form. Both shapes work now. No config change, no
schema migration — gbrain upgrade is the whole fix.
Docs
docs/INSTALL.md— every install path, end to enddocs/what-schemas-unlock.md— why schemas matter: 7 killer use cases, the structural argument for typed page kinds, the agent-co-curates pattern (v0.40.7.0)docs/schema-author-tutorial.md— 5-minute walkthrough: fork the bundled pack, add a custom type, backfill existing pages, prove the wiring viagbrain whoknowsdocs/architecture/— system design, topologies, retrieval theorydocs/guides/— how-to runbooks (sub-agent routing, minion deployment, skill development, brain-first lookup, idea capture, diligence ingestion)docs/integrations/— connecting external data sources (voice, email, calendar, embedding providers)docs/mcp/— per-client MCP setup (Claude Desktop, Code, Cursor, ChatGPT, Perplexity, Cowork)docs/eval/— eval framework, metric glossary, methodologydocs/ethos/— philosophy (thin harness, fat skills, markdown as recipes, origin story)AGENTS.md— entry point for non-Claude agentsCLAUDE.md— entry point for Claude Code (deep operating context)CONTRIBUTING.md— contributor guide, test discipline, eval-capture modeSECURITY.md— OAuth threat model, hardening defaults
Contributing
Run bun run test for the fast loop, bun run verify for the pre-push gate, bun run ci:local to run the full Docker-backed CI stack locally. Detailed test discipline in CONTRIBUTING.md.
Community PRs are batched into release waves rather than merged one-by-one — see the "PR wave workflow" section in CLAUDE.md. Contributor attribution stays attached via Co-Authored-By: trailers. We credit every accepted contribution in CHANGELOG.md.
If you find a bug or want a feature: open an issue first. Quick fixes (typo, doc bug, obvious regression) can go straight to a PR. Anything touching schema, retrieval ranking, MCP protocol, or the security boundary needs a design discussion in the issue first.
License + credit
MIT. I built GBrain to run my OpenClaw and Hermes deployments — the production brain behind my AI agents.
Origin story: docs/ethos/ORIGIN.md.
Community PR contributors are credited in CHANGELOG.md per release. ZeroEntropy (@zeroentropy) for the embedding + reranker stack that ships as the default. Voyage AI for the asymmetric-encoding recipe template. Ramp Labs for the search quality improvements lineage.