claude-code-workflow 6.3.48 → 6.3.49

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 (211) hide show
  1. package/.claude/CLAUDE.md +6 -8
  2. package/.claude/agents/action-planning-agent.md +28 -45
  3. package/.claude/agents/cli-lite-planning-agent.md +93 -1
  4. package/.claude/agents/code-developer.md +144 -27
  5. package/.claude/commands/ccw-coordinator.md +175 -21
  6. package/.claude/commands/ccw-debug.md +832 -0
  7. package/.claude/commands/ccw.md +90 -9
  8. package/.claude/commands/cli/cli-init.md +1 -0
  9. package/.claude/commands/issue/convert-to-plan.md +718 -0
  10. package/.claude/commands/issue/from-brainstorm.md +382 -0
  11. package/.claude/commands/memory/tips.md +332 -0
  12. package/.claude/commands/workflow/analyze-with-file.md +804 -0
  13. package/.claude/commands/workflow/brainstorm/auto-parallel.md +18 -43
  14. package/.claude/commands/workflow/brainstorm/role-analysis.md +705 -0
  15. package/.claude/commands/workflow/brainstorm-with-file.md +1153 -0
  16. package/.claude/commands/workflow/debug-with-file.md +7 -5
  17. package/.claude/commands/workflow/execute.md +6 -4
  18. package/.claude/commands/workflow/lite-plan.md +2 -2
  19. package/.claude/commands/workflow/plan-verify.md +162 -327
  20. package/.claude/commands/workflow/plan.md +162 -26
  21. package/.claude/commands/workflow/replan.md +78 -2
  22. package/.claude/commands/workflow/{review-fix.md → review-cycle-fix.md} +6 -6
  23. package/.claude/commands/workflow/review-module-cycle.md +2 -2
  24. package/.claude/commands/workflow/review-session-cycle.md +2 -2
  25. package/.claude/commands/workflow/tools/conflict-resolution.md +16 -26
  26. package/.claude/commands/workflow/tools/context-gather.md +81 -118
  27. package/.claude/commands/workflow/tools/task-generate-agent.md +94 -10
  28. package/.claude/skills/ccw-help/command.json +4 -4
  29. package/.claude/skills/lite-skill-generator/SKILL.md +650 -0
  30. package/.claude/skills/lite-skill-generator/templates/simple-skill.md +68 -0
  31. package/.claude/skills/lite-skill-generator/templates/style-guide.md +64 -0
  32. package/.claude/skills/skill-generator/SKILL.md +277 -85
  33. package/.claude/skills/skill-generator/phases/01-requirements-discovery.md +4 -15
  34. package/.claude/skills/skill-generator/phases/02-structure-generation.md +72 -17
  35. package/.claude/skills/skill-generator/phases/03-phase-generation.md +218 -51
  36. package/.claude/skills/skill-generator/phases/04-specs-templates.md +111 -41
  37. package/.claude/skills/skill-generator/phases/05-validation.md +139 -56
  38. package/.claude/skills/skill-generator/templates/autonomous-action.md +78 -268
  39. package/.claude/skills/skill-generator/templates/autonomous-orchestrator.md +14 -0
  40. package/.claude/skills/skill-generator/templates/code-analysis-action.md +12 -0
  41. package/.claude/skills/skill-generator/templates/llm-action.md +12 -0
  42. package/.claude/skills/skill-generator/templates/script-template.md +368 -0
  43. package/.claude/skills/skill-generator/templates/sequential-phase.md +14 -0
  44. package/.claude/skills/skill-generator/templates/skill-md.md +14 -0
  45. package/.claude/skills/skill-tuning/SKILL.md +130 -266
  46. package/.claude/skills/skill-tuning/phases/orchestrator.md +95 -283
  47. package/.claude/skills/skill-tuning/specs/problem-taxonomy.md +90 -198
  48. package/.claude/skills/skill-tuning/specs/tuning-strategies.md +193 -1345
  49. package/.claude/workflows/cli-templates/schemas/plan-verify-agent-schema.json +47 -0
  50. package/.claude/workflows/cli-templates/schemas/verify-json-schema.json +158 -0
  51. package/.claude/workflows/cli-tools-usage.md +1 -1
  52. package/.codex/AGENTS.md +1 -3
  53. package/.codex/prompts/analyze-with-file.md +607 -0
  54. package/.codex/prompts/brainstorm-to-cycle.md +455 -0
  55. package/.codex/prompts/brainstorm-with-file.md +933 -0
  56. package/.codex/prompts/debug-with-file.md +15 -20
  57. package/.codex/skills/ccw-cli-tools/SKILL.md +559 -0
  58. package/ccw/dist/commands/cli.d.ts.map +1 -1
  59. package/ccw/dist/commands/cli.js +29 -5
  60. package/ccw/dist/commands/cli.js.map +1 -1
  61. package/ccw/dist/commands/issue.d.ts +2 -0
  62. package/ccw/dist/commands/issue.d.ts.map +1 -1
  63. package/ccw/dist/commands/issue.js +62 -20
  64. package/ccw/dist/commands/issue.js.map +1 -1
  65. package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -1
  66. package/ccw/dist/config/litellm-api-config-manager.js +5 -3
  67. package/ccw/dist/config/litellm-api-config-manager.js.map +1 -1
  68. package/ccw/dist/config/litellm-provider-models.d.ts +73 -0
  69. package/ccw/dist/config/litellm-provider-models.d.ts.map +1 -0
  70. package/ccw/dist/config/litellm-provider-models.js +172 -0
  71. package/ccw/dist/config/litellm-provider-models.js.map +1 -0
  72. package/ccw/dist/config/provider-models.d.ts +25 -51
  73. package/ccw/dist/config/provider-models.d.ts.map +1 -1
  74. package/ccw/dist/config/provider-models.js +84 -149
  75. package/ccw/dist/config/provider-models.js.map +1 -1
  76. package/ccw/dist/config/storage-paths.d.ts.map +1 -1
  77. package/ccw/dist/config/storage-paths.js +23 -5
  78. package/ccw/dist/config/storage-paths.js.map +1 -1
  79. package/ccw/dist/core/auth/csrf-middleware.js +3 -3
  80. package/ccw/dist/core/auth/csrf-middleware.js.map +1 -1
  81. package/ccw/dist/core/dashboard-generator.d.ts.map +1 -1
  82. package/ccw/dist/core/dashboard-generator.js +3 -1
  83. package/ccw/dist/core/dashboard-generator.js.map +1 -1
  84. package/ccw/dist/core/routes/claude-routes.d.ts.map +1 -1
  85. package/ccw/dist/core/routes/claude-routes.js +206 -14
  86. package/ccw/dist/core/routes/claude-routes.js.map +1 -1
  87. package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
  88. package/ccw/dist/core/routes/cli-routes.js.map +1 -1
  89. package/ccw/dist/core/routes/commands-routes.d.ts +7 -0
  90. package/ccw/dist/core/routes/commands-routes.d.ts.map +1 -0
  91. package/ccw/dist/core/routes/commands-routes.js +480 -0
  92. package/ccw/dist/core/routes/commands-routes.js.map +1 -0
  93. package/ccw/dist/core/routes/model-routes.d.ts +11 -0
  94. package/ccw/dist/core/routes/model-routes.d.ts.map +1 -0
  95. package/ccw/dist/core/routes/model-routes.js +112 -0
  96. package/ccw/dist/core/routes/model-routes.js.map +1 -0
  97. package/ccw/dist/core/routes/nav-status-routes.d.ts.map +1 -1
  98. package/ccw/dist/core/routes/nav-status-routes.js +84 -1
  99. package/ccw/dist/core/routes/nav-status-routes.js.map +1 -1
  100. package/ccw/dist/core/routes/provider-routes.d.ts +11 -0
  101. package/ccw/dist/core/routes/provider-routes.d.ts.map +1 -0
  102. package/ccw/dist/core/routes/provider-routes.js +67 -0
  103. package/ccw/dist/core/routes/provider-routes.js.map +1 -0
  104. package/ccw/dist/core/routes/skills-routes.d.ts.map +1 -1
  105. package/ccw/dist/core/routes/skills-routes.js +219 -7
  106. package/ccw/dist/core/routes/skills-routes.js.map +1 -1
  107. package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
  108. package/ccw/dist/core/routes/system-routes.js +58 -6
  109. package/ccw/dist/core/routes/system-routes.js.map +1 -1
  110. package/ccw/dist/core/server.d.ts.map +1 -1
  111. package/ccw/dist/core/server.js +13 -0
  112. package/ccw/dist/core/server.js.map +1 -1
  113. package/ccw/dist/mcp-server/index.js +2 -2
  114. package/ccw/dist/mcp-server/index.js.map +1 -1
  115. package/ccw/dist/tools/claude-cli-tools.d.ts +48 -11
  116. package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
  117. package/ccw/dist/tools/claude-cli-tools.js +146 -50
  118. package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
  119. package/ccw/dist/tools/cli-config-manager.d.ts +1 -13
  120. package/ccw/dist/tools/cli-config-manager.d.ts.map +1 -1
  121. package/ccw/dist/tools/cli-config-manager.js +3 -27
  122. package/ccw/dist/tools/cli-config-manager.js.map +1 -1
  123. package/ccw/dist/tools/cli-executor-core.d.ts.map +1 -1
  124. package/ccw/dist/tools/cli-executor-core.js +7 -2
  125. package/ccw/dist/tools/cli-executor-core.js.map +1 -1
  126. package/ccw/dist/tools/cli-executor-state.d.ts.map +1 -1
  127. package/ccw/dist/tools/cli-history-store.d.ts +11 -0
  128. package/ccw/dist/tools/cli-history-store.d.ts.map +1 -1
  129. package/ccw/dist/tools/cli-history-store.js +82 -2
  130. package/ccw/dist/tools/cli-history-store.js.map +1 -1
  131. package/ccw/dist/tools/command-registry.d.ts +7 -0
  132. package/ccw/dist/tools/command-registry.d.ts.map +1 -1
  133. package/ccw/dist/tools/command-registry.js +14 -1
  134. package/ccw/dist/tools/command-registry.js.map +1 -1
  135. package/ccw/dist/tools/generate-module-docs.d.ts.map +1 -1
  136. package/ccw/dist/tools/generate-module-docs.js +11 -7
  137. package/ccw/dist/tools/generate-module-docs.js.map +1 -1
  138. package/ccw/dist/tools/litellm-executor.d.ts +1 -0
  139. package/ccw/dist/tools/litellm-executor.d.ts.map +1 -1
  140. package/ccw/dist/tools/litellm-executor.js +11 -9
  141. package/ccw/dist/tools/litellm-executor.js.map +1 -1
  142. package/ccw/dist/types/skill-types.d.ts +97 -0
  143. package/ccw/dist/types/skill-types.d.ts.map +1 -0
  144. package/ccw/dist/types/skill-types.js +6 -0
  145. package/ccw/dist/types/skill-types.js.map +1 -0
  146. package/ccw/src/commands/cli.ts +36 -5
  147. package/ccw/src/commands/issue.ts +81 -26
  148. package/ccw/src/config/litellm-api-config-manager.ts +5 -3
  149. package/ccw/src/config/litellm-provider-models.ts +222 -0
  150. package/ccw/src/config/provider-models.ts +91 -190
  151. package/ccw/src/config/storage-paths.ts +20 -5
  152. package/ccw/src/core/auth/csrf-middleware.ts +3 -3
  153. package/ccw/src/core/dashboard-generator.ts +3 -1
  154. package/ccw/src/core/routes/claude-routes.ts +233 -15
  155. package/ccw/src/core/routes/cli-routes.ts +2 -3
  156. package/ccw/src/core/routes/commands-routes.ts +620 -0
  157. package/ccw/src/core/routes/nav-status-routes.ts +95 -1
  158. package/ccw/src/core/routes/provider-routes.ts +78 -0
  159. package/ccw/src/core/routes/skills-routes.ts +266 -45
  160. package/ccw/src/core/routes/system-routes.ts +102 -50
  161. package/ccw/src/core/server.ts +13 -0
  162. package/ccw/src/mcp-server/index.ts +2 -2
  163. package/ccw/src/templates/dashboard-css/18-cli-settings.css +35 -0
  164. package/ccw/src/templates/dashboard-css/37-commands.css +193 -0
  165. package/ccw/src/templates/dashboard-js/components/navigation.js +4 -0
  166. package/ccw/src/templates/dashboard-js/i18n.js +116 -0
  167. package/ccw/src/templates/dashboard-js/views/cli-manager.js +249 -4
  168. package/ccw/src/templates/dashboard-js/views/commands-manager.js +503 -0
  169. package/ccw/src/templates/dashboard-js/views/issue-manager.js +7 -7
  170. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2 -7
  171. package/ccw/src/templates/dashboard-js/views/skills-manager.js +164 -23
  172. package/ccw/src/templates/dashboard.html +7 -0
  173. package/ccw/src/tools/claude-cli-tools.ts +170 -56
  174. package/ccw/src/tools/cli-config-manager.ts +2 -33
  175. package/ccw/src/tools/cli-executor-core.ts +8 -2
  176. package/ccw/src/tools/cli-history-store.ts +92 -2
  177. package/ccw/src/tools/command-registry.ts +16 -1
  178. package/ccw/src/tools/generate-module-docs.ts +11 -7
  179. package/ccw/src/tools/litellm-executor.ts +13 -9
  180. package/ccw/src/types/skill-types.ts +99 -0
  181. package/package.json +1 -1
  182. package/.claude/commands/enhance-prompt.md +0 -93
  183. package/.claude/commands/memory/code-map-memory.md +0 -687
  184. package/.claude/commands/memory/docs.md +0 -615
  185. package/.claude/commands/memory/load-skill-memory.md +0 -182
  186. package/.claude/commands/memory/skill-memory.md +0 -525
  187. package/.claude/commands/memory/swagger-docs.md +0 -773
  188. package/.claude/commands/memory/tech-research-rules.md +0 -310
  189. package/.claude/commands/memory/workflow-skill-memory.md +0 -517
  190. package/.claude/commands/task/breakdown.md +0 -208
  191. package/.claude/commands/task/create.md +0 -152
  192. package/.claude/commands/task/execute.md +0 -270
  193. package/.claude/commands/task/replan.md +0 -441
  194. package/.claude/commands/version.md +0 -254
  195. package/.claude/commands/workflow/action-plan-verify.md +0 -485
  196. package/.claude/commands/workflow/brainstorm/api-designer.md +0 -587
  197. package/.claude/commands/workflow/brainstorm/data-architect.md +0 -220
  198. package/.claude/commands/workflow/brainstorm/product-manager.md +0 -200
  199. package/.claude/commands/workflow/brainstorm/product-owner.md +0 -200
  200. package/.claude/commands/workflow/brainstorm/scrum-master.md +0 -200
  201. package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +0 -200
  202. package/.claude/commands/workflow/brainstorm/system-architect.md +0 -389
  203. package/.claude/commands/workflow/brainstorm/ui-designer.md +0 -221
  204. package/.claude/commands/workflow/brainstorm/ux-expert.md +0 -221
  205. package/.claude/commands/workflow/debug.md +0 -331
  206. package/.claude/commands/workflow/develop-with-file.md +0 -1044
  207. package/.claude/skills/ccw-loop/README.md +0 -303
  208. package/.claude/skills/skill-generator/templates/script-bash.md +0 -277
  209. package/.claude/skills/skill-generator/templates/script-python.md +0 -198
  210. package/.codex/prompts/debug.md +0 -318
  211. package/ccw/src/core/routes/mcp-routes.ts.backup +0 -549
