fix: start codex on Windows by using shell; keep mcp args parseable (#40)

Windows global installs expose codex as codex.cmd; spawning 'codex' without shell hits ENOENT.

Enable shell to align with Claude's Windows behavior and resolve PATH lookup.

Shell spawn makes cmd.exe strip TOML double quotes in -c arrays, so args become a string.

Switch mcp args to TOML literal (single-quoted) arrays to preserve types; update tests.
This commit is contained in:
zrq8
2026-01-08 10:44:01 +08:00
committed by GitHub
parent 9dc69d1e80
commit 2646df346e
3 changed files with 20 additions and 6 deletions
+2 -1
View File
@@ -80,7 +80,8 @@ export async function codexLocal(opts: {
spawnName: 'codex',
installHint: 'Codex CLI',
includeCause: true,
logExit: true
logExit: true,
shell: process.platform === 'win32'
});
} finally {
process.stdin.resume();
+1 -1
View File
@@ -15,7 +15,7 @@ describe('codexMcpConfig', () => {
expect(args).toEqual([
'-c', 'mcp_servers.hapi.command="hapi"',
'-c', 'mcp_servers.hapi.args=["mcp","--url","http://localhost:3000"]'
'-c', "mcp_servers.hapi.args=['mcp','--url','http://localhost:3000']"
]);
});
+17 -4
View File
@@ -20,12 +20,25 @@ function escapeTomlString(value: string): string {
.replace(/\t/g, '\\t');
}
/**
* Escape a string value for use in a TOML single-quoted literal string.
* Only single quotes need escaping (by doubling them).
*/
function escapeTomlLiteralString(value: string): string {
return value.replace(/'/g, "''");
}
function buildTomlLiteralArray(values: string[]): string {
const items = values.map((value) => `'${escapeTomlLiteralString(value)}'`);
return `[${items.join(',')}]`;
}
/**
* Build -c arguments for MCP server configuration.
*
* Generates arguments like:
* -c 'mcp_servers.hapi.command="hapi"'
* -c 'mcp_servers.hapi.args=["mcp", "--url", "http://..."]'
* -c 'mcp_servers.hapi.args=['mcp', '--url', 'http://...']'
*
* @param mcpServers - Map of server name to server config
* @returns Array of CLI arguments to pass to codex
@@ -39,9 +52,9 @@ export function buildMcpServerConfigArgs(
// -c 'mcp_servers.<name>.command="<command>"'
configArgs.push('-c', `mcp_servers.${name}.command="${escapeTomlString(server.command)}"`);
// -c 'mcp_servers.<name>.args=["arg1", "arg2"]'
// JSON.stringify produces valid TOML array syntax for simple string arrays
const argsToml = JSON.stringify(server.args);
// -c 'mcp_servers.<name>.args=['arg1','arg2']'
// Use TOML literal strings to avoid shell-quote mangling on Windows.
const argsToml = buildTomlLiteralArray(server.args);
configArgs.push('-c', `mcp_servers.${name}.args=${argsToml}`);
}