diff --git a/apps/cli/src/cli.ts b/apps/cli/src/cli.ts index 653d97c..648d7ff 100644 --- a/apps/cli/src/cli.ts +++ b/apps/cli/src/cli.ts @@ -35,6 +35,22 @@ async function main(): Promise { return 2; } + // -C / --cd : change the working directory before anything resolves cwd + // (Codex parity). Done here — after --help/--version short-circuit but before + // every subcommand/REPL/headless path that reads process.cwd() — so a single + // chdir covers them all. Validate eagerly so a bad path fails fast (exit 2) + // instead of surfacing as a confusing error deep in the agent. + if (args.cwd !== undefined) { + try { + process.chdir(args.cwd); + } catch (err) { + process.stderr.write( + `Cannot change to --cd directory "${args.cwd}": ${(err as Error).message}\n`, + ); + return 2; + } + } + if (args.doctor) { return doctor(); } diff --git a/apps/cli/src/parse-args.test.ts b/apps/cli/src/parse-args.test.ts index b7baf64..749474c 100644 --- a/apps/cli/src/parse-args.test.ts +++ b/apps/cli/src/parse-args.test.ts @@ -24,6 +24,15 @@ describe('parseArgs', () => { expect(parseArgs(['upgrade']).upgrade).toBe(true); }); + it('-C / --cd sets working directory', () => { + expect(parseArgs(['-C', '/work/dir']).cwd).toBe('/work/dir'); + expect(parseArgs(['--cd', '/another']).cwd).toBe('/another'); + }); + it('cwd is undefined without -C/--cd', () => { + expect(parseArgs([]).cwd).toBeUndefined(); + expect(parseArgs(['--mode', 'plan']).cwd).toBeUndefined(); + }); + it('-p "prompt"', () => { expect(parseArgs(['-p', 'do the thing']).prompt).toBe('do the thing'); expect(parseArgs(['--print', 'foo']).prompt).toBe('foo'); diff --git a/apps/cli/src/parse-args.ts b/apps/cli/src/parse-args.ts index ca7b58d..64ebfcd 100644 --- a/apps/cli/src/parse-args.ts +++ b/apps/cli/src/parse-args.ts @@ -27,6 +27,9 @@ export interface ParsedArgs { maxTurns?: number; bare: boolean; + /** `-C` / `--cd `: chdir to this directory before running (Codex parity). */ + cwd?: string; + // System prompt overrides systemPrompt?: string; appendSystemPrompt?: string; @@ -181,6 +184,9 @@ export function parseArgs(argv: string[]): ParsedArgs { case a === '--bare': out.bare = true; break; + case a === '-C' || a === '--cd': + out.cwd = next(); + break; case a === '--system-prompt': out.systemPrompt = next(); break; @@ -287,6 +293,9 @@ MODE --permission-mode Alias for --mode (Claude Code parity) --bare No plugins / MCP / skills — just kernel + tools +WORKING DIRECTORY + -C, --cd Change to before running (default: current dir) + MODEL & EFFORT --model deepseek-chat | deepseek-reasoner --effort low | medium | high | xhigh | max