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: ```bash . ~/.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: ```bash 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): ```bash 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 `gbrain` one 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: ```bash . ~/.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): ```bash 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): ```bash export DB_PASS=$(openssl rand -base64 24) ``` Set up a SIGINT trap (D12 basic recovery): ```bash 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: ```bash 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: 1. Login at https://supabase.com/dashboard 2. 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) 3. Wait ~2 min for the project to initialize 4. 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) ```bash # 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).** ```bash . ~/.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: ```bash 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 to `gstack-artifacts-init` in 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: > ELI10: The remote brain at `` is great for cross-machine knowledge, > but symbol queries like `gbrain code-def` / `code-refs` / `code-callers` need > 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) > ✅ Unlocks `gbrain code-def`, `code-refs`, `code-callers` per worktree > ✅ Independent engine — won't disturb remote brain or share transcripts > B) No, remote MCP only > ✅ Zero local state — only `~/.claude.json` MCP 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): ```bash ~/.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) ```bash # 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.