From 0a0121d2ca380f398b70bc220cf3ee000a65c900 Mon Sep 17 00:00:00 2001 From: Scott Wei Date: Mon, 27 Apr 2026 16:18:14 +0800 Subject: [PATCH 1/2] fix(cli): add logs/ and nerve.pid to init gitignore template These are runtime artifacts that should not be tracked. --- packages/cli/src/commands/init.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 6b02e6b..d4efff9 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -67,6 +67,8 @@ const PACKAGE_JSON = `{ `; const GITIGNORE = `data/ +logs/ +nerve.pid node_modules/ `; -- 2.43.0 From 57e4d992e2c12f7e27f4e387b648ddbe653d6c7c Mon Sep 17 00:00:00 2001 From: Scott Wei Date: Mon, 27 Apr 2026 16:37:41 +0800 Subject: [PATCH 2/2] fix(cli): add --skip-install flag to init, fix e2e test timeout - Add --skip-install flag to nerve init for testing/offline use - Use --skip-install in e2e tests to avoid real pnpm install - Reduce e2e init test timeout from 60s to 10s Closes #181 --- .../src/__tests__/e2e-validate-init.test.ts | 8 ++-- packages/cli/src/commands/init.ts | 46 ++++++++++++------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/packages/cli/src/__tests__/e2e-validate-init.test.ts b/packages/cli/src/__tests__/e2e-validate-init.test.ts index f5044e0..c3ff47c 100644 --- a/packages/cli/src/__tests__/e2e-validate-init.test.ts +++ b/packages/cli/src/__tests__/e2e-validate-init.test.ts @@ -192,11 +192,11 @@ describe("e2e init", () => { } }); - it("init --force creates workspace layout", { timeout: 60_000 }, async () => { + it("init --force creates workspace layout", { timeout: 10_000 }, async () => { fakeHome = mkdtempSync(join(tmpdir(), "nerve-init-e2e-")); const nerveRoot = join(fakeHome, ".uncaged-nerve"); - const result = await runTestCli(fakeHome, ["init", "--force"]); + const result = await runTestCli(fakeHome, ["init", "--force", "--skip-install"]); // init should exit 0 (install/git failures are warnings, not fatal) expect(result.exitCode).toBe(0); expect(result.stdout).toContain("✅"); @@ -213,10 +213,10 @@ describe("e2e init", () => { ); }); - it("generated nerve.yaml passes validate", { timeout: 60_000 }, async () => { + it("generated nerve.yaml passes validate", { timeout: 10_000 }, async () => { fakeHome = mkdtempSync(join(tmpdir(), "nerve-init-e2e-")); - await runTestCli(fakeHome, ["init", "--force"]); + await runTestCli(fakeHome, ["init", "--force", "--skip-install"]); const validateResult = await runTestCli(fakeHome, ["validate"]); expect(validateResult.exitCode).toBe(0); diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index d4efff9..9a8b415 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -240,9 +240,14 @@ const initWorkspaceCommand = defineCommand({ description: "Reinitialize even if workspace already exists (preserves data/)", default: false, }, + "skip-install": { + type: "boolean", + description: "Skip dependency installation (for testing or offline use)", + default: false, + }, }, async run({ args }) { - await runInitWorkspace(args.force); + await runInitWorkspace(args.force, args["skip-install"]); }, }); @@ -334,7 +339,7 @@ async function runInitFromGit(url: string): Promise { ); } -async function runInitWorkspace(force: boolean): Promise { +async function runInitWorkspace(force: boolean, skipInstall = false): Promise { const nerveRoot = getNerveRoot(); if (existsSync(nerveRoot) && !force) { @@ -357,21 +362,23 @@ async function runInitWorkspace(force: boolean): Promise { CPU_MIGRATION_SQL, ); - process.stdout.write("Installing dependencies…\n"); - const { cmd, installArgs } = await detectPackageManager(); - try { - await runCommand(cmd, installArgs, nerveRoot); - } catch { - process.stdout.write( - `⚠️ Install failed. Try manually:\n cd ${nerveRoot} && ${cmd} ${installArgs.join(" ")}\n`, - ); - } + if (!skipInstall) { + process.stdout.write("Installing dependencies…\n"); + const { cmd, installArgs } = await detectPackageManager(); + try { + await runCommand(cmd, installArgs, nerveRoot); + } catch { + process.stdout.write( + `⚠️ Install failed. Try manually:\n cd ${nerveRoot} && ${cmd} ${installArgs.join(" ")}\n`, + ); + } - if (!(await verifyNodeSqlite())) { - process.stdout.write( - "⚠️ Built-in SQLite (node:sqlite) is not available in this Node.js build. " + - "The daemon requires Node.js 22.5 or newer with SQLite enabled.\n", - ); + if (!(await verifyNodeSqlite())) { + process.stdout.write( + "⚠️ Built-in SQLite (node:sqlite) is not available in this Node.js build. " + + "The daemon requires Node.js 22.5 or newer with SQLite enabled.\n", + ); + } } if (!existsSync(join(nerveRoot, ".git"))) { @@ -406,6 +413,11 @@ export const initCommand = defineCommand({ description: "Clone an existing git repo into ~/.uncaged-nerve instead of scaffolding", required: false, }, + "skip-install": { + type: "boolean", + description: "Skip dependency installation (for testing or offline use)", + default: false, + }, }, subCommands: { workflow: initWorkflowCommand, @@ -416,6 +428,6 @@ export const initCommand = defineCommand({ await runInitFromGit(String(args.from)); return; } - await runInitWorkspace(args.force); + await runInitWorkspace(args.force, args["skip-install"]); }, }); -- 2.43.0