@@ -0,0 +1,503 @@
1
+ // Commands Manager View
2
+ // Manages Claude Code commands (.claude/commands/)
3
+
4
+ // ========== Commands State ==========
5
+ var commandsData = {
6
+ groups: {}, // Organized by group name: { cli: [...], workflow: [...], memory: [...], task: [...], issue: [...] }
7
+ allCommands: [],
8
+ projectGroupsConfig: { groups: {}, assignments: {} },
9
+ userGroupsConfig: { groups: {}, assignments: {} }
10
+ };
11
+ var expandedGroups = {
12
+ cli: true,
13
+ workflow: true,
14
+ memory: true,
15
+ task: true,
16
+ issue: true
17
+ };
18
+ var showDisabledCommands = false;
19
+ var commandsLoading = false;
20
+ var currentLocation = 'project'; // 'project' or 'user'
21
+
22
+ // ========== Main Render Function ==========
23
+ async function renderCommandsManager() {
24
+ const container = document.getElementById('mainContent');
25
+ if (!container) return;
26
+
27
+ // Hide stats grid and search
28
+ const statsGrid = document.getElementById('statsGrid');
29
+ const searchInput = document.getElementById('searchInput');
30
+ if (statsGrid) statsGrid.style.display = 'none';
31
+ if (searchInput) searchInput.parentElement.style.display = 'none';
32
+
33
+ // Show loading state
34
+ container.innerHTML = '<div class="commands-manager loading">' +
35
+ '<div class="loading-spinner"><i data-lucide="loader-2" class="w-8 h-8 animate-spin"></i></div>' +
36
+ '<p>' + t('common.loading') + '</p>' +
37
+ '</div>';
38
+
39
+ // Load commands data
40
+ await loadCommandsData();
41
+
42
+ // Render the main view
43
+ renderCommandsView();
44
+ }
45
+
46
+ async function loadCommandsData() {
47
+ commandsLoading = true;
48
+ try {
49
+ const response = await fetch('/api/commands?path=' + encodeURIComponent(projectPath));
50
+ if (!response.ok) throw new Error('Failed to load commands');
51
+ const data = await response.json();
52
+
53
+ // Store groups config
54
+ commandsData.projectGroupsConfig = data.projectGroupsConfig || { groups: {}, assignments: {} };
55
+ commandsData.userGroupsConfig = data.userGroupsConfig || { groups: {}, assignments: {} };
56
+
57
+ // Filter commands based on currentLocation
58
+ const allCommands = currentLocation === 'project'
59
+ ? (data.projectCommands || [])
60
+ : (data.userCommands || []);
61
+
62
+ // Organize commands by group
63
+ commandsData.groups = {};
64
+ commandsData.allCommands = allCommands;
65
+
66
+ allCommands.forEach(cmd => {
67
+ const group = cmd.group || 'other';
68
+ if (!commandsData.groups[group]) {
69
+ commandsData.groups[group] = [];
70
+ }
71
+ commandsData.groups[group].push(cmd);
72
+ });
73
+
74
+ // Update badge
75
+ updateCommandsBadge();
76
+ } catch (err) {
77
+ console.error('Failed to load commands:', err);
78
+ commandsData = {
79
+ groups: {},
80
+ allCommands: [],
81
+ projectGroupsConfig: { groups: {}, assignments: {} },
82
+ userGroupsConfig: { groups: {}, assignments: {} }
83
+ };
84
+ } finally {
85
+ commandsLoading = false;
86
+ }
87
+ }
88
+
89
+ function updateCommandsBadge() {
90
+ const badge = document.getElementById('badgeCommands');
91
+ if (badge) {
92
+ const enabledCount = commandsData.allCommands.filter(cmd => cmd.enabled).length;
93
+ badge.textContent = enabledCount;
94
+ }
95
+ }
96
+
97
+ async function switchLocation(location) {
98
+ if (location === currentLocation) return;
99
+ currentLocation = location;
100
+ await loadCommandsData();
101
+ renderCommandsView();
102
+ }
103
+
104
+ function renderCommandsView() {
105
+ const container = document.getElementById('mainContent');
106
+ if (!container) return;
107
+
108
+ const groups = commandsData.groups || {};
109
+
110
+ // Dynamic groups: known groups first, then custom groups hierarchically sorted, 'other' last
111
+ const knownOrder = ['cli', 'workflow', 'memory', 'task', 'issue'];
112
+ const allGroupNames = Object.keys(groups);
113
+
114
+ // Separate top-level known groups and nested groups
115
+ const topLevelKnown = allGroupNames.filter(g => knownOrder.includes(g));
116
+ const nestedAndCustom = allGroupNames.filter(g => g !== 'other' && !knownOrder.includes(g));
117
+
118
+ // Sort nested/custom groups hierarchically
119
+ nestedAndCustom.sort((a, b) => {
120
+ // Split by path separator
121
+ const aParts = a.split('/');
122
+ const bParts = b.split('/');
123
+
124
+ // Compare level by level
125
+ for (let i = 0; i < Math.min(aParts.length, bParts.length); i++) {
126
+ if (aParts[i] !== bParts[i]) {
127
+ return aParts[i].localeCompare(bParts[i]);
128
+ }
129
+ }
130
+
131
+ // If all parts are equal, shorter path comes first
132
+ return aParts.length - bParts.length;
133
+ });
134
+
135
+ const groupNames = [...topLevelKnown.filter(g => groups[g] && groups[g].length > 0),
136
+ ...nestedAndCustom.filter(g => groups[g] && groups[g].length > 0),
137
+ 'other'].filter(g => groups[g] && groups[g].length > 0);
138
+ const totalEnabled = commandsData.allCommands.filter(cmd => cmd.enabled).length;
139
+ const totalDisabled = commandsData.allCommands.filter(cmd => !cmd.enabled).length;
140
+
141
+ container.innerHTML = `
142
+ <div class="commands-manager">
143
+ <!-- Header -->
144
+ <div class="commands-header mb-6">
145
+ <div class="flex items-center justify-between">
146
+ <div class="flex items-center gap-3">
147
+ <div class="w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center">
148
+ <i data-lucide="terminal" class="w-5 h-5 text-primary"></i>
149
+ </div>
150
+ <div>
151
+ <h2 class="text-lg font-semibold text-foreground">${t('commands.title') || 'Commands Manager'}</h2>
152
+ <p class="text-sm text-muted-foreground">${t('commands.description') || 'Enable/disable CCW commands'}</p>
153
+ </div>
154
+ </div>
155
+ <div class="flex items-center gap-2">
156
+ <!-- Location Switcher -->
157
+ <div class="inline-flex bg-muted rounded-lg p-1">
158
+ <button class="px-3 py-1.5 text-sm rounded-md transition-all ${currentLocation === 'project' ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}"
159
+ onclick="switchLocation('project')">
160
+ <i data-lucide="folder" class="w-3.5 h-3.5 inline mr-1"></i>
161
+ ${t('commands.locationProject') || 'Project'}
162
+ </button>
163
+ <button class="px-3 py-1.5 text-sm rounded-md transition-all ${currentLocation === 'user' ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}"
164
+ onclick="switchLocation('user')">
165
+ <i data-lucide="user" class="w-3.5 h-3.5 inline mr-1"></i>
166
+ ${t('commands.locationUser') || 'Global'}
167
+ </button>
168
+ </div>
169
+ <!-- Show Disabled Toggle -->
170
+ <button class="px-4 py-2 text-sm ${showDisabledCommands ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'} rounded-lg hover:opacity-90 transition-opacity flex items-center gap-2"
171
+ onclick="toggleShowDisabledCommands()">
172
+ <i data-lucide="${showDisabledCommands ? 'eye' : 'eye-off'}" class="w-4 h-4"></i>
173
+ ${showDisabledCommands ? (t('commands.hideDisabled') || 'Hide Disabled') : (t('commands.showDisabled') || 'Show Disabled')} (${totalDisabled})
174
+ </button>
175
+ </div>
176
+ </div>
177
+ </div>
178
+
179
+ <!-- Summary Stats -->
180
+ <div class="commands-stats mb-6">
181
+ <div class="grid grid-cols-3 gap-4">
182
+ <div class="bg-card border border-border rounded-lg p-4">
183
+ <div class="text-2xl font-bold text-foreground">${commandsData.allCommands.length}</div>
184
+ <div class="text-sm text-muted-foreground">${t('commands.totalCommands') || 'Total Commands'}</div>
185
+ </div>
186
+ <div class="bg-card border border-border rounded-lg p-4">
187
+ <div class="text-2xl font-bold text-success">${totalEnabled}</div>
188
+ <div class="text-sm text-muted-foreground">${t('commands.enabledCommands') || 'Enabled'}</div>
189
+ </div>
190
+ <div class="bg-card border border-border rounded-lg p-4">
191
+ <div class="text-2xl font-bold text-muted-foreground">${totalDisabled}</div>
192
+ <div class="text-sm text-muted-foreground">${t('commands.disabledCommands') || 'Disabled'}</div>
193
+ </div>
194
+ </div>
195
+ </div>
196
+
197
+ <!-- Accordion Groups -->
198
+ <div class="commands-accordion">
199
+ ${groupNames.map(groupName => renderAccordionGroup(groupName, groups[groupName])).join('')}
200
+ </div>
201
+ </div>
202
+ `;
203
+
204
+ // Initialize Lucide icons
205
+ if (typeof lucide !== 'undefined') lucide.createIcons();
206
+ }
207
+
208
+ // Format group name for display (e.g., 'workflow/review' -> 'Workflow > Review')
209
+ function formatGroupName(groupName) {
210
+ if (!groupName.includes('/')) {
211
+ return t('commands.group.' + groupName) || groupName;
212
+ }
213
+
214
+ // Split path and translate each part
215
+ const parts = groupName.split('/');
216
+ const translatedParts = parts.map(part => t('commands.group.' + part) || part);
217
+ return translatedParts.join(' › ');
218
+ }
219
+
220
+ // Get icon for a group (use top-level parent's icon for nested groups)
221
+ function getGroupIcon(groupName) {
222
+ const groupIcons = {
223
+ cli: 'terminal',
224
+ workflow: 'git-branch',
225
+ memory: 'brain',
226
+ task: 'clipboard-list',
227
+ issue: 'alert-circle',
228
+ other: 'folder'
229
+ };
230
+
231
+ // For nested groups, use the top-level parent's icon
232
+ const topLevel = groupName.split('/')[0];
233
+ return groupIcons[topLevel] || 'folder';
234
+ }
235
+
236
+ // Get color for a group (use top-level parent's color for nested groups)
237
+ function getGroupColor(groupName) {
238
+ const groupColors = {
239
+ cli: 'text-primary bg-primary/10',
240
+ workflow: 'text-success bg-success/10',
241
+ memory: 'text-indigo bg-indigo/10',
242
+ task: 'text-warning bg-warning/10',
243
+ issue: 'text-destructive bg-destructive/10',
244
+ other: 'text-muted-foreground bg-muted'
245
+ };
246
+
247
+ // For nested groups, use the top-level parent's color
248
+ const topLevel = groupName.split('/')[0];
249
+ return groupColors[topLevel] || 'text-muted-foreground bg-muted';
250
+ }
251
+
252
+ function renderAccordionGroup(groupName, commands) {
253
+ // Default to expanded for new/custom groups
254
+ if (expandedGroups[groupName] === undefined) expandedGroups[groupName] = true;
255
+ const isExpanded = expandedGroups[groupName];
256
+ const enabledCommands = commands.filter(cmd => cmd.enabled);
257
+ const disabledCommands = commands.filter(cmd => !cmd.enabled);
258
+
259
+ // Filter commands based on showDisabledCommands
260
+ const visibleCommands = showDisabledCommands
261
+ ? commands
262
+ : enabledCommands;
263
+
264
+ const icon = getGroupIcon(groupName);
265
+ const colorClass = getGroupColor(groupName);
266
+ const displayName = formatGroupName(groupName);
267
+ const indentLevel = (groupName.match(/\//g) || []).length;
268
+ const indentStyle = indentLevel > 0 ? `style="margin-left: ${indentLevel * 20}px;"` : '';
269
+
270
+ return `
271
+ <div class="accordion-group mb-4" ${indentStyle}>
272
+ <!-- Group Header -->
273
+ <div class="accordion-header flex items-center justify-between px-4 py-3 bg-card border border-border rounded-lg hover:bg-hover transition-colors">
274
+ <div class="flex items-center gap-3 flex-1 cursor-pointer" onclick="toggleAccordionGroup('${groupName}')">
275
+ <i data-lucide="${isExpanded ? 'chevron-down' : 'chevron-right'}" class="w-5 h-5 text-muted-foreground transition-transform"></i>
276
+ <div class="w-8 h-8 ${colorClass} rounded-lg flex items-center justify-center">
277
+ <i data-lucide="${icon}" class="w-4 h-4"></i>
278
+ </div>
279
+ <div>
280
+ <h3 class="text-base font-semibold text-foreground">${displayName}</h3>
281
+ <p class="text-xs text-muted-foreground">${enabledCommands.length}/${commands.length} ${t('commands.enabled') || 'enabled'}</p>
282
+ </div>
283
+ </div>
284
+ <div class="flex items-center gap-3">
285
+ <!-- Group Toggle Switch -->
286
+ <label class="group-toggle-switch relative inline-flex items-center cursor-pointer" title="${enabledCommands.length === commands.length ? (t('commands.clickToDisableAll') || 'Click to disable all') : (t('commands.clickToEnableAll') || 'Click to enable all')}">
287
+ <input type="checkbox"
288
+ class="sr-only peer"
289
+ ${enabledCommands.length === commands.length ? 'checked' : ''}
290
+ onchange="toggleGroupEnabled('${groupName}', ${enabledCommands.length === commands.length})">
291
+ <div class="w-11 h-6 bg-muted peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-success"></div>
292
+ </label>
293
+ <span class="text-xs px-2 py-1 bg-muted rounded-full text-muted-foreground">${commands.length}</span>
294
+ </div>
295
+ </div>
296
+
297
+ <!-- Group Content (Compact Table) -->
298
+ ${isExpanded ? `
299
+ <div class="accordion-content mt-3">
300
+ <div class="bg-card border border-border rounded-lg overflow-hidden">
301
+ <table class="w-full commands-table" style="table-layout: fixed;">
302
+ <colgroup>
303
+ <col style="width: 200px;">
304
+ <col style="width: auto;">
305
+ <col style="width: 100px;">
306
+ <col style="width: 80px;">
307
+ </colgroup>
308
+ <thead class="bg-muted/30 border-b border-border">
309
+ <tr>
310
+ <th class="px-4 py-2 text-left text-xs font-medium text-muted-foreground uppercase">${t('commands.name') || 'Name'}</th>
311
+ <th class="px-4 py-2 text-left text-xs font-medium text-muted-foreground uppercase">${t('commands.description') || 'Description'}</th>
312
+ <th class="px-4 py-2 text-center text-xs font-medium text-muted-foreground uppercase">${t('commands.scope') || 'Scope'}</th>
313
+ <th class="px-4 py-2 text-center text-xs font-medium text-muted-foreground uppercase">${t('commands.status') || 'Status'}</th>
314
+ </tr>
315
+ </thead>
316
+ <tbody class="divide-y divide-border">
317
+ ${visibleCommands.map(cmd => renderCommandRow(cmd)).join('')}
318
+ </tbody>
319
+ </table>
320
+ </div>
321
+ </div>
322
+ ` : ''}
323
+ </div>
324
+ `;
325
+ }
326
+
327
+ function renderCommandRow(command) {
328
+ const isDisabled = !command.enabled;
329
+
330
+ return `
331
+ <tr class="hover:bg-muted/20 transition-colors ${isDisabled ? 'opacity-60' : ''}">
332
+ <td class="px-4 py-3 text-sm font-medium text-foreground">
333
+ <div class="flex items-center gap-2 flex-wrap">
334
+ <span class="break-words">${escapeHtml(command.name)}</span>
335
+ ${command.triggers && command.triggers.length > 0 ? `
336
+ <span class="text-xs px-1.5 py-0.5 bg-warning/10 text-warning rounded flex-shrink-0" title="${command.triggers.length} trigger(s)">
337
+ <i data-lucide="zap" class="w-3 h-3 inline mr-0.5"></i>${command.triggers.length}
338
+ </span>
339
+ ` : ''}
340
+ </div>
341
+ </td>
342
+ <td class="px-4 py-3 text-sm text-muted-foreground">
343
+ <div class="line-clamp-3 break-words">${escapeHtml(command.description || t('commands.noDescription') || '-')}</div>
344
+ </td>
345
+ <td class="px-4 py-3 text-center text-xs text-muted-foreground">
346
+ <span class="whitespace-nowrap">${command.scope || 'project'}</span>
347
+ </td>
348
+ <td class="px-4 py-3">
349
+ <div class="flex justify-center">
350
+ <label class="command-toggle-switch relative inline-flex items-center cursor-pointer">
351
+ <input type="checkbox"
352
+ class="sr-only peer"
353
+ ${command.enabled ? 'checked' : ''}
354
+ onchange="toggleCommandEnabled('${escapeHtml(command.name)}', ${command.enabled})"
355
+ data-command-toggle="${escapeHtml(command.name)}">
356
+ <div class="w-11 h-6 bg-muted peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary"></div>
357
+ </label>
358
+ </div>
359
+ </td>
360
+ </tr>
361
+ `;
362
+ }
363
+
364
+ function getGroupBadgeClass(group) {
365
+ const classes = {
366
+ cli: 'bg-primary/10 text-primary',
367
+ workflow: 'bg-success/10 text-success',
368
+ memory: 'bg-indigo/10 text-indigo',
369
+ task: 'bg-warning/10 text-warning',
370
+ issue: 'bg-destructive/10 text-destructive',
371
+ other: 'bg-muted text-muted-foreground'
372
+ };
373
+ return classes[group] || classes.other;
374
+ }
375
+
376
+ function toggleAccordionGroup(groupName) {
377
+ expandedGroups[groupName] = !expandedGroups[groupName];
378
+ renderCommandsView();
379
+ }
380
+
381
+ function toggleShowDisabledCommands() {
382
+ showDisabledCommands = !showDisabledCommands;
383
+ renderCommandsView();
384
+ }
385
+
386
+ // Track loading state for command toggle operations
387
+ var toggleLoadingCommands = {};
388
+
389
+ async function toggleCommandEnabled(commandName, currentlyEnabled) {
390
+ // Prevent double-click
391
+ var loadingKey = commandName;
392
+ if (toggleLoadingCommands[loadingKey]) return;
393
+
394
+ // Set loading state
395
+ toggleLoadingCommands[loadingKey] = true;
396
+ var toggleInput = document.querySelector('[data-command-toggle="' + commandName + '"]');
397
+ if (toggleInput) {
398
+ toggleInput.disabled = true;
399
+ }
400
+
401
+ try {
402
+ var response = await fetch('/api/commands/' + encodeURIComponent(commandName) + '/toggle', {
403
+ method: 'POST',
404
+ headers: { 'Content-Type': 'application/json' },
405
+ body: JSON.stringify({
406
+ projectPath: projectPath,
407
+ location: currentLocation,
408
+ enable: !currentlyEnabled
409
+ })
410
+ });
411
+
412
+ if (!response.ok) {
413
+ // Robust JSON parsing with fallback
414
+ var errorMessage = 'Operation failed';
415
+ try {
416
+ var error = await response.json();
417
+ errorMessage = error.message || errorMessage;
418
+ } catch (jsonErr) {
419
+ errorMessage = response.statusText || errorMessage;
420
+ }
421
+ throw new Error(errorMessage);
422
+ }
423
+
424
+ // Reload commands data
425
+ await loadCommandsData();
426
+ renderCommandsView();
427
+
428
+ if (window.showToast) {
429
+ var message = currentlyEnabled
430
+ ? t('commands.disableSuccess', { name: commandName }) || `Command "${commandName}" disabled`
431
+ : t('commands.enableSuccess', { name: commandName }) || `Command "${commandName}" enabled`;
432
+ showToast(message, 'success');
433
+ }
434
+ } catch (err) {
435
+ console.error('Failed to toggle command:', err);
436
+ if (window.showToast) {
437
+ showToast(err.message || t('commands.toggleError') || 'Failed to toggle command', 'error');
438
+ }
439
+ // Reset toggle state on error
440
+ if (toggleInput) {
441
+ toggleInput.checked = currentlyEnabled;
442
+ }
443
+ } finally {
444
+ // Clear loading state
445
+ delete toggleLoadingCommands[loadingKey];
446
+ if (toggleInput) {
447
+ toggleInput.disabled = false;
448
+ }
449
+ }
450
+ }
451
+
452
+ async function toggleGroupEnabled(groupName, currentlyAllEnabled) {
453
+ const enable = !currentlyAllEnabled;
454
+
455
+ try {
456
+ const response = await fetch('/api/commands/group/' + encodeURIComponent(groupName) + '/toggle', {
457
+ method: 'POST',
458
+ headers: { 'Content-Type': 'application/json' },
459
+ body: JSON.stringify({
460
+ projectPath: projectPath,
461
+ location: currentLocation,
462
+ enable: enable
463
+ })
464
+ });
465
+
466
+ if (!response.ok) {
467
+ var errorMessage = 'Operation failed';
468
+ try {
469
+ var error = await response.json();
470
+ errorMessage = error.message || errorMessage;
471
+ } catch (jsonErr) {
472
+ errorMessage = response.statusText || errorMessage;
473
+ }
474
+ throw new Error(errorMessage);
475
+ }
476
+
477
+ // Reload commands data
478
+ await loadCommandsData();
479
+ renderCommandsView();
480
+
481
+ if (window.showToast) {
482
+ const groupLabel = t('commands.group.' + groupName) || groupName;
483
+ const message = enable
484
+ ? (t('commands.enableGroupSuccess', { group: groupLabel }) || `Group "${groupLabel}" enabled`)
485
+ : (t('commands.disableGroupSuccess', { group: groupLabel }) || `Group "${groupLabel}" disabled`);
486
+ showToast(message, 'success');
487
+ }
488
+ } catch (err) {
489
+ console.error('Failed to toggle group:', err);
490
+ if (window.showToast) {
491
+ showToast(err.message || t('commands.toggleError') || 'Failed to toggle group', 'error');
492
+ }
493
+ }
494
+ }
495
+
496
+ function formatDisabledDate(isoString) {
497
+ try {
498
+ const date = new Date(isoString);
499
+ return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
500
+ } catch {
501
+ return isoString;
502
+ }
503
+ }
@@ -702,7 +702,7 @@ function renderQueueCard(queue, isActive) {
702
702
  const completedCount = queue.completed_solutions || queue.completed_tasks || 0;
703
703
  const progressPercent = itemCount > 0 ? Math.round((completedCount / itemCount) * 100) : 0;
704
704
  const issueCount = queue.issue_ids?.length || 0;
705
- const statusClass = queue.status === 'merged' ? 'merged' : queue.status || '';
705
+ const statusClass = queue.status || '';
706
706
  const safeQueueId = escapeHtml(queue.id || '');
707
707
 
708
708
  return `
@@ -740,17 +740,17 @@ function renderQueueCard(queue, isActive) {
740
740
  <button class="btn-sm" onclick="toggleQueueExpand('${safeQueueId}')" title="View details">
741
741
  <i data-lucide="eye" class="w-3 h-3"></i>
742
742
  </button>
743
- ${!isActive && queue.status !== 'merged' ? `
743
+ ${!isActive && queue.status !== 'archived' ? `
744
744
  <button class="btn-sm btn-primary" onclick="activateQueue('${safeQueueId}')" title="Set as active">
745
745
  <i data-lucide="check-circle" class="w-3 h-3"></i>
746
746
  </button>
747
747
  ` : ''}
748
- ${queue.status !== 'merged' ? `
748
+ ${queue.status !== 'archived' ? `
749
749
  <button class="btn-sm" onclick="showMergeQueueModal('${safeQueueId}')" title="Merge into another queue">
750
750
  <i data-lucide="git-merge" class="w-3 h-3"></i>
751
751
  </button>
752
752
  ` : ''}
753
- ${queue.status !== 'merged' && issueCount > 1 ? `
753
+ ${queue.status !== 'archived' && issueCount > 1 ? `
754
754
  <button class="btn-sm" onclick="showSplitQueueModal('${safeQueueId}')" title="Split queue into multiple queues">
755
755
  <i data-lucide="git-branch" class="w-3 h-3"></i>
756
756
  </button>
@@ -896,7 +896,7 @@ async function renderExpandedQueueView(queueId) {
896
896
  </div>
897
897
  </div>
898
898
  <div class="queue-detail-actions">
899
- ${!isActive && queue.status !== 'merged' ? `
899
+ ${!isActive && queue.status !== 'archived' ? `
900
900
  <button class="btn-primary" onclick="activateQueue('${safeQueueId}')">
901
901
  <i data-lucide="check-circle" class="w-4 h-4"></i>
902
902
  <span>${t('issues.activate') || 'Activate'}</span>
@@ -1141,7 +1141,7 @@ function showMergeQueueModal(sourceQueueId) {
1141
1141
  }
1142
1142
 
1143
1143
  const otherQueues = queueData.queues.filter(q =>
1144
- q.id !== sourceQueueId && q.status !== 'merged'
1144
+ q.id !== sourceQueueId && q.status !== 'archived'
1145
1145
  );
1146
1146
 
1147
1147
  const safeSourceId = escapeHtml(sourceQueueId || '');
@@ -1170,7 +1170,7 @@ function showMergeQueueModal(sourceQueueId) {
1170
1170
  </div>
1171
1171
  <p class="text-sm text-muted-foreground mt-2">
1172
1172
  <i data-lucide="info" class="w-4 h-4 inline mr-1"></i>
1173
- Items from source queue will be appended to target queue. Source queue will be marked as "merged".
1173
+ Items from source queue will be appended to target queue. Source queue will be archived.
1174
1174
  </p>
1175
1175
  `}
1176
1176
  </div>
@@ -1,18 +1,13 @@
1
1
  // MCP Manager View
2
2
  // Renders the MCP server management interface
3
3
 
4
- // CCW Tools available for MCP
4
+ // CCW Tools available for MCP (file operations + core memory only)
5
5
  const CCW_MCP_TOOLS = [
6
6
  // Core tools (always recommended)
7
7
  { name: 'write_file', desc: 'Write/create files', core: true },
8
8
  { name: 'edit_file', desc: 'Edit/replace content', core: true },
9
- { name: 'smart_search', desc: 'Hybrid search (regex + semantic)', core: true },
9
+ { name: 'read_file', desc: 'Read file contents', core: true },
10
10
  { name: 'core_memory', desc: 'Core memory management', core: true },
11
- // Optional tools
12
- { name: 'session_manager', desc: 'Workflow sessions', core: false },
13
- { name: 'generate_module_docs', desc: 'Generate docs', core: false },
14
- { name: 'update_module_claude', desc: 'Update CLAUDE.md', core: false },
15
- { name: 'cli_executor', desc: 'Gemini/Qwen/Codex CLI', core: false },
16
11
  ];
17
12
 
18
13
  // Get currently enabled tools from installed config (Claude)