mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-27 22:15:33 +00:00
fix(init): --help should not mutate config or scan filesystem
`gbrain init --help` (and `-h`) currently fall through to the smart-detection branch in runInit(), which scans cwd for .md files and on a directory with 1000+ files prints "Found ~1500 .md files. For a brain this size, Supabase gives faster search..." then defaults to PGLite — calling saveConfig() and overwriting any existing Postgres config with `engine: 'pglite' + database_path: ~/.gbrain/brain.pglite`. Confirmed in the wild: ran `gbrain init --help` from $HOME on a machine where ~/.gbrain/config.json pointed at a Supabase Postgres brain with 10K+ pages. The config was silently flipped to PGLite. The Supabase data was intact, but gbrain stopped pointing at it until the config was manually restored. Root cause: cli.ts:62-69 only routes --help → printOpHelp() for shared-op commands; CLI_ONLY commands (init, embed, etc.) fall through to their handler with --help still in argv. None of them check for it. Fix: add a --help/-h guard at the top of runInit() that prints help text and returns. Help should never mutate state — Postel's robustness principle for CLI tools. Help text covers all flags (engine selection, AI provider options, thin-client mode) so users running `--help` get the canonical list rather than having to read the source. A wider architectural fix — adding --help routing for all CLI_ONLY commands in cli.ts — is plausible follow-up, but each CLI_ONLY command would still need its own help text. This per-command pattern matches how shared ops handle it via printOpHelp(). Init is the highest-stakes case because it's the only CLI_ONLY command that calls saveConfig(). Smoke test: from a directory with 1500 .md files, with GBRAIN_HOME pointed at a fresh tempdir: - Before fix: ~/.gbrain/config.json materialized with engine: 'pglite' - After fix: help text printed, no config dir created `bun run typecheck` clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
dffb607ef7
commit
ed11fdd58c
@@ -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 <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 <DIR> Override default brain path (PGLite only)
|
||||
--key <APIKEY> Provide an API key non-interactively (Supabase only)
|
||||
--embedding-model <PROVIDER:MODEL>
|
||||
e.g. openai:text-embedding-3-large, voyage:voyage-multimodal-3
|
||||
--model <PROVIDER> Shorthand: pick recipe default for a provider
|
||||
--embedding-dimensions <N>
|
||||
Embedding dimensions (must match the model)
|
||||
--expansion-model <PROVIDER:MODEL>
|
||||
Model for query expansion (default: anthropic:claude-haiku)
|
||||
--chat-model <PROVIDER: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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user