claude-code-workflow 6.3.11 → 6.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.claude/CLAUDE.md +33 -33
  2. package/.claude/agents/issue-plan-agent.md +77 -5
  3. package/.claude/agents/issue-queue-agent.md +122 -18
  4. package/.claude/commands/issue/execute.md +53 -40
  5. package/.claude/commands/issue/new.md +113 -11
  6. package/.claude/commands/issue/plan.md +112 -37
  7. package/.claude/commands/issue/queue.md +28 -18
  8. package/.claude/skills/software-manual/scripts/assemble_docsify.py +584 -0
  9. package/.claude/skills/software-manual/templates/css/docsify-base.css +984 -0
  10. package/.claude/skills/software-manual/templates/docsify-shell.html +466 -0
  11. package/.claude/workflows/cli-templates/schemas/issues-jsonl-schema.json +141 -168
  12. package/.claude/workflows/cli-templates/schemas/solution-schema.json +3 -2
  13. package/.codex/prompts/issue-execute.md +3 -3
  14. package/.codex/prompts/issue-queue.md +3 -3
  15. package/ccw/dist/commands/issue.d.ts.map +1 -1
  16. package/ccw/dist/commands/issue.js +2 -1
  17. package/ccw/dist/commands/issue.js.map +1 -1
  18. package/ccw/src/commands/issue.ts +2 -1
  19. package/ccw/src/templates/dashboard-css/33-cli-stream-viewer.css +580 -467
  20. package/ccw/src/templates/dashboard-js/components/cli-stream-viewer.js +532 -461
  21. package/ccw/src/templates/dashboard-js/components/notifications.js +774 -774
  22. package/ccw/src/templates/dashboard-js/i18n.js +4 -0
  23. package/ccw/src/templates/dashboard.html +10 -0
  24. package/ccw/src/tools/claude-cli-tools.ts +388 -388
  25. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  26. package/codex-lens/src/codexlens/config.py +19 -3
  27. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  28. package/codex-lens/src/codexlens/search/ranking.py +15 -4
  29. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
  30. package/codex-lens/src/codexlens/semantic/vector_store.py +57 -47
  31. package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-313.pyc +0 -0
  32. package/codex-lens/src/codexlens/storage/registry.py +114 -101
  33. package/package.json +83 -83
