Files
gbrain/docs/INSTALL.md
T
Garry TanandClaude Fable 5 f15480b9d0 v0.42.75.0 fix(pglite): in-place WAL auto-repair for the macOS Aborted() startup crash (#2575, #223, #1670) (#3901)
* fix(pglite): in-place WAL auto-repair for the Aborted() startup crash (#223, #1670, #2575)

The 'macOS 26.x WASM bug' was a misdiagnosis: an unclean shutdown (typically
the OS-upgrade reboot) tears the data dir's WAL, and every subsequent open
fails WAL replay inside WASM with an opaque RuntimeError: Aborted(). This
ports the pg_resetwal recovery upstream rejected (electric-sql/pglite#994,
by @yestheboxer) and wires it into connect() as bounded auto-repair:

- src/core/pglite-resetwal.ts: pg_resetwal for PG17 NodeFS dirs, fail-closed
  layout validation, atomic+durable writes (tmp+fsync+rename), idempotent.
- src/core/pglite-repair.ts: whole-pg_wal-dir rename backup (zero transient
  disk), overwrite-order restore with mtime guard, cooldown sidecar +
  episode-scoped backup retention (newest 3 episodes), and a never-throws
  engine seam. Kill-switch: GBRAIN_PGLITE_WAL_REPAIR=off.
- pglite-engine.ts: verdict rename macos-26-3 -> wasm-abort, classifier now
  matches the real production message (it previously fell to 'unknown'),
  corrupt-beats-wasm precedence preserved, honest per-outcome error copy
  incl. the failed-not-restored arm, and repair only under a cleanly-acquired
  lock (new LockHandle.reaped provenance; never after reaping a holder).
- gbrain pglite-repair: manual dry-run/repair command (validate-before-lock,
  serve/reaped refusals, no --force by design).
- doctor: pglite_data_dir fs-check with recurrence escalation and backup
  inventory when a PGLite brain fails to connect.
- reinit-pglite: embedding flags default from file-only config so the
  recovery ladder's rebuild rung works bare mid-outage.
- stringifyPgliteInitError: message-less Emscripten ErrnoError objects no
  longer surface as [object Object].

Regression-tested against real brains: corrupt every WAL segment (truncate
and garbage variants), reopen, auto-repair fires, original rows readable,
process.exitCode stays contained (#2084).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(pglite): replace the macOS-26.x misdiagnosis with the corrupt-WAL recovery ladder

README + INSTALL.md shipped (via #1671) the claim that PGLite is incompatible
with macOS 26.x and that a Bun/WASM fix would restore it. The real cause is
torn WAL state from the upgrade reboot, now auto-repaired in place. Rewrites
those sections around the recovery ladder (auto-repair -> gbrain pglite-repair
-> reinit-pglite -> engine switch; native-Postgres recipe kept, credit
@roysaurav), adds the ENGINES.md troubleshooting section, updates the
KEY_FILES.md entries to current truth, files the two follow-up TODOs
(SIGTERM engine-close extension; pglite upgrade blocker), and regenerates
the llms bundles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(pglite): harden WAL auto-repair (pre-landing + adversarial review)

Review-army (security/testing/maintainability/perf) + Claude & Codex
adversarial passes on the WAL-repair wave. Correctness + safety hardening,
no behavior change to the happy path:

- Live-writer safety: repair refuses any reaped lock acquisition, a corrupt
  (unknowable-liveness) reap writes a cross-process quarantine marker that
  gates auto-repair AND the manual command for 10 min, isProcessAlive treats
  only ESRCH as dead (EPERM/malformed-pid read as alive), and a live
  postmaster.pid (native Postgres) is refused. Lock heartbeat + initial write
  are atomic (tmp+rename) so a torn read can't misclassify a healthy holder;
  an in-flight acquisition is no longer mistaken for corrupt.
- resetWal verifies the stored pg_control CRC before trusting/re-signing it —
  a damaged control file routes to rebuild instead of laundering corrupt
  checkpoint counters under a fresh CRC. Atomic 'wx' writes (no symlink
  follow), whole-pg_wal-dir rename backup, 64MB seg-size cap.
- Honest failure reporting: repairPgliteWal threads the real restore result
  out via WalRepairError so the 'failed-restored' vs 'failed-not-restored'
  message never lies; the not-restored copy names the correct restore paths.
- Episode lifecycle: episodes close on the next healthy connect (not just on
  a verified repair), a gutted (restored) backup loses its pin, stale (>24h)
  episode backups aren't reused, and the cooldown also caps repaired-only
  crash loops. Empty backup dirs are pruned on refusal.
- Command: rejects unknown flags and valueless --path (a destructive command
  must not silently mis-parse), confirm prompt goes to stderr (stdout stays
  clean for --json), embedding-flag defaults come from the config file only.
- Symlink confinement extended to global/; sidecar reuse path validated
  (prefix + no '..' + must still hold pg_wal); sidecar writes atomic.
- doctor recurrence escalation counts all attempts; data dir absolutized.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(pglite): current-state KEY_FILES + WAL-repair follow-up TODOs

KEY_FILES.md pglite entries updated to the hardened truth (reap marker +
quarantine, atomic writes, CRC gate, global-symlink refusal, WalRepairError,
episode lifecycle). TODOS.md files the deferred judgment-call follow-ups
(unclean-shutdown gate on auto-repair; non-gbrain pglite consumer boundary;
mixed-version torn-lock double-read).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore: bump version and changelog (v0.42.75.0)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 17:01:20 -07:00

7.3 KiB

Install

Three install paths. Pick one. Mix later if needed.

Already running OpenClaw or Hermes?

bun install -g github:garrytan/gbrain
gbrain init --pglite                  # 2 seconds; no server
gbrain skillpack scaffold --all       # 43 skills scaffolded into your agent workspace
gbrain doctor                         # green checks all the way down

Your agent now reads skills/RESOLVER.md once per request, routes intent to the right skill, executes. New entity mentions create new pages. Daily cron runs enrichment overnight.

Scaffolded skills are first-class files in your agent repo — edit freely. To pull upstream gbrain improvements later, gbrain skillpack reference <name> diffs your local copy vs the bundle. The legacy skillpack install managed-block model was retired in v0.36.0.0; if you're upgrading from an older release, run gbrain skillpack migrate-fence once to strip the legacy fence and keep your existing skill rows.

To upgrade later: gbrain upgrade runs schema migrations + post-upgrade prompts (chunker bumps, the v0.36.2.0 ZeroEntropy switch). Always TTY-only; non-TTY upgrades skip prompts with informational stderr lines.

2. CLI standalone

No agent platform, just shell + MCP-aware editor.

bun install -g github:garrytan/gbrain
gbrain init --pglite

If bun install -g hits a postinstall error (Bun blocks postinstall hooks in some environments), the CLI prints a recovery hint pointing at #218. Run gbrain doctor to diagnose, then gbrain apply-migrations --yes manually. The deterministic fallback is git clone https://github.com/garrytan/gbrain.git ~/gbrain && cd ~/gbrain && bun install && bun link.

The init flow detects your repo size and suggests Supabase for brains > 1000 markdown files. To switch later:

gbrain migrate --to supabase     # PGLite → Postgres
gbrain migrate --to pglite       # Postgres → PGLite (rare)

For shared / large / multi-machine deployments (a team or company brain with multiple users hitting one server over HTTP MCP with OAuth scoping per user), follow the dedicated walkthrough: Tutorial: set up GBrain as your company brain.

API keys live in ~/.gbrain/config.json (file plane) or env vars (OPENAI_API_KEY, OPENROUTER_API_KEY, ZEROENTROPY_API_KEY, VOYAGE_API_KEY, ANTHROPIC_API_KEY). Set via CLI:

gbrain config set zeroentropy_api_key sk-...
gbrain config set openrouter_api_key sk-or-...
gbrain config set anthropic_api_key sk-ant-...

Common follow-ups:

gbrain import ~/my-knowledge      # bulk-import a markdown folder
gbrain sync --watch               # live-sync a git repo (autopilot mode)
gbrain autopilot --install        # background daemon for nightly enrichment

Wire this same local brain into your coding agent — zero server, zero token:

claude mcp add gbrain -- gbrain serve    # Claude Code
codex  mcp add gbrain -- gbrain serve    # Codex

The agent spawns gbrain serve as a stdio subprocess against your local brain. Full walkthrough (both this local path and connecting to a remote brain), plus the brain-first protocol to paste into CLAUDE.md / AGENTS.md: Give your coding agent a memory.

3. MCP server (any MCP client)

gbrain serve                      # stdio MCP (Claude Desktop / Code / Cursor)
gbrain serve --http               # HTTP MCP with OAuth 2.1 + admin dashboard

Wire a coding agent to a remote brain in one command (when you have an HTTP server + a bearer token): gbrain connect prints a paste-ready setup block, or --install runs it and smoke-tests the token.

gbrain auth create "claude-code"
gbrain connect https://your-host/mcp --token gbrain_xxx                      # Claude Code (default)
gbrain connect https://your-host/mcp --token gbrain_xxx --agent codex        # Codex (env-var bearer)
gbrain connect https://your-host/mcp --agent perplexity --oauth --register   # Perplexity (OAuth)

Per-client setup guides live in docs/mcp/:

The HTTP server ships with an admin SPA at /admin, an SSE activity feed at /admin/events, DCR-style client registration, scope-gated read/write/admin access, and rate limiting.

Thin-client mode

Connect to someone else's brain without running a local engine:

gbrain init --mcp-only            # configures remote MCP, skips local DB

Useful for: team mounts, brain-as-a-service deployments, dev machines without disk space. Most local commands refuse with a paste-ready hint. See docs/architecture/topologies.md.

Verifying the install

gbrain doctor --json              # full health check
gbrain models                     # which AI models are configured for what
gbrain models doctor              # 1-token probe per configured model

If anything's yellow, gbrain doctor names the fix command in the message. Most issues are missing API keys or stale schema (gbrain upgrade --force-schema).

Troubleshooting

PGLite crashes on macOS 26.x (Tahoe)

This crash (RuntimeError: Aborted() at engine startup, typically first seen after a macOS upgrade) is not a macOS/WASM incompatibility. The upgrade reboot kills gbrain mid-write and tears the data dir's write-ahead log; every subsequent open then fails WAL replay. Recovery ladder:

  1. Auto-repair (default): just run any gbrain command — gbrain detects the abort, resets the WAL in place (data preserved; a backup of the pre-repair state is kept next to the data dir), and continues. Then run gbrain doctor.
  2. Manual repair: gbrain pglite-repair --dry-run to diagnose, gbrain pglite-repair --yes to repair in place.
  3. Rebuild: gbrain reinit-pglite (wipes and re-creates the brain from your brain repo; embedding settings default from your config).
  4. Switch engines — if you prefer a server database anyway, native Homebrew PostgreSQL works great and supports multiple concurrent agents:
# Install PostgreSQL + pgvector
brew install postgresql@17
brew services start postgresql@17
createdb gbrain

# Build pgvector from source (required for vector search)
cd /tmp && git clone --branch v0.8.0 https://github.com/pgvector/pgvector.git
cd pgvector && make && make install
psql gbrain -c "CREATE EXTENSION IF NOT EXISTS vector;"

# Point gbrain at your local Postgres
cat > ~/.gbrain/config.json << 'EOF'
{
  "engine": "postgres",
  "database_url": "postgresql://localhost:5432/gbrain",
  "schema_pack": "gbrain-base-v2"
}
EOF

# Run migrations and verify
gbrain apply-migrations --yes
gbrain doctor

Once gbrain doctor shows green, the brain works identically to PGLite — same commands, same skills, same data model. The only difference is the storage backend (plus multi-connection support: several agents can share one Postgres brain, which PGLite's single-process lock doesn't allow).