claude-code-workflow 6.3.9 → 6.3.10

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 (29) hide show
  1. package/.claude/CLAUDE.md +1 -1
  2. package/.claude/agents/issue-plan-agent.md +3 -10
  3. package/.claude/agents/issue-queue-agent.md +103 -83
  4. package/.claude/commands/issue/execute.md +195 -363
  5. package/.claude/commands/issue/plan.md +9 -2
  6. package/.claude/commands/issue/queue.md +130 -66
  7. package/.claude/commands/workflow/init.md +75 -29
  8. package/.claude/commands/workflow/lite-fix.md +8 -0
  9. package/.claude/commands/workflow/lite-plan.md +8 -0
  10. package/.claude/commands/workflow/review-module-cycle.md +4 -0
  11. package/.claude/commands/workflow/review-session-cycle.md +4 -0
  12. package/.claude/commands/workflow/review.md +4 -4
  13. package/.claude/commands/workflow/session/solidify.md +299 -0
  14. package/.claude/commands/workflow/session/start.md +10 -7
  15. package/.claude/commands/workflow/tools/context-gather.md +17 -10
  16. package/.claude/workflows/cli-templates/schemas/queue-schema.json +225 -108
  17. package/.claude/workflows/cli-templates/schemas/solution-schema.json +6 -28
  18. package/.claude/workflows/context-tools.md +17 -25
  19. package/.codex/AGENTS.md +10 -5
  20. package/ccw/dist/commands/issue.d.ts.map +1 -1
  21. package/ccw/dist/commands/issue.js +348 -115
  22. package/ccw/dist/commands/issue.js.map +1 -1
  23. package/ccw/src/commands/issue.ts +392 -149
  24. package/ccw/src/templates/dashboard-js/components/cli-status.js +1 -78
  25. package/ccw/src/templates/dashboard-js/i18n.js +0 -4
  26. package/ccw/src/templates/dashboard-js/views/cli-manager.js +0 -18
  27. package/ccw/src/templates/dashboard-js/views/issue-manager.js +57 -26
  28. package/package.json +1 -1
  29. package/.claude/workflows/context-tools-ace.md +0 -105
@@ -21,24 +21,6 @@ let nativeResumeEnabled = localStorage.getItem('ccw-native-resume') !== 'false';
21
21
  // Recursive Query settings (for hierarchical storage aggregation)
22
22
  let recursiveQueryEnabled = localStorage.getItem('ccw-recursive-query') !== 'false'; // default true
23
23
 
24
- // Code Index MCP provider (codexlens, ace, or none)
25
- let codeIndexMcpProvider = 'codexlens';
26
-
27
- // ========== Helper Functions ==========
28
- /**
29
- * Get the context-tools filename based on provider
30
- */
31
- function getContextToolsFileName(provider) {
32
- switch (provider) {
33
- case 'ace':
34
- return 'context-tools-ace.md';
35
- case 'none':
36
- return 'context-tools-none.md';
37
- default:
38
- return 'context-tools.md';
39
- }
40
- }
41
-
42
24
  // ========== Initialization ==========
