sumulige-claude 1.5.1 → 1.5.2

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 (219) hide show
  1. package/.claude/hooks/hook-registry.json +0 -15
  2. package/.claude/rules/coding-style.md +18 -7
  3. package/.claude/rules/hooks.md +15 -4
  4. package/.claude/rules/performance.md +15 -5
  5. package/.claude/rules/security.md +140 -4
  6. package/.claude/rules/testing.md +138 -9
  7. package/.claude/rules/web-design-standard.md +16 -5
  8. package/.claude/skills/algorithmic-art/metadata.yaml +28 -0
  9. package/.claude/skills/api-tester/SKILL.md +61 -0
  10. package/.claude/skills/api-tester/examples/basic.md +3 -0
  11. package/.claude/skills/api-tester/metadata.yaml +30 -0
  12. package/.claude/skills/api-tester/templates/default.md +3 -0
  13. package/.claude/skills/brand-guidelines/metadata.yaml +26 -0
  14. package/.claude/skills/canvas-design/metadata.yaml +27 -0
  15. package/.claude/skills/code-reviewer-123/SKILL.md +61 -0
  16. package/.claude/skills/code-reviewer-123/examples/basic.md +3 -0
  17. package/.claude/skills/code-reviewer-123/metadata.yaml +30 -0
  18. package/.claude/skills/code-reviewer-123/templates/default.md +3 -0
  19. package/.claude/skills/doc-coauthoring/metadata.yaml +27 -0
  20. package/.claude/skills/docx/metadata.yaml +30 -0
  21. package/.claude/skills/frontend-design/metadata.yaml +28 -0
  22. package/.claude/skills/internal-comms/metadata.yaml +28 -0
  23. package/.claude/skills/mcp-builder/metadata.yaml +26 -0
  24. package/.claude/skills/my-skill/SKILL.md +61 -0
  25. package/.claude/skills/my-skill/examples/basic.md +3 -0
  26. package/.claude/skills/my-skill/metadata.yaml +30 -0
  27. package/.claude/skills/my-skill/templates/default.md +3 -0
  28. package/.claude/skills/pdf/metadata.yaml +29 -0
  29. package/.claude/skills/pptx/metadata.yaml +29 -0
  30. package/.claude/skills/react-best-practices/metadata.yaml +26 -0
  31. package/.claude/skills/react-node-practices/SKILL.md +409 -0
  32. package/.claude/skills/react-node-practices/metadata.yaml +56 -0
  33. package/.claude/skills/skill-creator/metadata.yaml +25 -0
  34. package/.claude/skills/slack-gif-creator/metadata.yaml +28 -0
  35. package/.claude/skills/test-skill-name/SKILL.md +61 -0
  36. package/.claude/skills/test-skill-name/examples/basic.md +3 -0
  37. package/.claude/skills/test-skill-name/metadata.yaml +30 -0
  38. package/.claude/skills/test-skill-name/templates/default.md +3 -0
  39. package/.claude/skills/test-workflow/metadata.yaml +32 -0
  40. package/.claude/skills/theme-factory/metadata.yaml +26 -0
  41. package/.claude/skills/threejs-fundamentals/metadata.yaml +27 -0
  42. package/.claude/skills/web-artifacts-builder/metadata.yaml +30 -0
  43. package/.claude/skills/web-design-guidelines/metadata.yaml +26 -0
  44. package/.claude/skills/webapp-testing/metadata.yaml +26 -0
  45. package/.claude/skills/xlsx/metadata.yaml +29 -0
  46. package/LICENSE +21 -0
  47. package/cli.js +1 -1
  48. package/package.json +25 -3
  49. package/.claude/.kickoff-hint.txt +0 -52
  50. package/.claude/.sumulige-claude-version +0 -1
  51. package/.claude/.version +0 -1
  52. package/.claude/AGENTS.md +0 -42
  53. package/.claude/ANCHORS.md +0 -40
  54. package/.claude/CLAUDE.md +0 -138
  55. package/.claude/MEMORY.md +0 -69
  56. package/.claude/PROJECT_LOG.md +0 -101
  57. package/.claude/THINKING_CHAIN_GUIDE.md +0 -287
  58. package/.claude/USAGE.md +0 -175
  59. package/.claude/boris-optimizations.md +0 -167
  60. package/.claude/handoffs/INDEX.md +0 -21
  61. package/.claude/handoffs/LATEST.md +0 -76
  62. package/.claude/handoffs/handoff_2026-01-22T13-07-04-757Z.md +0 -76
  63. package/.claude/quality-gate.json +0 -82
  64. package/.claude/rag/skill-index.json +0 -135
  65. package/.claude/settings.json +0 -99
  66. package/.claude/settings.local.json +0 -175
  67. package/.claude/templates/PROJECT_KICKOFF.md +0 -89
  68. package/.claude/templates/PROJECT_PROPOSAL.md +0 -227
  69. package/.claude/templates/TASK_PLAN.md +0 -121
  70. package/.claude/templates/hooks/README.md +0 -302
  71. package/.claude/templates/hooks/hook.sh.template +0 -94
  72. package/.claude/templates/hooks/user-prompt-submit.cjs.template +0 -116
  73. package/.claude/templates/hooks/user-response-submit.cjs.template +0 -94
  74. package/.claude/templates/hooks/validate.js +0 -173
  75. package/.claude/templates/tasks/develop.md +0 -69
  76. package/.claude/templates/tasks/research.md +0 -64
  77. package/.claude/templates/tasks/test.md +0 -96
  78. package/.claude/thinking-routes/.last-sync +0 -1
  79. package/.claude/thinking-routes/QUICKREF.md +0 -98
  80. package/.claude/workflow/document-scanner.js +0 -426
  81. package/.claude/workflow/knowledge-engine.js +0 -941
  82. package/.claude/workflow/notebooklm/browser.js +0 -1028
  83. package/.claude/workflow/phases/phase1-research.js +0 -578
  84. package/.claude/workflow/phases/phase1-research.ts +0 -465
  85. package/.claude/workflow/phases/phase2-approve.js +0 -722
  86. package/.claude/workflow/phases/phase3-plan.js +0 -1200
  87. package/.claude/workflow/phases/phase4-develop.js +0 -894
  88. package/.claude/workflow/search-cache.js +0 -230
  89. package/.claude/workflow/templates/approval.md +0 -315
  90. package/.claude/workflow/templates/development.md +0 -377
  91. package/.claude/workflow/templates/planning.md +0 -328
  92. package/.claude/workflow/templates/research.md +0 -250
  93. package/.claude/workflow/types.js +0 -37
  94. package/.claude/workflow/web-search.js +0 -278
  95. package/.claude-plugin/marketplace.json +0 -71
  96. package/.github/workflows/sync-skills.yml +0 -74
  97. package/.versionrc +0 -25
  98. package/AGENTS.md +0 -580
  99. package/CHANGELOG.md +0 -481
  100. package/CLAUDE-template.md +0 -114
  101. package/DEV_TOOLS_GUIDE.md +0 -190
  102. package/PROJECT_STRUCTURE.md +0 -266
  103. package/Q&A.md +0 -325
  104. package/config/defaults.json +0 -34
  105. package/config/official-skills.json +0 -183
  106. package/config/quality-gate.json +0 -67
  107. package/config/skill-categories.json +0 -40
  108. package/config/version-manifest.json +0 -85
  109. package/demos/power-3d-scatter.html +0 -683
  110. package/development/cache/web-search/search_1193d605f8eb364651fc2f2041b58a31.json +0 -36
  111. package/development/cache/web-search/search_3798bf06960edc125f744a1abb5b72c5.json +0 -36
  112. package/development/cache/web-search/search_37c7d4843a53f0d83f1122a6f908a2a3.json +0 -36
  113. package/development/cache/web-search/search_44166fa0153709ee168485a22aa0ab40.json +0 -36
  114. package/development/cache/web-search/search_4deaebb1f77e86a8ca066dc5a49c59fd.json +0 -36
  115. package/development/cache/web-search/search_94da91789466070a7f545612e73c7372.json +0 -36
  116. package/development/cache/web-search/search_dd5de8491b8b803a3cb01339cd210fb0.json +0 -36
  117. package/development/knowledge-base/.index.clean.json +0 -1
  118. package/development/knowledge-base/.index.json +0 -486
  119. package/development/knowledge-base/test-best-practices.md +0 -29
  120. package/development/projects/proj_mkh1pazz_ixmt1/phase1/feasibility-report.md +0 -160
  121. package/development/projects/proj_mkh4jvnb_z7rwf/phase1/feasibility-report.md +0 -160
  122. package/development/projects/proj_mkh4jxkd_ewz5a/phase1/feasibility-report.md +0 -160
  123. package/development/projects/proj_mkh4k84n_ni73k/phase1/feasibility-report.md +0 -160
  124. package/development/projects/proj_mkh4wfyd_u9w88/phase1/feasibility-report.md +0 -160
  125. package/development/projects/proj_mkh4wsbo_iahvf/development/projects/proj_mkh4xbpg_4na5w/phase1/feasibility-report.md +0 -160
  126. package/development/projects/proj_mkh4wsbo_iahvf/phase1/feasibility-report.md +0 -160
  127. package/development/projects/proj_mkh4xulg_1ka8x/phase1/feasibility-report.md +0 -160
  128. package/development/projects/proj_mkh4xwhj_gch8j/phase1/feasibility-report.md +0 -160
  129. package/development/projects/proj_mkh4y2qk_9lm8z/phase1/feasibility-report.md +0 -160
  130. package/development/projects/proj_mkh4y2qk_9lm8z/phase2/requirements.md +0 -226
  131. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/PRD.md +0 -345
  132. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/TASK_PLAN.md +0 -284
  133. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/prototype/README.md +0 -14
  134. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/DEVELOPMENT_LOG.md +0 -35
  135. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/TASKS.md +0 -34
  136. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/.env.example +0 -5
  137. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/README.md +0 -60
  138. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/package.json +0 -25
  139. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/src/index.js +0 -70
  140. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/src/routes/index.js +0 -48
  141. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/tests/health.test.js +0 -20
  142. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/tests/jest.config.js +0 -21
  143. package/development/projects/proj_mkh7veqg_3lypc/phase1/feasibility-report.md +0 -160
  144. package/development/projects/proj_mkh7veqg_3lypc/phase2/requirements.md +0 -226
  145. package/development/projects/proj_mkh7veqg_3lypc/phase3/PRD.md +0 -345
  146. package/development/projects/proj_mkh7veqg_3lypc/phase3/TASK_PLAN.md +0 -284
  147. package/development/projects/proj_mkh7veqg_3lypc/phase3/prototype/README.md +0 -14
  148. package/development/projects/proj_mkh8k8fo_rmqn5/phase1/feasibility-report.md +0 -160
  149. package/development/projects/proj_mkh8xyhy_1vshq/phase1/feasibility-report.md +0 -178
  150. package/development/projects/proj_mkh8zddd_dhamf/phase1/feasibility-report.md +0 -377
  151. package/development/projects/proj_mkh8zddd_dhamf/phase2/requirements.md +0 -442
  152. package/development/projects/proj_mkh8zddd_dhamf/phase3/api-design.md +0 -800
  153. package/development/projects/proj_mkh8zddd_dhamf/phase3/architecture.md +0 -625
  154. package/development/projects/proj_mkh8zddd_dhamf/phase3/data-model.md +0 -830
  155. package/development/projects/proj_mkh8zddd_dhamf/phase3/risks.md +0 -957
  156. package/development/projects/proj_mkh8zddd_dhamf/phase3/wbs.md +0 -381
  157. package/development/todos/.state.json +0 -19
  158. package/development/todos/INDEX.md +0 -63
  159. package/development/todos/active/_README.md +0 -49
  160. package/development/todos/archived/_README.md +0 -11
  161. package/development/todos/backlog/_README.md +0 -11
  162. package/development/todos/backlog/mcp-integration.md +0 -35
  163. package/development/todos/completed/_README.md +0 -11
  164. package/development/todos/completed/boris-optimizations.md +0 -39
  165. package/development/todos/completed/develop/local-knowledge-index.md +0 -85
  166. package/development/todos/completed/develop/todo-system.md +0 -47
  167. package/development/todos/completed/develop/web-search-integration.md +0 -83
  168. package/development/todos/completed/test/phase1-e2e-test.md +0 -103
  169. package/docs/DEVELOPMENT.md +0 -461
  170. package/docs/MARKETPLACE.md +0 -352
  171. package/docs/RELEASE.md +0 -93
  172. package/jest.config.js +0 -63
  173. package/lib/commands.js +0 -3588
  174. package/lib/config-manager.js +0 -441
  175. package/lib/config-schema.js +0 -408
  176. package/lib/config-validator.js +0 -330
  177. package/lib/config.js +0 -122
  178. package/lib/errors.js +0 -305
  179. package/lib/incremental-sync.js +0 -274
  180. package/lib/marketplace.js +0 -487
  181. package/lib/migrations.js +0 -154
  182. package/lib/permission-audit.js +0 -255
  183. package/lib/quality-gate.js +0 -431
  184. package/lib/quality-rules.js +0 -373
  185. package/lib/utils.js +0 -150
  186. package/lib/version-check.js +0 -169
  187. package/lib/version-manifest.js +0 -171
  188. package/project-paradigm.md +0 -313
  189. package/prompts/how-to-find.md +0 -163
  190. package/prompts/linus-architect.md +0 -71
  191. package/prompts/software-architect.md +0 -173
  192. package/prompts/web-designer.md +0 -249
  193. package/scripts/fix-hooks.mjs +0 -97
  194. package/scripts/sync-external.mjs +0 -298
  195. package/scripts/sync-to-home.sh +0 -108
  196. package/scripts/update-registry.mjs +0 -325
  197. package/sources.yaml +0 -83
  198. package/tests/README.md +0 -263
  199. package/tests/commands.test.js +0 -1086
  200. package/tests/config-manager.test.js +0 -677
  201. package/tests/config-schema.test.js +0 -425
  202. package/tests/config-validator.test.js +0 -436
  203. package/tests/config.test.js +0 -100
  204. package/tests/errors.test.js +0 -477
  205. package/tests/manual/phase1-e2e.sh +0 -389
  206. package/tests/manual/phase2-test-cases.md +0 -311
  207. package/tests/manual/phase3-test-cases.md +0 -309
  208. package/tests/manual/phase4-test-cases.md +0 -414
  209. package/tests/manual/test-cases.md +0 -417
  210. package/tests/marketplace.test.js +0 -420
  211. package/tests/migrations.test.js +0 -187
  212. package/tests/quality-gate.test.js +0 -679
  213. package/tests/quality-rules.test.js +0 -619
  214. package/tests/sync-external.test.js +0 -214
  215. package/tests/update-registry.test.js +0 -251
  216. package/tests/utils.test.js +0 -171
  217. package/tests/version-check.test.js +0 -75
  218. package/tests/web-search.test.js +0 -392
  219. package/thinkinglens-silent.md +0 -138
