* docs(designs): agent-bootstrap plan + design docs (normative, review-absorbed) The scrubbed, in-repo sources of truth for the gbrain bootstrap wave: AGENT_BOOTSTRAP_DESIGN.md (product scope/sequencing) and AGENT_BOOTSTRAP_PLAN.md (implementation; all review-finding IDs inlined). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): format spec, question bank, identity templates, bundled assets agent.json manifest (format_version 1, initialized sentinel) + machine-local install receipt [CX2-1, CX2-12]; 12-question/6-required interview bank with consent keys and a persist:false sink for the optional provider key [CX2-13]; ten {{TOKEN}} identity templates (generic, adapted to gbrain ops — gates call recall/query/put_page, write-through-ops rule, keyless agent-authored facts, silence contract); assets embedded compiled-binary-safe via file-type imports [ENG-6]. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): runbook, README paste block, bootstrap guide, TODOS entries BOOTSTRAP_FOR_AGENTS.md (agent-driven install runbook: CLI phase list is the source of truth, never-invent rules, Codex approvals preflight, keyless posture, failure-modes table, version stamp for the skew check); README gains the full-agent paste block pinned to latest-stable inside the Claude Code/Codex quick start (memory-only tier stays); docs/guides/bootstrap.md carries the full install/security/consent/degradation/uninstall contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(designs): spike instrument for the bootstrap wave (build order 0) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): interview + render engines Interview gate with read-back confirm-hash (any later answer change clears the confirmation — the hostile single-batch case is structurally impossible), per-answer provenance, caps + escaping at set time, config-sink routing for the provider key; renderer with hard-fail token sweep, subordinate fencing of principal input, never-clobber + backups, deterministic minimal mode for the template repo, scaled byte floors. 58 unit tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): private-repo lifecycle — repo create, attach, uninstall, run lock gh-gated private repo creation with API-verified privacy (rate-limit distinct from public), refuse-foreign-origin with attach as the sanctioned path, atomic bootstrap mutex (pid liveness + age + token), receipt-keyed uninstall that never wholesale-deletes the gbrain home and only offers --delete-brain for a brain it created; read-only PGLite lock probe (never opens the engine). 54 unit tests, injectable exec seam throughout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(release): latest-stable ref, template-repo publish job, bootstrap CI guards release.yml advances the latest-stable tag only after assets publish (the paste block's permanent ref — copies in the wild never rot) and gains a PAT-gated publish-template job verified against the vendored tree; two skip-graceful guards (sanctioned-ref + runbook stamp; template/token bijection + placeholder assertion + generator byte-diff) wired into verify; README + runbook re-admitted to the CI cache hash; vendored deterministic template tree generated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(context): IPC v2 turn_context + 8KB assembly + visibility resolver + session identity Discriminated-union IPC with handler map, protocol echo (stale-serve detection), shared-secret gate, server-side source binding, per-kind budgets; turn-context assembly (reflex pointers + volunteered pages + world-only hot facts) under a data-not-instructions envelope trimmed to the harness's 10KB hook-output cap; facts.default_visibility resolved through one helper at all four sites (explicit caller wins, typos fail closed); typed sessionId threads _meta.session_id into the hot-memory cache key. 50 new tests; 180 adjacent tests confirmed green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(persistence): secret-scan, gbrain sources push, durability unification Pattern secret scanner (own runtime allowlist, redacted previews, corpus-write redaction mode); sources push runs the whole scan→stage→commit→pull→push sequence under one cross-platform lock (mkdir-atomic, pid+age+token) with a deny-glob backstop, commit-first divergence-safe pull, refuse-unverifiable visibility, and push-status telemetry; gbrain-home choke point unifies GBRAIN_HOME semantics with config (0700); durability is parent-repo-aware and rotates its push log at 0600. 35 new tests; 200 existing green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sources): harden/pull gates accept sources inside a parent git repo The bootstrap workspace registers brain/ (a subdirectory) as the source; the durability core already resolves the repo root, so the command gates now check inside-a-repo rather than .git-right-here [CX2-3]. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(serve): resident maintenance sweep + keyless capability probe The lock-owning serve process now closes the persistence loop: startup (3s post-connect, best-effort, unref'd) and idle (10-min quiet intervals through the injectable timer seam) sweeps run facts-fence reconciliation, deterministic link/timeline extraction over recent workspace pages, and spend-gated corpus ingest (skipped keyless — agent-authored fences cover it). gbrain sweep --once is the trusted CLI seam bootstrap verify uses. Capability probe renders the honest keyless/keyed report. Full reuse of the cycle extractor + extract cores; 26 new tests, neighbors green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(hooks): engine-free gbrain hook command, settings writers, transcript parser Four hook events (session-start digest + crashed-session recovery push, user-prompt turn-context injection under an 800ms deadline and the 10KB cap, stop buffers, session-end corpus write with redaction/retention/dedup + best-effort push); structural JSON settings merger keyed by a _gbrain marker (foreign hooks and permissions survive); dated host-spec registry; Claude Code .jsonl parser as a spec-target with a scrubbed 7-shape fixture. Heartbeat is counters-only by construction. 59 tests; zero engine modules in the import graph. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(bootstrap): cross-link the full-agent path from the connection docs Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): dispatcher, verify, status — the command assembled gbrain bootstrap {status,interview,render,repo,hooks,verify,uninstall,attach}: engine-free except verify (owns its engine, in-process sweep — no live-serve conflict); phase list is the TS source of truth with install.jsonl telemetry and the support blob; verify's fail-soft check suite covers the real write path (put_page → write-through file → sweep → graph floor → recall), passes keyless, persists snapshots, and ends with the first-run tour. cli.ts wired per the three-touchpoint rule; doctor gains the bootstrap check group (silent on machines with no bootstrap state). 28 new tests; 353 adjacent green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: KEY_FILES bootstrap cluster + CLAUDE.md dispatcher row (+ build:llms) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(bootstrap): e2e pins — hook-under-live-serve, attach, degraded modes, compiled binary, Docker harness The permanent pins: a real serve holds the PGLite lock while the engine-free hook completes (and a direct engine open provably throws LiveServeLockError); stale-socket fail-open; machine-2 attach with marker-keyed hook repair; decline-everything installs verify green with every degradation named; the compiled binary renders bundled templates in an empty cwd. Offline Docker harness (networkless, read-only) gated into heavy-tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(bootstrap): register doctor check categories + system-of-record allow comments The six bootstrap doctor checks join OPS_CHECK_NAMES; the sweep's batch link/ timeline inserts carry the explicit extract-path allow comments (the sweep IS the extraction path for workspace pages). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(test): shard wedge cap tracks suite growth (1500s -> 1800s) At ~9000 tests a healthy shard finished at 1466s and two progressing shards were false-killed at the old cap; 1800s restores ~25% headroom over the slowest observed healthy shard. Real hangs still hit it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(ci): cache-hash policy — README + runbook edits must invalidate [C2] The old deny-list assertion predates the paste block; README.md and BOOTSTRAP_FOR_AGENTS.md are policy-doc re-admissions now, so their edits must change the hash (a paste-block edit shipping under a cached green was the C2 hole). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(test): classify post-suite exit-hangs as warn-pass; file the leak forensics A shard killed by the wedge watchdog with every assigned file started and zero fail markers did all its work and leaked a handle at exit — pre-existing and master-reproducible (P1 TODO carries the full bisect forensics). Bun's per-test timeout turns a hung test into a (fail), so the classifier cannot mask one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(test): shard cap 2400s — the count-balanced heavy shard needs it under contention Observed: the heavy shard still progressing 22s before an 1800s kill while siblings finish at 1150-1550s (split balances file count, not weight). Filed the load-sensitive WAL-repair flake (pre-existing, master's v0.42.75.0 wave). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(bootstrap): quarantine env-mutating suites to the serial lane check-test-isolation R1: six new files mutate GBRAIN_HOME/env at module scope — the serial lane (one process per file) is the guard's prescribed home for them. All 114 tests pass post-rename. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(readme): per-harness install sections — Codex, Claude Code, then OpenClaw/Hermes Each harness gets its own complete paste-block section (desktop app first, terminal noted — Claude Code CLI is the identical harness; Codex CLI works pull-based today); the OpenClaw/Hermes platform path keeps equal weight with its one-click deploys and INSTALL_FOR_AGENTS block intact; memory-only and remote-connect tiers consolidated under 'Lighter ways in'. Supersedes the review's D5 ordering by user direction; stale heading references updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(readme): Codex as the recommended first step; OpenClaw/Hermes framed as-intended, high-cost The install section now routes newcomers explicitly: Codex first (subscription-priced, nothing to deploy), OpenClaw/Hermes as GBrain used the way it was designed — always on, at real server + API cost. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: doc-audit code chasers — broken recovery hints, stale op description, auto_link key Four small code fixes surfaced by the markdown accuracy audit: - doctor's auto-RLS recovery hint pointed at `apply-migrations --force-retry 35`, which cannot work (--force-retry targets the vX.Y.Z orchestrator registry, not the numeric schema MIGRATIONS array). Hint now points at the recreate SQL in docs/guides/rls-and-you.md; test pins against regression. - v0_11_0 migration printed the same broken-mechanism class of hint (`config set minion_mode` writes DB config nothing reads); now names `apply-migrations --mode` + preferences.json, the real setter. - submit_job's op description hardcoded a stale handler list; now points at registerBuiltinHandlers as the source plus the --follow discovery trick. - `auto_link` added to KNOWN_CONFIG_KEYS: read by link-extraction, reconcile-links, and sweep, and documented as the off-switch in brain-ops/maintain, but the allowlist rejected `config set auto_link false`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: repo-wide accuracy + MECE reform from the 9-bucket markdown audit A code-grounded audit of every markdown file (root, architecture, guides, mcp, tutorials, docs-root, operations/eval/designs, skills, recipes) followed by a fix wave with per-bucket ownership. Four classes of change: Accuracy — every documented command/flag verified against src/ before writing: dead commands replaced with working ones (pages purge-deleted, jobs watch --follow, gbrain restore, import-based Obsidian flow, space-separated --scopes, real thin-client recipes, working isolation verification, real supervisor restart procedure, curl-based ngrok health check, real minion_mode setter); count drift fixed with rot-proof phrasing (100+ ops, 50+ bundled skills via skills/manifest.json, 140+ engine methods, KNOBS_HASH_VERSION pointer instead of hardcoded versions); stale claims corrected (search-mode defaults, RETRIEVAL pipeline order incl. autocut, sentinel rules, refusal-list mechanism, engine snapshot, shard cap 2400s + EXIT-HANG classifier in TESTING.md, latest-stable + publish-template documented in RELEASING.md as release.yml promises). MECE — one home per concept, pointers elsewhere: test isolation → TESTING.md; OAuth registration + --bind/--public-url lore → DEPLOY.md; mode bundles → guides/search-modes.md (the home the CLAUDE.md dispatcher always promised); merge contract → schema-packs.md; WAL ladder → ENGINES.md; quiet-hours → quiet-hours.md; capture taxonomy → entity-detection.md; person-page taxonomy → compiled-truth.md; brain-first protocol → brain-first-lookup.md; refresh semantics → refresh-algorithm.md; KEY_FILES.md deduplicated (58 extension entries merged, one entry per file); infra-layer.md rewritten as a pointer page. Privacy — placeholder sweep across guides, docs, skills, and recipes per the iron rule; per-release narration stripped from reference docs (current-state prose only). Bootstrap coverage — AGENTS.md pointer, RESOLVER routing row, INSTALL.md path, tutorial cross-links, keyless-mode sections in spend-controls/headless-install. skills.lock.json regenerated; llms.txt/llms-full.txt rebuilt. Gates: verify 36/36, typecheck clean, doctor 96/96, skills-integrity + resolver + build-llms + config-set + migrations all green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(readme): refresh production-brain stats to current brain-repo counts 155,795 pages / 24,589 people / 5,340 companies, counted from the brain repo's current HEAD; the "100K-page brain" framing moves to 150K to match. Cron-fleet count unchanged (its store lives on the deployment host, not in the repos available for verification). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(scan,push): modern OpenAI/Voyage key patterns, scan staged blobs not disk - secret-scan matches sk-proj-/sk-svcacct-/sk-None- and pa- Voyage keys (the bare sk- pattern missed every current OpenAI key format). - workspacePush stages first, then scans the staged index blobs via git cat-file, closing the scan-then-stage TOCTOU where a file changed between snapshot and commit shipped unscanned. - shared binary-sniff helper, memoized glob regexes, atomic push-status write, and tests for pull_conflict + gitignored deny-match paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ci): regenerate flag registry for new commands, harden shard classifier + release token - cli-flag-registry.generated.ts regenerated: bootstrap/hook/sweep and sources push --message/--allow-unverified-remote were missing, so the strict #2185 validator rejected real invocations and skipped the new commands entirely. - EXIT-HANG shard classifier now requires every assigned file to have started before warn-passing a watchdog kill (was fail-open). - release.yml passes TEMPLATE_REPO_PAT via http.extraheader, off the argv. - compiled-binary e2e fails loud in CI instead of a silent permanent skip. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(hook,sweep,ipc): non-blocking hook pushes, bounded sweep + cache, source-bound resolve - session-start/session-end no longer run synchronous git + inline push inside their self-deadline; a detached child does the push and the hook returns immediately (blocked Claude Code startup for minutes on a dirty tree before). - serve sweep drops the unbounded listAllPageRefs, resolves only candidate targets, claims corpus files atomically (no double-LLM-spend race), and caps the fence LIKE scan; heartbeat writes are O_APPEND with rare compaction. - hot-memory cache evicts expired entries and bounds entry count (the key is caller-controlled via _meta.session_id). - v1 resolve IPC honors boundSourceId like turn_context; turn-context runs its arms concurrently. doctor reads push/heartbeat thresholds from hook.ts. - new tests: doctor bootstrap checks, hook push-gate + deadline, concurrent sweep claims, cache eviction, bound-source resolve. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(bootstrap): origin-ownership gate, world visibility, collision-safe source id, consent + templates - repo adoption requires an exact receipt repo_url match or authed-owner check (undefined repo_url was a wildcard); create verifies privacy BEFORE the first push. - verify sets facts.default_visibility=world if unset, so agent-authored facts surface in per-turn context (they defaulted private before). - source_id derives a path-hash suffix when 'workspace' is taken by another checkout; every consumer reads manifest.source_id. - skipped HOOKS_CONSENT now declines (was falling through to default yes); --minimal refuses on an initialized manifest; tilde fences escaped. - MCP registration pins --surface full; status hard-fails a public origin (template door); receipt writers guard against newer/corrupt receipts; uninstall only claims brain-deleted after a real rm. - templates ship jobs disabled + provider-consent + support-relay lines; soul-audit re-runs over the shared interview bank. TODOS: 11 follow-ups. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(security): close adversarial-review findings — scan fails closed, whole-PEM redaction, bound repo push Cross-model adversarial pass (Claude + Codex) on the bootstrap wave: - secret scan fails CLOSED: an unreadable, oversized, or binary staged blob now blocks the push (blocked_unscannable, exit 5) instead of committing unscanned; only a confirmed staged deletion is skipped. This was the headline "block secrets before they leave the machine" property failing open. - private-key redaction spans the whole PEM block (header+body+footer), not just the header line — the base64 body no longer survives into the corpus the sweep sends to an extraction provider. - bootstrap repo commits the workspace (secret-scan-gated) before the first push and verifies the remote actually received it, so a push-fail retry can't adopt an empty remote as success. - privacy verify is re-bound to origin immediately before push (a concurrent origin rewrite between verify and push is refused). - session-end corpus write is atomic and clears the stale ingested/in-progress sidecars so a resumed session's appended transcript is re-ingested. - public-origin refusal enforced at render (not only status); MCP "already registered" is verified to target this workspace, not blessed blindly; verify probe cleanup scopes deletes to its own slugs, not a token substring; allowlist fingerprint floor raised 8→16 hex. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * v0.45.0.0 feat(bootstrap): paste-in personal-agent install for Codex + Claude Code Turns a Codex or Claude Code session into a persistent personal agent: interview-rendered identity files, a local PGLite brain, per-turn context via serve IPC (Claude Code hooks / Codex pull protocol), session-triggered persistence, and a private GitHub repo as the agent's portable body. Keyless- first (the harness model is the LLM; one optional key adds embeddings + extraction). New `gbrain bootstrap` command family + `gbrain hook` + `gbrain sweep`; doctor bootstrap health checks; latest-stable distribution ref + template-repo publish job. Opt-in, additive — existing installs untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: regenerate flag registry for security-fix flags; drop fabricated gbrain capabilities doc ref CI caught two real failures under the merged state: - the flag registry lagged the blocked_unscannable/exit-5 flags the security round added, tripping the #2185 freshness guard. - headless-install.md described the keyless capability report as a `gbrain capabilities` command, which the #3502 doc-command resolver rejects — reworded to prose (the real surface is bootstrap verify's report). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: sync KEY_FILES + bootstrap plan to security-fix behavior Cross-referenced the security-fix round against the reference docs and corrected the drift those commits introduced: - workspace-push.ts entry: stage-FIRST-then-scan order (the TOCTOU fix), fail-closed blocked_unscannable, and the sources-push status -> exit-code map. - hooks.ts entry: MCP registration pins `serve --surface full`. - hook.ts entry: session-start/session-end pushes run in a detached child (non-blocking); atomic corpus write clears stale sidecars. - bootstrap.ts entry: render hard-refuses a public origin (template door). - verify.ts entry: source_id collision resolution (workspace-<path-hash>). - AGENT_BOOTSTRAP_PLAN as-shipped delta note for the scan/stage reorder. llms bundle unchanged (KEY_FILES is link-only); build:llms and test/build-llms.test.ts green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ci): silence SC2016 on the intentional askpass literal in release.yml The one-shot GIT_ASKPASS script must contain literal $1 and $TEMPLATE_REPO_PAT so they expand when /bin/sh runs it at git's credential prompt, not when the outer shell writes the file — single quotes are correct. Add a scoped shellcheck disable so actionlint passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(skills): declare 'bootstrap my data' trigger in cold-start frontmatter The doc reform added 'bootstrap my data' to cold-start's RESOLVER.md row (to disambiguate data-bootstrap from agent-bootstrap) but not to the skill's own frontmatter triggers, tripping the RESOLVER↔frontmatter round-trip contract (resolver.test.ts). Declare it; regenerate skills.lock.json. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): default per-turn hooks + search mode ON without a prompt Installing gbrain for your coding agent IS the consent for the behaviors that make it work, so stop re-litigating them with install-time questions whose "no" defeats the product: - Per-turn hooks (Claude Code) install ON by default — no prompt. Off-ramps: `--no-hooks` at install, `GBRAIN_HOOKS=0` at runtime, `bootstrap uninstall`. The "hooks installed" line now surfaces the kill switch so default-on is never silent. A persisted HOOKS_CONSENT=no (interview --skip) still declines. - Search mode defaults to `balanced` silently (nobody knows the modes at install; `gbrain search modes` changes it any time). - MCP scope stays the ONE deliberate prompt — project vs user is a real cross-repo privacy choice, not friction. Marks the two consents `silent: true` in the question bank (new QuestionSpec field), rewrites the runbook phases so the agent no longer asks them, adds the `--no-hooks` flag (+ registry regen), and adds default-on / opt-out tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(bootstrap): real end-to-end coverage — cross-session recall, per-turn content, Codex door, realistic corpus Closes the seven e2e gaps a coverage audit surfaced: the plumbing was well-unit-tested but the product claims ("Codex works, context shows up every turn with real content, it remembers across restarts, machine two recovers, Postgres works") were unproven end to end. Test-only wave — zero src changes. - Hermetic synthetic corpus (test/fixtures/bootstrap-corpus/ + a loader helper): 12 interlinked pages (52 edges, timelines), 12 world/private beliefs, 8 gold queries — curated from the gbrain-evals synthetic corpora, 100% placeholder names, so recall is asserted on a real multi-entity brain instead of a 2-node self-planted probe. - GAP1 magic moment: author a fact via the real write path, disconnect the engine, reopen against the same DB, recall it — a real session boundary, not verify.ts's same-connection SQL read-back. Plus a source-isolation assertion. - GAP2 per-turn content: hook-under-serve Pin 1 now seeds a known fact and asserts its text lands in the injected block AND private beliefs never do (was: empty brain, empty_block accepted as a pass). - GAP3 Codex door: assert the rendered AGENTS.md carries the Gate-3 brain-first pull protocol; make the fake codex shim implement `mcp get` so the [FIX7] target-verification can actually fail; the Docker cold-machine harness now exercises the hooks/MCP registration step instead of skipping it. - GAP4 corpus recall: turn-context + verify graph-floor/qrels run on the real multi-entity brain with real edges. - GAP5 attach: machine-two now re-ingests the cloned brain/ into a fresh DB and recalls a fact authored only on machine one — the multi-device payoff. - GAP6 keyed + Postgres (env-gated): real embeddings prove semantic recall a paraphrase query can reach but keyless BM25 cannot; bootstrap verify drives a real Postgres engine (skipIf DATABASE_URL/keys absent). - GAP7 persistence: session-end runs the REAL push (not the mocked seam) to a local bare remote and the remote receives the content; a planted secret is blocked at the gate; the 15-min cron installs and fires a scan-gated push. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(bootstrap): real-agent e2e — drive the actual claude + codex binaries end to end Closes the audit's biggest gap ("no real harness ever drives a turn"). Adapts gstack's PTY/headless agent harness to prove the bootstrap install + smoke work against the REAL binaries, not PATH shims. Test/CI/docs only — zero src changes. - test/helpers/agent-harness.ts: hermetic clean-room child env (ported from gstack; drops CONDUCTOR_/CLAUDE_/GSTACK_/MCP_/GBRAIN_, promotes GSTACK_ANTHROPIC_API_KEY→ANTHROPIC_API_KEY), real-binary resolvers + auth probes, headless `claude -p --output-format stream-json` and `codex exec --json` turn runners, a gbrain stdio MCP-config writer, and a keyless brain seeder. + a fixture-parse unit test (no binary needed). - test/e2e/bootstrap-real-claude.serial.test.ts: real `gbrain bootstrap` install → REAL `claude mcp add` (verified via `claude mcp get`) → verify exit 0 → a real `claude -p --mcp-config --strict-mcp-config` turn that invokes mcp__gbrain__search and answers from the brain (proven: toolCalls include mcp__gbrain__search, final text carries the seeded fact). - test/e2e/bootstrap-real-codex.serial.test.ts: same install with REAL `codex mcp add` into a real ~/.codex/config.toml + Gate-3 pull-protocol assertion, then a real `codex exec --json` turn surfacing the fact (MCP or the pull- protocol shell path). Bounded retry absorbs codex's occasional MCP-call cancellation without softening the fact-requiring assertion. - Everything hermetic (temp HOME/CLAUDE_CONFIG_DIR/CODEX_HOME/GBRAIN_HOME; real ~/.codex auth copied read-only) and skipIf-gated so it self-skips cleanly where the binaries/auth are absent. - heavy-tests.yml: gated `real-agent-e2e` job (nightly/label, never the PR shard; no-op on a runner without authed binaries). - TODOS: compiled `gbrain` binary can't serve a PGLite brain (bun compile omits the WASM/extension payloads); harness falls back to `bun run` serve. Verified against live claude 4.6 + codex 0.147.0: 15 pass / 0 fail; verify 36/36; typecheck clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ci): real-agent-e2e job — bash array + --timeout (actionlint SC2086 + bun-test-timeout guard) The real-agent-e2e job's file loop used an unquoted $FILES (SC2086) and ran `bun test` without --timeout (check-bun-test-timeout guard). Switch to a bash array and add --timeout=600000 (real-agent turns are slow; the tests self-skip without authed binaries so it's a no-op elsewhere). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(pglite): embed WASM + extension assets so the compiled binary can serve A `bun build --compile` gbrain binary could not `serve` a PGLite brain: the compile bundles JS but not PGLite's runtime payload (pglite.wasm, initdb.wasm, pglite.data, vector/pg_trgm tarballs), so `serve` on PGLite died with a bunfs/ENOENT. Now the assets ride inside the binary. - src/core/pglite-embedded-assets.ts: embeds the five assets via `import … with { type: 'file' }` (the ENG-6 idiom) and exposes getEmbeddedPgliteOptions() → { pgliteWasmModule, initdbWasmModule, fsBundle, extensions:{vector,pg_trgm} }. WASM/fsBundle are consumed as bytes; the two extension tarballs are materialized to a content-addressed temp file (atomic, size-verified reuse) because PGLite reads them via fs.createReadStream, which cannot read a /$bunfs path. Unconditional (works in bun-run and compiled), so no fragile mode branch. - src/core/pglite-engine.ts: static-import getEmbeddedPgliteOptions (engine path stays static per the engine-dynamic-import invariant); spread into both PGlite.create sites (initial + WAL-repair retry). The bunfs classifier stays as a backstop but no longer fires for a correct binary. - scripts/check-pglite-embedded.sh (+ smoketest): compiles a focused binary and asserts it boots PGLite, CREATE EXTENSION vector/pg_trgm, and round-trips a page — wired into `bun run verify` (now 37 checks), check:all, and check:pglite-embedded. Fail-soft only when compile is unavailable. - agent-harness.ts probeCompiledPglite now passes → the real-agent e2e uses the fast compiled MCP server. TODOS: the P2 "can't serve PGLite" item is closed. Verified: fresh compiled binary ran `search`/`query` against a PGLite brain and returned the seeded row (no bunfs/ENOENT); verify 37/37; pglite-engine 120/0 source-mode; typecheck clean; engine-dynamic-import + parity guards pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
26 KiB
name, description, triggers, tools, mutating
| name | description | triggers | tools | mutating | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| setup | Set up GBrain with auto-provision Supabase or PGLite, AGENTS.md injection, first import |
|
|
true |
Setup GBrain
Set up GBrain from scratch. Target: working brain in under 5 minutes.
Installing into an agent harness? (Claude Code, Codex, OpenClaw, etc.)
gbrain bootstrapis the paste-in install path — it wires hooks, the maintenance sweep, and harness config in one command. Seedocs/guides/bootstrap.md. This skill covers the brain-side setup (database, sync, first import); the two are complementary.
Contract
- Setup completes with a working brain verified by
gbrain doctor --json(all checks OK). - The brain-first lookup protocol is injected into the project's AGENTS.md or equivalent.
- Live sync is configured and verified (a test change pushed and found via search).
- Schema state is tracked in
~/.gbrain/update-state.jsonso future upgrades know what the user adopted or declined. - No Supabase anon key is requested; GBrain uses only the database connection string.
Install (if not already installed)
bun add github:garrytan/gbrain
How GBrain connects
GBrain connects directly to Postgres over the wire protocol. NOT through the
Supabase REST API. You need the database connection string (a postgresql:// URI),
not the project URL or anon key. The password is embedded in the connection string.
Use the Transaction pooler connection string (port 6543), not the direct connection (port 5432). The direct hostname resolves to IPv6 only, which many environments can't reach. Find it: click Connect in the top navigation bar, then Connection String > Transaction pooler, and copy the string.
Do NOT ask for the Supabase anon key. GBrain doesn't use it.
Why Supabase
Supabase gives you managed Postgres + pgvector (vector search built in) for $25/mo:
- 8GB database + 100GB storage on Pro tier
- No server to manage, automatic backups, dashboard for debugging
- pgvector pre-installed, just works
- Alternative: any Postgres with pgvector extension (self-hosted, Neon, Railway, etc.)
Prerequisites
- A Supabase account (Pro tier recommended, $25/mo) OR any Postgres with pgvector
- An OpenAI API key (for semantic search embeddings, ~$4-5 for 7,500 pages)
- A git-backed markdown knowledge base (or start fresh)
Available init options
gbrain init --supabase-- interactive wizard (prompts for connection string)gbrain init --url <connection_string>-- direct, no promptsgbrain init --non-interactive --url <connection_string>-- for scripts/agentsgbrain doctor --json-- health check after init
There is no --local, --sqlite, or offline mode. GBrain requires Postgres + pgvector
(local PGLite or remote Supabase / self-hosted).
Phase A.5: Choose Topology (run BEFORE Phase A)
GBrain supports three deployment shapes. Pick the right one before installing,
because picking wrong creates contention or duplicate work that's painful to
unwind. Read docs/architecture/topologies.md for the full picture; the short
version:
Ask the user this BEFORE running gbrain init:
"Three deployment shapes:
- Single brain (default) — one machine, one DB, one agent. Pick this if unsure.
- Cross-machine thin client — your brain lives on another machine (e.g. brain-host) running
gbrain serve --http, and this install just calls it over MCP. No local DB on this machine.- Per-worktree code + shared remote artifacts — Conductor users with multiple worktrees indexing the same code repo. Each worktree owns its own code engine; artifacts live on a shared remote brain. For code engines, configure Voyage's code-tuned model:
gbrain init --pglite --embedding-model voyage:voyage-code-3 --embedding-dimensions 1024(full guidance indocs/architecture/topologies.mdTopology 3).Which fits?"
If the user picks 1 (single brain) — proceed to Phase A
Continue with the existing gbrain init --supabase / --pglite setup below.
If the user picks 2 (cross-machine thin client)
-
Confirm a host already exists. Ask: "Is the remote
gbrain serve --httpalready running on the host machine?" If no, the user needs to set up the host first (Phases A-C on the host, thengbrain serve --http). Don't try to run init on this machine until the host is up. -
Get OAuth credentials from the host operator. Ask the user to run on the host:
gbrain auth register-client <name> \ --grant-types client_credentials \ --scopes read,write,adminThe
adminscope is required becausegbrain remote pingandgbrain remote doctor(Tier B convenience commands) call MCP ops withadminscope.read,writealone breaks ping/doctor. -
Run thin-client init on this machine:
gbrain init --mcp-only \ --issuer-url https://<host>:<port> \ --mcp-url https://<host>:<port>/mcp \ --oauth-client-id <id> \ --oauth-client-secret <secret>Or set
GBRAIN_REMOTE_CLIENT_SECRETenv var instead of the flag (preferred for headless / scripted setup). Pre-flight runs three smoke probes; any failure surfaces an actionable error. -
Configure your agent's MCP client. Add a server entry pointing at
<mcp_url>with the bearer token. Seedocs/mcp/CLAUDE_DESKTOP.md,docs/mcp/CLAUDE_CODE.md, etc. for per-client snippets. -
Verify with
gbrain doctor. Thin-client doctor runs OAuth discovery, token round-trip, and MCP smoke against the host. Should reportmode: thin-clientwith all checks green. -
Skip Phases B, C, C.5, and H entirely. They're for local engines. The host's autopilot handles sync/extract/embed. Thin clients consume only.
-
Continue to Phase D (brain-first lookup). It works identically over MCP — the agent uses the same brain-ops skill to query/search/get_page, they just round-trip through the host's
gbrain serve --http.
If init reports "thin-client config already present", a previous setup
already configured this machine. Refusing without --force is the correct
behavior; either accept the existing config or pass --force to refresh.
If the user picks 3 (split-engine per-worktree)
This shape requires per-worktree wiring that gstack handles, not gbrain
directly. gbrain's role is just to run a local engine when GBRAIN_HOME is
set — that already works.
Point the user at docs/architecture/topologies.md (the Topology 3 section)
for the wiring recipe, then continue with Phase A as normal — gbrain init
on this machine sets up the artifact brain (the "default" home). The
per-worktree code engines are configured per-worktree as gstack creates them.
If the user has a remote artifact brain (Topology 2 + 3 combined), follow the thin-client setup above for the artifact brain instead of Phase A.
Phase A: Supabase Setup (recommended)
Guide the user through creating a Supabase project:
- "Go to https://supabase.com and sign up or log in."
- "Click 'New Project' in the top left."
- Name:
gbrain - Region: pick the one closest to you
- Database password: generate a strong one and save it
- Name:
- "Wait about 2 minutes for the project to initialize."
- "Find the connection string: click Connect in the top navigation bar, then Connection String > Transaction pooler, and copy the string (port 6543)."
- Initialize gbrain:
gbrain init --non-interactive --url "postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres" - Verify:
gbrain doctor --json
OpenClaw/Hermes agent instructions: Store the Supabase access token in your persistent
env as SUPABASE_ACCESS_TOKEN. gbrain doesn't store it, you need it for future
gbrain doctor runs. Generate at: https://supabase.com/dashboard/account/tokens
Phase B: BYO Postgres (alternative)
If the user already has Postgres with pgvector:
- Get the connection string from the user.
- Run:
gbrain init --non-interactive --url "<connection_string>" - Verify:
gbrain doctor --json
If the connection fails with ECONNREFUSED and the URL contains supabase.co,
the user probably pasted the direct connection (IPv6 only). Guide them to the
Transaction pooler string instead (see Phase A step 4).
Phase C: First Import
- Discover markdown repos. Scan the environment for git repos with markdown content.
echo "=== GBrain Environment Discovery ==="
for dir in /data/* ~/git/* ~/Documents/* 2>/dev/null; do
if [ -d "$dir/.git" ]; then
md_count=$(find "$dir" -name "*.md" -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null | wc -l | tr -d ' ')
if [ "$md_count" -gt 10 ]; then
total_size=$(du -sh "$dir" 2>/dev/null | cut -f1)
echo " $dir ($total_size, $md_count .md files)"
fi
fi
done
echo "=== Discovery Complete ==="
-
Import the best candidate. For large imports (>1000 files), use nohup to survive session timeouts:
nohup gbrain import <dir> --no-embed --workers 4 > /tmp/gbrain-import.log 2>&1 &Then check progress:
tail -1 /tmp/gbrain-import.logFor smaller imports, run directly:
gbrain import <dir> --no-embed -
Prove search works. Pick a semantic query based on what you imported:
gbrain search "<topic from the imported data>"This is the magical moment: the user sees search finding things grep couldn't.
-
Start embeddings. Refresh stale embeddings (runs in background). Keyword search works NOW, semantic search improves as embeddings complete.
-
Backfill the knowledge graph. Populate typed links and structured timeline from the imported pages. Auto-link maintains both going forward, but historical pages need a one-time backfill.
gbrain extract links --source db --dry-run | head -20 # preview gbrain extract links --source db # commit gbrain extract timeline --source db # dated events gbrain stats # verify links > 0After this,
gbrain graph-query <slug> --depth 2works and search ranks well-connected entities higher. Idempotent — safe to re-run anytime. Supports--since YYYY-MM-DDfor incremental runs on huge brains.Skip if Phase C imported zero pages (auto-link handles new writes).
-
Offer file migration. If the repo has binary files (.raw/ directories with images, PDFs, audio):
"You have N binary files (X GB) in your brain repo. Want to move them to cloud storage? Your git repo will drop from X GB to Y MB. All links keep working."
If the user agrees, configure storage and run migration. The storage backend is a file-plane config object —
gbrain config setwrites the DB plane, which the files commands never read. Add astorageobject to~/.gbrain/config.jsondirectly (shape matchesStorageConfiginsrc/core/storage.ts; Supabase Storage recommended):{ "storage": { "backend": "supabase", "bucket": "brain-files", "projectUrl": "https://<project>.supabase.co", "serviceRoleKey": "<service-role-key>" } }Then run the migration:
# Migrate binary files to cloud (3-step lifecycle) gbrain files mirror <brain-dir> # Upload to cloud, keep local gbrain files redirect <brain-dir> # Replace local with .redirect.yaml pointers # (optional) gbrain files clean <brain-dir> --yes # Remove pointers tooAfter migration,
gbrain files upload-rawhandles new files automatically: small text/PDFs stay in git, large/media files go to cloud with.redirect.yamlpointers. Files >= 100 MB use TUS resumable upload for reliability.
If no markdown repos are found, create a starter brain with a few template pages (a person page, a company page, a concept page) from docs/GBRAIN_RECOMMENDED_SCHEMA.md.
Phase C.5: One-step autopilot + Minions install (v0.11.1+)
Run the migration runner once, then install autopilot. Two commands, done:
gbrain apply-migrations --yes # applies any pending migrations; idempotent on healthy installs
gbrain autopilot --install # supervises itself + forks the Minions worker; env-aware
What gbrain autopilot --install does:
- On macOS: writes a launchd plist at
~/Library/LaunchAgents/com.gbrain.autopilot.plist. - On Linux with systemd: writes
~/.config/systemd/user/gbrain-autopilot.servicewithRestart=on-failure. - On ephemeral containers (Render / Railway / Fly / Docker): writes
~/.gbrain/start-autopilot.shand prints the one-line your agent's bootstrap should source to launch autopilot on every container start. Auto-injects into OpenClaw'shooks/bootstrap/ensure-services.shif detected (use--no-injectto opt out). - On Linux without systemd: installs a crontab entry (every 5 min).
Autopilot then supervises the Minions worker as a child process. Users get
sync + extract + embed + backlinks + durable Postgres-backed job processing
from ONE install step. No separate gbrain jobs work daemon to manage.
On PGLite, autopilot runs inline (PGLite's exclusive file lock blocks a separate worker process). Everything else still works.
If apply-migrations prints "N host-specific items need your agent's
attention," read ~/.gbrain/migrations/pending-host-work.jsonl + walk
skills/migrations/v0.11.0.md + docs/guides/plugin-handlers.md to
register host-specific handlers. Re-run apply-migrations after each
batch.
Phase D: Brain-First Lookup Protocol
Inject the brain-first lookup protocol into the project's AGENTS.md (or equivalent). This replaces grep-based knowledge lookups with structured gbrain queries.
BEFORE (grep) vs AFTER (gbrain)
| Task | Before (grep) | After (gbrain) |
|---|---|---|
| Find a person | grep -r "Pedro" brain/ |
gbrain search "Pedro" |
| Understand a topic | grep -rl "deal" brain/ | head -5 && cat ... |
gbrain query "what's the status of the deal" |
| Read a known page | cat brain/people/pedro.md |
gbrain get people/pedro |
| Find connections | grep -rl "Brex" brain/ | xargs grep "Pedro" |
gbrain query "Pedro Brex relationship" |
Lookup sequence (MANDATORY for every entity question)
gbrain search "name"-- keyword match, fast, works without embeddingsgbrain query "what do we know about name"-- hybrid search, needs embeddingsgbrain get <slug>-- direct page read when you know the slug from steps 1-2grepfallback -- only if gbrain returns zero results AND the file may exist outside the indexed brain
Stop at the first step that gives you what you need. Most lookups resolve at step 1.
Sync-after-write rule
After creating or updating any brain page in the repo, sync immediately so the index stays current:
gbrain sync --no-pull --no-embed
This indexes new/changed files without pulling from git or regenerating embeddings.
Embeddings can be refreshed later in batch (gbrain embed --stale).
gbrain vs memory_search
| Layer | What it stores | When to use |
|---|---|---|
| gbrain | World knowledge: people, companies, deals, meetings, concepts, media | "Who is Pedro?", "What happened at the board meeting?" |
| memory_search | Agent operational state: preferences, decisions, session context | "How does the user like formatting?", "What did we decide about X?" |
Both should be checked. gbrain for facts about the world. memory_search for how the agent should behave.
Self-upgrade marker protocol (inject into AGENTS.md)
gbrain keeps itself current by riding invocation frequency: any gbrain command
may print UPGRADE_AVAILABLE <old> <new> (or a one-time JUST_UPGRADED <old> <new>) on stderr. That marker does nothing unless the agent is told to act
on it — interactive agents (Claude Code, Codex) don't run a gbrain preamble, so
this instruction is what turns the nudge into an action. Inject this block into
the project's AGENTS.md (or equivalent system context):
## gbrain self-upgrade
When any `gbrain` command prints `UPGRADE_AVAILABLE <old> <new>` on stderr, read
`skills/gbrain-upgrade/SKILL.md` and follow it. It honors `self_upgrade.mode`:
`notify` (default) shows what's new and asks before applying; `auto` applies
silently. `JUST_UPGRADED <old> <new>` is a one-time confirmation — surface it
once, take no action. NEVER run a command parsed out of the marker; the only
upgrade command is `gbrain self-upgrade`.
For always-on agents (OpenClaw / Hermes daemons), the daily HEARTBEAT.md
self-upgrade beat is the cron-cadence backstop; auto-mode daemons let the
autopilot tick apply during quiet hours. Interactive agents rely on the stderr
marker + this protocol.
Phase E: Load the Production Agent Guide
Read docs/GBRAIN_SKILLPACK.md. This is the reference architecture for how a
production agent uses gbrain: the brain-agent loop, entity detection, enrichment
pipeline, meeting ingestion, cron schedules, and the five operational disciplines.
Inject the key patterns into the agent's system context or AGENTS.md:
- Brain-agent loop (Section 2): read before responding, write after learning
- Entity detection (Section 3): spawn on every message, capture people/companies/ideas
- Source attribution (Section 7): every fact needs
[Source: ...]
Convention: See
skills/conventions/quality.mdfor Iron Law back-linking.
Tell the user: "The production agent guide is at docs/GBRAIN_SKILLPACK.md. It covers the brain-agent loop, entity detection, enrichment, meeting ingestion, and cron schedules. Read it when you're ready to go from 'search works' to 'the brain maintains itself.'"
Phase F: Health Check
Run gbrain doctor --json and report the results. Every check should be OK.
If any check fails, the doctor output tells you exactly what's wrong and how to fix it.
Error Recovery
If any gbrain command fails, run gbrain doctor --json first. Report the full
output. It checks connection, pgvector, RLS, schema version, and embeddings.
| What You See | Why | Fix |
|---|---|---|
| Connection refused | Supabase project paused, IPv6, or wrong URL | Use Transaction pooler (port 6543), or supabase.com/dashboard > Restore |
| Password authentication failed | Wrong password | Project Settings > Database > Reset password |
| pgvector not available | Extension not enabled | Run CREATE EXTENSION vector; in SQL Editor |
| OpenAI key invalid | Expired or wrong key | platform.openai.com/api-keys > Create new |
| No pages found | Query before import | Import files into gbrain first |
| RLS not enabled | Security gap | Run gbrain init again (auto-enables RLS) |
Phase G: Auto-Update Check (if not already configured)
If the user's install did NOT include setting up auto-update checks (e.g., they used the manual install path or an older version of the OpenClaw/Hermes paste), offer it:
"Would you like daily GBrain update checks? I'll let you know when there's a new version worth upgrading to — including new skills and schema recommendations. You'll always be asked before anything is installed."
If they agree:
- Test:
gbrain check-update --json - Register daily cron (see GBRAIN_SKILLPACK.md Section 17)
If already configured or user declines, skip.
Phase H: Live Sync Setup (MUST ADD)
The brain repo is the source of truth. If sync doesn't run automatically, the vector DB falls behind and gbrain returns stale answers. This phase is not optional.
Read docs/GBRAIN_SKILLPACK.md Section 18 for the full reference. Key points:
-
Check the connection first. GBrain is tuned for the Supabase Transaction pooler (port 6543): it auto-disables prepared statements there and routes migrations, DDL, and sync transactions to a separate direct connection. That derived direct connection (
db.<ref>.supabase.co:5432) is IPv6-only, so on an IPv4-only host, reads work but sync silently skips pages. Fix by making the direct connection reachable: setGBRAIN_DIRECT_DATABASE_URLto the Session pooler string (port 5432 on thepooler.supabase.comhost, IPv4), or enable Supabase's IPv4 add-on. -
Set up automatic sync. Choose the approach that fits your environment:
- Cron (recommended for agents): register a cron every 5-30 minutes:
gbrain sync --repo /data/brain && gbrain embed --stale - Watch mode:
gbrain sync --watch --repo /data/brainunder a process manager. Pair with a cron fallback (watch exits after 5 consecutive failures). - Webhook or git hook: if available in your environment.
- Cron (recommended for agents): register a cron every 5-30 minutes:
-
Verify sync works. Don't just check that the command ran. Check that it worked:
gbrain statsshould show page count close to syncable file count in the repo.- If page count is way too low, the direct connection is unreachable on IPv4 and sync is silently skipping pages (see point 1).
- Push a test change and confirm it appears in
gbrain search.
-
Chain sync + embed. Always run both:
gbrain sync --repo <path> && gbrain embed --stale. For small syncs, embeddings are generated inline. Theembed --staleis a safety net for any stale chunks.
Tell the user: "Live sync is configured. The brain will stay current automatically. I'll verify it's working in the next phase."
Phase I: Full Verification
Run the full verification runbook to confirm the entire installation is working.
- Read
docs/GBRAIN_VERIFY.md - Execute each check in order
- Report results to the user
- Fix any failures before declaring setup complete
Every check in the runbook should pass. The most important one is check 4 (live sync actually works): push a change, wait for sync, search for the corrected text. "Sync ran" is not the same as "sync worked."
Tell the user: "I've verified the full GBrain installation. Here's the status of each check: [list results]. Everything is working / [specific item] needs attention."
If already configured or user declines, skip.
Phase J: Cold Start — Populate Your Brain (AUTOMATIC)
Setup is done. The brain works. But it's empty. This is the most important moment — an empty brain is useless. Transition directly to the cold-start skill to fill it with the user's actual data.
Do not end setup without offering cold-start. The user just invested 15+ minutes in setup. The payoff is seeing their brain come alive with their own data. Stopping here is like installing a phone and never adding contacts.
Present this immediately after verification passes:
"✅ GBrain is set up and verified. Now let's fill it with your data.
I can connect your Google services (contacts, calendar, email), import your existing notes, pull in conversations from ChatGPT/Claude, and archive your tweets — all in one session. Each step is optional.
Ready to populate your brain?"
If the user says yes (or anything affirmative):
→ Load and execute skills/cold-start/SKILL.md immediately. Do not
just print a reference — actually run the cold-start skill.
If the user says no or wants to stop:
→ Record in ~/.gbrain/cold-start-state.json:
{"deferred": true, "deferred_at": "ISO-timestamp", "phases_completed": []}
→ Tell them: "You can run cold-start anytime by asking me to 'fill my brain' or 'cold start'."
Schema State Tracking
After presenting the recommended directories (Phase C/E) and the user selects which
ones to create, write ~/.gbrain/update-state.json recording:
schema_version_applied: current gbrain versionskillpack_version_applied: current gbrain versionschema_choices.adopted: directories the user createdschema_choices.declined: directories the user explicitly skippedschema_choices.custom: directories the user added that aren't in the recommended schema
This file enables future upgrades to suggest new schema additions without re-suggesting things the user already declined.
Anti-Patterns
- Ending setup without offering cold-start. An empty brain is useless. Phase J (cold-start) is where setup pays off. Always present the "Ready to populate?" prompt after verification. Skipping this is like installing an app and never logging in.
- Asking for the Supabase anon key. GBrain connects directly to Postgres over the wire protocol, not through the REST API. Only the database connection string is needed.
- Skipping live sync setup. If sync doesn't run automatically, the vector DB falls behind and search returns stale answers. Phase H is not optional.
- Declaring setup complete without verification. "The command ran" is not the same as "it worked." Push a test change, wait for sync, search for the corrected text.
- Leaving the direct connection unreachable on IPv4. GBrain uses the Transaction pooler (port 6543) for reads and a derived direct connection (
db.<ref>.supabase.co:5432, IPv6-only) for migrations, DDL, and sync transactions. On an IPv4-only host, reads work but sync silently skips pages. SetGBRAIN_DIRECT_DATABASE_URLto the Session pooler string (port 5432, IPv4), or enable the IPv4 add-on. - Importing without proving search. The magical moment is the user seeing search find things grep couldn't. Don't skip it.
Output Format
GBRAIN SETUP COMPLETE
=====================
Engine: [PGLite / Supabase Postgres]
Connection: [verified / pooler mode confirmed]
Pages imported: N
Embeddings: N/N (keyword search active, semantic improving)
Live sync: [configured / method]
Health check: all OK / [specific failures]
Verification: [GBRAIN_VERIFY.md results]
🧠 Ready to populate your brain? I can connect your Google services,
import your notes, and pull in your conversations — all in one session.
→ Launching cold-start...
The output should transition directly into cold-start (Phase J), not end with a bullet list. The bullet list is for when the user defers cold-start.
Tools Used
gbrain init --non-interactive --url ...-- create braingbrain import <dir> --no-embed [--workers N]-- import filesgbrain search <query>-- search braingbrain doctor --json-- health checkgbrain check-update --json-- check for updatesgbrain embed refresh-- generate embeddingsgbrain embed --stale-- backfill missing embeddingsgbrain sync --repo <path>-- one-shot sync from brain repogbrain sync --watch --repo <path>-- continuous sync pollinggbrain config get sync.last_run-- check last sync timestampgbrain stats-- page count + embed coverage