diff --git a/packages/core/src/evaluation/providers/claude-cli.ts b/packages/core/src/evaluation/providers/claude-cli.ts index 06ed5c81..91099a44 100644 --- a/packages/core/src/evaluation/providers/claude-cli.ts +++ b/packages/core/src/evaluation/providers/claude-cli.ts @@ -182,6 +182,10 @@ export class ClaudeCliProvider implements Provider { '--verbose', ]; + if (this.config.bypassPermissions !== false) { + args.push('--dangerously-skip-permissions'); + } + if (this.config.model) { args.push('--model', this.config.model); } diff --git a/packages/core/src/evaluation/providers/targets.ts b/packages/core/src/evaluation/providers/targets.ts index 3e3f4225..9ed10861 100644 --- a/packages/core/src/evaluation/providers/targets.ts +++ b/packages/core/src/evaluation/providers/targets.ts @@ -533,6 +533,8 @@ export interface ClaudeResolvedConfig { readonly logFormat?: 'summary' | 'json'; /** New stream_log field. false=no stream log (default), 'raw'=per-event, 'summary'=consolidated. */ readonly streamLog?: false | 'raw' | 'summary'; + /** When true (default), passes --dangerously-skip-permissions to the Claude CLI. Matches ClaudeSdkProvider behavior. */ + readonly bypassPermissions?: boolean; } export interface MockResolvedConfig { @@ -1853,6 +1855,11 @@ function resolveClaudeConfig( const maxBudgetUsd = typeof target.max_budget_usd === 'number' ? target.max_budget_usd : undefined; + const bypassPermissions = + target.bypass_permissions !== undefined + ? resolveOptionalBoolean(target.bypass_permissions) + : undefined; + return { executable, model, @@ -1864,6 +1871,7 @@ function resolveClaudeConfig( logDir, logFormat, streamLog: streamLogResult.streamLog, + bypassPermissions, }; } diff --git a/packages/core/test/evaluation/providers/claude-provider-aliases.test.ts b/packages/core/test/evaluation/providers/claude-provider-aliases.test.ts index 4834d02c..0ef9ee05 100644 --- a/packages/core/test/evaluation/providers/claude-provider-aliases.test.ts +++ b/packages/core/test/evaluation/providers/claude-provider-aliases.test.ts @@ -6,6 +6,7 @@ import { ClaudeProvider } from '../../../src/evaluation/providers/claude.js'; import { createBuiltinProviderRegistry } from '../../../src/evaluation/providers/index.js'; const mockClaudeConfig = { + executable: 'claude', model: undefined, cwd: undefined, timeoutMs: undefined, @@ -61,3 +62,32 @@ describe('Claude provider alias resolution', () => { expect(sdkProvider.kind).toBe('claude'); }); }); + +describe('ClaudeCliProvider buildArgs', () => { + it('includes --dangerously-skip-permissions by default', () => { + const provider = new ClaudeCliProvider('target', mockClaudeConfig); + // biome-ignore lint/suspicious/noExplicitAny: testing private method + const args: string[] = (provider as any).buildArgs(); + expect(args).toContain('--dangerously-skip-permissions'); + }); + + it('includes --dangerously-skip-permissions when bypassPermissions is true', () => { + const provider = new ClaudeCliProvider('target', { + ...mockClaudeConfig, + bypassPermissions: true, + }); + // biome-ignore lint/suspicious/noExplicitAny: testing private method + const args: string[] = (provider as any).buildArgs(); + expect(args).toContain('--dangerously-skip-permissions'); + }); + + it('omits --dangerously-skip-permissions when bypassPermissions is false', () => { + const provider = new ClaudeCliProvider('target', { + ...mockClaudeConfig, + bypassPermissions: false, + }); + // biome-ignore lint/suspicious/noExplicitAny: testing private method + const args: string[] = (provider as any).buildArgs(); + expect(args).not.toContain('--dangerously-skip-permissions'); + }); +});