sumulige-claude 1.5.1 → 1.6.0

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 (223) 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/README.md +280 -529
  48. package/cli.js +19 -3
  49. package/package.json +29 -3
  50. package/template/.codex/README.md +69 -0
  51. package/template/.codex/config.toml +56 -0
  52. package/template/AGENTS.md +94 -0
  53. package/.claude/.kickoff-hint.txt +0 -52
  54. package/.claude/.sumulige-claude-version +0 -1
  55. package/.claude/.version +0 -1
  56. package/.claude/AGENTS.md +0 -42
  57. package/.claude/ANCHORS.md +0 -40
  58. package/.claude/CLAUDE.md +0 -138
  59. package/.claude/MEMORY.md +0 -69
  60. package/.claude/PROJECT_LOG.md +0 -101
  61. package/.claude/THINKING_CHAIN_GUIDE.md +0 -287
  62. package/.claude/USAGE.md +0 -175
  63. package/.claude/boris-optimizations.md +0 -167
  64. package/.claude/handoffs/INDEX.md +0 -21
  65. package/.claude/handoffs/LATEST.md +0 -76
  66. package/.claude/handoffs/handoff_2026-01-22T13-07-04-757Z.md +0 -76
  67. package/.claude/quality-gate.json +0 -82
  68. package/.claude/rag/skill-index.json +0 -135
  69. package/.claude/settings.json +0 -99
  70. package/.claude/settings.local.json +0 -175
  71. package/.claude/templates/PROJECT_KICKOFF.md +0 -89
  72. package/.claude/templates/PROJECT_PROPOSAL.md +0 -227
  73. package/.claude/templates/TASK_PLAN.md +0 -121
  74. package/.claude/templates/hooks/README.md +0 -302
  75. package/.claude/templates/hooks/hook.sh.template +0 -94
  76. package/.claude/templates/hooks/user-prompt-submit.cjs.template +0 -116
  77. package/.claude/templates/hooks/user-response-submit.cjs.template +0 -94
  78. package/.claude/templates/hooks/validate.js +0 -173
  79. package/.claude/templates/tasks/develop.md +0 -69
  80. package/.claude/templates/tasks/research.md +0 -64
  81. package/.claude/templates/tasks/test.md +0 -96
  82. package/.claude/thinking-routes/.last-sync +0 -1
  83. package/.claude/thinking-routes/QUICKREF.md +0 -98
  84. package/.claude/workflow/document-scanner.js +0 -426
  85. package/.claude/workflow/knowledge-engine.js +0 -941
  86. package/.claude/workflow/notebooklm/browser.js +0 -1028
  87. package/.claude/workflow/phases/phase1-research.js +0 -578
  88. package/.claude/workflow/phases/phase1-research.ts +0 -465
  89. package/.claude/workflow/phases/phase2-approve.js +0 -722
  90. package/.claude/workflow/phases/phase3-plan.js +0 -1200
  91. package/.claude/workflow/phases/phase4-develop.js +0 -894
  92. package/.claude/workflow/search-cache.js +0 -230
  93. package/.claude/workflow/templates/approval.md +0 -315
  94. package/.claude/workflow/templates/development.md +0 -377
  95. package/.claude/workflow/templates/planning.md +0 -328
  96. package/.claude/workflow/templates/research.md +0 -250
  97. package/.claude/workflow/types.js +0 -37
  98. package/.claude/workflow/web-search.js +0 -278
  99. package/.claude-plugin/marketplace.json +0 -71
  100. package/.github/workflows/sync-skills.yml +0 -74
  101. package/.versionrc +0 -25
  102. package/AGENTS.md +0 -580
  103. package/CHANGELOG.md +0 -481
  104. package/CLAUDE-template.md +0 -114
  105. package/DEV_TOOLS_GUIDE.md +0 -190
  106. package/PROJECT_STRUCTURE.md +0 -266
  107. package/Q&A.md +0 -325
  108. package/config/defaults.json +0 -34
  109. package/config/official-skills.json +0 -183
  110. package/config/quality-gate.json +0 -67
  111. package/config/skill-categories.json +0 -40
  112. package/config/version-manifest.json +0 -85
  113. package/demos/power-3d-scatter.html +0 -683
  114. package/development/cache/web-search/search_1193d605f8eb364651fc2f2041b58a31.json +0 -36
  115. package/development/cache/web-search/search_3798bf06960edc125f744a1abb5b72c5.json +0 -36
  116. package/development/cache/web-search/search_37c7d4843a53f0d83f1122a6f908a2a3.json +0 -36
  117. package/development/cache/web-search/search_44166fa0153709ee168485a22aa0ab40.json +0 -36
  118. package/development/cache/web-search/search_4deaebb1f77e86a8ca066dc5a49c59fd.json +0 -36
  119. package/development/cache/web-search/search_94da91789466070a7f545612e73c7372.json +0 -36
  120. package/development/cache/web-search/search_dd5de8491b8b803a3cb01339cd210fb0.json +0 -36
  121. package/development/knowledge-base/.index.clean.json +0 -1
  122. package/development/knowledge-base/.index.json +0 -486
  123. package/development/knowledge-base/test-best-practices.md +0 -29
  124. package/development/projects/proj_mkh1pazz_ixmt1/phase1/feasibility-report.md +0 -160
  125. package/development/projects/proj_mkh4jvnb_z7rwf/phase1/feasibility-report.md +0 -160
  126. package/development/projects/proj_mkh4jxkd_ewz5a/phase1/feasibility-report.md +0 -160
  127. package/development/projects/proj_mkh4k84n_ni73k/phase1/feasibility-report.md +0 -160
  128. package/development/projects/proj_mkh4wfyd_u9w88/phase1/feasibility-report.md +0 -160
  129. package/development/projects/proj_mkh4wsbo_iahvf/development/projects/proj_mkh4xbpg_4na5w/phase1/feasibility-report.md +0 -160
  130. package/development/projects/proj_mkh4wsbo_iahvf/phase1/feasibility-report.md +0 -160
  131. package/development/projects/proj_mkh4xulg_1ka8x/phase1/feasibility-report.md +0 -160
  132. package/development/projects/proj_mkh4xwhj_gch8j/phase1/feasibility-report.md +0 -160
  133. package/development/projects/proj_mkh4y2qk_9lm8z/phase1/feasibility-report.md +0 -160
  134. package/development/projects/proj_mkh4y2qk_9lm8z/phase2/requirements.md +0 -226
  135. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/PRD.md +0 -345
  136. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/TASK_PLAN.md +0 -284
  137. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/prototype/README.md +0 -14
  138. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/DEVELOPMENT_LOG.md +0 -35
  139. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/TASKS.md +0 -34
  140. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/.env.example +0 -5
  141. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/README.md +0 -60
  142. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/package.json +0 -25
  143. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/src/index.js +0 -70
  144. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/src/routes/index.js +0 -48
  145. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/tests/health.test.js +0 -20
  146. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/tests/jest.config.js +0 -21
  147. package/development/projects/proj_mkh7veqg_3lypc/phase1/feasibility-report.md +0 -160
  148. package/development/projects/proj_mkh7veqg_3lypc/phase2/requirements.md +0 -226
  149. package/development/projects/proj_mkh7veqg_3lypc/phase3/PRD.md +0 -345
  150. package/development/projects/proj_mkh7veqg_3lypc/phase3/TASK_PLAN.md +0 -284
  151. package/development/projects/proj_mkh7veqg_3lypc/phase3/prototype/README.md +0 -14
  152. package/development/projects/proj_mkh8k8fo_rmqn5/phase1/feasibility-report.md +0 -160
  153. package/development/projects/proj_mkh8xyhy_1vshq/phase1/feasibility-report.md +0 -178
  154. package/development/projects/proj_mkh8zddd_dhamf/phase1/feasibility-report.md +0 -377
  155. package/development/projects/proj_mkh8zddd_dhamf/phase2/requirements.md +0 -442
  156. package/development/projects/proj_mkh8zddd_dhamf/phase3/api-design.md +0 -800
  157. package/development/projects/proj_mkh8zddd_dhamf/phase3/architecture.md +0 -625
  158. package/development/projects/proj_mkh8zddd_dhamf/phase3/data-model.md +0 -830
  159. package/development/projects/proj_mkh8zddd_dhamf/phase3/risks.md +0 -957
  160. package/development/projects/proj_mkh8zddd_dhamf/phase3/wbs.md +0 -381
  161. package/development/todos/.state.json +0 -19
  162. package/development/todos/INDEX.md +0 -63
  163. package/development/todos/active/_README.md +0 -49
  164. package/development/todos/archived/_README.md +0 -11
  165. package/development/todos/backlog/_README.md +0 -11
  166. package/development/todos/backlog/mcp-integration.md +0 -35
  167. package/development/todos/completed/_README.md +0 -11
  168. package/development/todos/completed/boris-optimizations.md +0 -39
  169. package/development/todos/completed/develop/local-knowledge-index.md +0 -85
  170. package/development/todos/completed/develop/todo-system.md +0 -47
  171. package/development/todos/completed/develop/web-search-integration.md +0 -83
  172. package/development/todos/completed/test/phase1-e2e-test.md +0 -103
  173. package/docs/DEVELOPMENT.md +0 -461
  174. package/docs/MARKETPLACE.md +0 -352
  175. package/docs/RELEASE.md +0 -93
  176. package/jest.config.js +0 -63
  177. package/lib/commands.js +0 -3588
  178. package/lib/config-manager.js +0 -441
  179. package/lib/config-schema.js +0 -408
  180. package/lib/config-validator.js +0 -330
  181. package/lib/config.js +0 -122
  182. package/lib/errors.js +0 -305
  183. package/lib/incremental-sync.js +0 -274
  184. package/lib/marketplace.js +0 -487
  185. package/lib/migrations.js +0 -154
  186. package/lib/permission-audit.js +0 -255
  187. package/lib/quality-gate.js +0 -431
  188. package/lib/quality-rules.js +0 -373
  189. package/lib/utils.js +0 -150
  190. package/lib/version-check.js +0 -169
  191. package/lib/version-manifest.js +0 -171
  192. package/project-paradigm.md +0 -313
  193. package/prompts/how-to-find.md +0 -163
  194. package/prompts/linus-architect.md +0 -71
  195. package/prompts/software-architect.md +0 -173
  196. package/prompts/web-designer.md +0 -249
  197. package/scripts/fix-hooks.mjs +0 -97
  198. package/scripts/sync-external.mjs +0 -298
  199. package/scripts/sync-to-home.sh +0 -108
  200. package/scripts/update-registry.mjs +0 -325
  201. package/sources.yaml +0 -83
  202. package/tests/README.md +0 -263
  203. package/tests/commands.test.js +0 -1086
  204. package/tests/config-manager.test.js +0 -677
  205. package/tests/config-schema.test.js +0 -425
  206. package/tests/config-validator.test.js +0 -436
  207. package/tests/config.test.js +0 -100
  208. package/tests/errors.test.js +0 -477
  209. package/tests/manual/phase1-e2e.sh +0 -389
  210. package/tests/manual/phase2-test-cases.md +0 -311
  211. package/tests/manual/phase3-test-cases.md +0 -309
  212. package/tests/manual/phase4-test-cases.md +0 -414
  213. package/tests/manual/test-cases.md +0 -417
  214. package/tests/marketplace.test.js +0 -420
  215. package/tests/migrations.test.js +0 -187
  216. package/tests/quality-gate.test.js +0 -679
  217. package/tests/quality-rules.test.js +0 -619
  218. package/tests/sync-external.test.js +0 -214
  219. package/tests/update-registry.test.js +0 -251
  220. package/tests/utils.test.js +0 -171
  221. package/tests/version-check.test.js +0 -75
  222. package/tests/web-search.test.js +0 -392
  223. 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
- };