@@ -1,487 +0,0 @@
1
- /**
2
- * Marketplace Commands
3
- *
4
- * Commands for managing the skill marketplace and external skill sources.
5
- */
6
-
7
- const fs = require('fs');
8
- const path = require('path');
9
- const { execSync } = require('child_process');
10
-
11
- const ROOT_DIR = path.join(__dirname, '..');
12
- const SOURCES_FILE = path.join(ROOT_DIR, 'sources.yaml');
13
- const MARKETPLACE_FILE = path.join(ROOT_DIR, '.claude-plugin', 'marketplace.json');
14
- const CATEGORIES_FILE = path.join(ROOT_DIR, 'config', 'skill-categories.json');
15
- const TEMPLATE_SKILLS_DIR = path.join(ROOT_DIR, 'template', '.claude', 'skills');
16
-
17
- // ============================================================================
18
- // Logging Utilities
19
- // ============================================================================
20
-
21
- const COLORS = {
22
- reset: '\x1b[0m',
23
- green: '\x1b[32m',
24
- blue: '\x1b[34m',
25
- yellow: '\x1b[33m',
26
- red: '\x1b[31m',
27
- cyan: '\x1b[36m',
28
- gray: '\x1b[90m',
29
- magenta: '\x1b[35m'
30
- };
31
-
32
- function log(message, color = 'reset') {
33
- console.log(`${COLORS[color]}${message}${COLORS.reset}`);
34
- }
35
-
36
- // ============================================================================
37
- // YAML Parser (Simple)
38
- // ============================================================================
39
-
40
- function parseSimpleYaml(content) {
41
- const result = { skills: [] };
42
- let currentSection = null;
43
- let currentSkill = null;
44
- let currentKey = null;
45
-
46
- content.split('\n').forEach(line => {
47
- const trimmed = line.trim();
48
- const indent = line.search(/\S/);
49
-
50
- // Skip empty lines and comments
51
- if (!trimmed || trimmed.startsWith('#')) {
52
- return;
53
- }
54
-
55
- // Version
56
- if (trimmed.startsWith('version:')) {
57
- result.version = parseInt(trimmed.split(':')[1].trim());
58
- return;
59
- }
60
-
61
- // Skills array starts
62
- if (trimmed === 'skills:') {
63
- currentSection = 'skills';
64
- return;
65
- }
66
-
67
- // New skill entry (starts with -)
68
- if (trimmed.startsWith('- name:')) {
69
- if (currentSkill) {
70
- result.skills.push(currentSkill);
71
- }
72
- currentSkill = { name: trimmed.split(':')[1].trim() };
73
- return;
74
- }
75
-
76
- // Skill properties
77
- if (currentSection === 'skills' && currentSkill) {
78
- // Determine nesting level by indent
79
- const isTopLevel = indent === 2;
80
-
81
- if (isTopLevel) {
82
- const match = trimmed.match(/^([\w-]+):\s*(.*)$/);
83
- if (match) {
84
- currentKey = match[1];
85
- let value = match[2].trim();
86
-
87
- // Handle arrays
88
- if (value === '[]') {
89
- value = [];
90
- } else if (value === 'true') {
91
- value = true;
92
- } else if (value === 'false') {
93
- value = false;
94
- } else if (value.startsWith('"') || value.startsWith("'")) {
95
- value = value.slice(1, -1);
96
- }
97
-
98
- currentSkill[currentKey] = value;
99
-
100
- // Initialize nested objects
101
- if (['source', 'target', 'author', 'sync'].includes(currentKey)) {
102
- currentSkill[currentKey] = {};
103
- }
104
- }
105
- } else if (currentKey) {
106
- // Nested property
107
- const match = trimmed.match(/^([\w-]+):\s*(.*)$/);
108
- if (match) {
109
- let value = match[2].trim();
110
- if (value === 'true') value = true;
111
- if (value === 'false') value = false;
112
- if (value === '[]') value = [];
113
- currentSkill[currentKey][match[1]] = value;
114
- }
115
- }
116
- }
117
- });
118
-
119
- // Push last skill
120
- if (currentSkill) {
121
- result.skills.push(currentSkill);
122
- }
123
-
124
- return result;
125
- }
126
-
127
- // ============================================================================
128
- // Marketplace Commands
129
- // ============================================================================
130
-
131
- const marketplaceCommands = {
132
- // -------------------------------------------------------------------------
133
- 'marketplace:list': () => {
134
- log('📋 SMC Skill Marketplace', 'blue');
135
- log('=====================================', 'gray');
136
- log('');
137
-
138
- // Load marketplace registry
139
- let registry = { plugins: [], metadata: { skill_count: 0, categories: {} } };
140
- if (fs.existsSync(MARKETPLACE_FILE)) {
141
- try {
142
- registry = JSON.parse(fs.readFileSync(MARKETPLACE_FILE, 'utf-8'));
143
- } catch (e) {
144
- log('Warning: Failed to parse marketplace.json', 'yellow');
145
- }
146
- }
147
-
148
- // Load sources.yaml
149
- let sources = { skills: [] };
150
- if (fs.existsSync(SOURCES_FILE)) {
151
- try {
152
- const content = fs.readFileSync(SOURCES_FILE, 'utf-8');
153
- sources = parseSimpleYaml(content);
154
- } catch (e) {
155
- log('Warning: Failed to parse sources.yaml', 'yellow');
156
- }
157
- }
158
-
159
- // Display by category
160
- const categories = registry.metadata.categories || {
161
- tools: { name: 'CLI 工具', icon: '🔧' },
162
- workflow: { name: '工作流编排', icon: '🎼' },
163
- development: { name: '开发辅助', icon: '💻' },
164
- productivity: { name: '效率工具', icon: '⚡' },
165
- automation: { name: '自动化', icon: '🤖' },
166
- data: { name: '数据处理', icon: '📊' },
167
- documentation: { name: '文档', icon: '📚' }
168
- };
169
-
170
- // Group skills by category
171
- const byCategory = {};
172
- for (const [key, cat] of Object.entries(categories)) {
173
- byCategory[key] = [];
174
- }
175
-
176
- // Add from registry
177
- for (const plugin of registry.plugins) {
178
- if (plugin.skill_list) {
179
- for (const skill of plugin.skill_list) {
180
- if (byCategory[skill.category]) {
181
- byCategory[skill.category].push({
182
- name: skill.name,
183
- description: skill.description,
184
- external: skill.external
185
- });
186
- }
187
- }
188
- }
189
- }
190
-
191
- // Add from sources.yaml
192
- for (const skill of sources.skills) {
193
- const cat = skill.target?.category || 'tools';
194
- if (!byCategory[cat]) {
195
- byCategory[cat] = [];
196
- }
197
- if (!byCategory[cat].some(s => s.name === skill.name)) {
198
- byCategory[cat].push({
199
- name: skill.name,
200
- description: skill.description,
201
- native: skill.native
202
- });
203
- }
204
- }
205
-
206
- // Display
207
- for (const [key, skills] of Object.entries(byCategory)) {
208
- if (skills.length === 0) continue;
209
-
210
- const cat = categories[key] || { name: key, icon: '📁' };
211
- log(`${cat.icon} ${cat.name}`, 'cyan');
212
- log('', 'gray');
213
-
214
- for (const skill of skills) {
215
- const badge = skill.native ? ' [native]' : skill.external ? ' [external]' : '';
216
- log(` ${skill.name}${badge}`, 'green');
217
- if (skill.description) {
218
- log(` ${skill.description}`, 'gray');
219
- }
220
- }
221
- log('', 'gray');
222
- }
223
-
224
- log('=====================================', 'gray');
225
- log(`Total: ${registry.metadata.skill_count || sources.skills.length} skills`, 'gray');
226
- log('', 'gray');
227
- log('Commands:', 'gray');
228
- log(' smc marketplace:install <name> Install a skill', 'gray');
229
- log(' smc marketplace:sync Sync external skills', 'gray');
230
- log(' smc marketplace:add <repo> Add external source', 'gray');
231
- },
232
-
233
- // -------------------------------------------------------------------------
234
- 'marketplace:install': (skillName) => {
235
- if (!skillName) {
236
- log('Usage: smc marketplace:install <skill-name>', 'yellow');
237
- log('', 'gray');
238
- log('Examples:', 'gray');
239
- log(' smc marketplace:install dev-browser', 'gray');
240
- log(' smc marketplace:install gastown', 'gray');
241
- return;
242
- }
243
-
244
- log(`📦 Installing skill: ${skillName}`, 'blue');
245
- log('', 'gray');
246
-
247
- // Load sources.yaml to find the skill
248
- let sources = { skills: [] };
249
- if (fs.existsSync(SOURCES_FILE)) {
250
- try {
251
- const content = fs.readFileSync(SOURCES_FILE, 'utf-8');
252
- sources = parseSimpleYaml(content);
253
- } catch (e) {
254
- log('Warning: Failed to parse sources.yaml', 'yellow');
255
- }
256
- }
257
-
258
- const skill = sources.skills.find(s => s.name === skillName);
259
- if (!skill) {
260
- log(`Skill "${skillName}" not found in sources.yaml`, 'yellow');
261
- log('', 'gray');
262
- log('Available skills:', 'gray');
263
- log(' smc marketplace:list', 'gray');
264
- return;
265
- }
266
-
267
- // Native skills are already in the repo
268
- if (skill.native) {
269
- log(`✅ Skill "${skillName}" is a native skill, already available at:`, 'green');
270
- log(` ${skill.target.path}`, 'gray');
271
- return;
272
- }
273
-
274
- // External skills - sync them
275
- log(`Syncing from external source...`, 'gray');
276
-
277
- try {
278
- execSync('npm run sync', { stdio: 'inherit' });
279
- log(``, 'gray');
280
- log(`✅ Skill "${skillName}" installed`, 'green');
281
- } catch (e) {
282
- log(`❌ Failed to install skill`, 'red');
283
- }
284
- },
285
-
286
- // -------------------------------------------------------------------------
287
- 'marketplace:sync': () => {
288
- log('🔄 Syncing external skills...', 'blue');
289
- log('', 'gray');
290
-
291
- try {
292
- execSync('npm run sync:all', { stdio: 'inherit' });
293
- log('', 'gray');
294
- log('✅ Sync complete', 'green');
295
- } catch (e) {
296
- log('❌ Sync failed', 'red');
297
- }
298
- },
299
-
300
- // -------------------------------------------------------------------------
301
- 'marketplace:add': (repo) => {
302
- if (!repo) {
303
- log('Usage: smc marketplace:add <owner/repo>', 'yellow');
304
- log('', 'gray');
305
- log('This command adds an external skill repository to sources.yaml', 'gray');
306
- log('', 'gray');
307
- log('Example:', 'gray');
308
- log(' smc marketplace:add SawyerHood/dev-browser', 'gray');
309
- return;
310
- }
311
-
312
- // Parse repo
313
- const match = repo.match(/^([^/]+)\/(.+)$/);
314
- if (!match) {
315
- log('Invalid repo format. Use: owner/repo', 'red');
316
- return;
317
- }
318
-
319
- const [, owner, name] = match;
320
- const skillName = name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
321
-
322
- log(`📝 Adding skill source: ${repo}`, 'blue');
323
- log('', 'gray');
324
-
325
- // Check sources.yaml exists
326
- if (!fs.existsSync(SOURCES_FILE)) {
327
- log(`sources.yaml not found. Creating...`, 'yellow');
328
- fs.writeFileSync(SOURCES_FILE, `version: 1\nskills:\n`);
329
- }
330
-
331
- // Read existing sources
332
- const content = fs.readFileSync(SOURCES_FILE, 'utf-8');
333
- const lines = content.split('\n');
334
-
335
- // Check if skill already exists
336
- if (lines.some(l => l.includes(`name: ${skillName}`))) {
337
- log(`Skill "${skillName}" already exists in sources.yaml`, 'yellow');
338
- return;
339
- }
340
-
341
- // Find where to insert (after existing skills or before # Comments)
342
- let insertIndex = lines.length;
343
- for (let i = 0; i < lines.length; i++) {
344
- if (lines[i].trim().startsWith('#') && lines[i].includes('Schema')) {
345
- insertIndex = i;
346
- break;
347
- }
348
- }
349
-
350
- // Build new skill entry
351
- const newEntry = `
352
- # ─────────────────────────────────────────────────────────────────────────────
353
- # ${skillName} - External skill from ${repo}
354
- # ─────────────────────────────────────────────────────────────────────────────
355
- - name: ${skillName}
356
- description: "TODO: Add description for ${skillName}"
357
- source:
358
- repo: ${repo}
359
- path: skills/${skillName}
360
- ref: main
361
- target:
362
- category: tools
363
- path: template/.claude/skills/tools/${skillName}
364
- author:
365
- name: ${owner}
366
- github: ${owner}
367
- license: MIT
368
- homepage: https://github.com/${repo}
369
- verified: false
370
- `;
371
-
372
- // Insert new entry
373
- lines.splice(insertIndex, 0, newEntry.trim());
374
-
375
- // Write back
376
- fs.writeFileSync(SOURCES_FILE, lines.join('\n'));
377
-
378
- log(`✅ Added "${skillName}" to sources.yaml`, 'green');
379
- log('', 'gray');
380
- log('Next steps:', 'gray');
381
- log(` 1. Edit sources.yaml to update description and category`, 'gray');
382
- log(` 2. Run: smc marketplace:sync`, 'gray');
383
- },
384
-
385
- // -------------------------------------------------------------------------
386
- 'marketplace:remove': (skillName) => {
387
- if (!skillName) {
388
- log('Usage: smc marketplace:remove <skill-name>', 'yellow');
389
- return;
390
- }
391
-
392
- log(`🗑️ Removing skill: ${skillName}`, 'blue');
393
- log('', 'gray');
394
-
395
- // Read sources.yaml
396
- if (!fs.existsSync(SOURCES_FILE)) {
397
- log('sources.yaml not found', 'yellow');
398
- return;
399
- }
400
-
401
- const content = fs.readFileSync(SOURCES_FILE, 'utf-8');
402
- const lines = content.split('\n');
403
-
404
- // Find and remove the skill entry
405
- let inSkillEntry = false;
406
- let removed = false;
407
- const newLines = [];
408
-
409
- for (let i = 0; i < lines.length; i++) {
410
- const line = lines[i];
411
-
412
- // Check if this is the skill to remove
413
- if (line.includes(`name: ${skillName}`) && line.trim().startsWith('-')) {
414
- inSkillEntry = true;
415
- removed = true;
416
- continue;
417
- }
418
-
419
- // Skip lines while in the skill entry
420
- if (inSkillEntry) {
421
- // End of skill entry
422
- if (line.trim().startsWith('- name:') || line.trim().startsWith('#')) {
423
- inSkillEntry = false;
424
- newLines.push(line);
425
- }
426
- continue;
427
- }
428
-
429
- newLines.push(line);
430
- }
431
-
432
- if (!removed) {
433
- log(`Skill "${skillName}" not found in sources.yaml`, 'yellow');
434
- return;
435
- }
436
-
437
- // Write back
438
- fs.writeFileSync(SOURCES_FILE, newLines.join('\n'));
439
-
440
- log(`✅ Removed "${skillName}" from sources.yaml`, 'green');
441
- log('', 'gray');
442
- log('Note: The skill files remain in the template directory.', 'yellow');
443
- log(' To remove them, delete:', 'yellow');
444
- log(` template/.claude/skills/*/${skillName}`, 'gray');
445
- },
446
-
447
- // -------------------------------------------------------------------------
448
- 'marketplace:status': () => {
449
- log('📊 Marketplace Status', 'blue');
450
- log('=====================================', 'gray');
451
- log('');
452
-
453
- // Check marketplace.json
454
- if (fs.existsSync(MARKETPLACE_FILE)) {
455
- const registry = JSON.parse(fs.readFileSync(MARKETPLACE_FILE, 'utf-8'));
456
- log(`Registry: ${MARKETPLACE_FILE}`, 'green');
457
- log(`Version: ${registry.metadata.version}`, 'gray');
458
- log(`Skills: ${registry.metadata.skill_count}`, 'gray');
459
- log(`Updated: ${registry.metadata.generated_at}`, 'gray');
460
- } else {
461
- log(`Registry: Not found (run: smc marketplace:sync)`, 'yellow');
462
- }
463
-
464
- log('');
465
-
466
- // Check sources.yaml
467
- if (fs.existsSync(SOURCES_FILE)) {
468
- const content = fs.readFileSync(SOURCES_FILE, 'utf-8');
469
- const sources = parseSimpleYaml(content);
470
- log(`Sources: ${SOURCES_FILE}`, 'green');
471
- log(`External sources: ${sources.skills.filter(s => !s.native).length}`, 'gray');
472
- log(`Native skills: ${sources.skills.filter(s => s.native).length}`, 'gray');
473
- } else {
474
- log(`Sources: Not found`, 'yellow');
475
- }
476
-
477
- log('');
478
- log('=====================================', 'gray');
479
- }
480
- };
481
-
482
- // ============================================================================
483
- // Exports
484
- // ============================================================================
485
-
486
- exports.marketplaceCommands = marketplaceCommands;
487
- exports.parseSimpleYaml = parseSimpleYaml;
package/lib/migrations.js DELETED
@@ -1,154 +0,0 @@
1
- /**
2
- * Migrations - Version control for project templates
3
- *
4
- * 每个迁移函数:
5
- * - from: 起始版本
6
- * - to: 目标版本
7
- * - migrate: 实际迁移逻辑
8
- *
9
- * 迁移链:v1.0.0 → v1.0.2 → v1.0.10 → ...
10
- */
11
-
12
- const fs = require('fs');
13
- const path = require('path');
14
-
15
- // 当前模板版本
16
- const TEMPLATE_VERSION = '1.0.10';
17
-
18
- // 版本文件路径
19
- const getVersionFile = (projectDir) => path.join(projectDir, '.claude', '.version');
20
-
21
- // 读取项目版本
22
- function getProjectVersion(projectDir) {
23
- const versionFile = getVersionFile(projectDir);
24
- if (!fs.existsSync(versionFile)) {
25
- // 没有 version 文件说明是旧版本项目
26
- return '1.0.0';
27
- }
28
- try {
29
- return fs.readFileSync(versionFile, 'utf-8').trim();
30
- } catch {
31
- return '1.0.0';
32
- }
33
- }
34
-
35
- // 写入项目版本
36
- function setProjectVersion(projectDir, version) {
37
- const versionFile = getVersionFile(projectDir);
38
- fs.writeFileSync(versionFile, version + '\n');
39
- }
40
-
41
- // 版本比较
42
- function compareVersions(v1, v2) {
43
- const parts1 = v1.split('.').map(Number);
44
- const parts2 = v2.split('.').map(Number);
45
-
46
- for (let i = 0; i < 3; i++) {
47
- if (parts1[i] < parts2[i]) return -1;
48
- if (parts1[i] > parts2[i]) return 1;
49
- }
50
- return 0;
51
- }
52
-
53
- // 迁移列表
54
- const migrations = [
55
- {
56
- from: '1.0.0',
57
- to: '1.0.10',
58
- description: 'Migrate hooks format from old to new',
59
- migrate: (projectDir) => {
60
- const settingsFile = path.join(projectDir, '.claude', 'settings.json');
61
- if (!fs.existsSync(settingsFile)) return;
62
-
63
- let settings;
64
- try {
65
- settings = JSON.parse(fs.readFileSync(settingsFile, 'utf-8'));
66
- } catch {
67
- return; // 无效 JSON,跳过
68
- }
69
-
70
- // 检测旧格式
71
- const isOldFormat = settings.matcher || (settings.hooks && typeof settings.hooks === 'object');
72
- if (!isOldFormat) return;
73
-
74
- // 读取新模板
75
- const templateDir = path.join(__dirname, '../template');
76
- const templateSettings = path.join(templateDir, '.claude', 'settings.json');
77
-
78
- if (fs.existsSync(templateSettings)) {
79
- fs.writeFileSync(settingsFile, fs.readFileSync(templateSettings, 'utf-8'));
80
- }
81
- }
82
- }
83
- ];
84
-
85
- /**
86
- * 执行迁移
87
- * @param {string} projectDir - 项目目录
88
- * @param {boolean} silent - 是否静默模式
89
- * @returns {object} { success, migrations, currentVersion }
90
- */
91
- function runMigrations(projectDir, silent = false) {
92
- const currentVersion = getProjectVersion(projectDir);
93
-
94
- // 已经是最新版本
95
- if (compareVersions(currentVersion, TEMPLATE_VERSION) >= 0) {
96
- return {
97
- success: true,
98
- migrations: [],
99
- currentVersion,
100
- templateVersion: TEMPLATE_VERSION
101
- };
102
- }
103
-
104
- // 找到需要执行的迁移
105
- const pendingMigrations = migrations.filter(m => {
106
- const cmp = compareVersions(currentVersion, m.to);
107
- return cmp < 0; // 只执行版本高于当前版本的迁移
108
- });
109
-
110
- // 按版本顺序执行
111
- pendingMigrations.sort((a, b) => compareVersions(a.to, b.to));
112
-
113
- const executed = [];
114
-
115
- for (const migration of pendingMigrations) {
116
- try {
117
- if (!silent) {
118
- console.log(`⬆️ Migrating: ${currentVersion} → ${migration.to}`);
119
- console.log(` ${migration.description}`);
120
- }
121
- migration.migrate(projectDir);
122
- executed.push(migration);
123
- setProjectVersion(projectDir, migration.to);
124
- if (!silent) {
125
- console.log(` ✅ Done`);
126
- }
127
- } catch (error) {
128
- if (!silent) {
129
- console.log(` ❌ Failed: ${error.message}`);
130
- }
131
- return {
132
- success: false,
133
- error: error.message,
134
- currentVersion,
135
- executed
136
- };
137
- }
138
- }
139
-
140
- return {
141
- success: true,
142
- migrations: executed,
143
- currentVersion: TEMPLATE_VERSION,
144
- templateVersion: TEMPLATE_VERSION
145
- };
146
- }
147
-
148
- module.exports = {
149
- TEMPLATE_VERSION,
150
- getProjectVersion,
151
- setProjectVersion,
152
- compareVersions,
153
- runMigrations
154
- };