diff --git a/.changeset/fix-web-daemon-spawn-windows.md b/.changeset/fix-web-daemon-spawn-windows.md new file mode 100644 index 0000000000..9a2a111842 --- /dev/null +++ b/.changeset/fix-web-daemon-spawn-windows.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Fix `kimi web` and `/web` failing to start the background server daemon on Windows with `spawn EFTYPE` when the CLI is installed via npm/pnpm or run from source. The official single-binary install script was not affected. diff --git a/apps/kimi-code/src/cli/sub/server/daemon.ts b/apps/kimi-code/src/cli/sub/server/daemon.ts index 1c840d418a..f8ef8ffa8b 100644 --- a/apps/kimi-code/src/cli/sub/server/daemon.ts +++ b/apps/kimi-code/src/cli/sub/server/daemon.ts @@ -204,9 +204,16 @@ export function spawnDaemonChild(options: SpawnDaemonChildOptions): void { if (options.idleGraceMs !== undefined) { args.push('--idle-grace-ms', String(options.idleGraceMs)); } + // On Windows `.mjs` files are not executable PE binaries, so we must run + // the script through the Node binary rather than spawning it directly. In + // SEA mode or when re-spawning from an already-running daemon, `program` is + // `process.execPath` itself, so no script argument is needed. + const execPath = process.execPath; + const spawnArgs = program === execPath ? args : [program, ...args]; + const logFd = openSync(logPath, 'a'); try { - const child = spawn(program, args, { + const child = spawn(execPath, spawnArgs, { detached: true, // Run from the server log directory instead of inheriting the caller's // cwd, so the long-lived daemon does not pin the directory it was