feat(cli): add settings file support for builtin Claude

- Enhance CLI status rendering to display settings file information for builtin Claude.
- Introduce settings file input in CLI manager for configuring the path to settings.json.
- Update Claude CLI tool interface to include settingsFile property.
- Implement settings file resolution and validation in CLI executor.
- Create a new collaborative planning workflow command with detailed documentation.
- Add test scripts for debugging tool configuration and command building.
This commit is contained in:
catlog22
2026-01-30 10:07:02 +08:00
parent 4b69492b16
commit 3f46a02df3
12 changed files with 1130 additions and 1267 deletions

View File

@@ -56,6 +56,12 @@ export interface ClaudeCliTool {
* Supports both absolute paths and paths relative to home directory (e.g., ~/.my-env)
*/
envFile?: string;
/**
* Path to Claude CLI settings.json file (builtin claude only)
* Passed to Claude CLI via --settings parameter
* Supports ~, absolute, relative, and Windows paths
*/
settingsFile?: string;
}
export type CliToolName = 'gemini' | 'qwen' | 'codex' | 'claude' | 'opencode' | string;
@@ -279,7 +285,8 @@ function ensureToolTags(tool: Partial<ClaudeCliTool>): ClaudeCliTool {
primaryModel: tool.primaryModel,
secondaryModel: tool.secondaryModel,
tags: tool.tags ?? [],
envFile: tool.envFile
envFile: tool.envFile,
settingsFile: tool.settingsFile
};
}
@@ -1015,6 +1022,7 @@ export function getToolConfig(projectDir: string, tool: string): {
secondaryModel: string;
tags?: string[];
envFile?: string;
settingsFile?: string;
} {
const config = loadClaudeCliTools(projectDir);
const toolConfig = config.tools[tool];
@@ -1034,7 +1042,8 @@ export function getToolConfig(projectDir: string, tool: string): {
primaryModel: toolConfig.primaryModel ?? '',
secondaryModel: toolConfig.secondaryModel ?? '',
tags: toolConfig.tags,
envFile: toolConfig.envFile
envFile: toolConfig.envFile,
settingsFile: toolConfig.settingsFile
};
}
@@ -1051,6 +1060,7 @@ export function updateToolConfig(
availableModels: string[];
tags: string[];
envFile: string | null;
settingsFile: string | null;
}>
): ClaudeCliToolsConfig {
const config = loadClaudeCliTools(projectDir);
@@ -1079,6 +1089,14 @@ export function updateToolConfig(
config.tools[tool].envFile = updates.envFile;
}
}
// Handle settingsFile: set to undefined if null/empty, otherwise set value
if (updates.settingsFile !== undefined) {
if (updates.settingsFile === null || updates.settingsFile === '') {
delete config.tools[tool].settingsFile;
} else {
config.tools[tool].settingsFile = updates.settingsFile;
}
}
saveClaudeCliTools(projectDir, config);
}

View File

@@ -9,7 +9,7 @@ import { spawn, ChildProcess } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import { validatePath } from '../utils/path-resolver.js';
import { validatePath, resolvePath } from '../utils/path-resolver.js';
import { escapeWindowsArg } from '../utils/shell-escape.js';
import { buildCommand, checkToolAvailability, clearToolCache, debugLog, errorLog, type NativeResumeConfig, type ToolAvailability } from './cli-executor-utils.js';
import type { ConversationRecord, ConversationTurn, ExecutionOutput, ExecutionRecord } from './cli-executor-state.js';
@@ -85,7 +85,7 @@ import { findEndpointById } from '../config/litellm-api-config-manager.js';
// CLI Settings (CLI封装) integration
import { loadEndpointSettings, getSettingsFilePath, findEndpoint } from '../config/cli-settings-manager.js';
import { loadClaudeCliTools, getToolConfig } from './claude-cli-tools.js';
import { loadClaudeCliTools, getToolConfig, getPrimaryModel } from './claude-cli-tools.js';
/**
* Parse .env file content into key-value pairs
@@ -338,8 +338,7 @@ import {
import {
isToolEnabled as isToolEnabledFromConfig,
enableTool as enableToolFromConfig,
disableTool as disableToolFromConfig,
getPrimaryModel
disableTool as disableToolFromConfig
} from './cli-config-manager.js';
// Built-in CLI tools
@@ -794,6 +793,25 @@ async function executeCliTool(
// Use configured primary model if no explicit model provided
const effectiveModel = model || getPrimaryModel(workingDir, tool);
// Load and validate settings file for Claude tool (builtin only)
let settingsFilePath: string | undefined;
if (tool === 'claude') {
const toolConfig = getToolConfig(workingDir, tool);
if (toolConfig.settingsFile) {
try {
const resolved = resolvePath(toolConfig.settingsFile);
if (fs.existsSync(resolved)) {
settingsFilePath = resolved;
debugLog('SETTINGS_FILE', `Resolved Claude settings file`, { configured: toolConfig.settingsFile, resolved });
} else {
errorLog('SETTINGS_FILE', `Claude settings file not found, skipping`, { configured: toolConfig.settingsFile, resolved });
}
} catch (err) {
errorLog('SETTINGS_FILE', `Failed to resolve Claude settings file`, { configured: toolConfig.settingsFile, error: (err as Error).message });
}
}
}
// Build command
const { command, args, useStdin, outputFormat: autoDetectedFormat } = buildCommand({
tool,
@@ -803,6 +821,7 @@ async function executeCliTool(
dir: cd,
include: includeDirs,
nativeResume: nativeResumeConfig,
settingsFile: settingsFilePath,
reviewOptions: mode === 'review' ? { uncommitted, base, commit, title } : undefined
});