fix: daemon mode spawn path — closes #27 #30

Merged
xiaoju merged 5 commits from fix/daemon-spawn-path into main 2026-04-22 14:21:33 +00:00
2 changed files with 23 additions and 5 deletions
+2
View File
@@ -248,6 +248,8 @@ async function runInitWorkspace(force: boolean): Promise<void> {
if (!existsSync(join(nerveRoot, ".git"))) {
try {
await runCommand("git", ["init"], nerveRoot);
await runCommand("git", ["add", "."], nerveRoot);
await runCommand("git", ["commit", "-m", "Initial nerve workspace"], nerveRoot);
} catch {
process.stdout.write("⚠️ git init failed — skipping.\n");
}
+21 -5
View File
@@ -1,7 +1,6 @@
import { createWriteStream } from "node:fs";
import { readFileSync } from "node:fs";
import { createWriteStream, existsSync, readFileSync } from "node:fs";
import { mkdir } from "node:fs/promises";
import { join } from "node:path";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { parseNerveConfig } from "@uncaged/nerve-core";
@@ -85,6 +84,23 @@ async function runForeground(nerveRoot: string): Promise<void> {
await kernel.ready;
}
/** Path to the CLI entry script (for spawning `start` without `-d`). */
function cliEntryScript(): string {
const here = fileURLToPath(import.meta.url);
const ext = here.endsWith(".ts") ? ".ts" : ".js";
// When bundled, `here` is already the CLI entry (e.g. dist/cli.js).
// When running from source, `here` is src/commands/start.ts → go up to src/cli.ts.
const candidates = [
join(dirname(here), `cli${ext}`), // bundled: dist/cli.js
join(dirname(here), "..", `cli${ext}`), // source: src/commands/start.ts → src/cli.ts
];
const cliPath = candidates.find((p) => existsSync(p));
if (!cliPath) {
throw new Error(`CLI entry not found (searched: ${candidates.join(", ")})`);
}
return cliPath;
}
async function runDaemon(nerveRoot: string): Promise<void> {
if (isRunning()) {
const pid = readPidFile();
@@ -108,9 +124,9 @@ async function runDaemon(nerveRoot: string): Promise<void> {
else resolve();
});
const selfPath = fileURLToPath(import.meta.url);
const cliPath = cliEntryScript();
const child = spawn(process.execPath, [selfPath, "start"], {
const child = spawn(process.execPath, [cliPath, "start"], {
detached: true,
stdio: ["ignore", logStream.fd, logStream.fd],
env: { ...process.env, NERVE_DAEMON_MODE: "1" },