diff --git a/src/commands/init.ts b/src/commands/init.ts index 5fa08bbfa..6e31ba8b0 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -11,6 +11,20 @@ import { createEngine } from '../core/engine-factory.ts'; import { discoverOAuth, mintClientCredentialsToken, smokeTestMcp } from '../core/remote-mcp-probe.ts'; export async function runInit(args: string[]) { + // Help guard: cli.ts only routes --help to printOpHelp() for shared-op + // commands; CLI_ONLY commands (init, embed, etc.) fall through to their + // handler with --help in argv. Without this guard, `gbrain init --help` + // proceeds into the smart-detection branch below, scans cwd for .md files, + // and on a directory with 1000+ files (e.g. $HOME for someone whose brain + // and notes share a root) silently overwrites the existing Supabase config + // with a fresh PGLite brain at ~/.gbrain/brain.pglite. Confirmed in the + // wild — flipped a working `engine: postgres` config to `engine: pglite` + // on a brain with 10K+ pages. Help should never mutate state. + if (args.includes('--help') || args.includes('-h')) { + printInitHelp(); + return; + } + const isSupabase = args.includes('--supabase'); const isPGLite = args.includes('--pglite'); const isMcpOnly = args.includes('--mcp-only'); @@ -729,3 +743,48 @@ export function reportModStatus(): void { console.log('Soul audit: run `gbrain soul-audit` to customize agent identity'); console.log(''); } + +function printInitHelp() { + console.log(` +gbrain init — initialize a brain (PGLite or Supabase Postgres) + +USAGE + gbrain init [flags] + +ENGINE SELECTION (mutually exclusive) + --pglite Use embedded PGLite (zero-config, default for <1000 .md files) + --supabase Use Supabase Postgres (recommended for 1000+ files) + --url Use a manual Postgres connection string + --mcp-only Thin-client mode: connect to a remote gbrain MCP, no local engine + +OPTIONS + --force Overwrite an existing config (gated by default) + --non-interactive Don't prompt; use defaults + --migrate-only Apply pending schema migrations against the configured engine + without re-saving config (used by post-upgrade and orchestrators) + --json JSON output for status reporting + --path Override default brain path (PGLite only) + --key Provide an API key non-interactively (Supabase only) + --embedding-model + e.g. openai:text-embedding-3-large, voyage:voyage-multimodal-3 + --model Shorthand: pick recipe default for a provider + --embedding-dimensions + Embedding dimensions (must match the model) + --expansion-model + Model for query expansion (default: anthropic:claude-haiku) + --chat-model + Default subagent driver (v0.27+) + +EXAMPLES + gbrain init --pglite # Local-only, no API keys + gbrain init --supabase # Interactive Supabase setup + gbrain init --url postgresql://... # Use a custom Postgres + gbrain init --mcp-only --url https://... # Thin-client mode + +NOTES + - Bare \`gbrain init\` in a directory with 1000+ .md files defaults to Supabase + interactive setup. With <1000 files (or with --pglite explicitly), defaults + to PGLite at ~/.gbrain/brain.pglite. + - Existing config is preserved unless --force is passed. +`.trim()); +}