@@ -1,388 +1,388 @@
1
- /**
2
- * Claude CLI Tools Configuration Manager
3
- * Manages .claude/cli-tools.json with fallback:
4
- * 1. Project workspace: {projectDir}/.claude/cli-tools.json (priority)
5
- * 2. Global: ~/.claude/cli-tools.json (fallback)
6
- */
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
- import * as os from 'os';
10
-
11
- // ========== Types ==========
12
-
13
- export interface ClaudeCliTool {
14
- enabled: boolean;
15
- isBuiltin: boolean;
16
- command: string;
17
- description: string;
18
- }
19
-
20
- export interface ClaudeCacheSettings {
21
- injectionMode: 'auto' | 'manual' | 'disabled';
22
- defaultPrefix: string;
23
- defaultSuffix: string;
24
- }
25
-
26
- export interface ClaudeCliToolsConfig {
27
- $schema?: string;
28
- version: string;
29
- tools: Record<string, ClaudeCliTool>;
30
- customEndpoints: Array<{
31
- id: string;
32
- name: string;
33
- enabled: boolean;
34
- }>;
35
- defaultTool: string;
36
- settings: {
37
- promptFormat: 'plain' | 'yaml' | 'json';
38
- smartContext: {
39
- enabled: boolean;
40
- maxFiles: number;
41
- };
42
- nativeResume: boolean;
43
- recursiveQuery: boolean;
44
- cache: ClaudeCacheSettings;
45
- codeIndexMcp: 'codexlens' | 'ace' | 'none'; // Code Index MCP provider
46
- };
47
- }
48
-
49
- // ========== Default Config ==========
50
-
51
- const DEFAULT_CONFIG: ClaudeCliToolsConfig = {
52
- version: '1.0.0',
53
- tools: {
54
- gemini: {
55
- enabled: true,
56
- isBuiltin: true,
57
- command: 'gemini',
58
- description: 'Google AI for code analysis'
59
- },
60
- qwen: {
61
- enabled: true,
62
- isBuiltin: true,
63
- command: 'qwen',
64
- description: 'Alibaba AI assistant'
65
- },
66
- codex: {
67
- enabled: true,
68
- isBuiltin: true,
69
- command: 'codex',
70
- description: 'OpenAI code generation'
71
- },
72
- claude: {
73
- enabled: true,
74
- isBuiltin: true,
75
- command: 'claude',
76
- description: 'Anthropic AI assistant'
77
- }
78
- },
79
- customEndpoints: [],
80
- defaultTool: 'gemini',
81
- settings: {
82
- promptFormat: 'plain',
83
- smartContext: {
84
- enabled: false,
85
- maxFiles: 10
86
- },
87
- nativeResume: true,
88
- recursiveQuery: true,
89
- cache: {
90
- injectionMode: 'auto',
91
- defaultPrefix: '',
92
- defaultSuffix: ''
93
- },
94
- codeIndexMcp: 'codexlens' // Default to CodexLens
95
- }
96
- };
97
-
98
- // ========== Helper Functions ==========
99
-
100
- function getProjectConfigPath(projectDir: string): string {
101
- return path.join(projectDir, '.claude', 'cli-tools.json');
102
- }
103
-
104
- function getGlobalConfigPath(): string {
105
- return path.join(os.homedir(), '.claude', 'cli-tools.json');
106
- }
107
-
108
- /**
109
- * Resolve config path with fallback:
110
- * 1. Project: {projectDir}/.claude/cli-tools.json
111
- * 2. Global: ~/.claude/cli-tools.json
112
- * Returns { path, source } where source is 'project' | 'global' | 'default'
113
- */
114
- function resolveConfigPath(projectDir: string): { path: string; source: 'project' | 'global' | 'default' } {
115
- const projectPath = getProjectConfigPath(projectDir);
116
- if (fs.existsSync(projectPath)) {
117
- return { path: projectPath, source: 'project' };
118
- }
119
-
120
- const globalPath = getGlobalConfigPath();
121
- if (fs.existsSync(globalPath)) {
122
- return { path: globalPath, source: 'global' };
123
- }
124
-
125
- return { path: projectPath, source: 'default' };
126
- }
127
-
128
- function ensureClaudeDir(projectDir: string): void {
129
- const claudeDir = path.join(projectDir, '.claude');
130
- if (!fs.existsSync(claudeDir)) {
131
- fs.mkdirSync(claudeDir, { recursive: true });
132
- }
133
- }
134
-
135
- // ========== Main Functions ==========
136
-
137
- /**
138
- * Load CLI tools configuration with fallback:
139
- * 1. Project: {projectDir}/.claude/cli-tools.json
140
- * 2. Global: ~/.claude/cli-tools.json
141
- * 3. Default config
142
- */
143
- export function loadClaudeCliTools(projectDir: string): ClaudeCliToolsConfig & { _source?: string } {
144
- const resolved = resolveConfigPath(projectDir);
145
-
146
- try {
147
- if (resolved.source === 'default') {
148
- // No config file found, return defaults
149
- return { ...DEFAULT_CONFIG, _source: 'default' };
150
- }
151
-
152
- const content = fs.readFileSync(resolved.path, 'utf-8');
153
- const parsed = JSON.parse(content) as Partial<ClaudeCliToolsConfig>;
154
-
155
- // Merge with defaults
156
- const config = {
157
- ...DEFAULT_CONFIG,
158
- ...parsed,
159
- tools: { ...DEFAULT_CONFIG.tools, ...(parsed.tools || {}) },
160
- settings: {
161
- ...DEFAULT_CONFIG.settings,
162
- ...(parsed.settings || {}),
163
- smartContext: {
164
- ...DEFAULT_CONFIG.settings.smartContext,
165
- ...(parsed.settings?.smartContext || {})
166
- },
167
- cache: {
168
- ...DEFAULT_CONFIG.settings.cache,
169
- ...(parsed.settings?.cache || {})
170
- }
171
- },
172
- _source: resolved.source
173
- };
174
-
175
- console.log(`[claude-cli-tools] Loaded config from ${resolved.source}: ${resolved.path}`);
176
- return config;
177
- } catch (err) {
178
- console.error('[claude-cli-tools] Error loading config:', err);
179
- return { ...DEFAULT_CONFIG, _source: 'default' };
180
- }
181
- }
182
-
183
- /**
184
- * Save CLI tools configuration to project .claude/cli-tools.json
185
- * Always saves to project directory (not global)
186
- */
187
- export function saveClaudeCliTools(projectDir: string, config: ClaudeCliToolsConfig & { _source?: string }): void {
188
- ensureClaudeDir(projectDir);
189
- const configPath = getProjectConfigPath(projectDir);
190
-
191
- // Remove internal _source field before saving
192
- const { _source, ...configToSave } = config;
193
-
194
- try {
195
- fs.writeFileSync(configPath, JSON.stringify(configToSave, null, 2), 'utf-8');
196
- console.log(`[claude-cli-tools] Saved config to project: ${configPath}`);
197
- } catch (err) {
198
- console.error('[claude-cli-tools] Error saving config:', err);
199
- throw new Error(`Failed to save CLI tools config: ${err}`);
200
- }
201
- }
202
-
203
- /**
204
- * Update enabled status for a specific tool
205
- */
206
- export function updateClaudeToolEnabled(
207
- projectDir: string,
208
- toolName: string,
209
- enabled: boolean
210
- ): ClaudeCliToolsConfig {
211
- const config = loadClaudeCliTools(projectDir);
212
-
213
- if (config.tools[toolName]) {
214
- config.tools[toolName].enabled = enabled;
215
- saveClaudeCliTools(projectDir, config);
216
- }
217
-
218
- return config;
219
- }
220
-
221
- /**
222
- * Update cache settings
223
- */
224
- export function updateClaudeCacheSettings(
225
- projectDir: string,
226
- cacheSettings: Partial<ClaudeCacheSettings>
227
- ): ClaudeCliToolsConfig {
228
- const config = loadClaudeCliTools(projectDir);
229
-
230
- config.settings.cache = {
231
- ...config.settings.cache,
232
- ...cacheSettings
233
- };
234
-
235
- saveClaudeCliTools(projectDir, config);
236
- return config;
237
- }
238
-
239
- /**
240
- * Update default tool
241
- */
242
- export function updateClaudeDefaultTool(
243
- projectDir: string,
244
- defaultTool: string
245
- ): ClaudeCliToolsConfig {
246
- const config = loadClaudeCliTools(projectDir);
247
- config.defaultTool = defaultTool;
248
- saveClaudeCliTools(projectDir, config);
249
- return config;
250
- }
251
-
252
- /**
253
- * Add custom endpoint
254
- */
255
- export function addClaudeCustomEndpoint(
256
- projectDir: string,
257
- endpoint: { id: string; name: string; enabled: boolean }
258
- ): ClaudeCliToolsConfig {
259
- const config = loadClaudeCliTools(projectDir);
260
-
261
- // Check if endpoint already exists
262
- const existingIndex = config.customEndpoints.findIndex(e => e.id === endpoint.id);
263
- if (existingIndex >= 0) {
264
- config.customEndpoints[existingIndex] = endpoint;
265
- } else {
266
- config.customEndpoints.push(endpoint);
267
- }
268
-
269
- saveClaudeCliTools(projectDir, config);
270
- return config;
271
- }
272
-
273
- /**
274
- * Remove custom endpoint
275
- */
276
- export function removeClaudeCustomEndpoint(
277
- projectDir: string,
278
- endpointId: string
279
- ): ClaudeCliToolsConfig {
280
- const config = loadClaudeCliTools(projectDir);
281
- config.customEndpoints = config.customEndpoints.filter(e => e.id !== endpointId);
282
- saveClaudeCliTools(projectDir, config);
283
- return config;
284
- }
285
-
286
- /**
287
- * Get config source info
288
- */
289
- export function getClaudeCliToolsInfo(projectDir: string): {
290
- projectPath: string;
291
- globalPath: string;
292
- activePath: string;
293
- source: 'project' | 'global' | 'default';
294
- } {
295
- const resolved = resolveConfigPath(projectDir);
296
- return {
297
- projectPath: getProjectConfigPath(projectDir),
298
- globalPath: getGlobalConfigPath(),
299
- activePath: resolved.path,
300
- source: resolved.source
301
- };
302
- }
303
-
304
- /**
305
- * Update Code Index MCP provider and switch CLAUDE.md reference
306
- * Strategy: Only modify global user-level CLAUDE.md (~/.claude/CLAUDE.md)
307
- * This is consistent with Chinese response and Windows platform settings
308
- */
309
- export function updateCodeIndexMcp(
310
- projectDir: string,
311
- provider: 'codexlens' | 'ace' | 'none'
312
- ): { success: boolean; error?: string; config?: ClaudeCliToolsConfig } {
313
- try {
314
- // Update config
315
- const config = loadClaudeCliTools(projectDir);
316
- config.settings.codeIndexMcp = provider;
317
- saveClaudeCliTools(projectDir, config);
318
-
319
- // Only update global CLAUDE.md (consistent with Chinese response / Windows platform)
320
- const globalClaudeMdPath = path.join(os.homedir(), '.claude', 'CLAUDE.md');
321
-
322
- // Define patterns for all formats
323
- const codexlensPattern = /@~\/\.claude\/workflows\/context-tools\.md/g;
324
- const acePattern = /@~\/\.claude\/workflows\/context-tools-ace\.md/g;
325
- const nonePattern = /@~\/\.claude\/workflows\/context-tools-none\.md/g;
326
-
327
- // Determine target file based on provider
328
- const targetFile = provider === 'ace'
329
- ? '@~/.claude/workflows/context-tools-ace.md'
330
- : provider === 'none'
331
- ? '@~/.claude/workflows/context-tools-none.md'
332
- : '@~/.claude/workflows/context-tools.md';
333
-
334
- if (!fs.existsSync(globalClaudeMdPath)) {
335
- // If global CLAUDE.md doesn't exist, check project-level
336
- const projectClaudeMdPath = path.join(projectDir, '.claude', 'CLAUDE.md');
337
- if (fs.existsSync(projectClaudeMdPath)) {
338
- let content = fs.readFileSync(projectClaudeMdPath, 'utf-8');
339
-
340
- // Replace any existing pattern with the target
341
- content = content.replace(codexlensPattern, targetFile);
342
- content = content.replace(acePattern, targetFile);
343
- content = content.replace(nonePattern, targetFile);
344
-
345
- fs.writeFileSync(projectClaudeMdPath, content, 'utf-8');
346
- console.log(`[claude-cli-tools] Updated project CLAUDE.md to use ${provider} (no global CLAUDE.md found)`);
347
- }
348
- } else {
349
- // Update global CLAUDE.md (primary target)
350
- let content = fs.readFileSync(globalClaudeMdPath, 'utf-8');
351
-
352
- // Replace any existing pattern with the target
353
- content = content.replace(codexlensPattern, targetFile);
354
- content = content.replace(acePattern, targetFile);
355
- content = content.replace(nonePattern, targetFile);
356
-
357
- fs.writeFileSync(globalClaudeMdPath, content, 'utf-8');
358
- console.log(`[claude-cli-tools] Updated global CLAUDE.md to use ${provider}`);
359
- }
360
-
361
- return { success: true, config };
362
- } catch (err) {
363
- console.error('[claude-cli-tools] Error updating Code Index MCP:', err);
364
- return { success: false, error: (err as Error).message };
365
- }
366
- }
367
-
368
- /**
369
- * Get current Code Index MCP provider
370
- */
371
- export function getCodeIndexMcp(projectDir: string): 'codexlens' | 'ace' | 'none' {
372
- const config = loadClaudeCliTools(projectDir);
373
- return config.settings.codeIndexMcp || 'codexlens';
374
- }
375
-
376
- /**
377
- * Get the context-tools file path based on provider
378
- */
379
- export function getContextToolsPath(provider: 'codexlens' | 'ace' | 'none'): string {
380
- switch (provider) {
381
- case 'ace':
382
- return 'context-tools-ace.md';
383
- case 'none':
384
- return 'context-tools-none.md';
385
- default:
386
- return 'context-tools.md';
387
- }
388
- }
1
+ /**
2
+ * Claude CLI Tools Configuration Manager
3
+ * Manages .claude/cli-tools.json with fallback:
4
+ * 1. Project workspace: {projectDir}/.claude/cli-tools.json (priority)
5
+ * 2. Global: ~/.claude/cli-tools.json (fallback)
6
+ */
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import * as os from 'os';
10
+
11
+ // ========== Types ==========
12
+
13
+ export interface ClaudeCliTool {
14
+ enabled: boolean;
15
+ isBuiltin: boolean;
16
+ command: string;
17
+ description: string;
18
+ }
19
+
20
+ export interface ClaudeCacheSettings {
21
+ injectionMode: 'auto' | 'manual' | 'disabled';
22
+ defaultPrefix: string;
23
+ defaultSuffix: string;
24
+ }
25
+
26
+ export interface ClaudeCliToolsConfig {
27
+ $schema?: string;
28
+ version: string;
29
+ tools: Record<string, ClaudeCliTool>;
30
+ customEndpoints: Array<{
31
+ id: string;
32
+ name: string;
33
+ enabled: boolean;
34
+ }>;
35
+ defaultTool: string;
36
+ settings: {
37
+ promptFormat: 'plain' | 'yaml' | 'json';
38
+ smartContext: {
39
+ enabled: boolean;
40
+ maxFiles: number;
41
+ };
42
+ nativeResume: boolean;
43
+ recursiveQuery: boolean;
44
+ cache: ClaudeCacheSettings;
45
+ codeIndexMcp: 'codexlens' | 'ace' | 'none'; // Code Index MCP provider
46
+ };
47
+ }
48
+
49
+ // ========== Default Config ==========
50
+
51
+ const DEFAULT_CONFIG: ClaudeCliToolsConfig = {
52
+ version: '1.0.0',
53
+ tools: {
54
+ gemini: {
55
+ enabled: true,
56
+ isBuiltin: true,
57
+ command: 'gemini',
58
+ description: 'Google AI for code analysis'
59
+ },
60
+ qwen: {
61
+ enabled: true,
62
+ isBuiltin: true,
63
+ command: 'qwen',
64
+ description: 'Alibaba AI assistant'
65
+ },
66
+ codex: {
67
+ enabled: true,
68
+ isBuiltin: true,
69
+ command: 'codex',
70
+ description: 'OpenAI code generation'
71
+ },
72
+ claude: {
73
+ enabled: true,
74
+ isBuiltin: true,
75
+ command: 'claude',
76
+ description: 'Anthropic AI assistant'
77
+ }
78
+ },
79
+ customEndpoints: [],
80
+ defaultTool: 'gemini',
81
+ settings: {
82
+ promptFormat: 'plain',
83
+ smartContext: {
84
+ enabled: false,
85
+ maxFiles: 10
86
+ },
87
+ nativeResume: true,
88
+ recursiveQuery: true,
89
+ cache: {
90
+ injectionMode: 'auto',
91
+ defaultPrefix: '',
92
+ defaultSuffix: ''
93
+ },
94
+ codeIndexMcp: 'codexlens' // Default to CodexLens
95
+ }
96
+ };
97
+
98
+ // ========== Helper Functions ==========
99
+
100
+ function getProjectConfigPath(projectDir: string): string {
101
+ return path.join(projectDir, '.claude', 'cli-tools.json');
102
+ }
103
+
104
+ function getGlobalConfigPath(): string {
105
+ return path.join(os.homedir(), '.claude', 'cli-tools.json');
106
+ }
107
+
108
+ /**
109
+ * Resolve config path with fallback:
110
+ * 1. Project: {projectDir}/.claude/cli-tools.json
111
+ * 2. Global: ~/.claude/cli-tools.json
112
+ * Returns { path, source } where source is 'project' | 'global' | 'default'
113
+ */
114
+ function resolveConfigPath(projectDir: string): { path: string; source: 'project' | 'global' | 'default' } {
115
+ const projectPath = getProjectConfigPath(projectDir);
116
+ if (fs.existsSync(projectPath)) {
117
+ return { path: projectPath, source: 'project' };
118
+ }
119
+
120
+ const globalPath = getGlobalConfigPath();
121
+ if (fs.existsSync(globalPath)) {
122
+ return { path: globalPath, source: 'global' };
123
+ }
124
+
125
+ return { path: projectPath, source: 'default' };
126
+ }
127
+
128
+ function ensureClaudeDir(projectDir: string): void {
129
+ const claudeDir = path.join(projectDir, '.claude');
130
+ if (!fs.existsSync(claudeDir)) {
131
+ fs.mkdirSync(claudeDir, { recursive: true });
132
+ }
133
+ }
134
+
135
+ // ========== Main Functions ==========
136
+
137
+ /**
138
+ * Load CLI tools configuration with fallback:
139
+ * 1. Project: {projectDir}/.claude/cli-tools.json
140
+ * 2. Global: ~/.claude/cli-tools.json
141
+ * 3. Default config
142
+ */
143
+ export function loadClaudeCliTools(projectDir: string): ClaudeCliToolsConfig & { _source?: string } {
144
+ const resolved = resolveConfigPath(projectDir);
145
+
146
+ try {
147
+ if (resolved.source === 'default') {
148
+ // No config file found, return defaults
149
+ return { ...DEFAULT_CONFIG, _source: 'default' };
150
+ }
151
+
152
+ const content = fs.readFileSync(resolved.path, 'utf-8');
153
+ const parsed = JSON.parse(content) as Partial<ClaudeCliToolsConfig>;
154
+
155
+ // Merge with defaults
156
+ const config = {
157
+ ...DEFAULT_CONFIG,
158
+ ...parsed,
159
+ tools: { ...DEFAULT_CONFIG.tools, ...(parsed.tools || {}) },
160
+ settings: {
161
+ ...DEFAULT_CONFIG.settings,
162
+ ...(parsed.settings || {}),
163
+ smartContext: {
164
+ ...DEFAULT_CONFIG.settings.smartContext,
165
+ ...(parsed.settings?.smartContext || {})
166
+ },
167
+ cache: {
168
+ ...DEFAULT_CONFIG.settings.cache,
169
+ ...(parsed.settings?.cache || {})
170
+ }
171
+ },
172
+ _source: resolved.source
173
+ };
174
+
175
+ console.log(`[claude-cli-tools] Loaded config from ${resolved.source}: ${resolved.path}`);
176
+ return config;
177
+ } catch (err) {
178
+ console.error('[claude-cli-tools] Error loading config:', err);
179
+ return { ...DEFAULT_CONFIG, _source: 'default' };
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Save CLI tools configuration to project .claude/cli-tools.json
185
+ * Always saves to project directory (not global)
186
+ */
187
+ export function saveClaudeCliTools(projectDir: string, config: ClaudeCliToolsConfig & { _source?: string }): void {
188
+ ensureClaudeDir(projectDir);
189
+ const configPath = getProjectConfigPath(projectDir);
190
+
191
+ // Remove internal _source field before saving
192
+ const { _source, ...configToSave } = config;
193
+
194
+ try {
195
+ fs.writeFileSync(configPath, JSON.stringify(configToSave, null, 2), 'utf-8');
196
+ console.log(`[claude-cli-tools] Saved config to project: ${configPath}`);
197
+ } catch (err) {
198
+ console.error('[claude-cli-tools] Error saving config:', err);
199
+ throw new Error(`Failed to save CLI tools config: ${err}`);
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Update enabled status for a specific tool
205
+ */
206
+ export function updateClaudeToolEnabled(
207
+ projectDir: string,
208
+ toolName: string,
209
+ enabled: boolean
210
+ ): ClaudeCliToolsConfig {
211
+ const config = loadClaudeCliTools(projectDir);
212
+
213
+ if (config.tools[toolName]) {
214
+ config.tools[toolName].enabled = enabled;
215
+ saveClaudeCliTools(projectDir, config);
216
+ }
217
+
218
+ return config;
219
+ }
220
+
221
+ /**
222
+ * Update cache settings
223
+ */
224
+ export function updateClaudeCacheSettings(
225
+ projectDir: string,
226
+ cacheSettings: Partial<ClaudeCacheSettings>
227
+ ): ClaudeCliToolsConfig {
228
+ const config = loadClaudeCliTools(projectDir);
229
+
230
+ config.settings.cache = {
231
+ ...config.settings.cache,
232
+ ...cacheSettings
233
+ };
234
+
235
+ saveClaudeCliTools(projectDir, config);
236
+ return config;
237
+ }
238
+
239
+ /**
240
+ * Update default tool
241
+ */
242
+ export function updateClaudeDefaultTool(
243
+ projectDir: string,
244
+ defaultTool: string
245
+ ): ClaudeCliToolsConfig {
246
+ const config = loadClaudeCliTools(projectDir);
247
+ config.defaultTool = defaultTool;
248
+ saveClaudeCliTools(projectDir, config);
249
+ return config;
250
+ }
251
+
252
+ /**
253
+ * Add custom endpoint
254
+ */
255
+ export function addClaudeCustomEndpoint(
256
+ projectDir: string,
257
+ endpoint: { id: string; name: string; enabled: boolean }
258
+ ): ClaudeCliToolsConfig {
259
+ const config = loadClaudeCliTools(projectDir);
260
+
261
+ // Check if endpoint already exists
262
+ const existingIndex = config.customEndpoints.findIndex(e => e.id === endpoint.id);
263
+ if (existingIndex >= 0) {
264
+ config.customEndpoints[existingIndex] = endpoint;
265
+ } else {
266
+ config.customEndpoints.push(endpoint);
267
+ }
268
+
269
+ saveClaudeCliTools(projectDir, config);
270
+ return config;
271
+ }
272
+
273
+ /**
274
+ * Remove custom endpoint
275
+ */
276
+ export function removeClaudeCustomEndpoint(
277
+ projectDir: string,
278
+ endpointId: string
279
+ ): ClaudeCliToolsConfig {
280
+ const config = loadClaudeCliTools(projectDir);
281
+ config.customEndpoints = config.customEndpoints.filter(e => e.id !== endpointId);
282
+ saveClaudeCliTools(projectDir, config);
283
+ return config;
284
+ }
285
+
286
+ /**
287
+ * Get config source info
288
+ */
289
+ export function getClaudeCliToolsInfo(projectDir: string): {
290
+ projectPath: string;
291
+ globalPath: string;
292
+ activePath: string;
293
+ source: 'project' | 'global' | 'default';
294
+ } {
295
+ const resolved = resolveConfigPath(projectDir);
296
+ return {
297
+ projectPath: getProjectConfigPath(projectDir),
298
+ globalPath: getGlobalConfigPath(),
299
+ activePath: resolved.path,
300
+ source: resolved.source
301
+ };
302
+ }
303
+
304
+ /**
305
+ * Update Code Index MCP provider and switch CLAUDE.md reference
306
+ * Strategy: Only modify global user-level CLAUDE.md (~/.claude/CLAUDE.md)
307
+ * This is consistent with Chinese response and Windows platform settings
308
+ */
309
+ export function updateCodeIndexMcp(
310
+ projectDir: string,
311
+ provider: 'codexlens' | 'ace' | 'none'
312
+ ): { success: boolean; error?: string; config?: ClaudeCliToolsConfig } {
313
+ try {
314
+ // Update config
315
+ const config = loadClaudeCliTools(projectDir);
316
+ config.settings.codeIndexMcp = provider;
317
+ saveClaudeCliTools(projectDir, config);
318
+
319
+ // Only update global CLAUDE.md (consistent with Chinese response / Windows platform)
320
+ const globalClaudeMdPath = path.join(os.homedir(), '.claude', 'CLAUDE.md');
321
+
322
+ // Define patterns for all formats
323
+ const codexlensPattern = /@~\/\.claude\/workflows\/context-tools\.md/g;
324
+ const acePattern = /@~\/\.claude\/workflows\/context-tools-ace\.md/g;
325
+ const nonePattern = /@~\/\.claude\/workflows\/context-tools-none\.md/g;
326
+
327
+ // Determine target file based on provider
328
+ const targetFile = provider === 'ace'
329
+ ? '@~/.claude/workflows/context-tools-ace.md'
330
+ : provider === 'none'
331
+ ? '@~/.claude/workflows/context-tools-none.md'
332
+ : '@~/.claude/workflows/context-tools.md';
333
+
334
+ if (!fs.existsSync(globalClaudeMdPath)) {
335
+ // If global CLAUDE.md doesn't exist, check project-level
336
+ const projectClaudeMdPath = path.join(projectDir, '.claude', 'CLAUDE.md');
337
+ if (fs.existsSync(projectClaudeMdPath)) {
338
+ let content = fs.readFileSync(projectClaudeMdPath, 'utf-8');
339
+
340
+ // Replace any existing pattern with the target
341
+ content = content.replace(codexlensPattern, targetFile);
342
+ content = content.replace(acePattern, targetFile);
343
+ content = content.replace(nonePattern, targetFile);
344
+
345
+ fs.writeFileSync(projectClaudeMdPath, content, 'utf-8');
346
+ console.log(`[claude-cli-tools] Updated project CLAUDE.md to use ${provider} (no global CLAUDE.md found)`);
347
+ }
348
+ } else {
349
+ // Update global CLAUDE.md (primary target)
350
+ let content = fs.readFileSync(globalClaudeMdPath, 'utf-8');
351
+
352
+ // Replace any existing pattern with the target
353
+ content = content.replace(codexlensPattern, targetFile);
354
+ content = content.replace(acePattern, targetFile);
355
+ content = content.replace(nonePattern, targetFile);
356
+
357
+ fs.writeFileSync(globalClaudeMdPath, content, 'utf-8');
358
+ console.log(`[claude-cli-tools] Updated global CLAUDE.md to use ${provider}`);
359
+ }
360
+
361
+ return { success: true, config };
362
+ } catch (err) {
363
+ console.error('[claude-cli-tools] Error updating Code Index MCP:', err);
364
+ return { success: false, error: (err as Error).message };
365
+ }
366
+ }
367
+
368
+ /**
369
+ * Get current Code Index MCP provider
370
+ */
371
+ export function getCodeIndexMcp(projectDir: string): 'codexlens' | 'ace' | 'none' {
372
+ const config = loadClaudeCliTools(projectDir);
373
+ return config.settings.codeIndexMcp || 'codexlens';
374
+ }
375
+
376
+ /**
377
+ * Get the context-tools file path based on provider
378
+ */
379
+ export function getContextToolsPath(provider: 'codexlens' | 'ace' | 'none'): string {
380
+ switch (provider) {
381
+ case 'ace':
382
+ return 'context-tools-ace.md';
383
+ case 'none':
384
+ return 'context-tools-none.md';
385
+ default:
386
+ return 'context-tools.md';
387
+ }
388
+ }