Brain-init (Paths 1/2/3/4 bodies), engine remediation, transcript gate, and CLAUDE.md persist load on demand — at most one install route ever runs. Skeleton 75.3KB -> 57.0KB; the Step 1 detect and Step 2 path dispatch stay always-loaded. New buildSetupGbrainFixture helper gives the periodic E2Es extract-don't-copy fixtures with a non-empty guard; the voyage-code-3 gate counts scan the tmpl union (the third init site lives in engine-remediation). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
12 KiB
Path-specific. Run ONLY the sub-section below for the path picked in Step 2 (or the Switch flow when Step 2 chose engine migration).
Path 1 (Supabase, existing URL)
Source the secret-read helper, collect URL with read -s + redacted preview:
. ~/.claude/skills/gstack/bin/gstack-gbrain-lib.sh
read_secret_to_env GBRAIN_POOLER_URL "Paste Session Pooler URL: " \
--echo-redacted 's#://[^@]*@#://***@#'
Then validate structurally:
printf '%s' "$GBRAIN_POOLER_URL" | ~/.claude/skills/gstack/bin/gstack-gbrain-supabase-verify -
If the verify exit code is 3 (direct-connection URL), the verifier's own message explains the fix; surface it and re-prompt for a Session Pooler URL.
On success, hand off to gbrain via env var (D10, never argv):
GBRAIN_DATABASE_URL="$GBRAIN_POOLER_URL" gbrain init --non-interactive --json
Then unset GBRAIN_POOLER_URL GBRAIN_DATABASE_URL immediately. The URL is
now persisted in ~/.gbrain/config.json at mode 0600 by gbrain itself.
Path 2a (Supabase, auto-provision — D7)
Show the D11 PAT scope disclosure verbatim BEFORE collecting the token:
This Supabase Personal Access Token grants full read/write/delete access to every project in your Supabase account, not just the
gbrainone we're about to create. Supabase doesn't currently support scoped tokens. We use this PAT only to: create one project, poll it until healthy, read the Session Pooler URL — then discard it from process memory. The token remains valid on Supabase's side until you manually revoke it at https://supabase.com/dashboard/account/tokens — we recommend revoking immediately after setup completes.
Then:
. ~/.claude/skills/gstack/bin/gstack-gbrain-lib.sh
read_secret_to_env SUPABASE_ACCESS_TOKEN "Paste PAT: "
Ask the D17 tier prompt via AskUserQuestion: "Which Supabase tier?" Present Free (2-project limit, pauses after 7d inactivity) vs Pro ($25/mo, no pauses, recommended for real use). Explain that tier is org-level (per the Management API contract) — user picks their org based on its current tier. Pro may require them to upgrade the org first at supabase.com.
List orgs, pick one (AskUserQuestion if multiple):
orgs=$(~/.claude/skills/gstack/bin/gstack-gbrain-supabase-provision list-orgs --json)
If the .orgs array is empty, surface: "Your Supabase account has no
organizations. Create one at https://supabase.com/dashboard, then re-run
/setup-gbrain." STOP.
Ask the user for a region (default us-east-1; valid values are the 18
enum values in the Supabase Management API — list a few common ones, let
them pick "Other" for a full list).
Generate the DB password (never shown to the user):
export DB_PASS=$(openssl rand -base64 24)
Set up a SIGINT trap (D12 basic recovery):
trap 'echo ""; echo "gstack-gbrain: interrupted. In-flight ref: $INFLIGHT_REF"; \
echo "Resume: /setup-gbrain --resume-provision $INFLIGHT_REF"; \
echo "Delete: https://supabase.com/dashboard/project/$INFLIGHT_REF"; \
unset SUPABASE_ACCESS_TOKEN DB_PASS; exit 130' INT TERM
Create + wait + fetch:
result=$(~/.claude/skills/gstack/bin/gstack-gbrain-supabase-provision \
create gbrain "$REGION" "$ORG_SLUG" --json)
INFLIGHT_REF=$(echo "$result" | jq -r .ref)
~/.claude/skills/gstack/bin/gstack-gbrain-supabase-provision wait "$INFLIGHT_REF" --json
pooler=$(~/.claude/skills/gstack/bin/gstack-gbrain-supabase-provision \
pooler-url "$INFLIGHT_REF" --json)
GBRAIN_DATABASE_URL=$(echo "$pooler" | jq -r .pooler_url)
export GBRAIN_DATABASE_URL
gbrain init --non-interactive --json
unset SUPABASE_ACCESS_TOKEN DB_PASS GBRAIN_DATABASE_URL INFLIGHT_REF
trap - INT TERM
After success, emit the PAT revocation reminder:
"Setup complete. Revoke the PAT you pasted at https://supabase.com/dashboard/account/tokens — we've already discarded it from memory and don't need it again. The gbrain project will continue working because it uses its own embedded database password."
Path 2b (Supabase, manual)
Walk the user through the supabase.com steps:
- Login at https://supabase.com/dashboard
- Click "New Project," name it
gbrain, pick a region, copy the generated database password (you'll need it for paste-back? no — it's embedded in the pooler URL we collect next) - Wait ~2 min for the project to initialize
- Settings → Database → Connection Pooler → Session → copy the URL (port 6543)
Then follow the same secret-read + verify + init flow as Path 1.
Path 3 (PGLite local)
# gstack default: voyage-code-3 (1024d) when VOYAGE_API_KEY is set — code
# retrieval beats general-purpose embeddings on real code queries (validated
# A/B). Without the key, gbrain auto-selects (OpenAI 1536d when available).
# Never select gbrain's legacy zeroentropyai recipe for a new brain: the hosted
# API sunsets September 4, 2026 (#2365); the wireup helper warns existing installs.
set -- # flags ride the positional params — unquoted $VAR breaks under zsh word-splitting (#1798)
if [ -n "${VOYAGE_API_KEY:-}" ]; then
set -- --embedding-model voyage:voyage-code-3 --embedding-dimensions 1024
fi
gbrain init --pglite --json "$@"
Done. No network, no secrets (beyond Voyage embedding API calls during sync, if
VOYAGE_API_KEY is set — ~$0.18 per 1M tokens, pennies per repo).
Path 4 (Remote gbrain MCP — HTTP transport with bearer token)
For users whose brain runs on another machine (Tailscale, ngrok, internal LAN, or a teammate's server). No local gbrain CLI install, no local DB. This skill registers the remote MCP and stops; ingestion + indexing happens on the brain host.
4a. Collect MCP URL. Prompt the user:
Paste your gbrain MCP URL (e.g. https://wintermute.tail554574.ts.net:3131/mcp):
Read with plain read -r (no secret hygiene needed — the URL alone isn't
a credential). Validate it starts with https:// (require TLS for any
non-loopback host); refuse http:// for non-localhost.
4b. Collect bearer token via the secret-read helper (D10, never argv).
. ~/.claude/skills/gstack/bin/gstack-gbrain-lib.sh
read_secret_to_env GBRAIN_MCP_TOKEN "Paste bearer token: " \
--echo-redacted 's/.\{6\}$/***REDACTED***/'
4c. Verify via gstack-gbrain-mcp-verify. Run the helper; capture the classified JSON output:
verify_json=$(GBRAIN_MCP_TOKEN="$GBRAIN_MCP_TOKEN" \
~/.claude/skills/gstack/bin/gstack-gbrain-mcp-verify "$MCP_URL")
status=$(echo "$verify_json" | jq -r .status)
If status != "success", the helper has already classified the failure
into NETWORK / AUTH / MALFORMED and emitted a one-line remediation hint.
Surface the hint above the raw error from error_text and STOP with
a clear "fix and re-run /setup-gbrain" message. Do NOT continue to Step 5a
on a failed verify — partial registration would leave the user with a
half-broken state.
Capture two values from the verify output for downstream steps:
SERVER_VERSION(e.g.,0.27.1) — written to the CLAUDE.md block in Step 8.URL_FORM_SUPPORTED(true|false) — passed togstack-artifacts-initin Step 7 to control which form of the brain-admin hookup command is printed.
4d. (Path 4) Offer local PGLite for code search. Per plan D10/D11, ask:
D# — Want symbol-aware code search on this machine? Project/branch/task: <one-sentence grounding using detected slug + branch> ELI10: The remote brain at
<MCP_URL>is great for cross-machine knowledge, but symbol queries likegbrain code-def/code-refs/code-callersneed a local index of THIS machine's code. We can spin up a tiny isolated PGLite database (~30 seconds, no accounts, ~120 MB disk) just for code, separate from your remote brain. Transcripts and artifacts continue routing through the artifacts repo to the remote brain — local PGLite stays code-only. Stakes: without it, semantic code search in this repo's worktrees falls back to Grep. Recommendation: A — 30 seconds, no ongoing cost, unlocks the symbol tools. Completeness: A=10/10 (full split-engine), B=7/10 (remote-only). A) Yes, set up local PGLite for code (recommended) ✅ Unlocksgbrain code-def,code-refs,code-callersper worktree ✅ Independent engine — won't disturb remote brain or share transcripts B) No, remote MCP only ✅ Zero local state — only~/.claude.jsonMCP registration ❌ Symbol code queries fall back to Grep in this repo's worktrees Net: A = full split-engine; B = remote-only.
If A (Yes): install + init local PGLite with rollback-safe semantics (D7):
~/.claude/skills/gstack/bin/gstack-gbrain-install || exit $?
# At this point the local gbrain CLI is on PATH. Init PGLite, but back up any
# existing ~/.gbrain/config.json first (rollback if init fails).
if [ -f "$HOME/.gbrain/config.json" ]; then
BACKUP="$HOME/.gbrain/config.json.gstack-bak-$(date +%s)"
mv "$HOME/.gbrain/config.json" "$BACKUP"
fi
# gstack default for local code-search PGLite: voyage-code-3 (1024d) when
# VOYAGE_API_KEY is set. It wins the A/B over voyage-4-large and OpenAI
# text-embedding-3-large on this codebase's symbol queries. Falls back to
# gbrain's auto-selected provider when the key isn't present.
set -- # flags ride the positional params — unquoted $VAR breaks under zsh word-splitting (#1798)
if [ -n "${VOYAGE_API_KEY:-}" ]; then
set -- --embedding-model voyage:voyage-code-3 --embedding-dimensions 1024
fi
if ! gbrain init --pglite --json "$@"; then
if [ -n "${BACKUP:-}" ] && [ -f "$BACKUP" ]; then mv "$BACKUP" "$HOME/.gbrain/config.json"; fi
echo "gbrain init failed. Existing config (if any) was restored. PGLite at ~/.gbrain/pglite/ may be in a partial state — \`rm -rf ~/.gbrain/pglite\` to reset." >&2
echo "Continuing setup without local code search; you can re-run /setup-gbrain to retry." >&2
fi
Then continue to Step 5a. The remote-http MCP registration in 5a runs as
today; the local PGLite is independent of MCP registration (Claude Code talks
to the remote brain via MCP for queries; gbrain CLI talks to local PGLite
for code-def/refs/callers).
If B (No): skip the install + init. The local engine stays absent.
gbrain_local_status will be missing-config (or no-cli if gbrain isn't
installed). /sync-gbrain will SKIP the code stage cleanly per plan D12.
4e. Skip Steps 3, 4 (other paths) and 5 (local doctor) when B was picked.
When A was picked, Step 3 already ran (via gstack-gbrain-install) and Step 4
already ran (via gbrain init --pglite); jump straight to Step 5a. When B
was picked, Steps 3/4/5 are no-ops; also skip Step 7.5 (transcript ingest)
since memory-stage routes through the artifacts pipeline in remote-http mode
per plan D11.
The bearer token (GBRAIN_MCP_TOKEN) stays in process env until Step 5a's
claude mcp add --header consumes it; then unset GBRAIN_MCP_TOKEN
immediately. Token security trade-off documented in
setup-gbrain/memory.md: brief argv exposure during claude mcp add,
resting state in ~/.claude.json mode 0600.
Switch (from detect's existing-engine state)
# Going PGLite → Supabase, collect URL first (Path 1 flow), then:
timeout 180s gbrain migrate --to supabase --url "$URL" --json
# Going Supabase → PGLite:
timeout 180s gbrain migrate --to pglite --json
If timeout returns 124 (exit code for timeout): surface D9 message
("Migration didn't complete in 3 minutes — another gstack session may be
holding a lock on the source brain. Close other workspaces and re-run
/setup-gbrain --switch. Your original brain is untouched."). STOP.