mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-22 22:44:13 +08:00
feat: add claudeArgs input for direct CLI argument passing
- Add claude_args input to action.yml for flexible CLI control - Parse arguments with industry-standard shell-quote library - Maintain proper argument order: -p [claudeArgs] [legacy] [BASE_ARGS] - Keep tag mode defaults (needed for functionality) - Agent mode has no defaults (full user control) - Add comprehensive tests for new functionality - Add example workflow showing usage
This commit is contained in:
@@ -10,7 +10,8 @@ const execAsync = promisify(exec);
|
|||||||
|
|
||||||
const PIPE_PATH = `${process.env.RUNNER_TEMP}/claude_prompt_pipe`;
|
const PIPE_PATH = `${process.env.RUNNER_TEMP}/claude_prompt_pipe`;
|
||||||
const EXECUTION_FILE = `${process.env.RUNNER_TEMP}/claude-execution-output.json`;
|
const EXECUTION_FILE = `${process.env.RUNNER_TEMP}/claude-execution-output.json`;
|
||||||
const BASE_ARGS = ["-p", "--verbose", "--output-format", "stream-json"];
|
// These base args are always appended at the end
|
||||||
|
const BASE_ARGS = ["--verbose", "--output-format", "stream-json"];
|
||||||
|
|
||||||
export type ClaudeOptions = {
|
export type ClaudeOptions = {
|
||||||
allowedTools?: string;
|
allowedTools?: string;
|
||||||
@@ -68,10 +69,21 @@ export function prepareRunConfig(
|
|||||||
promptPath: string,
|
promptPath: string,
|
||||||
options: ClaudeOptions,
|
options: ClaudeOptions,
|
||||||
): PreparedConfig {
|
): PreparedConfig {
|
||||||
// Start with base args
|
// Build arguments in correct order:
|
||||||
const claudeArgs = [...BASE_ARGS];
|
// 1. -p flag for prompt via pipe
|
||||||
|
const claudeArgs = ["-p"];
|
||||||
// Add specific options first (these can be overridden by claudeArgs)
|
|
||||||
|
// 2. User's custom arguments (can override defaults)
|
||||||
|
if (options.claudeArgs && options.claudeArgs.trim() !== "") {
|
||||||
|
const parsed = parseShellArgs(options.claudeArgs);
|
||||||
|
const customArgs = parsed.filter(
|
||||||
|
(arg): arg is string => typeof arg === "string",
|
||||||
|
);
|
||||||
|
claudeArgs.push(...customArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Legacy specific options for backward compatibility
|
||||||
|
// These will eventually be removed in favor of claudeArgs
|
||||||
if (options.allowedTools) {
|
if (options.allowedTools) {
|
||||||
claudeArgs.push("--allowedTools", options.allowedTools);
|
claudeArgs.push("--allowedTools", options.allowedTools);
|
||||||
}
|
}
|
||||||
@@ -79,12 +91,6 @@ export function prepareRunConfig(
|
|||||||
claudeArgs.push("--disallowedTools", options.disallowedTools);
|
claudeArgs.push("--disallowedTools", options.disallowedTools);
|
||||||
}
|
}
|
||||||
if (options.maxTurns) {
|
if (options.maxTurns) {
|
||||||
const maxTurnsNum = parseInt(options.maxTurns, 10);
|
|
||||||
if (isNaN(maxTurnsNum) || maxTurnsNum <= 0) {
|
|
||||||
throw new Error(
|
|
||||||
`maxTurns must be a positive number, got: ${options.maxTurns}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
claudeArgs.push("--max-turns", options.maxTurns);
|
claudeArgs.push("--max-turns", options.maxTurns);
|
||||||
}
|
}
|
||||||
if (options.mcpConfig) {
|
if (options.mcpConfig) {
|
||||||
@@ -102,6 +108,11 @@ export function prepareRunConfig(
|
|||||||
if (options.model) {
|
if (options.model) {
|
||||||
claudeArgs.push("--model", options.model);
|
claudeArgs.push("--model", options.model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. Base args always at the end
|
||||||
|
claudeArgs.push(...BASE_ARGS);
|
||||||
|
|
||||||
|
// Validate timeout if provided (affects process wrapper, not Claude)
|
||||||
if (options.timeoutMinutes) {
|
if (options.timeoutMinutes) {
|
||||||
const timeoutMinutesNum = parseInt(options.timeoutMinutes, 10);
|
const timeoutMinutesNum = parseInt(options.timeoutMinutes, 10);
|
||||||
if (isNaN(timeoutMinutesNum) || timeoutMinutesNum <= 0) {
|
if (isNaN(timeoutMinutesNum) || timeoutMinutesNum <= 0) {
|
||||||
@@ -111,15 +122,6 @@ export function prepareRunConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse and append custom arguments (these can override the above)
|
|
||||||
if (options.claudeArgs && options.claudeArgs.trim() !== "") {
|
|
||||||
const parsed = parseShellArgs(options.claudeArgs);
|
|
||||||
const customArgs = parsed.filter(
|
|
||||||
(arg): arg is string => typeof arg === "string",
|
|
||||||
);
|
|
||||||
claudeArgs.push(...customArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse custom environment variables
|
// Parse custom environment variables
|
||||||
const customEnv = parseCustomEnvVars(options.claudeEnv);
|
const customEnv = parseCustomEnvVars(options.claudeEnv);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ describe("prepareRunConfig", () => {
|
|||||||
const options: ClaudeOptions = {};
|
const options: ClaudeOptions = {};
|
||||||
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
||||||
|
|
||||||
expect(prepared.claudeArgs.slice(0, 4)).toEqual([
|
expect(prepared.claudeArgs).toEqual([
|
||||||
"-p",
|
"-p",
|
||||||
"--verbose",
|
"--verbose",
|
||||||
"--output-format",
|
"--output-format",
|
||||||
@@ -125,13 +125,13 @@ describe("prepareRunConfig", () => {
|
|||||||
|
|
||||||
expect(prepared.claudeArgs).toEqual([
|
expect(prepared.claudeArgs).toEqual([
|
||||||
"-p",
|
"-p",
|
||||||
"--verbose",
|
|
||||||
"--output-format",
|
|
||||||
"stream-json",
|
|
||||||
"--allowedTools",
|
"--allowedTools",
|
||||||
"Bash,Read",
|
"Bash,Read",
|
||||||
"--max-turns",
|
"--max-turns",
|
||||||
"3",
|
"3",
|
||||||
|
"--verbose",
|
||||||
|
"--output-format",
|
||||||
|
"stream-json",
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -149,9 +149,6 @@ describe("prepareRunConfig", () => {
|
|||||||
|
|
||||||
expect(prepared.claudeArgs).toEqual([
|
expect(prepared.claudeArgs).toEqual([
|
||||||
"-p",
|
"-p",
|
||||||
"--verbose",
|
|
||||||
"--output-format",
|
|
||||||
"stream-json",
|
|
||||||
"--allowedTools",
|
"--allowedTools",
|
||||||
"Bash,Read",
|
"Bash,Read",
|
||||||
"--disallowedTools",
|
"--disallowedTools",
|
||||||
@@ -166,10 +163,13 @@ describe("prepareRunConfig", () => {
|
|||||||
"Be concise",
|
"Be concise",
|
||||||
"--fallback-model",
|
"--fallback-model",
|
||||||
"claude-sonnet-4-20250514",
|
"claude-sonnet-4-20250514",
|
||||||
|
"--verbose",
|
||||||
|
"--output-format",
|
||||||
|
"stream-json",
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("maxTurns validation", () => {
|
describe("maxTurns handling", () => {
|
||||||
test("should accept valid maxTurns value", () => {
|
test("should accept valid maxTurns value", () => {
|
||||||
const options: ClaudeOptions = { maxTurns: "5" };
|
const options: ClaudeOptions = { maxTurns: "5" };
|
||||||
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
||||||
@@ -177,25 +177,28 @@ describe("prepareRunConfig", () => {
|
|||||||
expect(prepared.claudeArgs).toContain("5");
|
expect(prepared.claudeArgs).toContain("5");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should throw error for non-numeric maxTurns", () => {
|
test("should pass through non-numeric maxTurns without validation (v1.0)", () => {
|
||||||
const options: ClaudeOptions = { maxTurns: "abc" };
|
const options: ClaudeOptions = { maxTurns: "abc" };
|
||||||
expect(() => prepareRunConfig("/tmp/test-prompt.txt", options)).toThrow(
|
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
||||||
"maxTurns must be a positive number, got: abc",
|
// v1.0: No validation - let Claude handle it
|
||||||
);
|
expect(prepared.claudeArgs).toContain("--max-turns");
|
||||||
|
expect(prepared.claudeArgs).toContain("abc");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should throw error for negative maxTurns", () => {
|
test("should pass through negative maxTurns without validation (v1.0)", () => {
|
||||||
const options: ClaudeOptions = { maxTurns: "-1" };
|
const options: ClaudeOptions = { maxTurns: "-1" };
|
||||||
expect(() => prepareRunConfig("/tmp/test-prompt.txt", options)).toThrow(
|
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
||||||
"maxTurns must be a positive number, got: -1",
|
// v1.0: No validation - let Claude handle it
|
||||||
);
|
expect(prepared.claudeArgs).toContain("--max-turns");
|
||||||
|
expect(prepared.claudeArgs).toContain("-1");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should throw error for zero maxTurns", () => {
|
test("should pass through zero maxTurns without validation (v1.0)", () => {
|
||||||
const options: ClaudeOptions = { maxTurns: "0" };
|
const options: ClaudeOptions = { maxTurns: "0" };
|
||||||
expect(() => prepareRunConfig("/tmp/test-prompt.txt", options)).toThrow(
|
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
||||||
"maxTurns must be a positive number, got: 0",
|
// v1.0: No validation - let Claude handle it
|
||||||
);
|
expect(prepared.claudeArgs).toContain("--max-turns");
|
||||||
|
expect(prepared.claudeArgs).toContain("0");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -229,6 +232,75 @@ describe("prepareRunConfig", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("claudeArgs handling", () => {
|
||||||
|
test("should parse and include custom claude arguments", () => {
|
||||||
|
const options: ClaudeOptions = {
|
||||||
|
claudeArgs: "--max-turns 10 --model claude-3-opus-20240229",
|
||||||
|
};
|
||||||
|
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
||||||
|
|
||||||
|
expect(prepared.claudeArgs).toEqual([
|
||||||
|
"-p",
|
||||||
|
"--max-turns",
|
||||||
|
"10",
|
||||||
|
"--model",
|
||||||
|
"claude-3-opus-20240229",
|
||||||
|
"--verbose",
|
||||||
|
"--output-format",
|
||||||
|
"stream-json",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should handle claudeArgs with legacy options", () => {
|
||||||
|
const options: ClaudeOptions = {
|
||||||
|
claudeArgs: "--max-turns 10",
|
||||||
|
allowedTools: "Bash,Read",
|
||||||
|
};
|
||||||
|
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
||||||
|
|
||||||
|
expect(prepared.claudeArgs).toEqual([
|
||||||
|
"-p",
|
||||||
|
"--max-turns",
|
||||||
|
"10",
|
||||||
|
"--allowedTools",
|
||||||
|
"Bash,Read",
|
||||||
|
"--verbose",
|
||||||
|
"--output-format",
|
||||||
|
"stream-json",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should handle empty claudeArgs", () => {
|
||||||
|
const options: ClaudeOptions = {
|
||||||
|
claudeArgs: "",
|
||||||
|
};
|
||||||
|
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
||||||
|
|
||||||
|
expect(prepared.claudeArgs).toEqual([
|
||||||
|
"-p",
|
||||||
|
"--verbose",
|
||||||
|
"--output-format",
|
||||||
|
"stream-json",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should handle claudeArgs with quoted strings", () => {
|
||||||
|
const options: ClaudeOptions = {
|
||||||
|
claudeArgs: '--system-prompt "You are a helpful assistant"',
|
||||||
|
};
|
||||||
|
const prepared = prepareRunConfig("/tmp/test-prompt.txt", options);
|
||||||
|
|
||||||
|
expect(prepared.claudeArgs).toEqual([
|
||||||
|
"-p",
|
||||||
|
"--system-prompt",
|
||||||
|
"You are a helpful assistant",
|
||||||
|
"--verbose",
|
||||||
|
"--output-format",
|
||||||
|
"stream-json",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("custom environment variables", () => {
|
describe("custom environment variables", () => {
|
||||||
test("should parse empty claudeEnv correctly", () => {
|
test("should parse empty claudeEnv correctly", () => {
|
||||||
const options: ClaudeOptions = { claudeEnv: "" };
|
const options: ClaudeOptions = { claudeEnv: "" };
|
||||||
|
|||||||
@@ -1,39 +1,31 @@
|
|||||||
name: Claude with Custom Args Example
|
name: Claude Args Example
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
prompt:
|
prompt:
|
||||||
description: "Prompt for Claude"
|
description: 'Prompt for Claude'
|
||||||
required: false
|
required: true
|
||||||
default: "Respond with a joke"
|
type: string
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
claude-custom:
|
claude-with-custom-args:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: anthropics/claude-code-action@v1
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Run Claude with custom arguments
|
||||||
|
uses: anthropics/claude-code-action@v1
|
||||||
with:
|
with:
|
||||||
|
mode: agent
|
||||||
|
prompt: ${{ github.event.inputs.prompt }}
|
||||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||||
|
|
||||||
# Option 1: Simple prompt with custom args
|
# New claudeArgs input allows direct CLI argument control
|
||||||
prompt: "Review this code and provide feedback"
|
# Arguments are passed in the order: -p [claudeArgs] [legacy options] [BASE_ARGS]
|
||||||
claude_args: "--max-turns 3 --model claude-3-5-sonnet-latest"
|
claude_args: |
|
||||||
|
--max-turns 15
|
||||||
# Option 2: Slash command with custom MCP config
|
--model claude-3-opus-20240229
|
||||||
# prompt: "/review"
|
--allowedTools Edit,Read,Write,Bash
|
||||||
# claude_args: "--mcp-config /workspace/custom-mcp.json --max-turns 5"
|
--disallowedTools WebSearch
|
||||||
|
--system-prompt "You are a senior engineer focused on code quality"
|
||||||
# Option 3: Override output format and add custom system prompt
|
|
||||||
# prompt: "Fix the failing tests"
|
|
||||||
# claude_args: "--output-format json --system-prompt 'You are an expert test fixer'"
|
|
||||||
# How it works:
|
|
||||||
# The action will execute: claude -p --verbose --output-format stream-json [your claude_args]
|
|
||||||
# Where the prompt is piped via stdin
|
|
||||||
|
|
||||||
# Benefits:
|
|
||||||
# - Full control over Claude CLI arguments
|
|
||||||
# - Use any Claude feature without waiting for action updates
|
|
||||||
# - Override defaults when needed
|
|
||||||
# - Combine with existing inputs or use standalone
|
|
||||||
@@ -23,6 +23,7 @@ import { GITHUB_SERVER_URL } from "../github/api/config";
|
|||||||
import type { Mode, ModeContext } from "../modes/types";
|
import type { Mode, ModeContext } from "../modes/types";
|
||||||
export type { CommonFields, PreparedContext } from "./types";
|
export type { CommonFields, PreparedContext } from "./types";
|
||||||
|
|
||||||
|
// Tag mode defaults - these tools are needed for tag mode to function
|
||||||
const BASE_ALLOWED_TOOLS = [
|
const BASE_ALLOWED_TOOLS = [
|
||||||
"Edit",
|
"Edit",
|
||||||
"MultiEdit",
|
"MultiEdit",
|
||||||
@@ -32,18 +33,18 @@ const BASE_ALLOWED_TOOLS = [
|
|||||||
"Read",
|
"Read",
|
||||||
"Write",
|
"Write",
|
||||||
];
|
];
|
||||||
const DISALLOWED_TOOLS = ["WebSearch", "WebFetch"];
|
|
||||||
|
|
||||||
export function buildAllowedToolsString(
|
export function buildAllowedToolsString(
|
||||||
customAllowedTools?: string[],
|
customAllowedTools?: string[],
|
||||||
includeActionsTools: boolean = false,
|
includeActionsTools: boolean = false,
|
||||||
useCommitSigning: boolean = false,
|
useCommitSigning: boolean = false,
|
||||||
): string {
|
): string {
|
||||||
|
// Tag mode needs these tools to function properly
|
||||||
let baseTools = [...BASE_ALLOWED_TOOLS];
|
let baseTools = [...BASE_ALLOWED_TOOLS];
|
||||||
|
|
||||||
// Always include the comment update tool from the comment server
|
// Always include the comment update tool for tag mode
|
||||||
baseTools.push("mcp__github_comment__update_claude_comment");
|
baseTools.push("mcp__github_comment__update_claude_comment");
|
||||||
|
|
||||||
// Add commit signing tools if enabled
|
// Add commit signing tools if enabled
|
||||||
if (useCommitSigning) {
|
if (useCommitSigning) {
|
||||||
baseTools.push(
|
baseTools.push(
|
||||||
@@ -51,7 +52,7 @@ export function buildAllowedToolsString(
|
|||||||
"mcp__github_file_ops__delete_files",
|
"mcp__github_file_ops__delete_files",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// When not using commit signing, add specific Bash git commands only
|
// When not using commit signing, add specific Bash git commands
|
||||||
baseTools.push(
|
baseTools.push(
|
||||||
"Bash(git add:*)",
|
"Bash(git add:*)",
|
||||||
"Bash(git commit:*)",
|
"Bash(git commit:*)",
|
||||||
@@ -62,7 +63,7 @@ export function buildAllowedToolsString(
|
|||||||
"Bash(git rm:*)",
|
"Bash(git rm:*)",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add GitHub Actions MCP tools if enabled
|
// Add GitHub Actions MCP tools if enabled
|
||||||
if (includeActionsTools) {
|
if (includeActionsTools) {
|
||||||
baseTools.push(
|
baseTools.push(
|
||||||
@@ -71,7 +72,7 @@ export function buildAllowedToolsString(
|
|||||||
"mcp__github_ci__download_job_log",
|
"mcp__github_ci__download_job_log",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let allAllowedTools = baseTools.join(",");
|
let allAllowedTools = baseTools.join(",");
|
||||||
if (customAllowedTools && customAllowedTools.length > 0) {
|
if (customAllowedTools && customAllowedTools.length > 0) {
|
||||||
allAllowedTools = `${allAllowedTools},${customAllowedTools.join(",")}`;
|
allAllowedTools = `${allAllowedTools},${customAllowedTools.join(",")}`;
|
||||||
@@ -83,15 +84,16 @@ export function buildDisallowedToolsString(
|
|||||||
customDisallowedTools?: string[],
|
customDisallowedTools?: string[],
|
||||||
allowedTools?: string[],
|
allowedTools?: string[],
|
||||||
): string {
|
): string {
|
||||||
let disallowedTools = [...DISALLOWED_TOOLS];
|
// Tag mode: Disable WebSearch and WebFetch by default for security
|
||||||
|
let disallowedTools = ["WebSearch", "WebFetch"];
|
||||||
// If user has explicitly allowed some hardcoded disallowed tools, remove them from disallowed list
|
|
||||||
|
// If user has explicitly allowed some default disallowed tools, remove them
|
||||||
if (allowedTools && allowedTools.length > 0) {
|
if (allowedTools && allowedTools.length > 0) {
|
||||||
disallowedTools = disallowedTools.filter(
|
disallowedTools = disallowedTools.filter(
|
||||||
(tool) => !allowedTools.includes(tool),
|
(tool) => !allowedTools.includes(tool),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let allDisallowedTools = disallowedTools.join(",");
|
let allDisallowedTools = disallowedTools.join(",");
|
||||||
if (customDisallowedTools && customDisallowedTools.length > 0) {
|
if (customDisallowedTools && customDisallowedTools.length > 0) {
|
||||||
if (allDisallowedTools) {
|
if (allDisallowedTools) {
|
||||||
|
|||||||
@@ -58,28 +58,15 @@ export const agentMode: Mode = {
|
|||||||
promptContent,
|
promptContent,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Export tool environment variables for agent mode
|
// Agent mode: User has full control via claudeArgs or legacy inputs
|
||||||
const baseTools = [
|
// No default tools are enforced - Claude Code's defaults will apply
|
||||||
"Edit",
|
// Export user-specified tools only if provided
|
||||||
"MultiEdit",
|
if (context.inputs.allowedTools.length > 0) {
|
||||||
"Glob",
|
core.exportVariable("INPUT_ALLOWED_TOOLS", context.inputs.allowedTools.join(","));
|
||||||
"Grep",
|
}
|
||||||
"LS",
|
if (context.inputs.disallowedTools.length > 0) {
|
||||||
"Read",
|
core.exportVariable("INPUT_DISALLOWED_TOOLS", context.inputs.disallowedTools.join(","));
|
||||||
"Write",
|
}
|
||||||
];
|
|
||||||
|
|
||||||
// Add user-specified tools
|
|
||||||
const allowedTools = [...baseTools, ...context.inputs.allowedTools];
|
|
||||||
const disallowedTools = [
|
|
||||||
"WebSearch",
|
|
||||||
"WebFetch",
|
|
||||||
...context.inputs.disallowedTools,
|
|
||||||
];
|
|
||||||
|
|
||||||
// Export as INPUT_ prefixed variables for the base action
|
|
||||||
core.exportVariable("INPUT_ALLOWED_TOOLS", allowedTools.join(","));
|
|
||||||
core.exportVariable("INPUT_DISALLOWED_TOOLS", disallowedTools.join(","));
|
|
||||||
|
|
||||||
// Agent mode uses a minimal MCP configuration
|
// Agent mode uses a minimal MCP configuration
|
||||||
// We don't need comment servers or PR-specific tools for automation
|
// We don't need comment servers or PR-specific tools for automation
|
||||||
|
|||||||
Reference in New Issue
Block a user