@cmnwlth/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/commands.ts","../src/discover.ts","../src/deps.ts","../src/init.ts","../src/onboard.ts","../src/prompt.ts"],"sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport path from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { cmdConfig, cmdReseed, delegateCurate, delegateSync } from \"./commands.js\";\nimport { defaultOnboardDeps } from \"./deps.js\";\nimport { defaultBrainDir } from \"./init.js\";\nimport { runOnboard, runWizard, type OnboardOptions, type WizardDefaults } from \"./onboard.js\";\nimport { createReadlinePrompter, isInteractive, type Prompter } from \"./prompt.js\";\n\nexport { runInit, findRepoRoot, defaultBrainDir } from \"./init.js\";\nexport type { InitOptions, InitDeps, InitResult, InitBySource } from \"./init.js\";\nexport { defaultInitDeps, defaultOnboardDeps } from \"./deps.js\";\nexport { runOnboard, runWizard } from \"./onboard.js\";\nexport type {\n OnboardOptions,\n OnboardDeps,\n OnboardResult,\n WizardAnswers,\n WizardDefaults,\n WizardDeps,\n WizardOutcome,\n} from \"./onboard.js\";\nexport {\n isInteractive,\n createReadlinePrompter,\n parseConfirm,\n parseText,\n parseSelection,\n} from \"./prompt.js\";\nexport type { Prompter } from \"./prompt.js\";\nexport { findGitRepos } from \"./discover.js\";\nexport type { FindGitReposOptions } from \"./discover.js\";\n\n/** Print `commonwealth` usage to stderr. */\nfunction printUsage(): void {\n process.stderr.write(\n [\n \"commonwealth — git-backed markdown team-brain\",\n \"\",\n \"Usage:\",\n \" commonwealth init [flags] onboard: build, create/join brain, plugin, daemon\",\n \" commonwealth reseed [<repo>...] [--all] mine repo(s) into the mapped brain and capture\",\n \" commonwealth config <list | get <k> | set <k> <v>> read/set the brain's shared config\",\n \" commonwealth status review queue + sync-daemon state\",\n \" commonwealth health freshness/trust rollup for the brain\",\n \" commonwealth consolidate [--dry-run] supersede near-duplicate canon notes\",\n \" commonwealth sync <start | stop | once> control/run the sync daemon\",\n \" commonwealth pending list notes awaiting review\",\n \" commonwealth promote <id...> | --all approve staged notes into canon\",\n \" commonwealth reject <id...> discard staged notes\",\n \" commonwealth scope <show | allow <p> | deny <p> | check> per-user capture scope\",\n \" commonwealth recall <query> search the brain\",\n \"\",\n \"All commands resolve the brain from the registry for the current directory — no --dir needed.\",\n \"\",\n \"init flags: [--brain <dir>] [--yes] [--reseed] [--auto-adr] [--remote <url>]\",\n \" [--sync <dir,dir,...>] [--seed-repo <dir,dir,...>]\",\n \" [--no-scope] [--no-seed] [--no-plugin] [--no-daemon] [--no-build]\",\n \"\",\n \"`init` is a single idempotent command: it builds the workspace (if needed), creates or\",\n \"joins the brain, syncs one or more folders into it (allowlist + a global-registry mapping\",\n \"with a ~/.commonwealth/brains/<name> symlink), seeds it from one or more repos, installs\",\n \"the Commonwealth plugin (global MCP + session hooks), and starts the sync daemon. Run in a\",\n \"terminal without --yes for an interactive wizard that scans for and lets you multi-select\",\n \"folders/repos; with --yes (or non-interactively) it uses defaults + flags and never prompts.\",\n \"\",\n \"Options:\",\n \" --brain <dir> Create/use the brain at <dir> (default: ~/.commonwealth/brains/<project>)\",\n \" --yes Run non-interactively; skip the wizard and all prompts\",\n \" --reseed Re-seed even if this project already resolves to a brain\",\n \" --auto-adr Enable auto-ADR capture for the brain\",\n \" --remote <url> Add <url> as the brain's git origin remote\",\n \" --sync <dir,dir,...> Folders to sync into the brain (default: this repo)\",\n \" --seed-repo <dir,...> Repos to seed from now (default: the --sync folders)\",\n \" --no-scope Skip adding folders to the capture allowlist\",\n \" --no-seed Create the brain but skip gathering/staging seed candidates\",\n \" --no-plugin Skip installing the Commonwealth plugin (alias: --no-mcp)\",\n \" --no-daemon Skip starting the sync daemon\",\n \" --no-build Skip the workspace build even if dist artifacts are missing\",\n \"\",\n ].join(\"\\n\"),\n );\n}\n\n/**\n * `commonwealth` CLI entry. Parses argv, dispatches `init` to the full {@link runOnboard}\n * orchestration, prints the plan + a one-line summary to stderr, and resolves the exit code.\n * Diagnostics go to stderr; there is no stdout data contract for `init`. Unknown commands and\n * `--help` print usage.\n *\n * `parseArgs` has no native boolean negation, so `--no-seed`/`--no-mcp`/`--no-daemon`/`--no-build`\n * are stripped from argv here and turned into `false` gates before parsing the rest.\n *\n * @param argv Arguments after `node <script>` (i.e. `process.argv.slice(2)`).\n * @returns Exit code: 0 on success, 2 on usage error.\n */\nexport async function run(argv: string[]): Promise<number> {\n const [command, ...rest] = argv;\n\n if (command === undefined || command === \"--help\" || command === \"-h\") {\n printUsage();\n return command === undefined ? 2 : 0;\n }\n\n // Unified subcommand surface (#93). `reseed`/`config` compose core+seed; the rest delegate to\n // the registry-aware curate/sync binaries (inheriting cwd, so they hit the mapped brain).\n switch (command) {\n case \"init\":\n return cmdInit(rest);\n case \"reseed\":\n return cmdReseed(rest);\n case \"config\":\n return cmdConfig(rest);\n case \"status\": {\n const queue = await delegateCurate([\"list\"]);\n const daemon = await delegateSync([\"status\"]);\n return queue || daemon;\n }\n case \"sync\": {\n const sub = rest[0] === \"once\" ? \"sync\" : (rest[0] ?? \"status\");\n return delegateSync([sub, ...rest.slice(1)]);\n }\n case \"health\":\n return delegateCurate([\"health\"]);\n case \"consolidate\":\n return delegateCurate([\"consolidate\", ...rest]);\n case \"pending\":\n return delegateCurate([\"list\"]);\n case \"promote\":\n return delegateCurate(rest.includes(\"--all\") ? [\"approve-all\"] : [\"approve\", ...rest]);\n case \"reject\":\n return delegateCurate([\"reject\", ...rest]);\n case \"scope\":\n return delegateCurate([\"scope\", ...rest]);\n case \"recall\":\n return delegateCurate([\"context\", \"--cwd\", process.cwd(), \"--query\", rest.join(\" \")]);\n default:\n process.stderr.write(`Unknown command: ${command}\\n`);\n printUsage();\n return 2;\n }\n}\n\n/** `commonwealth init` — the onboarding orchestrator (build → create/seed/join → plugin → daemon). */\nasync function cmdInit(rest: string[]): Promise<number> {\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n printUsage();\n return 0;\n }\n\n // parseArgs has no native negation; consume --no-* flags first and derive the gates.\n // `--no-plugin` is the canonical gate; `--no-mcp` is a backward-compatible alias.\n const negations = [\n \"--no-scope\",\n \"--no-seed\",\n \"--no-plugin\",\n \"--no-mcp\",\n \"--no-daemon\",\n \"--no-build\",\n ];\n const scope = !rest.includes(\"--no-scope\");\n const seed = !rest.includes(\"--no-seed\");\n const plugin = !rest.includes(\"--no-plugin\") && !rest.includes(\"--no-mcp\");\n const daemon = !rest.includes(\"--no-daemon\");\n const build = !rest.includes(\"--no-build\");\n const positional = rest.filter((a) => !negations.includes(a));\n\n let values: {\n brain?: string;\n yes?: boolean;\n reseed?: boolean;\n \"auto-adr\"?: boolean;\n remote?: string;\n sync?: string;\n \"seed-repo\"?: string;\n };\n try {\n ({ values } = parseArgs({\n args: positional,\n options: {\n brain: { type: \"string\" },\n yes: { type: \"boolean\", default: false },\n reseed: { type: \"boolean\", default: false },\n \"auto-adr\": { type: \"boolean\", default: false },\n remote: { type: \"string\" },\n sync: { type: \"string\" },\n \"seed-repo\": { type: \"string\" },\n },\n allowPositionals: false,\n }));\n } catch (err) {\n process.stderr.write(`${(err as Error).message}\\n`);\n printUsage();\n return 2;\n }\n\n const cwd = process.cwd();\n // The scope/registry/brain-name base is the invocation dir, not the git root (#61).\n const projectDir = path.resolve(cwd);\n\n // Non-interactive without --yes: do NOTHING but point the user at a terminal. This runs BEFORE\n // any executable probe (`hasExecutable`) or dep resolution (`defaultOnboardDeps`), so the path\n // is fully side-effect-free and can't fail — a subprocess spawned here under CI fork-pressure\n // could throw and exit 1, which would (and did) flake the release gate. \"does not touch anything.\"\n const interactive = isInteractive();\n if (!interactive && !values.yes) {\n process.stderr.write(\"Non-interactive: re-run in a terminal or pass --yes.\\n\");\n return 0;\n }\n\n const claudePresent = hasExecutable(\"claude\");\n const deps = defaultOnboardDeps({ curateEntry: process.env.COMMONWEALTH_CURATE_BIN });\n\n // Parse a comma-separated dir list into resolved absolute paths (blanks dropped).\n const splitDirs = (raw: string | undefined): string[] | undefined => {\n if (raw === undefined) return undefined;\n const dirs = raw\n .split(\",\")\n .map((d) => d.trim())\n .filter((d) => d.length > 0);\n return dirs.length > 0 ? dirs : undefined;\n };\n\n let opts: OnboardOptions;\n let prompter: Prompter | null = null;\n\n try {\n if (interactive && !values.yes) {\n // Interactive terminal, no --yes: run the wizard.\n const defaults: WizardDefaults = {\n brain: defaultBrainDir(projectDir),\n projectDir,\n scope: true,\n seed: true,\n plugin: claudePresent,\n daemon: true,\n autoAdr: false,\n };\n prompter = createReadlinePrompter();\n const outcome = await runWizard(defaults, prompter);\n if (!outcome.proceed) {\n process.stderr.write(\"Aborted.\\n\");\n return 0;\n }\n // The wizard already confirmed; runOnboard must not prompt again (opts.yes is true).\n opts = outcome.opts;\n } else {\n // --yes (interactive or not): defaults + explicit flags, non-interactive. The\n // non-interactive-without-yes case already returned above.\n const syncFolders = splitDirs(values.sync) ?? [projectDir];\n const seedRepos = splitDirs(values[\"seed-repo\"]) ?? (seed ? syncFolders : []);\n opts = {\n brain: values.brain,\n yes: true,\n reseed: values.reseed,\n seed,\n plugin,\n daemon,\n build,\n scope,\n autoAdr: values[\"auto-adr\"],\n remote: values.remote,\n syncFolders,\n seedRepos,\n };\n }\n\n const result = await runOnboard(cwd, opts, deps);\n\n process.stderr.write(\n `init: mode=${result.mode} brain=${result.brainDir} built=${result.built} ` +\n `staged=${result.staged} scopedFolders=${result.scopedFolders} ` +\n `mappedFolders=${result.mappedFolders} seededRepos=${result.seededRepos} ` +\n `scope=${result.scope} autoAdr=${result.autoAdr} ` +\n `remote=${result.remote} plugin=${result.plugin} daemon=${result.daemon} ` +\n `scopeConfig=${result.scopeConfigPath}\\n`,\n );\n return 0;\n } finally {\n prompter?.close();\n }\n}\n\n/** True if the `<name>` executable resolves on the current PATH. */\nfunction hasExecutable(name: string): boolean {\n const probe = process.platform === \"win32\" ? \"where\" : \"which\";\n const res = spawnSync(probe, [name], { stdio: \"ignore\" });\n return res.status === 0;\n}\n\nconst isEntrypoint =\n process.argv[1] !== undefined && import.meta.url === new URL(`file://${process.argv[1]}`).href;\n\nif (isEntrypoint) {\n run(process.argv.slice(2))\n .then((code) => {\n process.exitCode = code;\n })\n .catch((err: unknown) => {\n process.stderr.write(`${(err as Error).stack ?? String(err)}\\n`);\n process.exitCode = 1;\n });\n}\n","import { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport { FEATURE_FLAGS, loadBrainConfig, resolveBrainDir, setFeature } from \"@cmnwlth/core\";\nimport { gatherCandidates } from \"@cmnwlth/seed\";\nimport { findGitRepos } from \"./discover.js\";\n\n/**\n * The unified `commonwealth <verb>` subcommands beyond `init` (#93). Every command resolves the\n * brain the same way the MCP server and hooks do — via the registry against the cwd — so the\n * user never passes `--dir` or reruns `init` to act on their brain. Verbs with battle-tested\n * logic in the curate/sync binaries delegate to them (registry-aware since #69, so inheriting\n * the cwd is enough); `reseed` and `config` compose core + seed directly.\n */\n\nconst require = createRequire(import.meta.url);\n\n/** Resolve a workspace package's built bin entry (e.g. `@cmnwlth/curate`). */\nfunction resolvePkgBin(pkg: string): string {\n const pkgJsonPath = require.resolve(`${pkg}/package.json`);\n const pkgJson = require(`${pkg}/package.json`) as { bin?: string | Record<string, string> };\n const rel = typeof pkgJson.bin === \"string\" ? pkgJson.bin : Object.values(pkgJson.bin ?? {})[0];\n if (!rel) throw new Error(`${pkg} exposes no bin`);\n return path.join(path.dirname(pkgJsonPath), rel);\n}\n\n/** Spawn `node <bin> <args>` with inherited stdio; resolves to the child's exit code. */\nfunction runBin(bin: string, args: string[], input?: string): Promise<number> {\n return new Promise((resolve) => {\n const child = spawn(\"node\", [bin, ...args], {\n stdio: [input === undefined ? \"inherit\" : \"pipe\", \"inherit\", \"inherit\"],\n });\n child.on(\"error\", () => resolve(1));\n child.on(\"close\", (code) => resolve(code ?? 0));\n if (input !== undefined && child.stdin) {\n child.stdin.on(\"error\", () => {});\n child.stdin.write(input, () => child.stdin!.end());\n }\n });\n}\n\n/** Resolve the brain for the cwd, or print an actionable error and return null. */\nasync function brainOrError(): Promise<string | null> {\n const env = process.env.COMMONWEALTH_BRAIN_DIR;\n const brain = env && env.length > 0 ? path.resolve(env) : await resolveBrainDir(process.cwd());\n if (!brain) {\n process.stderr.write(\n `No Commonwealth brain is configured for ${process.cwd()}. Run \\`commonwealth init\\` here, ` +\n `or add a prefix → brain mapping to ~/.commonwealth/registry.json.\\n`,\n );\n return null;\n }\n return brain;\n}\n\n/** `commonwealth config <list | get <key> | set <key> <value>>` — the brain's shared config. */\nexport async function cmdConfig(rest: string[]): Promise<number> {\n const brain = await brainOrError();\n if (!brain) return 1;\n const [sub, key, value] = rest;\n const config = await loadBrainConfig(brain);\n const flagNames = FEATURE_FLAGS.map((f) => f.name);\n\n if (sub === undefined || sub === \"list\") {\n process.stdout.write(\n `brain: ${brain}\\nname: ${config.name}\\n` +\n `remotes: ${config.remotes.join(\", \") || \"(none)\"}\\nfeatures:\\n`,\n );\n for (const flag of FEATURE_FLAGS) {\n const val = config.features[flag.name] ?? flag.default;\n process.stdout.write(` ${flag.name} = ${val} — ${flag.description}\\n`);\n }\n return 0;\n }\n if (sub === \"get\") {\n if (!key) {\n process.stderr.write(\"usage: commonwealth config get <key>\\n\");\n return 2;\n }\n if (key === \"name\") process.stdout.write(`${config.name}\\n`);\n else if (flagNames.includes(key)) process.stdout.write(`${config.features[key] ?? false}\\n`);\n else {\n process.stderr.write(`Unknown config key \"${key}\". Known: name, ${flagNames.join(\", \")}\\n`);\n return 2;\n }\n return 0;\n }\n if (sub === \"set\") {\n if (!key || value === undefined) {\n process.stderr.write(\"usage: commonwealth config set <key> <value>\\n\");\n return 2;\n }\n if (!flagNames.includes(key)) {\n process.stderr.write(`Unknown feature flag \"${key}\". Known: ${flagNames.join(\", \")}\\n`);\n return 2;\n }\n const on = value === \"true\" || value === \"1\" || value === \"on\" || value === \"yes\";\n await setFeature(brain, key, on);\n process.stderr.write(`[commonwealth] set ${key} = ${on} for ${brain}\\n`);\n return 0;\n }\n process.stderr.write(\"usage: commonwealth config <list | get <key> | set <key> <value>>\\n\");\n return 2;\n}\n\n/**\n * `commonwealth reseed [<repo>...] [--all]` — mine repo(s) into the MAPPED brain and capture.\n * Defaults to the current repo; `<repo>...` names explicit dirs; `--all` mines every git repo\n * found under the cwd. Notes file under `<project>/<kind>/` (source per repo, ADR-0015) and\n * land per the brain's `autoPromote` — set it false first (`commonwealth config set autoPromote\n * false`) to review before canon.\n */\nexport async function cmdReseed(rest: string[]): Promise<number> {\n const brain = await brainOrError();\n if (!brain) return 1;\n const all = rest.includes(\"--all\");\n const explicit = rest.filter((a) => !a.startsWith(\"-\")).map((a) => path.resolve(a));\n\n const repos =\n explicit.length > 0\n ? explicit\n : all\n ? await findGitRepos(process.cwd())\n : [path.resolve(process.cwd())];\n if (repos.length === 0) {\n process.stderr.write(\"No repositories to reseed.\\n\");\n return 0;\n }\n\n const curateBin = resolvePkgBin(\"@cmnwlth/curate\");\n let total = 0;\n for (const repo of repos) {\n const { candidates } = await gatherCandidates(repo);\n if (candidates.length === 0) {\n process.stderr.write(`[commonwealth] ${repo}: no candidates.\\n`);\n continue;\n }\n process.stderr.write(`[commonwealth] ${repo}: mined ${candidates.length} candidate(s)…\\n`);\n // Delegate to curate capture (registry-aware; applies scope+dedup+secret gates + autoPromote).\n // --force bypasses the per-session scope gate: reseed is a deliberate import, not a session.\n const code = await runBin(\n curateBin,\n [\"capture\", \"--dir\", brain, \"--cwd\", repo, \"--force\"],\n JSON.stringify(candidates),\n );\n if (code === 0) total += candidates.length;\n }\n process.stderr.write(\n `[commonwealth] reseed done: ${total} candidate(s) captured into ${brain}.\\n`,\n );\n return 0;\n}\n\n/** Delegate a verb to the registry-aware curate binary, inheriting the cwd + stdio. */\nexport function delegateCurate(args: string[]): Promise<number> {\n return runBin(resolvePkgBin(\"@cmnwlth/curate\"), args);\n}\n\n/** Delegate a verb to the registry-aware sync binary, inheriting the cwd + stdio. */\nexport function delegateSync(args: string[]): Promise<number> {\n return runBin(resolvePkgBin(\"@cmnwlth/sync\"), args);\n}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\n\n/** Options for {@link findGitRepos}. */\nexport interface FindGitReposOptions {\n /** How many directory levels below `baseDir` to descend (default 2). `0` = only `baseDir`. */\n maxDepth?: number;\n}\n\n/**\n * Discover git repositories under `baseDir`: every directory that directly contains a `.git`\n * entry (a file or directory), scanning up to `maxDepth` levels deep. Skips `node_modules` and\n * any dot-directory (e.g. `.git`, `.cache`) so it never descends into vendored or hidden trees.\n *\n * Never throws: an unreadable directory is simply skipped. Results are absolute, de-duped, and\n * sorted lexicographically for deterministic output.\n *\n * @param baseDir Directory to scan from.\n * @param opts Optional depth cap ({@link FindGitReposOptions}).\n * @returns Absolute paths of directories that are git repos, sorted and de-duped.\n */\nexport async function findGitRepos(\n baseDir: string,\n opts: FindGitReposOptions = {},\n): Promise<string[]> {\n const maxDepth = opts.maxDepth ?? 2;\n const root = path.resolve(baseDir);\n const found = new Set<string>();\n\n const visit = async (dir: string, depth: number): Promise<void> => {\n let entries: import(\"node:fs\").Dirent[];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n } catch {\n return; // unreadable dir -> skip\n }\n\n if (entries.some((e) => e.name === \".git\")) {\n found.add(dir);\n }\n\n if (depth >= maxDepth) return;\n\n for (const entry of entries) {\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n if (entry.name === \"node_modules\") continue;\n if (entry.name.startsWith(\".\")) continue;\n const child = path.join(dir, entry.name);\n try {\n const stat = await fs.stat(child);\n if (!stat.isDirectory()) continue;\n } catch {\n continue; // dangling symlink or unreadable -> skip\n }\n await visit(child, depth + 1);\n }\n };\n\n await visit(root, 0);\n return [...found].sort();\n}\n","import { spawn, spawnSync } from \"node:child_process\";\nimport { existsSync, promises as fs } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\nimport { createRequire } from \"node:module\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as core from \"@cmnwlth/core\";\nimport type { NewNoteInput } from \"@cmnwlth/core\";\nimport { gatherCandidates } from \"@cmnwlth/seed\";\nimport { findRepoRoot, runInit, type InitDeps } from \"./init.js\";\nimport type { OnboardDeps } from \"./onboard.js\";\n\n/** Options for {@link defaultInitDeps}, mostly to make wiring testable/overridable. */\nexport interface DefaultInitDepsOptions {\n /** Absolute path to `commonwealth-curate`'s built entry (its `capture` subcommand is spawned). */\n curateEntry?: string;\n /** When true, `confirm` always resolves `true` (from `--yes`). */\n assumeYes?: boolean;\n}\n\n/**\n * Resolve the `commonwealth-curate` CLI entry point: explicit override → `COMMONWEALTH_CURATE_BIN`\n * env → the `@cmnwlth/curate` package's declared `bin`. Throws only if none resolve, and\n * that throw is caught by {@link makeStage} (staging degrades to a no-op with a log line).\n */\nfunction resolveCurateEntry(override?: string): string {\n if (override) return override;\n const fromEnv = process.env.COMMONWEALTH_CURATE_BIN;\n if (fromEnv) return fromEnv;\n\n const require = createRequire(import.meta.url);\n const pkgJsonPath = require.resolve(\"@cmnwlth/curate/package.json\");\n const pkg = require(\"@cmnwlth/curate/package.json\") as {\n bin?: string | Record<string, string>;\n };\n const rel = typeof pkg.bin === \"string\" ? pkg.bin : pkg.bin?.[\"commonwealth-curate\"];\n if (!rel) throw new Error(\"@cmnwlth/curate exposes no `commonwealth-curate` bin\");\n return path.resolve(path.dirname(pkgJsonPath), rel);\n}\n\n/**\n * Build a `stage` that pipes candidates as JSON into `node <curateEntry> capture --dir\n * <brain>` and counts the staged notes from stdout (curate prints one line per staged\n * note). Never throws: on spawn failure or non-zero exit it logs to stderr and returns\n * `{ captured: 0 }`, so a broken curate can't abort the wizard.\n */\nfunction makeStage(\n curateEntry: string,\n log: (m: string) => void,\n): (brainDir: string, candidates: NewNoteInput[]) => Promise<{ captured: number }> {\n return (brainDir, candidates) =>\n new Promise((resolve) => {\n const child = spawn(\"node\", [curateEntry, \"capture\", \"--dir\", brainDir, \"--force\"], {\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n });\n\n let out = \"\";\n child.stdout.setEncoding(\"utf8\");\n child.stdout.on(\"data\", (chunk: string) => {\n out += chunk;\n });\n\n child.on(\"error\", (err) => {\n log(`Staging failed to spawn commonwealth-curate: ${err.message}`);\n resolve({ captured: 0 });\n });\n\n child.on(\"close\", (code) => {\n if (code !== 0) {\n log(`commonwealth-curate exited with code ${code ?? \"null\"}; staged nothing.`);\n resolve({ captured: 0 });\n return;\n }\n const captured = out.split(\"\\n\").filter((line) => line.trim().length > 0).length;\n resolve({ captured });\n });\n\n // Guard the stdin stream: if the child dies before consuming input, the write emits an\n // EPIPE 'error' that would otherwise be unhandled and crash `init` (#104). The 'error'/\n // 'close' handlers above still resolve the promise.\n child.stdin.on(\"error\", () => {});\n child.stdin.end(JSON.stringify(candidates));\n });\n}\n\n/** Prompt on stdin for a yes/no answer; anything starting with `y` (case-insensitive) is yes. */\nfunction promptConfirm(message: string): Promise<boolean> {\n return new Promise((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n rl.question(`${message} [y/N] `, (answer) => {\n rl.close();\n resolve(/^y(es)?$/i.test(answer.trim()));\n });\n });\n}\n\n/**\n * Wire the real {@link InitDeps}: seed for gathering, core for brain/marker resolution, a\n * spawned `commonwealth-curate capture` for staging, a readline prompt for confirmation, and\n * stderr for logging. Pure orchestration lives in {@link runInit}; this is the only place\n * that performs real I/O.\n *\n * @param opts Optional overrides ({@link DefaultInitDepsOptions}).\n * @returns A fully-wired {@link InitDeps}.\n */\nexport function defaultInitDeps(opts: DefaultInitDepsOptions = {}): InitDeps {\n const log = (m: string): void => {\n process.stderr.write(m + \"\\n\");\n };\n\n let curateEntry: string | null = null;\n let curateError: string | null = null;\n try {\n curateEntry = resolveCurateEntry(opts.curateEntry);\n } catch (err) {\n curateError = (err as Error).message;\n }\n\n const stage = curateEntry\n ? makeStage(curateEntry, log)\n : async (): Promise<{ captured: number }> => {\n log(`Cannot stage: ${curateError ?? \"commonwealth-curate not found\"}.`);\n return { captured: 0 };\n };\n\n return {\n gather: (repoDir) => gatherCandidates(repoDir),\n resolveBrain: (cwd) => core.resolveBrainDir(cwd),\n createBrain: (dir, name) => core.initBrain(dir, { name }),\n registerBrain: async (repoDir, brainDir) => {\n // ADR-0011: the global registry is the source of truth; no per-project marker.\n await core.addRegistryMapping(repoDir, brainDir);\n await core.linkBrain(path.basename(brainDir), brainDir);\n },\n stage,\n confirm: opts.assumeYes ? async () => true : promptConfirm,\n log,\n };\n}\n\n/** Options for {@link defaultOnboardDeps}, mostly to make wiring testable/overridable. */\nexport interface DefaultOnboardDepsOptions {\n /** Repo root to resolve dist paths from; defaults to the nearest `.git` ancestor of cwd. */\n repoRoot?: string;\n /** Absolute path to `commonwealth-curate`'s built entry, forwarded to {@link defaultInitDeps}. */\n curateEntry?: string;\n}\n\n/** The workspace packages whose `dist/index.js` must exist for the plugin to run standalone. */\nconst REQUIRED_DIST_PACKAGES = [\"core\", \"mcp\", \"sync\", \"curate\", \"seed\", \"cli\"] as const;\n\n/** True if the `<name>` executable resolves on the current PATH. */\nfunction hasExecutable(name: string): boolean {\n const probe = process.platform === \"win32\" ? \"where\" : \"which\";\n const res = spawnSync(probe, [name], { stdio: \"ignore\" });\n return res.status === 0;\n}\n\n/**\n * True if `claude <args>` (a list/plural command) reports an entry named `name`. Prefers the\n * structured `--json` output (exact `id`/`name`/`plugin` match) so an unrelated entry whose text\n * merely contains `name` cannot be mistaken for ours; falls back to a whole-word text scan when\n * `--json` is unavailable. Never throws — an unresolvable claude means \"not present\".\n */\nfunction hasClaudeEntry(args: string[], name: string): boolean {\n const json = spawnSync(\"claude\", [...args, \"--json\"], { encoding: \"utf8\" });\n if (json.status === 0 && json.stdout) {\n try {\n const parsed: unknown = JSON.parse(json.stdout);\n const rows = Array.isArray(parsed)\n ? parsed\n : Array.isArray((parsed as { plugins?: unknown }).plugins)\n ? (parsed as { plugins: unknown[] }).plugins\n : [];\n return rows.some((row) => {\n if (typeof row !== \"object\" || row === null) return false;\n const r = row as { id?: unknown; name?: unknown; plugin?: unknown };\n return (\n r.id === name ||\n r.name === name ||\n r.plugin === name ||\n (typeof r.id === \"string\" && r.id.split(\"@\")[0] === name)\n );\n });\n } catch {\n // fall through to the text scan\n }\n }\n const text = spawnSync(\"claude\", args, { encoding: \"utf8\" });\n const out = `${text.stdout ?? \"\"}${text.stderr ?? \"\"}`;\n return text.status === 0 && new RegExp(`(^|\\\\s)${name}(\\\\s|@|$)`, \"m\").test(out);\n}\n\n/**\n * Wire the real {@link OnboardDeps}: a dist-presence check that triggers `pnpm -r build` + the\n * plugin bundle, `runInit` for the brain core, an idempotent plugin install via the repo\n * marketplace (`claude plugin marketplace add` + `claude plugin install`), and a detached\n * sync daemon. Every step degrades to a `skipped` note rather than throwing, so a missing\n * `pnpm`/`claude` never aborts onboarding. Pure orchestration lives in {@link runOnboard}.\n *\n * @param opts Optional overrides ({@link DefaultOnboardDepsOptions}).\n * @returns A fully-wired {@link OnboardDeps}.\n */\n/**\n * The Commonwealth install root (the monorepo checkout), found by walking up from THIS\n * module for `pnpm-workspace.yaml`. This is where the built per-package dist binaries\n * live — resolved from the CLI's own location, NOT the user's cwd, so `init` works when\n * run inside an arbitrary project. Returns null when not running from a workspace checkout\n * (e.g. a future npm-global install), in which case build/spawn steps degrade gracefully.\n */\nfunction commonwealthRoot(): string | null {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n for (;;) {\n if (existsSync(path.join(dir, \"pnpm-workspace.yaml\"))) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\nexport function defaultOnboardDeps(opts: DefaultOnboardDepsOptions = {}): OnboardDeps {\n const log = (m: string): void => {\n process.stderr.write(m + \"\\n\");\n };\n\n // Resolve tool binaries from the Commonwealth install, not the target project's cwd.\n const repoRoot = opts.repoRoot ?? commonwealthRoot() ?? findRepoRoot(process.cwd());\n const isWorkspace = existsSync(path.join(repoRoot, \"pnpm-workspace.yaml\"));\n const distEntry = (pkg: string): string =>\n path.join(repoRoot, \"packages\", pkg, \"dist\", \"index.js\");\n\n const ensureBuilt = async (): Promise<{ built: boolean; skipped?: string }> => {\n if (!isWorkspace) {\n return { built: false, skipped: \"not a workspace checkout; assuming an installed build\" };\n }\n const missing = REQUIRED_DIST_PACKAGES.filter((pkg) => !existsSync(distEntry(pkg)));\n if (missing.length === 0) return { built: false };\n if (!hasExecutable(\"pnpm\")) {\n return {\n built: false,\n skipped: `pnpm not found; cannot build (missing: ${missing.join(\", \")})`,\n };\n }\n const build = spawnSync(\"pnpm\", [\"-r\", \"build\"], { cwd: repoRoot, stdio: \"inherit\" });\n if (build.status !== 0) {\n const reason = build.error\n ? build.error.message\n : build.signal\n ? `signal ${build.signal}`\n : `exit code ${build.status}`;\n return { built: false, skipped: `pnpm -r build failed (${reason})` };\n }\n // Best-effort: refresh the vendored plugin bundle; failure here is non-fatal.\n const bundle = path.join(repoRoot, \"packages\", \"plugin\", \"scripts\", \"bundle.mjs\");\n if (existsSync(bundle)) {\n const res = spawnSync(\"node\", [bundle], { cwd: repoRoot, stdio: \"inherit\" });\n if (res.status !== 0)\n log(`Plugin bundle exited with code ${res.status ?? \"null\"} (ignored).`);\n }\n return { built: true };\n };\n\n const init = (cwd: string, initOpts: Parameters<OnboardDeps[\"init\"]>[1]) =>\n runInit(\n cwd,\n initOpts,\n defaultInitDeps({ assumeYes: initOpts.yes, curateEntry: opts.curateEntry }),\n );\n\n const configureScope = async (\n repoRoot: string,\n ): Promise<{ added: boolean; skipped?: string }> => {\n let curateEntry: string;\n try {\n curateEntry = resolveCurateEntry(opts.curateEntry);\n } catch (err) {\n return { added: false, skipped: `commonwealth-curate not found: ${(err as Error).message}` };\n }\n const res = spawnSync(\"node\", [curateEntry, \"scope\", \"allow\", repoRoot], { stdio: \"ignore\" });\n if (res.error || res.status !== 0) {\n const reason = res.error ? res.error.message : `exit code ${res.status ?? \"null\"}`;\n return { added: false, skipped: `scope allow failed (${reason})` };\n }\n return { added: true };\n };\n\n const setAutoAdr = async (\n brainDir: string,\n on: boolean,\n ): Promise<{ set: boolean; skipped?: string }> => {\n let curateEntry: string;\n try {\n curateEntry = resolveCurateEntry(opts.curateEntry);\n } catch (err) {\n return { set: false, skipped: `commonwealth-curate not found: ${(err as Error).message}` };\n }\n const verb = on ? \"enable\" : \"disable\";\n const res = spawnSync(\"node\", [curateEntry, \"feature\", verb, \"autoAdr\", \"--dir\", brainDir], {\n stdio: \"ignore\",\n });\n if (res.error || res.status !== 0) {\n const reason = res.error ? res.error.message : `exit code ${res.status ?? \"null\"}`;\n return { set: false, skipped: `feature ${verb} autoAdr failed (${reason})` };\n }\n return { set: true };\n };\n\n const setRemote = async (\n brainDir: string,\n url: string,\n ): Promise<{ set: boolean; skipped?: string }> => {\n const existing = spawnSync(\"git\", [\"-C\", brainDir, \"remote\", \"get-url\", \"origin\"], {\n stdio: \"ignore\",\n });\n if (existing.status === 0) return { set: false, skipped: \"origin exists\" };\n\n const add = spawnSync(\"git\", [\"-C\", brainDir, \"remote\", \"add\", \"origin\", url], {\n stdio: \"ignore\",\n });\n if (add.error || add.status !== 0) {\n const reason = add.error ? add.error.message : `exit code ${add.status ?? \"null\"}`;\n return { set: false, skipped: `git remote add failed (${reason})` };\n }\n return { set: true };\n };\n\n /**\n * Install the Commonwealth plugin at USER scope via the repo marketplace (ADR-0012),\n * replacing the old raw local-scope `claude mcp add`. Steps, all best-effort and\n * idempotent, NONE throwing:\n * a) refresh the vendored plugin bundle (so the plugin's vendor/ is up to date);\n * b) `claude plugin marketplace add <repoRoot>` — skipped if a `commonwealth` marketplace\n * is already configured (checked via `marketplace list`);\n * c) `claude plugin install commonwealth@cmnwlth` — skipped if already installed\n * (checked via `plugin list`);\n * d) remove a STALE raw `commonwealth` MCP registration (`claude mcp remove -s local`) so\n * it doesn't shadow the plugin's `commonwealth` server.\n * The brain is resolved per repo by the plugin + its SessionStart hook, so no brain dir is\n * pinned here.\n */\n const installPlugin = async (): Promise<{ installed: boolean; skipped?: string }> => {\n if (!hasExecutable(\"claude\")) {\n return { installed: false, skipped: \"claude CLI not found\" };\n }\n\n // (a) Refresh the vendored bundle so the installed plugin runs the current build.\n const bundle = path.join(repoRoot, \"packages\", \"plugin\", \"scripts\", \"bundle.mjs\");\n if (existsSync(bundle)) {\n const res = spawnSync(\"node\", [bundle], { cwd: repoRoot, stdio: \"inherit\" });\n if (res.status !== 0)\n log(`Plugin bundle exited with code ${res.status ?? \"null\"} (ignored).`);\n }\n\n // (b) Register the repo as a marketplace unless a `commonwealth` marketplace already exists.\n if (!hasClaudeEntry([\"plugin\", \"marketplace\", \"list\"], \"commonwealth\")) {\n const add = spawnSync(\"claude\", [\"plugin\", \"marketplace\", \"add\", repoRoot], {\n stdio: \"inherit\",\n });\n if (add.error || add.status !== 0) {\n return {\n installed: false,\n skipped: `claude plugin marketplace add failed (code ${add.status ?? \"null\"})`,\n };\n }\n }\n\n // (c) Install the plugin unless it is already installed.\n if (!hasClaudeEntry([\"plugin\", \"list\"], \"commonwealth\")) {\n const install = spawnSync(\"claude\", [\"plugin\", \"install\", \"commonwealth@cmnwlth\"], {\n stdio: \"inherit\",\n });\n if (install.error || install.status !== 0) {\n return {\n installed: false,\n skipped: `claude plugin install failed (code ${install.status ?? \"null\"})`,\n };\n }\n }\n\n // (d) Clean up any stale raw local-scope MCP registration so it can't shadow the plugin.\n const staleGet = spawnSync(\"claude\", [\"mcp\", \"get\", \"commonwealth\"], { stdio: \"ignore\" });\n if (staleGet.status === 0) {\n spawnSync(\"claude\", [\"mcp\", \"remove\", \"commonwealth\", \"-s\", \"local\"], { stdio: \"ignore\" });\n }\n\n return { installed: true };\n };\n\n const startDaemon = async (\n brainDir: string,\n ): Promise<{ started: boolean; alreadyRunning?: boolean; skipped?: string }> => {\n const syncEntry = distEntry(\"sync\");\n if (!existsSync(syncEntry)) {\n return { started: false, skipped: \"sync daemon not built\" };\n }\n const status = spawnSync(\"node\", [syncEntry, \"status\", \"--dir\", brainDir], {\n encoding: \"utf8\",\n });\n const output = `${status.stdout ?? \"\"}${status.stderr ?? \"\"}`;\n if (/\\brunning on\\b/.test(output) && !/\\bnot running on\\b/.test(output)) {\n return { started: false, alreadyRunning: true };\n }\n try {\n const child = spawn(\"node\", [syncEntry, \"start\", \"--dir\", brainDir], {\n detached: true,\n stdio: \"ignore\",\n });\n child.unref();\n return { started: true };\n } catch (err) {\n return { started: false, skipped: `failed to start daemon: ${(err as Error).message}` };\n }\n };\n\n const registerBrain = async (\n folder: string,\n brainDir: string,\n ): Promise<{ mapped: boolean; linked: boolean; skipped?: string }> => {\n try {\n const map = await core.addRegistryMapping(folder, brainDir);\n const link = await core.linkBrain(path.basename(brainDir), brainDir);\n return { mapped: map.added || map.updated, linked: link.linked, skipped: link.skipped };\n } catch (err) {\n return { mapped: false, linked: false, skipped: (err as Error).message };\n }\n };\n\n const seedFrom = async (\n brainDir: string,\n repoDir: string,\n ): Promise<{ staged: number; skipped?: string }> => {\n let curateEntry: string;\n try {\n curateEntry = resolveCurateEntry(opts.curateEntry);\n } catch (err) {\n return { staged: 0, skipped: `commonwealth-curate not found: ${(err as Error).message}` };\n }\n const seedEntry = distEntry(\"seed\");\n if (!existsSync(seedEntry)) return { staged: 0, skipped: \"seed CLI not built\" };\n\n return new Promise((resolve) => {\n const gather = spawn(\"node\", [seedEntry, \"gather\", \"--repo\", repoDir], {\n stdio: [\"ignore\", \"pipe\", \"inherit\"],\n });\n const capture = spawn(\"node\", [curateEntry, \"capture\", \"--dir\", brainDir, \"--force\"], {\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n });\n\n let settled = false;\n const done = (result: { staged: number; skipped?: string }): void => {\n if (settled) return;\n settled = true;\n resolve(result);\n };\n\n gather.on(\"error\", (err) =>\n done({ staged: 0, skipped: `seed spawn failed (${err.message})` }),\n );\n capture.on(\"error\", (err) =>\n done({ staged: 0, skipped: `capture spawn failed (${err.message})` }),\n );\n\n gather.stdout.pipe(capture.stdin);\n\n let out = \"\";\n capture.stdout.setEncoding(\"utf8\");\n capture.stdout.on(\"data\", (chunk: string) => {\n out += chunk;\n });\n\n capture.on(\"close\", (code) => {\n if (code !== 0) {\n done({ staged: 0, skipped: `capture exited with code ${code ?? \"null\"}` });\n return;\n }\n const staged = out.split(\"\\n\").filter((line) => line.trim().length > 0).length;\n done({ staged });\n });\n });\n };\n\n const ensureUserConfig = async (): Promise<{ path: string }> => {\n const configPath =\n process.env.COMMONWEALTH_CONFIG ?? path.join(os.homedir(), \".commonwealth\", \"config.json\");\n if (!existsSync(configPath)) {\n try {\n await fs.mkdir(path.dirname(configPath), { recursive: true });\n await fs.writeFile(\n configPath,\n `${JSON.stringify({ allow: [], deny: [] }, null, 2)}\\n`,\n \"utf8\",\n );\n } catch (err) {\n log(`Could not create scope config at ${configPath}: ${(err as Error).message}`);\n }\n }\n return { path: configPath };\n };\n\n return {\n ensureBuilt,\n init,\n configureScope,\n registerBrain,\n seedFrom,\n ensureUserConfig,\n setAutoAdr,\n setRemote,\n installPlugin,\n startDaemon,\n confirm: promptConfirm,\n log,\n };\n}\n","import { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { NewNoteInput } from \"@cmnwlth/core\";\n\n/** Per-source counts of what seeding mined from the repo. */\nexport interface InitBySource {\n adr: number;\n git: number;\n config: number;\n}\n\n/** Flags that shape an `init` run, parsed from the CLI. */\nexport interface InitOptions {\n /** Explicit brain directory to create/use instead of {@link defaultBrainDir}. */\n brain?: string;\n /** Skip the confirmation prompt and seed non-interactively. */\n yes?: boolean;\n /** Re-run seeding even if this project already resolves to a brain (skip JOIN). */\n reseed?: boolean;\n /** Gather + stage seed candidates. Defaults to `true`; `false` creates the brain but skips staging. */\n seed?: boolean;\n}\n\n/**\n * Injected side effects so {@link runInit} is deterministic and unit-testable without\n * touching the filesystem, spawning `commonwealth-curate`, or prompting a human.\n */\nexport interface InitDeps {\n /** Mine cold-start candidates from the repo (usually `@cmnwlth/seed`'s `gatherCandidates`). */\n gather(repoDir: string): Promise<{ candidates: NewNoteInput[]; bySource: InitBySource }>;\n /** Resolve the brain this project already belongs to, or `null` if none. */\n resolveBrain(cwd: string): Promise<string | null>;\n /** Scaffold a fresh brain at `dir` with the given human-readable name. */\n createBrain(dir: string, name: string): Promise<void>;\n /**\n * Record that `repoDir` maps to `brainDir` in the global brain registry (ADR-0011). The\n * registry is the default source of truth; the per-project `.commonwealth/brain` marker\n * remains an optional manual override (`core.setBrainMarker`), not written here.\n */\n registerBrain(repoDir: string, brainDir: string): Promise<void>;\n /** Stage candidates into the brain's review queue; returns how many were captured. */\n stage(brainDir: string, candidates: NewNoteInput[]): Promise<{ captured: number }>;\n /** Ask the user a yes/no question; resolves to their answer. */\n confirm(message: string): Promise<boolean>;\n /** Emit a human-facing line (diagnostics stream, never stdout data). */\n log(message: string): void;\n}\n\n/** What an {@link runInit} run did, for the CLI to summarize and tests to assert on. */\nexport interface InitResult {\n /** `new` = brain created + seeded; `join` = mounted existing brain; `skipped` = created but seeding declined. */\n mode: \"new\" | \"join\" | \"skipped\";\n /** The brain directory this project is now pinned to. */\n brainDir: string;\n /** How many candidate notes were staged into the review queue. */\n staged: number;\n /** How many candidates seeding gathered (0 in JOIN mode). */\n gathered: number;\n}\n\n/**\n * Walk up from `startDir` looking for a `.git` directory; return the repo root, or fall\n * back to `startDir` when no `.git` ancestor exists (e.g. a not-yet-initialized project).\n *\n * @param startDir Directory to start the upward search from.\n * @returns The nearest ancestor containing `.git`, else `startDir`.\n */\nexport function findRepoRoot(startDir: string): string {\n let dir = path.resolve(startDir);\n for (;;) {\n if (existsSync(path.join(dir, \".git\"))) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) return path.resolve(startDir);\n dir = parent;\n }\n}\n\n/**\n * Compute the default brain directory for a project. The brain is a SEPARATE repo living\n * under `~/.commonwealth/brains/<basename>-<hash>`, never nested inside the project itself.\n * The short hash of the FULL resolved path disambiguates same-named projects in different\n * locations (`~/work/app` vs `~/personal/app`), which would otherwise collapse to one brain\n * and silently share it (#103). Deterministic, so re-running `init` maps to the same brain.\n *\n * @param repoRoot The project's repo root.\n * @returns An absolute path for the project's default brain.\n */\nexport function defaultBrainDir(repoRoot: string): string {\n const resolved = path.resolve(repoRoot);\n const hash = createHash(\"sha256\").update(resolved).digest(\"hex\").slice(0, 8);\n return path.join(os.homedir(), \".commonwealth\", \"brains\", `${path.basename(resolved)}-${hash}`);\n}\n\n/**\n * Orchestrate `commonwealth init`. Deterministic and side-effect-free except through `deps`.\n *\n * Flow: resolve the repo root and any existing brain. If one exists and we're not\n * reseeding, JOIN it (register the mapping, done). Otherwise create a new brain, register\n * the project → brain mapping, gather seed candidates, preview them, and — guarded behind\n * confirmation unless `--yes` — stage them into the review queue. Brain creation and the\n * registry mapping are idempotent and always run; every content write (staging) is gated\n * by `confirm`.\n *\n * @param cwd The directory `commonwealth init` was invoked from.\n * @param opts Parsed CLI flags.\n * @param deps Injected side effects.\n * @returns A structured summary of what happened.\n */\nexport async function runInit(cwd: string, opts: InitOptions, deps: InitDeps): Promise<InitResult> {\n // The mapping/scope/brain-name base is the INVOCATION dir, not the git root. `findRepoRoot`\n // may climb above `cwd` to a parent repo (a nested package, or a folder-of-repos sitting\n // under a stray parent `.git`); using that as the registry prefix over-scopes every sibling\n // to the wrong brain (#61). The git root stays a separate concern, used only for mining.\n const projectDir = path.resolve(cwd);\n const repoRoot = findRepoRoot(cwd);\n\n const existing = await deps.resolveBrain(cwd);\n // JOIN the already-resolved brain only when the user isn't overriding it with --brain and\n // isn't reseeding. An explicit --brain means \"use THIS brain\" (switch), so it must not be\n // silently ignored in favor of the auto-resolved one (#103).\n if (existing !== null && !opts.reseed && !opts.brain) {\n await deps.registerBrain(projectDir, existing);\n deps.log(`Joined existing brain at ${existing}. Run the sync daemon to pull.`);\n return { mode: \"join\", brainDir: existing, staged: 0, gathered: 0 };\n }\n\n // Brain selection: an explicit --brain wins; otherwise a --reseed re-mines into the brain this\n // project ALREADY resolves to (never silently re-point a custom brain at the default, #103);\n // only a brand-new project with no brain falls back to the default dir.\n const brainDir = opts.brain ?? existing ?? defaultBrainDir(projectDir);\n await deps.createBrain(brainDir, path.basename(brainDir));\n await deps.registerBrain(projectDir, brainDir);\n\n if (opts.seed === false) {\n deps.log(`Seeding skipped. Brain created at ${brainDir}.`);\n return { mode: \"skipped\", brainDir, staged: 0, gathered: 0 };\n }\n\n const { candidates, bySource } = await deps.gather(repoRoot);\n deps.log(\n `Found ${candidates.length} candidates — adr:${bySource.adr} git:${bySource.git} config:${bySource.config}`,\n );\n\n if (candidates.length > 0 && !opts.yes) {\n const ok = await deps.confirm(\n `Seed ${candidates.length} candidates into the brain's review queue?`,\n );\n if (!ok) {\n deps.log(`Skipped seeding. Brain created at ${brainDir}.`);\n return { mode: \"skipped\", brainDir, staged: 0, gathered: candidates.length };\n }\n }\n\n const { captured } = candidates.length ? await deps.stage(brainDir, candidates) : { captured: 0 };\n\n deps.log(\n `Your brain has ${captured} notes pending review. Run \\`commonwealth-curate list\\` to approve, ` +\n `then start a Claude session here and ask it something your team already knows.`,\n );\n\n return { mode: \"new\", brainDir, staged: captured, gathered: candidates.length };\n}\n","import path from \"node:path\";\nimport type { InitOptions, InitResult } from \"./init.js\";\nimport type { Prompter } from \"./prompt.js\";\nimport { findGitRepos } from \"./discover.js\";\n\n/**\n * Flags that shape a full `commonwealth init` orchestration. The step gates (`seed`, `mcp`,\n * `daemon`, `build`, `scope`) default to `true` when omitted; pass `false` to skip that step. This\n * is a type alias (not an interface) so it stays free of empty-interface lint noise.\n */\nexport type OnboardOptions = {\n /** Explicit brain directory to create/use instead of the project default. */\n brain?: string;\n /** Skip the whole-plan confirmation and run non-interactively. */\n yes?: boolean;\n /** Re-run seeding even if this project already resolves to a brain. */\n reseed?: boolean;\n /** Gather + stage seed candidates. Default: true. `false` skips staging. */\n seed?: boolean;\n /**\n * Install the Commonwealth plugin (global MCP + session hooks) via the repo marketplace.\n * Default: true. The plugin resolves the brain per repo dynamically, so no brain dir is\n * pinned. `mcp` is a backward-compatible alias for this gate.\n */\n plugin?: boolean;\n /** Backward-compatible alias for {@link OnboardOptions.plugin}. */\n mcp?: boolean;\n /** Start the sync daemon for the brain. Default: true. */\n daemon?: boolean;\n /** Build/bundle the workspace if dist artifacts are missing. Default: true. */\n build?: boolean;\n /** Add the repo root to the capture allowlist (`scope allow`). Default: true. */\n scope?: boolean;\n /** Enable auto-ADR capture for the brain. Default: false. */\n autoAdr?: boolean;\n /** Add this URL as the brain's git `origin` remote. Default: undefined (skip). */\n remote?: string;\n /**\n * Folders to sync into this brain: each is added to the capture allowlist and wired to the\n * brain via the global user registry (plus a convenience symlink). Default: `[cwd]` (#61).\n */\n syncFolders?: string[];\n /**\n * Repos to mine (seed) into the brain now. Default: {@link OnboardOptions.syncFolders} when\n * seeding is enabled, else `[]`.\n */\n seedRepos?: string[];\n};\n\n/**\n * Injected side effects so {@link runOnboard} is deterministic and unit-testable without\n * building the workspace, delegating to `runInit`, spawning `claude`, or starting a daemon.\n */\nexport interface OnboardDeps {\n /** Build the workspace when dist artifacts are missing; a no-op (with a note) otherwise. */\n ensureBuilt(): Promise<{ built: boolean; skipped?: string }>;\n /** Create/seed/join the brain (delegates to `runInit` with real init deps). */\n init(cwd: string, initOpts: InitOptions): Promise<InitResult>;\n /** Idempotently add `folder` to the capture allowlist (`scope allow`; de-dupes). */\n configureScope(folder: string): Promise<{ added: boolean; skipped?: string }>;\n /**\n * Register `folder → brainDir` in the global user registry (the default brain-wiring source\n * of truth) and drop a convenience `~/.commonwealth/brains/<name>` symlink. Idempotent;\n * never throws. `mapped` reflects the registry write, `linked` the symlink; `skipped` carries\n * a reason when the symlink could not be created (the mapping still counts).\n */\n registerBrain(\n folder: string,\n brainDir: string,\n ): Promise<{ mapped: boolean; linked: boolean; skipped?: string }>;\n /** Mine `repoDir` and stage the candidates into `brainDir`'s review queue. */\n seedFrom(brainDir: string, repoDir: string): Promise<{ staged: number; skipped?: string }>;\n /**\n * Ensure the per-user scope config file exists (creating an empty one if missing) and return\n * its resolved path. Called near the end of onboarding regardless of scope choices.\n */\n ensureUserConfig(): Promise<{ path: string }>;\n /** Enable/disable auto-ADR capture for `brainDir`. */\n setAutoAdr(brainDir: string, on: boolean): Promise<{ set: boolean; skipped?: string }>;\n /** Add `url` as the brain's git `origin` remote unless one already exists. */\n setRemote(brainDir: string, url: string): Promise<{ set: boolean; skipped?: string }>;\n /**\n * Idempotently install the Commonwealth plugin (global MCP + session hooks) via the repo\n * marketplace with the `claude` CLI. No brain dir is needed — the plugin + its SessionStart\n * hook resolve the brain per repo dynamically (ADR-0012). Never throws. `installed` is true\n * when the plugin is present after the step; `skipped` carries a reason when it is not.\n */\n installPlugin(): Promise<{ installed: boolean; skipped?: string }>;\n /** Start the sync daemon for `brainDir`, or report it already running. */\n startDaemon(\n brainDir: string,\n ): Promise<{ started: boolean; alreadyRunning?: boolean; skipped?: string }>;\n /** Ask the user a yes/no question; resolves to their answer. */\n confirm(message: string): Promise<boolean>;\n /** Emit a human-facing line (diagnostics stream, never stdout data). */\n log(message: string): void;\n}\n\n/** What a {@link runOnboard} run did, for the CLI to summarize and tests to assert on. */\nexport interface OnboardResult {\n /** The brain directory this project is now pinned to. */\n brainDir: string;\n /** Delegated `runInit` mode: `new` / `join` / `skipped`. */\n mode: InitResult[\"mode\"];\n /** Whether {@link OnboardDeps.ensureBuilt} actually built anything. */\n built: boolean;\n /** How many candidate notes were staged into the review queue (summed across seeded repos). */\n staged: number;\n /** How many folders were added to the capture allowlist. */\n scopedFolders: number;\n /** How many folders were wired into a brain via the global registry. */\n mappedFolders: number;\n /** How many repos were seeded (mined) into the brain. */\n seededRepos: number;\n /** Resolved path of the per-user scope config file (always ensured to exist). */\n scopeConfigPath: string;\n /** Short allowlist status string (e.g. `added`, `skipped`). */\n scope: string;\n /** Short auto-ADR status string (e.g. `enabled`, `skipped`). */\n autoAdr: string;\n /** Short brain-remote status string (e.g. `set`, `origin exists`, `skipped`). */\n remote: string;\n /** Short plugin-install status string (e.g. `installed`, `skipped`). */\n plugin: string;\n /** Short daemon status string (e.g. `started`, `already running`, `skipped`). */\n daemon: string;\n}\n\n/**\n * Orchestrate the full `commonwealth init`: build the workspace (if needed), create/seed/join\n * the brain, install the Commonwealth plugin (global MCP + session hooks), and start the sync\n * daemon — a single idempotent command. Deterministic and side-effect-free except through `deps`.\n *\n * Flow: build a plan and log it; unless `--yes`, confirm the whole plan (a decline does NOTHING\n * and returns early); then run each enabled step in order — ensureBuilt, init, installPlugin,\n * startDaemon — and log a done summary. Each step is individually gated by its option and every\n * step is idempotent, so re-running is safe.\n *\n * @param cwd The directory `commonwealth init` was invoked from.\n * @param opts Parsed CLI flags (step gates default to enabled).\n * @param deps Injected side effects.\n * @returns A structured summary of what happened.\n */\nexport async function runOnboard(\n cwd: string,\n opts: OnboardOptions,\n deps: OnboardDeps,\n): Promise<OnboardResult> {\n const doBuild = opts.build !== false;\n const doSeed = opts.seed !== false;\n const doScope = opts.scope !== false;\n const doAutoAdr = opts.autoAdr === true;\n const doRemote = typeof opts.remote === \"string\" && opts.remote.trim().length > 0;\n // Install the plugin unless explicitly disabled. `plugin` is the canonical gate; `mcp` is a\n // backward-compatible alias, so either being `false` disables the step.\n const doPlugin = opts.plugin !== false && opts.mcp !== false;\n const doDaemon = opts.daemon !== false;\n\n // Default the sync/scope target to the INVOCATION dir, not the git root — `findRepoRoot`\n // may climb to a parent repo and over-scope every sibling (#61). Mining still uses the git\n // root (inside `runInit`); the wizard/`--sync` let the user pick folders explicitly.\n // Distinguish \"flag omitted\" (undefined → default to the invocation dir) from an explicit\n // empty selection (the wizard's \"none\" → []), which must be RESPECTED, not silently\n // overridden to cwd (#103). The cwd is still wired to the brain by runInit below regardless;\n // this only governs which EXTRA folders get scoped/mapped.\n const syncFolders = opts.syncFolders ?? [path.resolve(cwd)];\n const seedRepos = opts.seedRepos ?? (doSeed ? syncFolders : []);\n\n const brainLabel = opts.brain ?? \"the project's default brain dir\";\n const plan = [\n doBuild ? \"build the workspace if needed\" : null,\n `create brain at ${brainLabel}`,\n doScope ? `sync ${syncFolders.length} folder(s) into the brain` : null,\n seedRepos.length > 0 ? `seed from ${seedRepos.length} repo(s)` : null,\n doAutoAdr ? \"enable auto-ADR\" : null,\n doRemote ? `set brain remote to ${opts.remote}` : null,\n doPlugin ? \"install the Commonwealth plugin (global MCP + session hooks)\" : null,\n doDaemon ? \"start the sync daemon\" : null,\n \"ensure the per-user scope config exists\",\n ].filter((step): step is string => step !== null);\n deps.log(`Will: ${plan.join(\", \")}.`);\n\n if (!opts.yes) {\n const ok = await deps.confirm(\"Proceed with the plan above?\");\n if (!ok) {\n deps.log(\"Aborted. Nothing was changed.\");\n return {\n brainDir: opts.brain ?? \"\",\n mode: \"skipped\",\n built: false,\n staged: 0,\n scopedFolders: 0,\n mappedFolders: 0,\n seededRepos: 0,\n scopeConfigPath: \"\",\n scope: \"skipped\",\n autoAdr: \"skipped\",\n remote: \"skipped\",\n plugin: \"skipped\",\n daemon: \"skipped\",\n };\n }\n }\n\n let built = false;\n if (doBuild) {\n const res = await deps.ensureBuilt();\n built = res.built;\n if (res.skipped) deps.log(`Build: ${res.skipped}`);\n else deps.log(built ? \"Build: built workspace.\" : \"Build: dist up to date.\");\n }\n\n // Create/join the brain only; seeding is done per-repo below via seedFrom.\n const initResult = await deps.init(cwd, {\n brain: opts.brain,\n yes: opts.yes,\n reseed: opts.reseed,\n seed: false,\n });\n const brainDir = initResult.brainDir;\n\n let scopedFolders = 0;\n let mappedFolders = 0;\n let scope = \"skipped\";\n if (doScope) {\n for (const folder of syncFolders) {\n const scopeRes = await deps.configureScope(folder);\n if (scopeRes.skipped) {\n deps.log(`WARNING: scope step skipped for ${folder}: ${scopeRes.skipped}`);\n } else if (scopeRes.added) {\n scopedFolders += 1;\n deps.log(`Scope: added ${folder}`);\n } else {\n deps.log(`Scope: ${folder} already allowed`);\n }\n\n const regRes = await deps.registerBrain(folder, brainDir);\n if (regRes.mapped) mappedFolders += 1;\n deps.log(`registered ${folder} -> ${brainDir} (symlink brains/${path.basename(brainDir)})`);\n if (regRes.skipped) {\n deps.log(`WARNING: brain symlink skipped for ${folder}: ${regRes.skipped}`);\n }\n }\n scope = scopedFolders > 0 ? `added ${scopedFolders}` : \"none added\";\n }\n\n let staged = 0;\n let seededRepos = 0;\n if (seedRepos.length > 0) {\n for (const repo of seedRepos) {\n const seedRes = await deps.seedFrom(brainDir, repo);\n if (seedRes.skipped) {\n deps.log(`WARNING: seed step skipped for ${repo}: ${seedRes.skipped}`);\n } else {\n staged += seedRes.staged;\n seededRepos += 1;\n deps.log(`Seed: staged ${seedRes.staged} from ${repo}`);\n }\n }\n }\n\n let autoAdr = \"skipped\";\n if (doAutoAdr) {\n const res = await deps.setAutoAdr(brainDir, true);\n autoAdr = res.skipped ?? (res.set ? \"enabled\" : \"not enabled\");\n deps.log(`Auto-ADR: ${autoAdr}`);\n }\n\n let remote = \"skipped\";\n if (doRemote) {\n const res = await deps.setRemote(brainDir, opts.remote as string);\n remote = res.skipped ?? (res.set ? \"set\" : \"not set\");\n deps.log(`Remote: ${remote}`);\n }\n\n let plugin = \"skipped\";\n if (doPlugin) {\n const res = await deps.installPlugin();\n if (res.skipped) {\n deps.log(`WARNING: plugin step skipped: ${res.skipped}`);\n plugin = res.skipped;\n } else {\n plugin = res.installed ? \"installed\" : \"not installed\";\n deps.log(`Plugin: ${plugin}`);\n }\n }\n\n let daemon = \"skipped\";\n if (doDaemon) {\n const res = await deps.startDaemon(brainDir);\n if (res.skipped) {\n deps.log(`WARNING: daemon step skipped: ${res.skipped}`);\n daemon = res.skipped;\n } else if (res.alreadyRunning) {\n daemon = \"already running\";\n deps.log(`Daemon: ${daemon}`);\n } else {\n daemon = res.started ? \"started\" : \"not started\";\n deps.log(`Daemon: ${daemon}`);\n }\n }\n\n // Always ensure the per-user scope config exists, regardless of scope choices above.\n const { path: scopeConfigPath } = await deps.ensureUserConfig();\n\n deps.log(\n `Done. mode=${initResult.mode} brain=${brainDir} staged=${staged} ` +\n `scopedFolders=${scopedFolders} mappedFolders=${mappedFolders} seededRepos=${seededRepos} ` +\n `scope=${scope} autoAdr=${autoAdr} remote=${remote} plugin=${plugin} daemon=${daemon}. ` +\n `Scope config: ${scopeConfigPath}. ` +\n \"Open a Claude session here and ask it something your team knows.\",\n );\n\n return {\n brainDir,\n mode: initResult.mode,\n built,\n staged,\n scopedFolders,\n mappedFolders,\n seededRepos,\n scopeConfigPath,\n scope,\n autoAdr,\n remote,\n plugin,\n daemon,\n };\n}\n\n/** The answers a wizard collects, ready to be turned into {@link OnboardOptions}. */\nexport interface WizardAnswers {\n brain: string;\n scope: boolean;\n seed: boolean;\n plugin: boolean;\n daemon: boolean;\n autoAdr: boolean;\n remote: string;\n}\n\n/** Defaults the wizard seeds its prompts with (Enter accepts each). */\nexport interface WizardDefaults {\n brain: string;\n /**\n * The invocation dir — the fallback sync/seed target when no sibling repos are found, and the\n * base whose parent is offered as the default scan directory. Deliberately NOT the git root:\n * that can climb above `cwd` and over-scope (#61).\n */\n projectDir: string;\n scope: boolean;\n seed: boolean;\n plugin: boolean;\n daemon: boolean;\n autoAdr: boolean;\n}\n\n/** What {@link runWizard} produces: the assembled options, or an abort signal. */\nexport type WizardOutcome =\n { proceed: true; opts: OnboardOptions } | { proceed: false; opts: null };\n\n/** Injectable side effects for {@link runWizard} (defaults to the real discovery). */\nexport interface WizardDeps {\n /** Scan `baseDir` for git repositories (defaults to {@link findGitRepos}). */\n scan(baseDir: string): Promise<string[]>;\n}\n\n/** Real wizard deps: scan the filesystem for git repos. */\nfunction defaultWizardDeps(): WizardDeps {\n return { scan: (baseDir) => findGitRepos(baseDir) };\n}\n\n/**\n * Drive the interactive wizard: ask each choice with a sensible default (Enter accepts), then a\n * final `Proceed?` confirm. Pure orchestration over a {@link Prompter} + {@link WizardDeps}, so\n * tests script answers with a fake and never touch a real TTY or filesystem. A declined\n * `Proceed?` returns `{ proceed: false }` and the caller must perform ZERO side effects.\n *\n * After the brain prompt it asks which directory to scan for projects, discovers the git repos\n * beneath it, and lets the user multi-select which folders to SYNC into the brain and which repos\n * to SEED now (seed defaults to the sync selection). When nothing is found it falls back to the\n * repo root for both.\n *\n * The returned `opts` carry `yes: true` because the wizard has already confirmed — the caller must\n * NOT prompt again inside {@link runOnboard}.\n *\n * @param defaults Per-prompt defaults (usually derived from environment probing).\n * @param prompter The interactive prompter.\n * @param deps Injectable discovery (defaults to scanning the real filesystem).\n * @returns A {@link WizardOutcome}: the options to run, or an abort.\n */\nexport async function runWizard(\n defaults: WizardDefaults,\n prompter: Prompter,\n deps: WizardDeps = defaultWizardDeps(),\n): Promise<WizardOutcome> {\n const brain = await prompter.text(\"Brain directory\", defaults.brain);\n\n const scanDefault = path.dirname(defaults.projectDir);\n const scanDir = await prompter.text(\"Scan which directory for projects?\", scanDefault);\n const repos = await deps.scan(scanDir);\n\n let syncFolders: string[];\n let seedRepos: string[];\n if (repos.length > 0) {\n const items = repos.map((r) => ({ label: r, value: r }));\n const allTrue = repos.map(() => true);\n syncFolders = await prompter.select(\"Folders to SYNC into this brain\", items, allTrue);\n const seedDefault = repos.map((r) => syncFolders.includes(r));\n seedRepos = await prompter.select(\"Repos to SEED from now\", items, seedDefault);\n } else {\n syncFolders = [defaults.projectDir];\n seedRepos = [defaults.projectDir];\n }\n\n const plugin = await prompter.confirm(\n \"Install the Commonwealth plugin (global MCP + session hooks)?\",\n defaults.plugin,\n );\n const daemon = await prompter.confirm(\"Start the sync daemon?\", defaults.daemon);\n const autoAdr = await prompter.confirm(\"Enable auto-ADR?\", defaults.autoAdr);\n const remote = await prompter.text(\"Brain git remote (blank to skip)\", \"\");\n\n const opts: OnboardOptions = {\n brain: brain.trim() === \"\" ? undefined : brain,\n yes: true,\n seed: seedRepos.length > 0,\n plugin,\n daemon,\n scope: true,\n autoAdr,\n remote: remote.trim() === \"\" ? undefined : remote,\n syncFolders,\n seedRepos,\n };\n\n const ok = await prompter.confirm(\"Proceed?\", true);\n if (!ok) return { proceed: false, opts: null };\n return { proceed: true, opts };\n}\n","import { createInterface } from \"node:readline/promises\";\n\n/**\n * A minimal interactive prompter over a terminal. {@link createReadlinePrompter} wires this to\n * `node:readline/promises`; the wizard depends only on this interface so tests can drive it with a\n * scripted fake and never touch a real TTY.\n */\nexport interface Prompter {\n /** Ask for free text; show `message [def]: `; empty input returns `def`. */\n text(message: string, def: string): Promise<string>;\n /** Ask a yes/no question defaulting to `def`; empty input returns `def`. */\n confirm(message: string, def: boolean): Promise<boolean>;\n /**\n * Numbered multi-select over the given items. Prints each with a `[x]`/`[ ]` marker reflecting\n * `defaultSelected`, then accepts `all` / `none` / a comma-or-space list of 1-based indices;\n * empty input keeps the defaults. Returns the chosen items' `value`s (in item order).\n */\n select(\n message: string,\n items: { label: string; value: string }[],\n defaultSelected: boolean[],\n ): Promise<string[]>;\n /** Release the underlying readline interface (idempotent). */\n close(): void;\n}\n\n/**\n * True only when BOTH stdin and stdout are TTYs — the precondition for interactive prompting.\n * Non-TTY (piped/CI) callers must fall back to defaults + flags and never block on stdin.\n */\nexport function isInteractive(): boolean {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n}\n\n/**\n * Parse a yes/no answer. Recognizes `y`/`yes`/`n`/`no` case-insensitively (trimmed); empty input\n * returns `def`; anything else also falls back to `def` (a lenient default-accept). Pure, so it is\n * unit-testable without a TTY.\n *\n * @param input Raw line the user typed.\n * @param def The default applied to empty (or unrecognized) input.\n * @returns The resolved boolean answer.\n */\nexport function parseConfirm(input: string, def: boolean): boolean {\n const v = input.trim().toLowerCase();\n if (v === \"\") return def;\n if (v === \"y\" || v === \"yes\") return true;\n if (v === \"n\" || v === \"no\") return false;\n return def;\n}\n\n/**\n * Resolve a free-text answer against its default: empty (trimmed) input returns `def`, otherwise\n * the trimmed input. Pure counterpart to {@link Prompter.text} for unit tests.\n *\n * @param input Raw line the user typed.\n * @param def The default applied to empty input.\n * @returns The resolved text answer.\n */\nexport function parseText(input: string, def: string): string {\n const v = input.trim();\n return v === \"\" ? def : v;\n}\n\n/**\n * Resolve a multi-select answer against a list of candidate values. Pure counterpart to\n * {@link Prompter.select} so tests never touch a TTY. Rules:\n * - empty (trimmed) input keeps `defaultSelected` (values whose flag is true, in order);\n * - `all` selects every value; `none` selects nothing;\n * - otherwise the input is split on commas/whitespace and each token parsed as a 1-based index;\n * out-of-range or non-numeric tokens are ignored, duplicates collapse, and the result is\n * returned in `values` order.\n *\n * @param input Raw line the user typed.\n * @param values The candidate values, in display order.\n * @param defaultSelected Per-value default flags (same length/order as `values`).\n * @returns The chosen values, in `values` order.\n */\nexport function parseSelection(\n input: string,\n values: string[],\n defaultSelected: boolean[],\n): string[] {\n const v = input.trim().toLowerCase();\n if (v === \"\") return values.filter((_, i) => defaultSelected[i]);\n if (v === \"all\") return [...values];\n if (v === \"none\") return [];\n\n const picked = new Set<number>();\n for (const token of v.split(/[\\s,]+/).filter((t) => t.length > 0)) {\n const n = Number.parseInt(token, 10);\n if (!Number.isInteger(n)) continue;\n const idx = n - 1; // 1-based input -> 0-based index\n if (idx >= 0 && idx < values.length) picked.add(idx);\n }\n return values.filter((_, i) => picked.has(i));\n}\n\n/** Render the `[Y/n]` / `[y/N]` hint reflecting the default. */\nfunction confirmHint(def: boolean): string {\n return def ? \"[Y/n]\" : \"[y/N]\";\n}\n\n/**\n * A real {@link Prompter} backed by `node:readline/promises` over stdin/stdout. Only construct this\n * after {@link isInteractive} returns true; on a non-TTY it would block waiting for input.\n *\n * @returns A prompter whose `close()` ends the readline interface.\n */\nexport function createReadlinePrompter(): Prompter {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n let closed = false;\n\n return {\n async text(message: string, def: string): Promise<string> {\n const answer = await rl.question(`${message} [${def}]: `);\n return parseText(answer, def);\n },\n async confirm(message: string, def: boolean): Promise<boolean> {\n const answer = await rl.question(`${message} ${confirmHint(def)}: `);\n return parseConfirm(answer, def);\n },\n async select(\n message: string,\n items: { label: string; value: string }[],\n defaultSelected: boolean[],\n ): Promise<string[]> {\n const lines = items.map(\n (item, i) => ` ${i + 1}. [${defaultSelected[i] ? \"x\" : \" \"}] ${item.label}`,\n );\n const prompt = `${message}\\n${lines.join(\"\\n\")}\\nSelect (all/none/1,3 — Enter keeps defaults): `;\n const answer = await rl.question(prompt);\n return parseSelection(\n answer,\n items.map((item) => item.value),\n defaultSelected,\n );\n },\n close(): void {\n if (closed) return;\n closed = true;\n rl.close();\n },\n };\n}\n"],"mappings":"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","names":["spawnSync","path","path","require","path","spawn","existsSync","fs","createRequire","os","path","gatherCandidates","path","require","createRequire","path","spawn","gatherCandidates","existsSync","repoRoot","os","fs","path","path","createInterface","path","hasExecutable","spawnSync"]}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@cmnwlth/cli",
3
+ "version": "0.1.0",
4
+ "description": "The unified `commonwealth` CLI — starting with the zero-config `init` onboarding wizard",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "bin": {
8
+ "commonwealth": "./dist/index.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "dependencies": {
16
+ "@cmnwlth/core": "0.1.0",
17
+ "@cmnwlth/curate": "0.1.0",
18
+ "@cmnwlth/seed": "0.1.0",
19
+ "@cmnwlth/sync": "0.1.0"
20
+ },
21
+ "publishConfig": {
22
+ "access": "public",
23
+ "provenance": true
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/kristoffeys/commonwealth.git",
28
+ "directory": "packages/cli"
29
+ },
30
+ "homepage": "https://github.com/kristoffeys/commonwealth#readme",
31
+ "bugs": "https://github.com/kristoffeys/commonwealth/issues",
32
+ "scripts": {
33
+ "build": "tsup",
34
+ "typecheck": "tsc --noEmit"
35
+ }
36
+ }