From 7b9c2f68d42d77c4f726c7a9efd94e4af3e022f8 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Wed, 6 May 2026 09:24:52 -0700 Subject: [PATCH] feat: setup-gbrain Path 4 (remote MCP) + artifacts rename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Path 4 lets users paste an HTTPS MCP URL + bearer token and registers it as an HTTP-transport MCP without needing a local gbrain CLI install. The flow: - Step 2 gains a fourth option (Remote gbrain MCP) - Step 4 adds Path 4 sub-flow: collect URL, secret-read bearer, verify via gstack-gbrain-mcp-verify (NETWORK / AUTH / MALFORMED classifier) - Step 5 (local doctor), Step 7.5 (transcript ingest), Step 5a's stdio branch all skip on Path 4 - Step 5a adds an HTTP+bearer registration form: claude mcp add --transport http --header "Authorization: Bearer ..." - Step 7 renamed "session memory sync" → "artifacts sync" and now calls gstack-artifacts-init (which always prints the brain-admin hookup command — no auto-execute, codex Finding #3) - Step 8 CLAUDE.md block branches: remote-http includes URL + server version (never the token); local-stdio keeps engine + config-file - Step 9 smoke test on Path 4 prints the curl-equivalent for post-restart verification (MCP tools aren't visible mid-session) - Step 10 verdict block has separate templates per mode Idempotency: re-running with gbrain_mcp_mode=remote-http already in detect output skips Step 2 entirely and goes to verification. Co-Authored-By: Claude Opus 4.7 (1M context) --- setup-gbrain/SKILL.md | 265 +++++++++++++++++++++++++++++++++---- setup-gbrain/SKILL.md.tmpl | 265 +++++++++++++++++++++++++++++++++---- 2 files changed, 472 insertions(+), 58 deletions(-) diff --git a/setup-gbrain/SKILL.md b/setup-gbrain/SKILL.md index 522ac792..44607b30 100644 --- a/setup-gbrain/SKILL.md +++ b/setup-gbrain/SKILL.md @@ -758,7 +758,12 @@ invocation flags here and skip to the matching step. ## Step 2: Pick a path (AskUserQuestion) Only fire this if Step 1 shows no existing working config AND no shortcut -flag was passed. The question title: "Where should your brain live?" +flag was passed. **Special case:** if `gbrain_mcp_mode=remote-http` in the +detect output, an HTTP MCP is already registered — skip directly to Step 5a +verification (re-test the registration) and Step 6 onward, treating this run +as idempotent. Don't ask Step 2 again. + +The question title: "Where should your brain live?" Options (present based on detected state): @@ -775,6 +780,11 @@ Options (present based on detected state): yourself; paste the URL back when ready. - **3 — PGLite local.** Zero accounts, ~30 seconds. Isolated brain on this Mac only. Best for try-first. +- **4 — Remote gbrain MCP.** Someone else (or another machine of yours) is + already running `gbrain serve` with HTTP transport. You paste the MCP URL + + a bearer token; this skill registers it as your MCP. No local brain DB, + no local install needed. Recommended when the brain is shared across + machines or run by a teammate. - **Switch** (only if Step 1 detected an existing engine): "You already have a `` brain. Migrate it to the other engine?" → runs `gbrain migrate --to ` wrapped in `timeout 180s` (D9). @@ -785,7 +795,11 @@ Do NOT silently pick; fire the AskUserQuestion. ## Step 3: Install gbrain CLI (if missing) -Only if `gbrain_on_path=false`: +**SKIP entirely on Path 4 (Remote MCP).** Path 4 doesn't need a local gbrain +binary — all calls go through MCP to the remote server. Jump to Step 4 (the +Path 4 subsection). + +For Paths 1, 2a, 2b, 3, switch — only if `gbrain_on_path=false`: ```bash ~/.claude/skills/gstack/bin/gstack-gbrain-install @@ -930,6 +944,64 @@ gbrain init --pglite --json Done. No network, no secrets. +### 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. Skip Steps 3, 4 (other paths), 5 (local doctor), 7.5 (transcript ingest).** +All four require a working local `gbrain` CLI that Path 4 does not install. +The skill jumps straight to Step 5a (HTTP+bearer registration) → Step 6 +(per-remote policy) → Step 7 (artifacts repo) → Step 8 (CLAUDE.md) → Step 9 +(remote smoke test) → Step 10 (verdict). + +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 @@ -948,6 +1020,13 @@ holding a lock on the source brain. Close other workspaces and re-run ## Step 5: Verify gbrain doctor +**SKIP entirely on Path 4 (Remote MCP).** The brain host runs its own +doctor; we don't have local DB access to introspect. Step 4c's verify +round-trip already proved the server is reachable, authed, and on a +compatible MCP version. + +For Paths 1, 2a, 2b, 3, switch: + ```bash doctor=$(gbrain doctor --json) status=$(echo "$doctor" | jq -r .status) @@ -963,7 +1042,33 @@ doctor output and STOP. Only if `which claude` resolves. Ask: "Give Claude Code a typed tool surface for gbrain? (recommended yes)" -If yes, register at **user scope** with an **absolute path** to the gbrain +The registration form depends on the path picked in Step 2: + +### Path 4 (Remote MCP — HTTP transport with bearer) + +Tear down any prior registration (could be local-stdio from an old setup, +or stale remote-http with a rotated token), then register with HTTP + +bearer at user scope: + +```bash +claude mcp remove gbrain -s user 2>/dev/null || true +claude mcp remove gbrain 2>/dev/null || true +claude mcp add --scope user --transport http gbrain "$MCP_URL" \ + --header "Authorization: Bearer $GBRAIN_MCP_TOKEN" +unset GBRAIN_MCP_TOKEN # zero from process env after registration +claude mcp list | grep gbrain # verify: should show "✓ Connected" +``` + +**Token-storage note:** `claude mcp add --header "Authorization: Bearer ..."` +puts the bearer on argv during process startup, briefly visible to `ps` for +~10ms. The token's resting state is `~/.claude.json` (mode 0600 — Claude +Code's own credential surface for every MCP server). This trade-off is +documented in `setup-gbrain/memory.md`. If a future Claude Code release adds +a stdin or env-var input form for headers, switch to that. + +### Paths 1, 2a, 2b, 3 (Local stdio) + +Register at **user scope** with an **absolute path** to the gbrain binary. User scope makes the MCP available in every Claude Code session on this machine, not just the current workspace. Absolute path avoids PATH resolution issues when Claude Code spawns `gbrain serve` as a subprocess. @@ -971,19 +1076,17 @@ resolution issues when Claude Code spawns `gbrain serve` as a subprocess. ```bash GBRAIN_BIN=$(command -v gbrain) [ -z "$GBRAIN_BIN" ] && GBRAIN_BIN="$HOME/.bun/bin/gbrain" +claude mcp remove gbrain -s user 2>/dev/null || true +claude mcp remove gbrain 2>/dev/null || true claude mcp add --scope user gbrain -- "$GBRAIN_BIN" serve claude mcp list | grep gbrain # verify: should show "✓ Connected" ``` -If the user already had a local-scope registration from an earlier run, -remove it first so both scopes don't conflict: -```bash -claude mcp remove gbrain 2>/dev/null || true -``` +### Both paths If `claude` is not on PATH: emit "MCP registration skipped — this skill is -Claude-Code-targeted; register `gbrain serve` in your agent's MCP config -manually." Continue to step 6. +Claude-Code-targeted; register `gbrain serve` (or your remote MCP URL) in +your agent's MCP config manually." Continue to step 6. **Heads-up for the user:** an already-open Claude Code session will not pick up the new MCP tools until restart. Tell them: "Restart any open @@ -1025,30 +1128,53 @@ For `/setup-gbrain --repo` invocations, execute ONLY Step 6 and exit. --- -## Step 7: Offer gstack-brain-sync + wire it into gbrain +## Step 7: Offer artifacts sync + wire it into gbrain -Separate AskUserQuestion: "Also sync your gstack session memory (learnings, -plans, retros) to a private git repo that gbrain can index across machines?" +Renamed from "session memory sync" in v1.27.0.0 — the on-disk concept is +artifacts (CEO plans, designs, /investigate reports, retros) rather than +"session memory," which was a confusing name for what was always a +human-readable artifact bucket. Behavioral transcript ingest is its own +step (7.5) with its own option set. + +Separate AskUserQuestion: "Also sync your gstack artifacts (CEO plans, +designs, reports, retros) to a private git repo that gbrain can index +across machines?" Options: - Yes, full sync (everything allowlisted) - Yes, artifacts-only (plans, designs, retros — skip behavioral data) - No thanks -If yes: +If yes, run the artifacts-init helper. It asks the user to pick a git host +(GitHub via `gh`, GitLab via `glab`, or paste a URL manually), creates +`gstack-artifacts-$USER` (private), and writes the canonical HTTPS URL to +`~/.gstack-artifacts-remote.txt`. Pass `--url-form-supported` from Step 4c's +verify output (Path 4) or `false` (Paths 1/2/3 — local mode doesn't probe): ```bash -~/.claude/skills/gstack/bin/gstack-brain-init -~/.claude/skills/gstack/bin/gstack-config set gbrain_sync_mode artifacts-only +URL_FORM=${URL_FORM_SUPPORTED:-false} +~/.claude/skills/gstack/bin/gstack-artifacts-init --url-form-supported "$URL_FORM" +~/.claude/skills/gstack/bin/gstack-config set artifacts_sync_mode artifacts-only # or "full" if user picked yes-full ``` -Then wire the brain repo into gbrain so its content is searchable from any -gbrain client (this Claude Code session, future Macs, optional cloud agents). -The helper creates a `git worktree` of `~/.gstack/`, registers it as a -federated source on the user's gbrain (Supabase or PGLite), and runs an -initial `gbrain sync`. Local-Mac only. No cloud agent required. Subsequent -skill runs trigger incremental sync via the existing skill-end push hook. +`gstack-artifacts-init` always prints a "Send this to your brain admin" block +at the end with the exact `gbrain sources add` command. Per codex Finding #3: +the skill never auto-executes server-side gbrain commands; even if the user +IS the brain admin, copy-pasting the printed command is the consistent UX. + +### Path 4 (Remote MCP) — done after artifacts-init + +In remote mode, the local `gstack-gbrain-source-wireup` helper does NOT run +(it shells out to a local `gbrain` CLI which Path 4 doesn't install). The +brain admin runs the printed command on the brain host instead. Skip to Step 7.5. + +### Paths 1, 2a, 2b, 3 (Local stdio) — wire up the federated source + +Then wire the artifacts repo into gbrain so its content is searchable from +any gbrain client. The helper creates a `git worktree` of `~/.gstack/`, +registers it as a federated source via `gbrain sources add --path +--federated`, and runs an initial `gbrain sync`. Local-Mac only. Capture the database URL out of `~/.gbrain/config.json` first and pass it explicitly so the wireup is robust against any other process rewriting @@ -1078,6 +1204,15 @@ the prereq is fixed. ## Step 7.5: Transcript & memory ingest gate +**SKIP entirely on Path 4 (Remote MCP).** Transcript ingest shells out to +the local `gbrain` CLI which Path 4 doesn't install. Remote-mode users +rely on the brain server's own ingest cadence — if your brain admin wants +this machine's transcripts indexed, they pull from your `gstack-artifacts-$USER` +repo (set up in Step 7) on whatever schedule they prefer. Set +`gstack-config set transcript_ingest_mode off` and continue to Step 8. + +For Paths 1, 2a, 2b, 3: + After memory sync is wired (Step 7) but before persisting the CLAUDE.md config (Step 8), offer to bring this Mac's coding-agent transcripts + curated `~/.gstack/` artifacts into gbrain so the retrieval surface @@ -1147,15 +1282,37 @@ Step 8). ## Step 8: Persist `## GBrain Configuration` in CLAUDE.md -Find-and-replace (or append) this section in CLAUDE.md: +Find-and-replace (or append) the section. Block format depends on mode: + +### Path 4 (Remote MCP) ```markdown ## GBrain Configuration (configured by /setup-gbrain) +- Mode: remote-http +- MCP URL: {MCP_URL} +- Server version: gbrain v{SERVER_VERSION} (from Step 4c verify) +- Setup date: {today} +- MCP registered: yes (user scope) +- Token: stored in ~/.claude.json (do not commit; never written to CLAUDE.md) +- Artifacts repo: {gstack_artifacts_remote URL or "none"} +- Artifacts sync: {off|artifacts-only|full} +- Current repo policy: {read-write|read-only|deny|unset} +``` + +The bearer token is **never** written to CLAUDE.md (CLAUDE.md is checked +in to git in many projects). It lives only in `~/.claude.json` where +`claude mcp add` placed it. + +### Paths 1, 2a, 2b, 3 (Local stdio) + +```markdown +## GBrain Configuration (configured by /setup-gbrain) +- Mode: local-stdio - Engine: {pglite|postgres} - Config file: ~/.gbrain/config.json (mode 0600) - Setup date: {today} - MCP registered: {yes/no} -- Memory sync: {off|artifacts-only|full} +- Artifacts sync: {off|artifacts-only|full} - Current repo policy: {read-write|read-only|deny|unset} ``` @@ -1207,6 +1364,34 @@ the round-trip works. ## Step 9: Smoke test +### Path 4 (Remote MCP) + +The `mcp__gbrain__*` tools aren't visible mid-session — they're loaded at +Claude Code session start. So the live smoke test in this same skill run is +informational: print the curl-equivalent the user can run after restarting +Claude Code. The verify round-trip in Step 4c already proved the server is +reachable + authed + on a compatible MCP version, so we don't re-test that. + +Print to stdout: + +``` +After restarting Claude Code, the `mcp__gbrain__*` tools become callable. +Smoke test: ask the agent to run `mcp__gbrain__search` with any query +("test page" works). You should see a JSON list of pages. + +To verify from the shell right now (without waiting for restart): + curl -s -X POST -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -H 'Authorization: Bearer ' \ + -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \ + +``` + +Do NOT print the actual token in the curl command — leave the placeholder +`` so the snippet is safe to copy into chat / share. + +### Paths 1, 2a, 2b, 3 (Local stdio) + ```bash SLUG="setup-gbrain-smoke-test-$(date +%s)" echo "Set up on $(date). Smoke test for /setup-gbrain." | gbrain put "$SLUG" @@ -1227,15 +1412,37 @@ state, repairs only what's missing, and reports here. ```bash ~/.claude/skills/gstack/bin/gstack-gbrain-detect 2>/dev/null || true ~/.claude/skills/gstack/bin/gstack-config get transcript_ingest_mode 2>/dev/null || echo "off" -~/.claude/skills/gstack/bin/gstack-config get gbrain_sync_mode 2>/dev/null || echo "off" +~/.claude/skills/gstack/bin/gstack-config get artifacts_sync_mode 2>/dev/null || echo "off" [ -f ~/.gstack/.gbrain-sync-state.json ] && cat ~/.gstack/.gbrain-sync-state.json || echo "{}" ``` -Print the verdict block. Each row is `[OK]/[FIX]/[WARN]/[ERR]` — see -template below; substitute your detect outputs: +Read `gbrain_mcp_mode` from the detect output and pick the right verdict +template. Each row is `[OK]/[FIX]/[WARN]/[ERR]`. + +### Path 4 (Remote MCP) ``` -gbrain status: GREEN +gbrain status: GREEN (mode: remote-http) + + MCP ............. OK {SERVER_NAME} v{SERVER_VERSION} at {MCP_URL} + Auth ............ OK bearer accepted (verified via /tools/list) + Engine .......... N/A remote mode + Doctor .......... N/A remote mode (brain admin runs `gbrain doctor`) + Repo policy ..... OK {read-write|read-only|deny} + Artifacts repo .. OK {gstack_artifacts_remote URL} + Artifacts sync .. OK {artifacts_sync_mode} + Transcripts ..... N/A remote mode (ingest happens on brain host) + CLAUDE.md ....... OK + Smoke test ...... INFO printed for post-restart manual verification + +Restart Claude Code to pick up the `mcp__gbrain__*` tools. +Re-run `/setup-gbrain` any time the bearer rotates or the URL moves. +``` + +### Paths 1, 2a, 2b, 3 (Local stdio) + +``` +gbrain status: GREEN (mode: local-stdio) CLI ............. OK Engine .......... OK at @@ -1243,7 +1450,7 @@ gbrain status: GREEN MCP ............. OK registered (user scope) Repo policy ..... OK Code import ..... OK - Memory sync ..... OK to + Artifacts sync .. OK to Transcripts ..... OK sessions, last ingest CLAUDE.md ....... OK Smoke test ...... OK put → search → delete round-trip diff --git a/setup-gbrain/SKILL.md.tmpl b/setup-gbrain/SKILL.md.tmpl index fb748044..a2a49cee 100644 --- a/setup-gbrain/SKILL.md.tmpl +++ b/setup-gbrain/SKILL.md.tmpl @@ -80,7 +80,12 @@ invocation flags here and skip to the matching step. ## Step 2: Pick a path (AskUserQuestion) Only fire this if Step 1 shows no existing working config AND no shortcut -flag was passed. The question title: "Where should your brain live?" +flag was passed. **Special case:** if `gbrain_mcp_mode=remote-http` in the +detect output, an HTTP MCP is already registered — skip directly to Step 5a +verification (re-test the registration) and Step 6 onward, treating this run +as idempotent. Don't ask Step 2 again. + +The question title: "Where should your brain live?" Options (present based on detected state): @@ -97,6 +102,11 @@ Options (present based on detected state): yourself; paste the URL back when ready. - **3 — PGLite local.** Zero accounts, ~30 seconds. Isolated brain on this Mac only. Best for try-first. +- **4 — Remote gbrain MCP.** Someone else (or another machine of yours) is + already running `gbrain serve` with HTTP transport. You paste the MCP URL + + a bearer token; this skill registers it as your MCP. No local brain DB, + no local install needed. Recommended when the brain is shared across + machines or run by a teammate. - **Switch** (only if Step 1 detected an existing engine): "You already have a `` brain. Migrate it to the other engine?" → runs `gbrain migrate --to ` wrapped in `timeout 180s` (D9). @@ -107,7 +117,11 @@ Do NOT silently pick; fire the AskUserQuestion. ## Step 3: Install gbrain CLI (if missing) -Only if `gbrain_on_path=false`: +**SKIP entirely on Path 4 (Remote MCP).** Path 4 doesn't need a local gbrain +binary — all calls go through MCP to the remote server. Jump to Step 4 (the +Path 4 subsection). + +For Paths 1, 2a, 2b, 3, switch — only if `gbrain_on_path=false`: ```bash ~/.claude/skills/gstack/bin/gstack-gbrain-install @@ -252,6 +266,64 @@ gbrain init --pglite --json Done. No network, no secrets. +### 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. Skip Steps 3, 4 (other paths), 5 (local doctor), 7.5 (transcript ingest).** +All four require a working local `gbrain` CLI that Path 4 does not install. +The skill jumps straight to Step 5a (HTTP+bearer registration) → Step 6 +(per-remote policy) → Step 7 (artifacts repo) → Step 8 (CLAUDE.md) → Step 9 +(remote smoke test) → Step 10 (verdict). + +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 @@ -270,6 +342,13 @@ holding a lock on the source brain. Close other workspaces and re-run ## Step 5: Verify gbrain doctor +**SKIP entirely on Path 4 (Remote MCP).** The brain host runs its own +doctor; we don't have local DB access to introspect. Step 4c's verify +round-trip already proved the server is reachable, authed, and on a +compatible MCP version. + +For Paths 1, 2a, 2b, 3, switch: + ```bash doctor=$(gbrain doctor --json) status=$(echo "$doctor" | jq -r .status) @@ -285,7 +364,33 @@ doctor output and STOP. Only if `which claude` resolves. Ask: "Give Claude Code a typed tool surface for gbrain? (recommended yes)" -If yes, register at **user scope** with an **absolute path** to the gbrain +The registration form depends on the path picked in Step 2: + +### Path 4 (Remote MCP — HTTP transport with bearer) + +Tear down any prior registration (could be local-stdio from an old setup, +or stale remote-http with a rotated token), then register with HTTP + +bearer at user scope: + +```bash +claude mcp remove gbrain -s user 2>/dev/null || true +claude mcp remove gbrain 2>/dev/null || true +claude mcp add --scope user --transport http gbrain "$MCP_URL" \ + --header "Authorization: Bearer $GBRAIN_MCP_TOKEN" +unset GBRAIN_MCP_TOKEN # zero from process env after registration +claude mcp list | grep gbrain # verify: should show "✓ Connected" +``` + +**Token-storage note:** `claude mcp add --header "Authorization: Bearer ..."` +puts the bearer on argv during process startup, briefly visible to `ps` for +~10ms. The token's resting state is `~/.claude.json` (mode 0600 — Claude +Code's own credential surface for every MCP server). This trade-off is +documented in `setup-gbrain/memory.md`. If a future Claude Code release adds +a stdin or env-var input form for headers, switch to that. + +### Paths 1, 2a, 2b, 3 (Local stdio) + +Register at **user scope** with an **absolute path** to the gbrain binary. User scope makes the MCP available in every Claude Code session on this machine, not just the current workspace. Absolute path avoids PATH resolution issues when Claude Code spawns `gbrain serve` as a subprocess. @@ -293,19 +398,17 @@ resolution issues when Claude Code spawns `gbrain serve` as a subprocess. ```bash GBRAIN_BIN=$(command -v gbrain) [ -z "$GBRAIN_BIN" ] && GBRAIN_BIN="$HOME/.bun/bin/gbrain" +claude mcp remove gbrain -s user 2>/dev/null || true +claude mcp remove gbrain 2>/dev/null || true claude mcp add --scope user gbrain -- "$GBRAIN_BIN" serve claude mcp list | grep gbrain # verify: should show "✓ Connected" ``` -If the user already had a local-scope registration from an earlier run, -remove it first so both scopes don't conflict: -```bash -claude mcp remove gbrain 2>/dev/null || true -``` +### Both paths If `claude` is not on PATH: emit "MCP registration skipped — this skill is -Claude-Code-targeted; register `gbrain serve` in your agent's MCP config -manually." Continue to step 6. +Claude-Code-targeted; register `gbrain serve` (or your remote MCP URL) in +your agent's MCP config manually." Continue to step 6. **Heads-up for the user:** an already-open Claude Code session will not pick up the new MCP tools until restart. Tell them: "Restart any open @@ -347,30 +450,53 @@ For `/setup-gbrain --repo` invocations, execute ONLY Step 6 and exit. --- -## Step 7: Offer gstack-brain-sync + wire it into gbrain +## Step 7: Offer artifacts sync + wire it into gbrain -Separate AskUserQuestion: "Also sync your gstack session memory (learnings, -plans, retros) to a private git repo that gbrain can index across machines?" +Renamed from "session memory sync" in v1.27.0.0 — the on-disk concept is +artifacts (CEO plans, designs, /investigate reports, retros) rather than +"session memory," which was a confusing name for what was always a +human-readable artifact bucket. Behavioral transcript ingest is its own +step (7.5) with its own option set. + +Separate AskUserQuestion: "Also sync your gstack artifacts (CEO plans, +designs, reports, retros) to a private git repo that gbrain can index +across machines?" Options: - Yes, full sync (everything allowlisted) - Yes, artifacts-only (plans, designs, retros — skip behavioral data) - No thanks -If yes: +If yes, run the artifacts-init helper. It asks the user to pick a git host +(GitHub via `gh`, GitLab via `glab`, or paste a URL manually), creates +`gstack-artifacts-$USER` (private), and writes the canonical HTTPS URL to +`~/.gstack-artifacts-remote.txt`. Pass `--url-form-supported` from Step 4c's +verify output (Path 4) or `false` (Paths 1/2/3 — local mode doesn't probe): ```bash -~/.claude/skills/gstack/bin/gstack-brain-init -~/.claude/skills/gstack/bin/gstack-config set gbrain_sync_mode artifacts-only +URL_FORM=${URL_FORM_SUPPORTED:-false} +~/.claude/skills/gstack/bin/gstack-artifacts-init --url-form-supported "$URL_FORM" +~/.claude/skills/gstack/bin/gstack-config set artifacts_sync_mode artifacts-only # or "full" if user picked yes-full ``` -Then wire the brain repo into gbrain so its content is searchable from any -gbrain client (this Claude Code session, future Macs, optional cloud agents). -The helper creates a `git worktree` of `~/.gstack/`, registers it as a -federated source on the user's gbrain (Supabase or PGLite), and runs an -initial `gbrain sync`. Local-Mac only. No cloud agent required. Subsequent -skill runs trigger incremental sync via the existing skill-end push hook. +`gstack-artifacts-init` always prints a "Send this to your brain admin" block +at the end with the exact `gbrain sources add` command. Per codex Finding #3: +the skill never auto-executes server-side gbrain commands; even if the user +IS the brain admin, copy-pasting the printed command is the consistent UX. + +### Path 4 (Remote MCP) — done after artifacts-init + +In remote mode, the local `gstack-gbrain-source-wireup` helper does NOT run +(it shells out to a local `gbrain` CLI which Path 4 doesn't install). The +brain admin runs the printed command on the brain host instead. Skip to Step 7.5. + +### Paths 1, 2a, 2b, 3 (Local stdio) — wire up the federated source + +Then wire the artifacts repo into gbrain so its content is searchable from +any gbrain client. The helper creates a `git worktree` of `~/.gstack/`, +registers it as a federated source via `gbrain sources add --path +--federated`, and runs an initial `gbrain sync`. Local-Mac only. Capture the database URL out of `~/.gbrain/config.json` first and pass it explicitly so the wireup is robust against any other process rewriting @@ -400,6 +526,15 @@ the prereq is fixed. ## Step 7.5: Transcript & memory ingest gate +**SKIP entirely on Path 4 (Remote MCP).** Transcript ingest shells out to +the local `gbrain` CLI which Path 4 doesn't install. Remote-mode users +rely on the brain server's own ingest cadence — if your brain admin wants +this machine's transcripts indexed, they pull from your `gstack-artifacts-$USER` +repo (set up in Step 7) on whatever schedule they prefer. Set +`gstack-config set transcript_ingest_mode off` and continue to Step 8. + +For Paths 1, 2a, 2b, 3: + After memory sync is wired (Step 7) but before persisting the CLAUDE.md config (Step 8), offer to bring this Mac's coding-agent transcripts + curated `~/.gstack/` artifacts into gbrain so the retrieval surface @@ -469,15 +604,37 @@ Step 8). ## Step 8: Persist `## GBrain Configuration` in CLAUDE.md -Find-and-replace (or append) this section in CLAUDE.md: +Find-and-replace (or append) the section. Block format depends on mode: + +### Path 4 (Remote MCP) ```markdown ## GBrain Configuration (configured by /setup-gbrain) +- Mode: remote-http +- MCP URL: {MCP_URL} +- Server version: gbrain v{SERVER_VERSION} (from Step 4c verify) +- Setup date: {today} +- MCP registered: yes (user scope) +- Token: stored in ~/.claude.json (do not commit; never written to CLAUDE.md) +- Artifacts repo: {gstack_artifacts_remote URL or "none"} +- Artifacts sync: {off|artifacts-only|full} +- Current repo policy: {read-write|read-only|deny|unset} +``` + +The bearer token is **never** written to CLAUDE.md (CLAUDE.md is checked +in to git in many projects). It lives only in `~/.claude.json` where +`claude mcp add` placed it. + +### Paths 1, 2a, 2b, 3 (Local stdio) + +```markdown +## GBrain Configuration (configured by /setup-gbrain) +- Mode: local-stdio - Engine: {pglite|postgres} - Config file: ~/.gbrain/config.json (mode 0600) - Setup date: {today} - MCP registered: {yes/no} -- Memory sync: {off|artifacts-only|full} +- Artifacts sync: {off|artifacts-only|full} - Current repo policy: {read-write|read-only|deny|unset} ``` @@ -529,6 +686,34 @@ the round-trip works. ## Step 9: Smoke test +### Path 4 (Remote MCP) + +The `mcp__gbrain__*` tools aren't visible mid-session — they're loaded at +Claude Code session start. So the live smoke test in this same skill run is +informational: print the curl-equivalent the user can run after restarting +Claude Code. The verify round-trip in Step 4c already proved the server is +reachable + authed + on a compatible MCP version, so we don't re-test that. + +Print to stdout: + +``` +After restarting Claude Code, the `mcp__gbrain__*` tools become callable. +Smoke test: ask the agent to run `mcp__gbrain__search` with any query +("test page" works). You should see a JSON list of pages. + +To verify from the shell right now (without waiting for restart): + curl -s -X POST -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -H 'Authorization: Bearer ' \ + -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \ + +``` + +Do NOT print the actual token in the curl command — leave the placeholder +`` so the snippet is safe to copy into chat / share. + +### Paths 1, 2a, 2b, 3 (Local stdio) + ```bash SLUG="setup-gbrain-smoke-test-$(date +%s)" echo "Set up on $(date). Smoke test for /setup-gbrain." | gbrain put "$SLUG" @@ -549,15 +734,37 @@ state, repairs only what's missing, and reports here. ```bash ~/.claude/skills/gstack/bin/gstack-gbrain-detect 2>/dev/null || true ~/.claude/skills/gstack/bin/gstack-config get transcript_ingest_mode 2>/dev/null || echo "off" -~/.claude/skills/gstack/bin/gstack-config get gbrain_sync_mode 2>/dev/null || echo "off" +~/.claude/skills/gstack/bin/gstack-config get artifacts_sync_mode 2>/dev/null || echo "off" [ -f ~/.gstack/.gbrain-sync-state.json ] && cat ~/.gstack/.gbrain-sync-state.json || echo "{}" ``` -Print the verdict block. Each row is `[OK]/[FIX]/[WARN]/[ERR]` — see -template below; substitute your detect outputs: +Read `gbrain_mcp_mode` from the detect output and pick the right verdict +template. Each row is `[OK]/[FIX]/[WARN]/[ERR]`. + +### Path 4 (Remote MCP) ``` -gbrain status: GREEN +gbrain status: GREEN (mode: remote-http) + + MCP ............. OK {SERVER_NAME} v{SERVER_VERSION} at {MCP_URL} + Auth ............ OK bearer accepted (verified via /tools/list) + Engine .......... N/A remote mode + Doctor .......... N/A remote mode (brain admin runs `gbrain doctor`) + Repo policy ..... OK {read-write|read-only|deny} + Artifacts repo .. OK {gstack_artifacts_remote URL} + Artifacts sync .. OK {artifacts_sync_mode} + Transcripts ..... N/A remote mode (ingest happens on brain host) + CLAUDE.md ....... OK + Smoke test ...... INFO printed for post-restart manual verification + +Restart Claude Code to pick up the `mcp__gbrain__*` tools. +Re-run `/setup-gbrain` any time the bearer rotates or the URL moves. +``` + +### Paths 1, 2a, 2b, 3 (Local stdio) + +``` +gbrain status: GREEN (mode: local-stdio) CLI ............. OK Engine .......... OK at @@ -565,7 +772,7 @@ gbrain status: GREEN MCP ............. OK registered (user scope) Repo policy ..... OK Code import ..... OK - Memory sync ..... OK to + Artifacts sync .. OK to Transcripts ..... OK sessions, last ingest CLAUDE.md ....... OK Smoke test ...... OK put → search → delete round-trip