diff --git a/cli/src/__tests__/cli-args.test.ts b/cli/src/__tests__/cli-args.test.ts index c8c3db485b..e3829fd150 100644 --- a/cli/src/__tests__/cli-args.test.ts +++ b/cli/src/__tests__/cli-args.test.ts @@ -208,3 +208,46 @@ describe('Codebuff --trust-agents', () => { expect(result.initialPrompt).toBe('fix it') }) }) + +describe('Freebuff initial prompt', () => { + test('takes bare words as the initial prompt', () => { + const result = parseArgs({ + argv: ['node', 'freebuff', 'fix the flaky login test'], + isFreebuff: true, + version: '1.0.0', + }) + expect(result.initialPrompt).toBe('fix the flaky login test') + expect(result.command).toBeUndefined() + }) + + test('keeps login and doctor as commands, not prompts', () => { + for (const command of ['login', 'doctor']) { + const result = parseArgs({ + argv: ['node', 'freebuff', command], + isFreebuff: true, + version: '1.0.0', + }) + expect(result.command).toBe(command) + expect(result.initialPrompt).toBeNull() + } + }) + + test('joins a multi-word prompt that follows flags', () => { + const result = parseArgs({ + argv: ['node', 'freebuff', '--trust-agents', 'fix', 'it'], + isFreebuff: true, + version: '1.0.0', + }) + expect(result.trustAgents).toBe(true) + expect(result.initialPrompt).toBe('fix it') + }) + + test('leaves the codebuff prompt path alone', () => { + const result = parseArgs({ + argv: ['node', 'codebuff', 'fix', 'it'], + isFreebuff: false, + version: '1.0.0', + }) + expect(result.initialPrompt).toBe('fix it') + }) +}) diff --git a/cli/src/cli-args.ts b/cli/src/cli-args.ts index c338ac837a..959752fe0d 100644 --- a/cli/src/cli-args.ts +++ b/cli/src/cli-args.ts @@ -68,8 +68,12 @@ export function parseArgs({ "Load this repository's .agents files and mcp.json without asking (for CI)", ) .addArgument( - new Argument('[command]', 'Command to run: login, or doctor to check this computer for common problems').choices(['login', 'doctor']), + new Argument( + '[prompt...]', + 'Command to run (login, or doctor), or an initial prompt to send to the agent', + ), ) + .allowExcessArguments(true) .helpOption('-h, --help', 'Show this help message') } else { // Codebuff: full CLI with all options @@ -128,9 +132,21 @@ export function parseArgs({ if (options.plan) initialMode = 'PLAN' } + // Freebuff accepts a first task the way Codebuff does: bare words that are not + // one of its commands become the session's initial prompt, so a launcher can + // start the session with its task instead of typing it into the TUI. + const freebuffCommands: readonly string[] = ['login', 'doctor'] + const freebuffCommand = + isFreebuff && args[0] !== undefined && freebuffCommands.includes(args[0]) + ? args[0] + : undefined + return { - initialPrompt: !isFreebuff && args.length > 0 ? args.join(' ') : null, - command: args[0], + initialPrompt: + args.length > 0 && (!isFreebuff || freebuffCommand === undefined) + ? args.join(' ') + : null, + command: isFreebuff ? freebuffCommand : args[0], agent: options.agent, clearLogs: options.clearLogs || false, continue: Boolean(continueFlag),