From 7519603fbdc915aa5152e90b40f9dfd7ca6d318a Mon Sep 17 00:00:00 2001 From: catlog22 Date: Sun, 11 Jan 2026 19:58:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=20CLI=20=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E9=85=8D=E7=BD=AE=E7=AE=A1=E7=90=86=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=85=8D=E7=BD=AE=E8=AF=BB=E5=8F=96=E5=92=8C=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/CLAUDE.md | 15 ++++---- ccw/src/tools/claude-cli-tools.ts | 59 +++++++++++++++++-------------- 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 762d768c..689d86d1 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -1,23 +1,26 @@ # Claude Instructions - -- **CLI Tools Usage**: @~/.claude/workflows/cli-tools-usage.md - **Coding Philosophy**: @~/.claude/workflows/coding-philosophy.md -- **Context Requirements**: @~/.claude/workflows/context-tools.md -- **File Modification**: @~/.claude/workflows/file-modification.md -- **CLI Endpoints Config**: @.claude/cli-tools.json ## CLI Endpoints -**Strictly follow the @.claude/cli-tools.json configuration** +- **CLI Tools Usage**: @~/.claude/workflows/cli-tools-usage.md +- **CLI Endpoints Config**: @~/.claude/cli-tools.json + +**Strictly follow the cli-tools.json configuration** Available CLI endpoints are dynamically defined by the config file: - Built-in tools and their enable/disable status - Custom API endpoints registered via the Dashboard - Managed through the CCW Dashboard Status page + + ## Tool Execution +- **Context Requirements**: @~/.claude/workflows/context-tools.md +- **File Modification**: @~/.claude/workflows/file-modification.md + ### Agent Calls - **Always use `run_in_background: false`** for Task tool agent calls: `Task({ subagent_type: "xxx", prompt: "...", run_in_background: false })` to ensure synchronous execution and immediate result visibility - **TaskOutput usage**: Only use `TaskOutput({ task_id: "xxx", block: false })` + sleep loop to poll completion status. NEVER read intermediate output during agent/CLI execution - wait for final result only diff --git a/ccw/src/tools/claude-cli-tools.ts b/ccw/src/tools/claude-cli-tools.ts index 7519aecb..a8ee5db7 100644 --- a/ccw/src/tools/claude-cli-tools.ts +++ b/ccw/src/tools/claude-cli-tools.ts @@ -1,8 +1,14 @@ /** * Claude CLI Tools Configuration Manager * Manages .claude/cli-tools.json (tools) and .claude/cli-settings.json (settings) - * with fallback: - * 1. Project workspace: {projectDir}/.claude/ (priority) + * + * Configuration Strategy: + * - READ: Project → Global → Default (fallback chain) + * - CREATE: Always in ~/.claude/ (global user-level config) + * - SAVE: Based on source (project config saves to project, others to global) + * + * Read priority: + * 1. Project workspace: {projectDir}/.claude/ (if exists) * 2. Global: ~/.claude/ (fallback) */ import * as fs from 'fs'; @@ -295,12 +301,12 @@ function migrateConfig(config: any, projectDir: string): ClaudeCliToolsConfig { /** * Ensure CLI tools configuration file exists - * Creates default config if missing (auto-rebuild feature) - * @param projectDir - Project directory path - * @param createInProject - If true, create in project dir; if false, create in global dir + * Creates default config in global ~/.claude directory (user-level config) + * @param projectDir - Project directory path (used for reading existing project config) + * @param createInProject - DEPRECATED: Always creates in global dir. Kept for backward compatibility. * @returns The config that was created/exists */ -export function ensureClaudeCliTools(projectDir: string, createInProject: boolean = true): ClaudeCliToolsConfig & { _source?: string } { +export function ensureClaudeCliTools(projectDir: string, createInProject: boolean = false): ClaudeCliToolsConfig & { _source?: string } { const resolved = resolveConfigPath(projectDir); if (resolved.source !== 'default') { @@ -308,25 +314,12 @@ export function ensureClaudeCliTools(projectDir: string, createInProject: boolea return loadClaudeCliTools(projectDir); } - // Config doesn't exist - create default - console.log('[claude-cli-tools] Config not found, creating default cli-tools.json'); + // Config doesn't exist - create in global directory only + console.log('[claude-cli-tools] Config not found, creating default cli-tools.json in ~/.claude'); const defaultConfig: ClaudeCliToolsConfig = { ...DEFAULT_TOOLS_CONFIG }; - if (createInProject) { - // Create in project directory - ensureClaudeDir(projectDir); - const projectPath = getProjectConfigPath(projectDir); - try { - fs.writeFileSync(projectPath, JSON.stringify(defaultConfig, null, 2), 'utf-8'); - console.log(`[claude-cli-tools] Created default config at: ${projectPath}`); - return { ...defaultConfig, _source: 'project' }; - } catch (err) { - console.error('[claude-cli-tools] Failed to create project config:', err); - } - } - - // Fallback: create in global directory + // Always create in global directory (user-level config) const globalDir = path.join(os.homedir(), '.claude'); if (!fs.existsSync(globalDir)) { fs.mkdirSync(globalDir, { recursive: true }); @@ -405,14 +398,28 @@ export function loadClaudeCliTools(projectDir: string): ClaudeCliToolsConfig & { } /** - * Save CLI tools configuration to project .claude/cli-tools.json + * Save CLI tools configuration + * - If config was loaded from project, saves to project + * - Otherwise saves to global ~/.claude/cli-tools.json */ export function saveClaudeCliTools(projectDir: string, config: ClaudeCliToolsConfig & { _source?: string }): void { - ensureClaudeDir(projectDir); - const configPath = getProjectConfigPath(projectDir); - const { _source, ...configToSave } = config; + // Determine save location based on source + let configPath: string; + if (_source === 'project') { + // Config was loaded from project, save back to project + ensureClaudeDir(projectDir); + configPath = getProjectConfigPath(projectDir); + } else { + // Default: save to global directory + const globalDir = path.join(os.homedir(), '.claude'); + if (!fs.existsSync(globalDir)) { + fs.mkdirSync(globalDir, { recursive: true }); + } + configPath = getGlobalConfigPath(); + } + try { fs.writeFileSync(configPath, JSON.stringify(configToSave, null, 2), 'utf-8'); console.log(`[claude-cli-tools] Saved tools config to: ${configPath}`);