* feat(core): execution-environment detection — local | cloud-sandbox | ephemeral-container detectExecutionEnvironment() + isCredentialInjectingProxy() with injected signals (CLAUDE_CODE_REMOTE, cse_ session-id prefix, proxy-injected token placeholder, anthropic-egress proxy JWT, container markers). binaryOnPath moves here as the canonical PATH probe. autopilot's detectInstallTarget ephemeral branch now routes through the shared detector. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): repo-visibility ladder + per-turn Stop push + same-session failure banner The durability lane. One repo-visibility verdict for every consumer (REST first — never GraphQL, which sandbox proxies pin; authed ls-remote + an attributed anonymous probe as the git-protocol fallback), replacing three drifted probes. A 200 counts as public only with advertisement proof; a 401/404 counts as private-signal only with an auth challenge — fail-closed in BOTH directions. Private verdicts cache 1h (private-only, per origin). gbrain hook stop now spawns a debounced detached push per turn (per-root state; cloud-sandbox defaults to every turn, elsewhere 5 min; a failing status bypasses the debounce), closing the /exit and VM-reclaim gaps. Push status is per workspace root, read through one shared reader by the user-prompt banner (additionalContext + systemMessage — visible to the human, not just the model), the SessionStart note, and doctor. Escape hatches for self-hosted git: flag > env > file-plane config key. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): environment-aware install — honest cron skip, cloud repo-create guard, execution_env surfaces installDurabilityCron probes for crontab before writing anything (containers and cloud sandboxes ship without one — expected, reported as an honest skip naming the event-driven pushes that still cover persistence). The repo phase installs the container-friendly harden half (post-commit hook, no scheduler) outside local machines. createPrivateRepo fails fast in cloud sandboxes with the flow that works (create outside, open the session ON the repo, attach). bootstrap verify gains a never-gating execution_env check; bootstrap status --json carries execution_environment for installing agents to branch on. Also fixes a live-PATH resolution class: binaryOnPath and the crontab execs now pass the current env explicitly (Bun resolves against the startup snapshot otherwise). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(bootstrap): lifecycle hygiene — uninstall teardown, doctor job liveness, .mcp.json out of the repo, honest persistence copy uninstall now tears down the durability wiring it installed (launchd/cron job, untracked post-commit hook, credential wiring — the committed helper and AGENTS rules stay). doctor gains bootstrap_durability_job: presence + LIVENESS (launchctl load-state, crontab line, pull-log freshness) — a plist on disk with a dead job no longer reads as healthy. Rendered .gitignore now covers .mcp.json (absolute machine paths must not land in the private repo); verify warns on pre-fix installs that committed it; the never-built state/mcp.json promise is gone from GITHUB.md. Persistence copy tells the truth everywhere: event-driven pushes do the durability work, the 30-min job is a multi-machine pull freshener. Post-commit hook install/removal is worktree-safe (git-path resolution; the git marker is a FILE there) and the cron wrapper's self-disable tests the repo dir, not its git marker. Two follow-up TODOs filed (plugin hook distribution; Channels push lane). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): committed hook carrier for cloud + cloud-setup-script emitter + cloud runbook Cloud sessions clone fresh and snapshot hook config at session start — the gitignored settings.local.json never exists there, so hooks never fired in cloud at all. Cloud installs now write the repo-COMMITTED .claude/settings.json with PATH-resolved, fail-open commands (no machine paths; a host without the binary no-ops); local installs keep settings.local.json; the writers enforce that one event never fires from both carriers, and removal cleans both. New: gbrain bootstrap cloud-setup-script prints the paste-ready environment setup script (npm transport — bun fetching is proxy-incompatible in cloud; never the unrelated npm-registry package). Runbook gains a NEVER FABRICATE TOOLING hard rule, a cloud-sandbox section (expected degradations as facts to relay, the attach-first flow), and failure-table rows for the proxy-403 and missing-crontab signatures. Codex lane stated honestly: AGENTS.md Gate 2 now has the pull-side push-health check. Guide documents the new knobs and the cloud contract; llms bundles regenerated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(bootstrap): per-turn push e2e chain, cloud-sandbox sim, per-root status reader migration + registry regen bootstrap-persistence e2e gains the Stop-hook chain (one stop banks the turn to the real bare remote; the debounce holds across stops; debounce-0 lands consecutive turns) and fixes a pre-existing post-#4024 break: repoPhaseComplete required a github-parseable origin, so session-end pushes deferred FOREVER for self-hosted/file-transport origins — non-github repo_urls now bind by exact URL equality (redirect protection preserved). Degraded-modes e2e gains the cloud-sandbox simulation (status reports the environment; repo creation refuses with the attach flow). workspace-push tests read per-root status through the shared reader. Flag registry regenerated (new git argv literals from the git-path/ls-files calls — the accepted argv-bleed class). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(doctor): categorize bootstrap_durability_job (categories drift guard) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(bootstrap): adversarial-review hardening — fail-closed privacy, no push-storm, no exfil paths Both Claude and Codex adversarial passes ran; 11 findings fixed (union): - Non-github 401+WWW-Authenticate no longer reads as private (RFC 7235 makes the header mandatory on every 401, so a middlebox 401s identically) — the top exfil path both models flagged; now unverifiable/fail-closed, operator confirms via the escape hatch. github.com still needs x-github-request-id. - Escape hatches downgrade ONLY 'unverifiable' — a PROVEN-public origin still refuses (hatches never authorize a public push). - treeNeedsPush measures against origin/<branch> (the push's own ref), not @{u}: a no-upstream branch no longer reports a committed-but-unpushed tree as push_clean and silently strands it. - [D20] failing-retry uses a fixed 60s floor, not min(debounce,60s) — cloud debounce=0 no longer re-runs the network ladder every turn. - Committed hook carrier: dedupe/suppress only on the EXACT portable-command shape, not a 'gbrain hook' substring (blocks the suppress-local-run-evil supply-chain vector); GBRAIN_HOME refused in the committed carrier. - push-status reason sanitized (charset+length) at every surface (banner, doctor, status blob) so remote git stderr can't inject via the remediation. - Per-root state: ghost-root records (deleted workspaces) filtered so a dead failing record can't re-fire the banner forever; uninstall removes them. - statusReport support blob reads push status through the shared per-root reader; visibility cache strips URL userinfo (no PAT persisted). - anonProbe strips userinfo + redirect:manual + SSRF flags + --end-of-options on ls-remote; cron self-disable uses git rev-parse (worktree-safe both ways); cloud-setup-script fails loud on a broken update; durability liveness won't certify a never-run crontab as live; config get/unset resolve the dotted file-plane keys; .bak/.broken gitignored; typed config fields. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * v0.45.8.0 feat(bootstrap): first-class cloud-sandbox install + per-turn persistence + fail-closed privacy ladder VERSION + package.json + CHANGELOG + TODOS + llms bundles. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: sync KEY_FILES + README for the cloud-DX wave (v0.45.8.0) New KEY_FILES entries for execution-env.ts and repo-visibility.ts; updated the bootstrap repo/hooks, workspace-push, brain-repo-durability, and hook.ts entries to current behavior (ladder verification, committed cloud hook carrier, per-root push status, crontab probe + liveness, per-turn stop push + banner). README's Claude Code line now states per-turn + cloud persistence honestly. llms bundles regenerated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(bootstrap): doc-review pass — attach records repo_url (enables cloud persistence), verify reads per-root push status, honest docs Cross-model doc review (Codex) caught that the headline cloud-persistence claim was hollow and two docs over-claimed: - attach now records repo_url from the adopted origin, so the no-daemon push gate (repoPhaseComplete) recognizes the repo phase as done — WITHOUT this, the per-turn/session-end pushes deferred forever after an attach, which is the ONLY install path in a cloud sandbox (repo is refused there). Privacy is still enforced at push time by the ladder. - bootstrap verify's push_probe reads the shared per-root reader [D8], not the legacy single file — a fresh v0.45.8 install no longer reports 'no push recorded' when per-root status exists. - Docs corrected to match code: runbook stamp → 0.45.8.0; README states the per-turn cadence honestly (debounced local, next-turn failure notice); GITHUB.md qualifies auto-push as Claude Code (Codex is pull); KEY_FILES says repo/status use REST (not the full ladder) and drops the stale --push; bootstrap.md hooks-location covers both carriers; README verbs surface says seven. llms bundles regenerated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(bootstrap): regenerate vendored template-repo tree + isolate env-mutating tests (verify gate) The verify CI gate caught two things the piecemeal local runs missed: - templates/bootstrap/template-repo/ is a GENERATED tree; the source-template edits (AGENTS.md Gate 2, CLAUDE.md cloud note) plus the version stamp had drifted. Regenerated from source (check:bootstrap-templates green). - test/bootstrap-repo.test.ts + test/durability-cron.test.ts newly mutated process.env in non-serial files; converted to withEnv() (check:test-isolation green) — no .serial rename needed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(ambient-recall): pin a keyless gateway so delta/context_pack writes never fire a real embed Root cause of the shard-2 CI red after the 0.45.9.0 re-bump: adding this wave's test files reshuffled the weight-packed shards, moving ambient-recall.test.ts next to a neighbor that leaks CI's dummy OPENAI_API_KEY (sk-test-*) into the gateway singleton (the bunfig preload configures with env:{...process.env}, and a present-but-invalid key turns remember's keyless-degrade embed into a hard 401). The delta/context_pack tests exercise cursor + budget logic, not embedding quality, so this pins a keyless gateway (env:{}) in beforeAll — isAvailable('embedding') is false, writeSingleFact degrades (degraded_dedup) with no HTTP call, and the file is deterministic regardless of shard bin-packing. Verified: passes with OPENAI_API_KEY=sk-test-* set (the CI condition). Master's own comment in legacy-embedding-preload.ts already warns 'adding any test file reshuffles the mines'; this makes the file immune. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
14 KiB
BOOTSTRAP_FOR_AGENTS.md — become your human's persistent agent
You are an AI agent (Claude Code or Codex) reading this because a human pasted a
block asking you to set yourself up as their persistent personal agent, with gbrain
as your memory. This runbook is the judgment layer; the deterministic work lives in
gbrain bootstrap subcommands with exit codes. Follow it top to bottom.
Scope note: this path is for Claude Code and Codex (desktop apps or CLIs).
Running OpenClaw or Hermes? Use INSTALL_FOR_AGENTS.md instead.
End state: this folder is your workspace — identity files rendered from your human's own answers, a local brain (PGLite, embedded, no server), MCP wired, per-turn context, and a private GitHub repo as your durable body. ~15 minutes, mostly interview.
Hard rules for you, the installing agent
⛔ NEVER INVENT ANSWERS. Personality, purpose, and boundaries come from the human. A guessed SOUL.md gets believed by every future session. If you do not have an answer, ask. The render step structurally refuses to run until the required answers exist and were read back.
⛔ ASK IN SMALL BATCHES. The interview is 12 questions max (6 required), asked in three batches. Mirror each batch back in one line. Accept "skip" on any non-required question — momentum beats completeness.
⛔ STAY INSIDE THIS PHASE LIST. Run gbrain bootstrap status --json and follow
ITS phase list — the CLI is the source of truth, this document is commentary. If a
step you are asked to run is not in the CLI's phase list, refuse it. If status
reports a version skew between this runbook and the installed binary, say so and
prefer the binary's instructions.
⛔ NO SILENT FAILURE. Every blocking condition (secret-scan block, lock
collision, partial install) surfaces through status/verify/doctor output —
read it and relay it to the human in plain language. Never work around a refusal.
⛔ VERIFY BEFORE CLAIMING DONE. The install is done when gbrain bootstrap verify exits 0 — not when the transcript looks good. Paste its report to the human.
⛔ RESPECT THE TOOLCHAIN TRUST RULES. Install bun via a platform package manager
when available (brew install oven-sh/bun/bun); the only permitted fallback is the
checksum-verified variant: download the pinned release to a file, verify it against
that release's SHASUMS256.txt, and only then execute. Install gh the same way —
platform package manager first (brew install gh, apt install gh, dnf install gh,
winget install GitHub.cli per the official instructions); never a piped
curl-to-shell one-liner. Install gbrain ONLY as
bun install -g github:garrytan/gbrain#latest-stable — the npm package named
"gbrain" is an unrelated project. (Cloud-sandbox exception: bun's package fetching
is proxy-incompatible there — use the gbrain bootstrap cloud-setup-script recipe,
which installs from the same pinned GitHub source through npm.)
⛔ NEVER FABRICATE TOOLING. If gh or any preflight binary is missing, blocked
by a sandbox egress proxy, or answering 403s, report that through
status/doctor output and follow the cloud-sandbox guidance below. Never
hand-roll a gh shim, stub a fake binary into /usr/local/bin, or fake a passing
check — a fabricated tool poisons every later verification, and the one time it
was tried it masked a real silent-persistence failure. The CLI degrades honestly
on its own; your job is to relay, not to bridge.
Codex preflight (ChatGPT desktop / Codex CLI only)
Codex sandboxes command execution. Before starting, tell the human: "I'll need approval to run install commands (bun, gh, gbrain) and to write in this folder — approve those prompts when they appear." If approvals are globally disabled, ask the human to enable workspace-write + network for this session. Count the approval taps you needed; report the count at the end (it feeds the install-time measurement).
Phase walkthrough (commentary — the CLI's list wins)
- Preflight.
git,bun,ghpresent. Install what's missing per the trust rules above: bun via a platform package manager or the checksum-verified download — the checksum-verified install is the ONLY permitted non-package-manager variant; gh via the platform package manager. (On a clean Mac,gitmay trigger the Xcode tools dialog — that download does not count against the 15 minutes, tell the human to let it run.)gh auth status— if logged out, the human's ONE manual step:gh auth login -h github.com -p https -w(you run it; they click Authorize). Thengbrain bootstrap status— it is idempotent and resume-aware; after any partial failure, re-run it and continue where it points. - Engine.
gbrain init --pglite(2 seconds, no server). Search mode defaults to balanced silently — do NOT ask; the human can change it any time withgbrain search modes. The one thing to raise here is the OPTIONAL provider key — with no key you run keyless: keyword search plus memory you author yourself through the write tools; everything works, one key upgrades search to semantic and enables automatic fact extraction. Never pressure for a key. If the human provides one, pass it to the CLI prompt — it goes to the 0600 config file, never into the interview answers, never into chat logs you keep. - Interview.
gbrain bootstrap interview --init, then ask the questions from the bank (the CLI prints them) in three batches, recording each answer verbatim with--set KEY "value". Push once on vague answers to the required questions. Claude Code only: with the final batch, also ask the ONE operational consent — MCP scope. It is not one of the 12 interview questions; consents ride alongside the bank. The choice: project (recommended — any other repo you open cannot read your brain) vs user (your agent everywhere, but any repo you open can reach it — read and write — and two open sessions contend for the database). Record it withgbrain bootstrap interview --set MCP_SCOPE <project|user>BEFORE the read-back, so the confirmation covers it. On Codex, skip this question entirely — the wiring step states the Codex reality instead. After the last batch: read ALL answers back in one compact block, ask "Is this the thing you want in the room?", and only then rungbrain bootstrap interview --confirm <hash>with the hash--statusprinted for the read-back set. The gate fails if you confirm a set the human never saw. - Render.
gbrain bootstrap render— identity files appear. Show the human SOUL.md. Existing files are never overwritten (re-runs are safe;--forcebacks up first). - Skills + brain wiring. The CLI scaffolds the skill set and registers
brain/as the workspace source. Nothing to judge here; relay the output. - Wire the harness.
gbrain bootstrap hooks --harness <detected>:- Claude Code: installs per-turn hooks ON by default — do NOT ask; loading the
brain every turn is the whole point of installing gbrain for your agent. Tell
the human it is on and how to turn it off (
GBRAIN_HOOKS=0, or re-run with--no-hooks, orgbrain bootstrap uninstall). MCP scope is NOT asked here —hooksconsumes the MCP_SCOPE answer recorded during the interview. - Codex: registers MCP (
codex mcp add) and relies on the AGENTS.md protocol — say plainly that Codex gets pull-based context, not per-turn push. Do NOT offer an MCP scope choice:codex mcp addhas no scope flag, so the registration is always user-global. State it as fact — any repo opened on this machine can reach the brain (read and write) through its MCP tools; the off-ramps arecodex mcp remove gbrain(registration only) orgbrain bootstrap uninstall(full teardown).
- Claude Code: installs per-turn hooks ON by default — do NOT ask; loading the
brain every turn is the whole point of installing gbrain for your agent. Tell
the human it is on and how to turn it off (
- Private repo.
gbrain bootstrap repo— creates a PRIVATE GitHub repo from the workspace, verifies the privacy bit through the API, pushes. If the human started from a repo they created themselves (create-repo-first: an EMPTY private repo under their own account, cloned and opened here), this ADOPTS that repo instead of creating one — verifies it is private and pushes the workspace. A non-empty repo, or one owned by an org, is refused with a clear message (make an empty personal repo, or rungbrain bootstrap attachfor an existing agent clone). Asks the background-persistence consent (a git post-commit auto-push plus a 30-minute pull job for multi-machine freshness; declining still persists via the per-turn and session-end pushes). If the human has no GitHub or declines: local-only mode with an honest warning;bootstrap repocan run any time later. Note: the per-turn/session push stays deferred until this phase records the verified repo, so nothing is ever pushed to an unverified-privacy origin. - Verify.
gbrain bootstrap verify— the whole contract: brain round-trip through the real write path, graph floor, token sweep, secret scan, repo privacy, hooks smoke, capability report (keyless or keyed). Exit 0 or it is not done. Paste the report. Then relay the first-run tour it prints (three prompts the human should try, starting with restarting the session).
Machine two
If this workspace was cloned from an existing agent repo (agent.json says
initialized), run gbrain bootstrap attach instead of the interview/render/repo
phases — it wires this machine (source, hooks, MCP) and verifies. If agent.json
says it is an uninitialized template, proceed with the normal flow from phase 1.
Cloud sandboxes (claude.ai/code and similar proxied environments)
How you know: gbrain bootstrap status --json reports
execution_environment: "cloud-sandbox" (the CLI detects the documented
signals — the CLAUDE_CODE_REMOTE env var, the proxy-injected token
placeholder). Trust the CLI's detection over your own guesses.
Expected degradations — these are facts to relay, not bugs to bridge:
- No crontab, no surviving background processes. The VM is reclaimed after inactivity. The scheduled pull is skipped honestly; the per-turn (Stop hook) and session-end pushes carry persistence. Decline nothing, fabricate nothing.
- GitHub GraphQL is always blocked by the egress proxy, and REST reaches
only repos attached to the session — a repo created mid-session is NOT
attached, so
gbrain bootstrap reporefuses fast in cloud with the flow that works. Privacy verification falls back to pure git protocol on its own. git pushworks only against the session's working branch. A user PAT does not bypass any of this.- Only repo-committed files carry into the next session.
~/.gbrain,~/.claude, and the gitignored.claude/settings.local.jsonevaporate. Hooks therefore live in the COMMITTED.claude/settings.json(the CLI writes PATH-resolved, fail-open commands there in cloud); hook config is snapshotted at session start, so hooks written mid-session activate on the NEXT session — say so instead of debugging it.
The correct cloud flow:
- The human creates the private repo from a normal machine (or github.com) and opens the cloud session ON that repo.
- The environment's setup script installs the gbrain binary — print it with
gbrain bootstrap cloud-setup-scriptand have the human paste it into the environment config (npm-based; bun's fetching is proxy-incompatible there). - Inside the session:
gbrain bootstrap attach, thengbrain bootstrap hooks --harness claude-code(writes the committed carrier), commit + push, and tell the human the hooks go live next session.
Failure modes, and what they actually mean
| Symptom | Real cause | Fix |
|---|---|---|
interview --status exits nonzero forever |
A required answer is genuinely missing | Ask the human. Do not default it. |
| Render refuses with unresolved tokens | Interview incomplete or a template edit broke a token | Finish the interview; status names the tokens. |
verify fails the magic-moment check |
The fact never landed (keyless: the Facts fence was not written) | Re-run the write step it names; check gbrain doctor. |
| Secret-scan block on push | A credential-shaped string in a tracked file | Fix or allowlist deliberately (.gbrain-scan-allow); never force. |
| "bootstrap already running (pid N)" | A concurrent bootstrap holds the lock | Wait or investigate that pid; the lock self-clears when stale. |
| Brain tools fail with a lock error | Another live session's serve owns the database | Close the other session; sequential use is the v1 contract. |
| Hook reports "brain context unavailable" | serve not running or degraded | gbrain doctor names it; hooks fail open by design. |
| gh answers 403 "not enabled for this session" | Cloud proxy scoping — the repo is not attached to the session | Expected in cloud; the visibility ladder falls back to git protocol. NEVER shim gh. |
| "crontab: command not found" / cron skipped | Containers and cloud sandboxes ship without a scheduler | Expected; event-driven pushes cover it — the skip message says exactly this. |
| A turn shows "workspace push is FAILING" | The background push is refusing (visibility, secret-scan, or network reasons) | Run gbrain doctor; the banner repeats every 30 min until fixed. |
Hand off
Finish by telling the human: the private repo URL (or the local-only status), the
capability mode (keyless vs keyed), the three commands they will actually reuse
(gbrain doctor, gbrain bootstrap verify, gbrain sources push), and the
first-run tour. Then delete nothing — this runbook was fetched, not installed.