43
25
  function initCliStatus() {
44
26
  // Load all statuses in one call using aggregated endpoint
@@ -259,12 +241,7 @@ async function loadCliToolsConfig() {
259
241
  defaultCliTool = data.defaultTool;
260
242
  }
261
243
 
262
- // Load Code Index MCP provider from config
263
- if (data.settings?.codeIndexMcp) {
264
- codeIndexMcpProvider = data.settings.codeIndexMcp;
265
- }
266
-
267
- console.log('[CLI Config] Loaded from:', data._configInfo?.source || 'unknown', '| Default:', data.defaultTool, '| CodeIndexMCP:', codeIndexMcpProvider);
244
+ console.log('[CLI Config] Loaded from:', data._configInfo?.source || 'unknown', '| Default:', data.defaultTool);
268
245
  return data;
269
246
  } catch (err) {
270
247
  console.error('Failed to load CLI tools config:', err);
@@ -637,33 +614,6 @@ function renderCliStatus() {
637
614
  </div>
638
615
  <p class="cli-setting-desc">Cache prefix/suffix injection mode for prompts</p>
639
616
  </div>
640
- <div class="cli-setting-item">
641
- <label class="cli-setting-label">
642
- <i data-lucide="search" class="w-3 h-3"></i>
643
- Code Index MCP
644
- </label>
645
- <div class="cli-setting-control">
646
- <div class="flex items-center bg-muted rounded-lg p-0.5">
647
- <button class="code-mcp-btn px-3 py-1.5 text-xs font-medium rounded-md transition-all ${codeIndexMcpProvider === 'codexlens' ? 'bg-primary text-primary-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}"
648
- onclick="setCodeIndexMcpProvider('codexlens')">
649
- CodexLens
650
- </button>
651
- <button class="code-mcp-btn px-3 py-1.5 text-xs font-medium rounded-md transition-all ${codeIndexMcpProvider === 'ace' ? 'bg-primary text-primary-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}"
652
- onclick="setCodeIndexMcpProvider('ace')">
653
- ACE
654
- </button>
655
- <button class="code-mcp-btn px-3 py-1.5 text-xs font-medium rounded-md transition-all ${codeIndexMcpProvider === 'none' ? 'bg-primary text-primary-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}"
656
- onclick="setCodeIndexMcpProvider('none')">
657
- None
658
- </button>
659
- </div>
660
- </div>
661
- <p class="cli-setting-desc">Code search provider (updates CLAUDE.md context-tools reference)</p>
662
- <p class="cli-setting-desc text-xs text-muted-foreground mt-1">
663
- <i data-lucide="file-text" class="w-3 h-3 inline-block mr-1"></i>
664
- Current: <code class="bg-muted px-1 rounded">${getContextToolsFileName(codeIndexMcpProvider)}</code>
665
- </p>
666
- </div>
667
617
  </div>
668
618
  </div>
669
619
  `;
@@ -786,33 +736,6 @@ async function setCacheInjectionMode(mode) {
786
736
  }
787
737
  }
788
738
 
789
- async function setCodeIndexMcpProvider(provider) {
790
- try {
791
- const response = await fetch('/api/cli/code-index-mcp', {
792
- method: 'PUT',
793
- headers: { 'Content-Type': 'application/json' },
794
- body: JSON.stringify({ provider: provider })
795
- });
796
- if (response.ok) {
797
- codeIndexMcpProvider = provider;
798
- if (window.claudeCliToolsConfig && window.claudeCliToolsConfig.settings) {
799
- window.claudeCliToolsConfig.settings.codeIndexMcp = provider;
800
- }
801
- const providerName = provider === 'ace' ? 'ACE (Augment)' : provider === 'none' ? 'None (Built-in only)' : 'CodexLens';
802
- showRefreshToast(`Code Index MCP switched to ${providerName}`, 'success');
803
- // Re-render both CLI status and settings section
804
- if (typeof renderCliStatus === 'function') renderCliStatus();
805
- if (typeof renderCliSettingsSection === 'function') renderCliSettingsSection();
806
- } else {
807
- const data = await response.json();
808
- showRefreshToast(`Failed to switch Code Index MCP: ${data.error}`, 'error');
809
- }
810
- } catch (err) {
811
- console.error('Failed to switch Code Index MCP:', err);
812
- showRefreshToast('Failed to switch Code Index MCP', 'error');
813
- }
814
- }
815
-
816
739
  async function refreshAllCliStatus() {
817
740
  await loadAllStatuses();
818
741
  renderCliStatus();
@@ -560,8 +560,6 @@ const i18n = {
560
560
  'cli.recursiveQueryDesc': 'Aggregate CLI history and memory data from parent and child projects',
561
561
  'cli.maxContextFiles': 'Max Context Files',
562
562
  'cli.maxContextFilesDesc': 'Maximum files to include in smart context',
563
- 'cli.codeIndexMcp': 'Code Index MCP',
564
- 'cli.codeIndexMcpDesc': 'Code search provider (updates CLAUDE.md context-tools reference)',
565
563
 
566
564
  // CCW Install
567
565
  'ccw.install': 'CCW Install',
@@ -2414,8 +2412,6 @@ const i18n = {
2414
2412
  'cli.recursiveQueryDesc': '聚合显示父项目和子项目的 CLI 历史与内存数据',
2415
2413
  'cli.maxContextFiles': '最大上下文文件数',
2416
2414
  'cli.maxContextFilesDesc': '智能上下文包含的最大文件数',
2417
- 'cli.codeIndexMcp': '代码索引 MCP',
2418
- 'cli.codeIndexMcpDesc': '代码搜索提供者 (更新 CLAUDE.md 的 context-tools 引用)',
2419
2415
 
2420
2416
  // CCW Install
2421
2417
  'ccw.install': 'CCW 安装',
@@ -987,24 +987,6 @@ function renderCliSettingsSection() {
987
987
  '</div>' +
988
988
  '<p class="cli-setting-desc">' + t('cli.maxContextFilesDesc') + '</p>' +
989
989
  '</div>' +
990
- '<div class="cli-setting-item">' +
991
- '<label class="cli-setting-label">' +
992
- '<i data-lucide="search" class="w-3 h-3"></i>' +
993
- t('cli.codeIndexMcp') +
994
- '</label>' +
995
- '<div class="cli-setting-control">' +
996
- '<select class="cli-setting-select" onchange="setCodeIndexMcpProvider(this.value)">' +
997
- '<option value="codexlens"' + (codeIndexMcpProvider === 'codexlens' ? ' selected' : '') + '>CodexLens</option>' +
998
- '<option value="ace"' + (codeIndexMcpProvider === 'ace' ? ' selected' : '') + '>ACE (Augment)</option>' +
999
- '<option value="none"' + (codeIndexMcpProvider === 'none' ? ' selected' : '') + '>None (Built-in)</option>' +
1000
- '</select>' +
1001
- '</div>' +
1002
- '<p class="cli-setting-desc">' + t('cli.codeIndexMcpDesc') + '</p>' +
1003
- '<p class="cli-setting-desc text-xs text-muted-foreground">' +
1004
- '<i data-lucide="file-text" class="w-3 h-3 inline-block mr-1"></i>' +
1005
- 'Current: <code class="bg-muted px-1 rounded">' + getContextToolsFileName(codeIndexMcpProvider) + '</code>' +
1006
- '</p>' +
1007
- '</div>' +
1008
990
  '</div>';
1009
991
 
1010
992
  container.innerHTML = settingsHtml;
@@ -6,7 +6,7 @@
6
6
  // ========== Issue State ==========
7
7
  var issueData = {
8
8
  issues: [],
9
- queue: { tasks: [], conflicts: [], execution_groups: [], grouped_items: {} },
9
+ queue: { tasks: [], solutions: [], conflicts: [], execution_groups: [], grouped_items: {} },
10
10
  selectedIssue: null,
11
11
  selectedSolution: null,
12
12
  selectedSolutionIssueId: null,
@@ -65,7 +65,7 @@ async function loadQueueData() {
65
65
  issueData.queue = await response.json();
66
66
  } catch (err) {
67
67
  console.error('Failed to load queue:', err);
68
- issueData.queue = { tasks: [], conflicts: [], execution_groups: [], grouped_items: {} };
68
+ issueData.queue = { tasks: [], solutions: [], conflicts: [], execution_groups: [], grouped_items: {} };
69
69
  }
70
70
  }
71
71
 
@@ -360,7 +360,9 @@ function filterIssuesByStatus(status) {
360
360
  // ========== Queue Section ==========
361
361
  function renderQueueSection() {
362
362
  const queue = issueData.queue;
363
- const queueItems = queue.tasks || [];
363
+ // Support both solution-level and task-level queues
364
+ const queueItems = queue.solutions || queue.tasks || [];
365
+ const isSolutionLevel = !!(queue.solutions && queue.solutions.length > 0);
364
366
  const metadata = queue._metadata || {};
365
367
 
366
368
  // Check if queue is empty
@@ -443,8 +445,8 @@ function renderQueueSection() {
443
445
  <!-- Queue Stats -->
444
446
  <div class="queue-stats-grid mb-4">
445
447
  <div class="queue-stat-card">
446
- <span class="queue-stat-value">${metadata.total_tasks || queueItems.length}</span>
447
- <span class="queue-stat-label">${t('issues.totalTasks') || 'Total'}</span>
448
+ <span class="queue-stat-value">${isSolutionLevel ? (metadata.total_solutions || queueItems.length) : (metadata.total_tasks || queueItems.length)}</span>
449
+ <span class="queue-stat-label">${isSolutionLevel ? (t('issues.totalSolutions') || 'Solutions') : (t('issues.totalTasks') || 'Total')}</span>
448
450
  </div>
449
451
  <div class="queue-stat-card pending">
450
452
  <span class="queue-stat-value">${metadata.pending_count || queueItems.filter(i => i.status === 'pending').length}</span>
@@ -510,6 +512,9 @@ function renderQueueSection() {
510
512
 
511
513
  function renderQueueGroup(group, items) {
512
514
  const isParallel = group.type === 'parallel';
515
+ // Support both solution-level (solution_count) and task-level (task_count)
516
+ const itemCount = group.solution_count || group.task_count || items.length;
517
+ const itemLabel = group.solution_count ? 'solutions' : 'tasks';
513
518
 
514
519
  return `
515
520
  <div class="queue-group" data-group-id="${group.id}">
@@ -518,7 +523,7 @@ function renderQueueGroup(group, items) {
518
523
  <i data-lucide="${isParallel ? 'git-merge' : 'arrow-right'}" class="w-4 h-4"></i>
519
524
  ${group.id} (${isParallel ? t('issues.parallelGroup') || 'Parallel' : t('issues.sequentialGroup') || 'Sequential'})
520
525
  </div>
521
- <span class="text-sm text-muted-foreground">${group.task_count} tasks</span>
526
+ <span class="text-sm text-muted-foreground">${itemCount} ${itemLabel}</span>
522
527
  </div>
523
528
  <div class="queue-items ${isParallel ? 'parallel' : 'sequential'}">
524
529
  ${items.map((item, idx) => renderQueueItem(item, idx, items.length)).join('')}
@@ -537,6 +542,9 @@ function renderQueueItem(item, index, total) {
537
542
  blocked: 'blocked'
538
543
  };
539
544
 
545
+ // Check if this is a solution-level item (has task_count) or task-level (has task_id)
546
+ const isSolutionItem = item.task_count !== undefined;
547
+
540
548
  return `
541
549
  <div class="queue-item ${statusColors[item.status] || ''}"
542
550
  draggable="true"
@@ -545,7 +553,20 @@ function renderQueueItem(item, index, total) {
545
553
  onclick="openQueueItemDetail('${item.item_id}')">
546
554
  <span class="queue-item-id font-mono text-xs">${item.item_id}</span>
547
555
  <span class="queue-item-issue text-xs text-muted-foreground">${item.issue_id}</span>
548
- <span class="queue-item-task text-sm">${item.task_id}</span>
556
+ ${isSolutionItem ? `
557
+ <span class="queue-item-solution text-sm" title="${item.solution_id || ''}">
558
+ <i data-lucide="package" class="w-3 h-3 inline mr-1"></i>
559
+ ${item.task_count} ${t('issues.tasks') || 'tasks'}
560
+ </span>
561
+ ${item.files_touched && item.files_touched.length > 0 ? `
562
+ <span class="queue-item-files text-xs text-muted-foreground" title="${item.files_touched.join(', ')}">
563
+ <i data-lucide="file" class="w-3 h-3"></i>
564
+ ${item.files_touched.length}
565
+ </span>
566
+ ` : ''}
567
+ ` : `
568
+ <span class="queue-item-task text-sm">${item.task_id || '-'}</span>
569
+ `}
549
570
  <span class="queue-item-priority" style="opacity: ${item.semantic_priority || 0.5}">
550
571
  <i data-lucide="arrow-up" class="w-3 h-3"></i>
551
572
  </span>
@@ -569,9 +590,12 @@ function renderConflictsSection(conflicts) {
569
590
  ${conflicts.map(c => `
570
591
  <div class="conflict-item">
571
592
  <span class="conflict-file font-mono text-xs">${c.file}</span>
572
- <span class="conflict-tasks text-xs text-muted-foreground">${c.tasks.join(' → ')}</span>
573
- <span class="conflict-status ${c.resolved ? 'resolved' : 'pending'}">
574
- ${c.resolved ? 'Resolved' : 'Pending'}
593
+ <span class="conflict-items text-xs text-muted-foreground">${(c.solutions || c.tasks || []).join(' → ')}</span>
594
+ ${c.rationale ? `<span class="conflict-rationale text-xs text-muted-foreground" title="${c.rationale}">
595
+ <i data-lucide="info" class="w-3 h-3"></i>
596
+ </span>` : ''}
597
+ <span class="conflict-status ${c.resolved || c.resolution ? 'resolved' : 'pending'}">
598
+ ${c.resolved || c.resolution ? 'Resolved' : 'Pending'}
575
599
  </span>
576
600
  </div>
577
601
  `).join('')}
@@ -1156,7 +1180,9 @@ function escapeHtml(text) {
1156
1180
  }
1157
1181
 
1158
1182
  function openQueueItemDetail(itemId) {
1159
- const item = issueData.queue.tasks?.find(q => q.item_id === itemId);
1183
+ // Support both solution-level and task-level queues
1184
+ const items = issueData.queue.solutions || issueData.queue.tasks || [];
1185
+ const item = items.find(q => q.item_id === itemId);
1160
1186
  if (item) {
1161
1187
  openIssueDetail(item.issue_id);
1162
1188
  }
@@ -1600,7 +1626,7 @@ async function showQueueHistoryModal() {
1600
1626
  </span>
1601
1627
  <span class="text-xs text-muted-foreground">
1602
1628
  <i data-lucide="check-circle" class="w-3 h-3 inline"></i>
1603
- ${q.completed_tasks || 0}/${q.total_tasks || 0} tasks
1629
+ ${q.completed_solutions || q.completed_tasks || 0}/${q.total_solutions || q.total_tasks || 0} ${q.total_solutions ? 'solutions' : 'tasks'}
1604
1630
  </span>
1605
1631
  <span class="text-xs text-muted-foreground">
1606
1632
  <i data-lucide="calendar" class="w-3 h-3 inline"></i>
@@ -1689,17 +1715,21 @@ async function viewQueueDetail(queueId) {
1689
1715
  throw new Error(queue.error);
1690
1716
  }
1691
1717
 
1692
- const tasks = queue.queue || [];
1718
+ // Support both solution-level and task-level queues
1719
+ const items = queue.solutions || queue.queue || queue.tasks || [];
1720
+ const isSolutionLevel = !!(queue.solutions && queue.solutions.length > 0);
1693
1721
  const metadata = queue._metadata || {};
1694
1722
 
1695
1723
  // Group by execution_group
1696
1724
  const grouped = {};
1697
- tasks.forEach(task => {
1698
- const group = task.execution_group || 'ungrouped';
1725
+ items.forEach(item => {
1726
+ const group = item.execution_group || 'ungrouped';
1699
1727
  if (!grouped[group]) grouped[group] = [];
1700
- grouped[group].push(task);
1728
+ grouped[group].push(item);
1701
1729
  });
1702
1730
 
1731
+ const itemLabel = isSolutionLevel ? 'solutions' : 'tasks';
1732
+
1703
1733
  const detailHtml = `
1704
1734
  <div class="queue-detail-view">
1705
1735
  <div class="queue-detail-header mb-4">
@@ -1715,40 +1745,41 @@ async function viewQueueDetail(queueId) {
1715
1745
 
1716
1746
  <div class="queue-detail-stats mb-4">
1717
1747
  <div class="stat-item">
1718
- <span class="stat-value">${tasks.length}</span>
1719
- <span class="stat-label">Total</span>
1748
+ <span class="stat-value">${items.length}</span>
1749
+ <span class="stat-label">${isSolutionLevel ? 'Solutions' : 'Total'}</span>
1720
1750
  </div>
1721
1751
  <div class="stat-item completed">
1722
- <span class="stat-value">${tasks.filter(t => t.status === 'completed').length}</span>
1752
+ <span class="stat-value">${items.filter(t => t.status === 'completed').length}</span>
1723
1753
  <span class="stat-label">Completed</span>
1724
1754
  </div>
1725
1755
  <div class="stat-item pending">
1726
- <span class="stat-value">${tasks.filter(t => t.status === 'pending').length}</span>
1756
+ <span class="stat-value">${items.filter(t => t.status === 'pending').length}</span>
1727
1757
  <span class="stat-label">Pending</span>
1728
1758
  </div>
1729
1759
  <div class="stat-item failed">
1730
- <span class="stat-value">${tasks.filter(t => t.status === 'failed').length}</span>
1760
+ <span class="stat-value">${items.filter(t => t.status === 'failed').length}</span>
1731
1761
  <span class="stat-label">Failed</span>
1732
1762
  </div>
1733
1763
  </div>
1734
1764
 
1735
1765
  <div class="queue-detail-groups">
1736
- ${Object.entries(grouped).map(([groupId, items]) => `
1766
+ ${Object.entries(grouped).map(([groupId, groupItems]) => `
1737
1767
  <div class="queue-group-section">
1738
1768
  <div class="queue-group-header">
1739
1769
  <i data-lucide="folder" class="w-4 h-4"></i>
1740
1770
  <span>${groupId}</span>
1741
- <span class="text-xs text-muted-foreground">(${items.length} tasks)</span>
1771
+ <span class="text-xs text-muted-foreground">(${groupItems.length} ${itemLabel})</span>
1742
1772
  </div>
1743
1773
  <div class="queue-group-items">
1744
- ${items.map(item => `
1774
+ ${groupItems.map(item => `
1745
1775
  <div class="queue-detail-item ${item.status || ''}">
1746
1776
  <div class="item-main">
1747
- <span class="item-id font-mono text-xs">${item.queue_id || item.task_id || 'N/A'}</span>
1748
- <span class="item-title text-sm">${item.title || item.action || 'Untitled'}</span>
1777
+ <span class="item-id font-mono text-xs">${item.item_id || item.queue_id || item.task_id || 'N/A'}</span>
1778
+ <span class="item-title text-sm">${isSolutionLevel ? (item.task_count + ' tasks') : (item.title || item.action || 'Untitled')}</span>
1749
1779
  </div>
1750
1780
  <div class="item-meta">
1751
1781
  <span class="item-issue text-xs">${item.issue_id || ''}</span>
1782
+ ${isSolutionLevel && item.files_touched ? `<span class="item-files text-xs">${item.files_touched.length} files</span>` : ''}
1752
1783
  <span class="item-status ${item.status || ''}">${item.status || 'unknown'}</span>
1753
1784
  </div>
1754
1785
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-workflow",
3
- "version": "6.3.9",
3
+ "version": "6.3.10",
4
4
  "description": "JSON-driven multi-agent development framework with intelligent CLI orchestration (Gemini/Qwen/Codex), context-first architecture, and automated workflow execution",
5
5
  "type": "module",
6
6
  "main": "ccw/src/index.js",
@@ -1,105 +0,0 @@
1
- ## MCP Tools Usage
2
-
3
- ### search_context (ACE) - Code Search (REQUIRED - HIGHEST PRIORITY)
4
-
5
- **OVERRIDES**: All other search/discovery rules in other workflow files
6
-
7
- **When**: ANY code discovery task, including:
8
- - Find code, understand codebase structure, locate implementations
9
- - Explore unknown locations
10
- - Verify file existence before reading
11
- - Pattern-based file discovery
12
- - Semantic code understanding
13
-
14
- **Priority Rule**:
15
- 1. **Always use mcp__ace-tool__search_context FIRST** for any code/file discovery
16
- 2. Only use Built-in Grep for single-file exact line search (after location confirmed)
17
- 3. Only use Built-in Read for known, confirmed file paths
18
-
19
- **How**:
20
- ```javascript
21
- // Natural language code search - best for understanding and exploration
22
- mcp__ace-tool__search_context({
23
- project_root_path: "/path/to/project",
24
- query: "authentication logic"
25
- })
26
-
27
- // With keywords for better semantic matching
28
- mcp__ace-tool__search_context({
29
- project_root_path: "/path/to/project",
30
- query: "I want to find where the server handles user login. Keywords: auth, login, session"
31
- })
32
- ```
33
-
34
- **Good Query Examples**:
35
- - "Where is the function that handles user authentication?"
36
- - "What tests are there for the login functionality?"
37
- - "How is the database connected to the application?"
38
- - "I want to find where the server handles chunk merging. Keywords: upload chunk merge"
39
- - "Locate where the system refreshes cached data. Keywords: cache refresh, invalidation"
40
-
41
- **Bad Query Examples** (use grep or file view instead):
42
- - "Find definition of constructor of class Foo" (use grep tool instead)
43
- - "Find all references to function bar" (use grep tool instead)
44
- - "Show me how Checkout class is used in services/payment.py" (use file view tool instead)
45
-
46
- **Key Features**:
47
- - Real-time index of the codebase (always up-to-date)
48
- - Cross-language retrieval support
49
- - Semantic search with embeddings
50
- - No manual index initialization required
51
-
52
- ---
53
-
54
- ### read_file - Read File Contents
55
-
56
- **When**: Read files found by search_context
57
-
58
- **How**:
59
- ```javascript
60
- read_file(path="/path/to/file.ts") // Single file
61
- read_file(path="/src/**/*.config.ts") // Pattern matching
62
- ```
63
-
64
- ---
65
-
66
- ### edit_file - Modify Files
67
-
68
- **When**: Built-in Edit tool fails or need advanced features
69
-
70
- **How**:
71
- ```javascript
72
- edit_file(path="/file.ts", old_string="...", new_string="...", mode="update")
73
- edit_file(path="/file.ts", line=10, content="...", mode="insert_after")
74
- ```
75
-
76
- **Modes**: `update` (replace text), `insert_after`, `insert_before`, `delete_line`
77
-
78
- ---
79
-
80
- ### write_file - Create/Overwrite Files
81
-
82
- **When**: Create new files or completely replace content
83
-
84
- **How**:
85
- ```javascript
86
- write_file(path="/new-file.ts", content="...")
87
- ```
88
-
89
- ---
90
-
91
- ### Exa - External Search
92
-
93
- **When**: Find documentation/examples outside codebase
94
-
95
- **How**:
96
- ```javascript
97
- mcp__exa__search(query="React hooks 2025 documentation")
98
- mcp__exa__search(query="FastAPI auth example", numResults=10)
99
- mcp__exa__search(query="latest API docs", livecrawl="always")
100
- ```
101
-
102
- **Parameters**:
103
- - `query` (required): Search query string
104
- - `numResults` (optional): Number of results to return (default: 5)
105
- - `livecrawl` (optional): `"always"` or `"fallback"` for live crawling