sumulige-claude 1.0.6 → 1.0.8

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 (53) hide show
  1. package/.claude/.kickoff-hint.txt +51 -0
  2. package/.claude/ANCHORS.md +40 -0
  3. package/.claude/MEMORY.md +34 -0
  4. package/.claude/PROJECT_LOG.md +101 -0
  5. package/.claude/THINKING_CHAIN_GUIDE.md +287 -0
  6. package/.claude/commands/commit-push-pr.md +59 -0
  7. package/.claude/commands/commit.md +53 -0
  8. package/.claude/commands/pr.md +76 -0
  9. package/.claude/commands/review.md +61 -0
  10. package/.claude/commands/sessions.md +62 -0
  11. package/.claude/commands/skill-create.md +131 -0
  12. package/.claude/commands/test.md +56 -0
  13. package/.claude/commands/todos.md +99 -0
  14. package/.claude/commands/verify-work.md +63 -0
  15. package/.claude/hooks/code-formatter.cjs +187 -0
  16. package/.claude/hooks/code-tracer.cjs +331 -0
  17. package/.claude/hooks/conversation-recorder.cjs +340 -0
  18. package/.claude/hooks/decision-tracker.cjs +398 -0
  19. package/.claude/hooks/export.cjs +329 -0
  20. package/.claude/hooks/multi-session.cjs +181 -0
  21. package/.claude/hooks/privacy-filter.js +224 -0
  22. package/.claude/hooks/project-kickoff.cjs +114 -0
  23. package/.claude/hooks/rag-skill-loader.cjs +159 -0
  24. package/.claude/hooks/session-end.sh +61 -0
  25. package/.claude/hooks/sync-to-log.sh +83 -0
  26. package/.claude/hooks/thinking-silent.cjs +145 -0
  27. package/.claude/hooks/tl-summary.sh +54 -0
  28. package/.claude/hooks/todo-manager.cjs +248 -0
  29. package/.claude/hooks/verify-work.cjs +134 -0
  30. package/.claude/sessions/active-sessions.json +359 -0
  31. package/.claude/settings.local.json +43 -2
  32. package/.claude/thinking-routes/.last-sync +1 -0
  33. package/.claude/thinking-routes/QUICKREF.md +98 -0
  34. package/.claude-plugin/marketplace.json +71 -0
  35. package/.github/workflows/sync-skills.yml +74 -0
  36. package/AGENTS.md +81 -22
  37. package/DEV_TOOLS_GUIDE.md +190 -0
  38. package/PROJECT_STRUCTURE.md +10 -1
  39. package/README.md +142 -708
  40. package/cli.js +116 -822
  41. package/config/defaults.json +34 -0
  42. package/config/skill-categories.json +40 -0
  43. package/development/todos/INDEX.md +14 -58
  44. package/docs/DEVELOPMENT.md +423 -0
  45. package/docs/MARKETPLACE.md +352 -0
  46. package/lib/commands.js +698 -0
  47. package/lib/config.js +71 -0
  48. package/lib/marketplace.js +486 -0
  49. package/lib/utils.js +62 -0
  50. package/package.json +11 -5
  51. package/scripts/sync-external.mjs +298 -0
  52. package/scripts/update-registry.mjs +325 -0
  53. package/sources.yaml +83 -0
@@ -0,0 +1,698 @@
1
+ /**
2
+ * Commands - All CLI command implementations
3
+ *
4
+ * Extracted from cli.js for better organization
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const { execSync } = require('child_process');
10
+ const { loadConfig, CONFIG_DIR, CONFIG_FILE, SKILLS_DIR, ensureDir, saveConfig } = require('./config');
11
+ const { copyRecursive, toTitleCase } = require('./utils');
12
+
13
+ const TEMPLATE_DIR = path.join(__dirname, '../template');
14
+
15
+ // ============================================================================
16
+ // Commands
17
+ // ============================================================================
18
+
19
+ const commands = {
20
+ // -------------------------------------------------------------------------
21
+ init: () => {
22
+ console.log('🚀 Initializing Sumulige Claude...');
23
+
24
+ // Create config directory
25
+ ensureDir(CONFIG_DIR);
26
+
27
+ // Create config file
28
+ if (!fs.existsSync(CONFIG_FILE)) {
29
+ saveConfig(loadConfig());
30
+ console.log('✅ Created config:', CONFIG_FILE);
31
+ } else {
32
+ console.log('ℹ️ Config already exists:', CONFIG_FILE);
33
+ }
34
+
35
+ // Create skills directory
36
+ ensureDir(SKILLS_DIR);
37
+ console.log('✅ Created skills directory:', SKILLS_DIR);
38
+
39
+ // Install openskills if not installed
40
+ try {
41
+ execSync('openskills --version', { stdio: 'ignore' });
42
+ console.log('✅ OpenSkills already installed');
43
+ } catch {
44
+ console.log('📦 Installing OpenSkills...');
45
+ try {
46
+ execSync('npm i -g openskills', { stdio: 'inherit' });
47
+ console.log('✅ OpenSkills installed');
48
+ } catch (e) {
49
+ console.log('⚠️ Failed to install OpenSkills. Run: npm i -g openskills');
50
+ }
51
+ }
52
+
53
+ console.log('');
54
+ console.log('🎉 Sumulige Claude initialized!');
55
+ console.log('');
56
+ console.log('Next steps:');
57
+ console.log(' sumulige-claude sync # Sync to current project');
58
+ console.log(' sumulige-claude agent # Run agent orchestration');
59
+ console.log(' sumulige-claude status # Show configuration');
60
+ },
61
+
62
+ // -------------------------------------------------------------------------
63
+ sync: () => {
64
+ console.log('🔄 Syncing Sumulige Claude to current project...');
65
+
66
+ const projectDir = process.cwd();
67
+ const projectConfigDir = path.join(projectDir, '.claude');
68
+ const agentsFile = path.join(projectConfigDir, 'AGENTS.md');
69
+ const readmeFile = path.join(projectConfigDir, 'README.md');
70
+ const templateReadme = path.join(TEMPLATE_DIR, '.claude', 'README.md');
71
+
72
+ // Create .claude directory
73
+ ensureDir(projectConfigDir);
74
+ console.log('✅ Created .claude directory');
75
+
76
+ // Sync config
77
+ const config = loadConfig();
78
+
79
+ // Generate AGENTS.md
80
+ const agentsMd = generateAgentsMd(config);
81
+ fs.writeFileSync(agentsFile, agentsMd);
82
+ console.log('✅ Created AGENTS.md');
83
+
84
+ // Silently sync README.md if template updated
85
+ if (fs.existsSync(templateReadme)) {
86
+ const templateContent = fs.readFileSync(templateReadme, 'utf-8');
87
+ let needsUpdate = true;
88
+
89
+ if (fs.existsSync(readmeFile)) {
90
+ const existingContent = fs.readFileSync(readmeFile, 'utf-8');
91
+ const templateVersion = templateContent.match(/@version:\s*(\d+\.\d+\.\d+)/)?.[1] || '0.0.0';
92
+ const existingVersion = existingContent.match(/@version:\s*(\d+\.\d+\.\d+)/)?.[1] || '0.0.0';
93
+ needsUpdate = templateVersion !== existingVersion;
94
+ }
95
+
96
+ if (needsUpdate) {
97
+ fs.writeFileSync(readmeFile, templateContent);
98
+ }
99
+ }
100
+
101
+ // Sync todos directory structure
102
+ const todosTemplateDir = path.join(TEMPLATE_DIR, 'development', 'todos');
103
+ const todosProjectDir = path.join(projectDir, 'development', 'todos');
104
+
105
+ if (fs.existsSync(todosTemplateDir)) {
106
+ copyRecursive(todosTemplateDir, todosProjectDir);
107
+ }
108
+
109
+ // Sync skills
110
+ try {
111
+ execSync('openskills sync -y', { stdio: 'pipe' });
112
+ console.log('✅ Synced skills');
113
+ } catch (e) {
114
+ console.log('⚠️ Failed to sync skills');
115
+ }
116
+
117
+ console.log('');
118
+ console.log('✅ Sync complete!');
119
+ },
120
+
121
+ // -------------------------------------------------------------------------
122
+ agent: (task) => {
123
+ if (!task) {
124
+ console.log('Usage: sumulige-claude agent <task>');
125
+ console.log('');
126
+ console.log('Example: sumulige-claude agent "Build a React dashboard"');
127
+ return;
128
+ }
129
+
130
+ const config = loadConfig();
131
+ console.log('🤖 Starting Agent Orchestration...');
132
+ console.log('');
133
+ console.log('Task:', task);
134
+ console.log('');
135
+ console.log('Available Agents:');
136
+ Object.entries(config.agents).forEach(([name, agent]) => {
137
+ const model = agent.model || config.model;
138
+ console.log(` - ${name}: ${model} (${agent.role})`);
139
+ });
140
+ console.log('');
141
+ console.log('💡 In Claude Code, use /skill <name> to invoke specific agent capabilities');
142
+ },
143
+
144
+ // -------------------------------------------------------------------------
145
+ status: () => {
146
+ const config = loadConfig();
147
+ console.log('📊 Sumulige Claude Status');
148
+ console.log('');
149
+ console.log('Config:', CONFIG_FILE);
150
+ console.log('');
151
+ console.log('Agents:');
152
+ Object.entries(config.agents).forEach(([name, agent]) => {
153
+ const model = agent.model || config.model;
154
+ console.log(` ${name.padEnd(12)} ${model.padEnd(20)} (${agent.role})`);
155
+ });
156
+ console.log('');
157
+ console.log('Skills:', config.skills.join(', '));
158
+ console.log('');
159
+ console.log('ThinkingLens:', config.thinkingLens.enabled ? '✅ Enabled' : '❌ Disabled');
160
+ console.log('');
161
+
162
+ // Show project todos status
163
+ const projectDir = process.cwd();
164
+ const todosIndex = path.join(projectDir, 'development', 'todos', 'INDEX.md');
165
+
166
+ if (fs.existsSync(todosIndex)) {
167
+ const content = fs.readFileSync(todosIndex, 'utf-8');
168
+
169
+ const totalMatch = content.match(/Total:\s+`([^`]+)`\s+(\d+)%/);
170
+ const p0Match = content.match(/P0[^`]*`([^`]+)`\s+(\d+)%\s+\((\d+)\/(\d+)\)/);
171
+ const p1Match = content.match(/P1[^`]*`([^`]+)`\s+(\d+)%\s+\((\d+)\/(\d+)\)/);
172
+ const p2Match = content.match(/P2[^`]*`([^`]+)`\s+(\d+)%\s+\((\d+)\/(\d+)\)/);
173
+
174
+ const activeMatch = content.match(/\|\s+🚧 进行中[^|]*\|\s+`active\/`\s+\|\s+(\d+)/);
175
+ const completedMatch = content.match(/\|\s+✅ 已完成[^|]*\|\s+`completed\/`\s+\|\s+(\d+)/);
176
+ const backlogMatch = content.match(/\|\s+📋 待办[^|]*\|\s+`backlog\/`\s+\|\s+(\d+)/);
177
+
178
+ console.log('📋 Project Tasks:');
179
+ console.log('');
180
+ if (totalMatch) {
181
+ console.log(` Total: ${totalMatch[1]} ${totalMatch[2]}%`);
182
+ }
183
+ if (p0Match) {
184
+ console.log(` P0: ${p0Match[1]} ${p0Match[2]}% (${p0Match[3]}/${p0Match[4]})`);
185
+ }
186
+ if (p1Match) {
187
+ console.log(` P1: ${p1Match[1]} ${p1Match[2]}% (${p1Match[3]}/${p1Match[4]})`);
188
+ }
189
+ if (p2Match) {
190
+ console.log(` P2: ${p2Match[1]} ${p2Match[2]}% (${p2Match[3]}/${p2Match[4]})`);
191
+ }
192
+ console.log('');
193
+ console.log(` 🚧 Active: ${activeMatch ? activeMatch[1] : 0}`);
194
+ console.log(` ✅ Completed: ${completedMatch ? completedMatch[1] : 0}`);
195
+ console.log(` 📋 Backlog: ${backlogMatch ? backlogMatch[1] : 0}`);
196
+ console.log('');
197
+ console.log(` View: cat development/todos/INDEX.md`);
198
+ } else {
199
+ console.log('📋 Project Tasks: (not initialized)');
200
+ console.log(' Run: node .claude/hooks/todo-manager.cjs --force');
201
+ }
202
+ },
203
+
204
+ // -------------------------------------------------------------------------
205
+ 'skill:list': () => {
206
+ try {
207
+ const result = execSync('openskills list', { encoding: 'utf-8' });
208
+ console.log(result);
209
+ } catch (e) {
210
+ console.log('⚠️ OpenSkills not installed. Run: npm i -g openskills');
211
+ }
212
+ },
213
+
214
+ // -------------------------------------------------------------------------
215
+ 'skill:create': (skillName) => {
216
+ if (!skillName) {
217
+ console.log('Usage: sumulige-claude skill:create <skill-name>');
218
+ console.log('');
219
+ console.log('Example: sumulige-claude skill:create api-tester');
220
+ console.log('');
221
+ console.log('The skill will be created at:');
222
+ console.log(' .claude/skills/<skill-name>/');
223
+ return;
224
+ }
225
+
226
+ // Validate skill name (kebab-case)
227
+ if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(skillName)) {
228
+ console.log('❌ Invalid skill name. Use kebab-case (e.g., api-tester, code-reviewer)');
229
+ return;
230
+ }
231
+
232
+ const projectDir = process.cwd();
233
+ const skillsDir = path.join(projectDir, '.claude', 'skills');
234
+ const skillDir = path.join(skillsDir, skillName);
235
+ const templateDir = path.join(TEMPLATE_DIR, '.claude', 'skills', 'template');
236
+
237
+ // Check if skill already exists
238
+ if (fs.existsSync(skillDir)) {
239
+ console.log(`⚠️ Skill "${skillName}" already exists at ${skillDir}`);
240
+ return;
241
+ }
242
+
243
+ console.log(`📝 Creating skill: ${skillName}`);
244
+ console.log('');
245
+
246
+ // Create skill directory structure
247
+ fs.mkdirSync(path.join(skillDir, 'templates'), { recursive: true });
248
+ fs.mkdirSync(path.join(skillDir, 'examples'), { recursive: true });
249
+ console.log('✅ Created directory structure');
250
+
251
+ // Copy template files
252
+ if (fs.existsSync(templateDir)) {
253
+ const skillTemplate = fs.readFileSync(path.join(templateDir, 'SKILL.md'), 'utf-8');
254
+ const metadataTemplate = fs.readFileSync(path.join(templateDir, 'metadata.yaml'), 'utf-8');
255
+
256
+ // Replace placeholders
257
+ const date = new Date().toISOString().split('T')[0];
258
+ let skillContent = skillTemplate
259
+ .replace(/Skill Name/g, toTitleCase(skillName.replace(/-/g, ' ')))
260
+ .replace(/{current-date}/g, date)
261
+ .replace(/skill-name/g, skillName);
262
+
263
+ let metadataContent = metadataTemplate
264
+ .replace(/skill-name/g, skillName);
265
+
266
+ fs.writeFileSync(path.join(skillDir, 'SKILL.md'), skillContent);
267
+ fs.writeFileSync(path.join(skillDir, 'metadata.yaml'), metadataContent);
268
+ console.log('✅ Created SKILL.md and metadata.yaml');
269
+ }
270
+
271
+ // Create example templates
272
+ fs.writeFileSync(
273
+ path.join(skillDir, 'templates', 'default.md'),
274
+ `# Default Template for ${skillName}\n\nReplace this with your actual template.\n`
275
+ );
276
+ fs.writeFileSync(
277
+ path.join(skillDir, 'examples', 'basic.md'),
278
+ `# Basic Example for ${skillName}\n\nReplace this with your actual example.\n`
279
+ );
280
+ console.log('✅ Created templates and examples');
281
+
282
+ // Update RAG index
283
+ const ragDir = path.join(projectDir, '.claude', 'rag');
284
+ const ragIndexFile = path.join(ragDir, 'skill-index.json');
285
+ let ragIndex = { skills: [], auto_load: { enabled: true } };
286
+
287
+ ensureDir(ragDir);
288
+
289
+ if (fs.existsSync(ragIndexFile)) {
290
+ try {
291
+ ragIndex = JSON.parse(fs.readFileSync(ragIndexFile, 'utf-8'));
292
+ } catch (e) { }
293
+ }
294
+
295
+ // Add new skill to index
296
+ const newSkill = {
297
+ name: skillName,
298
+ description: `TODO: Add description for ${skillName}`,
299
+ keywords: [skillName.replace(/-/g, ' ')],
300
+ path: `.claude/skills/${skillName}/SKILL.md`
301
+ };
302
+
303
+ // Avoid duplicates
304
+ if (!ragIndex.skills.some(s => s.name === skillName)) {
305
+ ragIndex.skills.push(newSkill);
306
+ fs.writeFileSync(ragIndexFile, JSON.stringify(ragIndex, null, 2));
307
+ console.log('✅ Updated RAG skill index');
308
+ }
309
+
310
+ console.log('');
311
+ console.log('✅ Skill created successfully!');
312
+ console.log('');
313
+ console.log(`Next steps:`);
314
+ console.log(` 1. Edit .claude/skills/${skillName}/SKILL.md`);
315
+ console.log(` 2. Add your templates and examples`);
316
+ console.log(` 3. Use in Claude Code: /skill ${skillName}`);
317
+ },
318
+
319
+ // -------------------------------------------------------------------------
320
+ 'skill:check': (skillName) => {
321
+ const projectDir = process.cwd();
322
+ const skillsDir = path.join(projectDir, '.claude', 'skills');
323
+
324
+ console.log('🔍 Checking skill dependencies...');
325
+ console.log('');
326
+
327
+ const checkSkill = (name, visited = new Set()) => {
328
+ if (visited.has(name)) {
329
+ console.log(`⚠️ Circular dependency detected: ${name}`);
330
+ return;
331
+ }
332
+ visited.add(name);
333
+
334
+ const skillDir = path.join(skillsDir, name);
335
+ const metadataFile = path.join(skillDir, 'metadata.yaml');
336
+
337
+ if (!fs.existsSync(skillDir)) {
338
+ console.log(`❌ Skill "${name}" not found`);
339
+ return;
340
+ }
341
+
342
+ if (!fs.existsSync(metadataFile)) {
343
+ console.log(`ℹ️ ${name}: No metadata.yaml`);
344
+ return;
345
+ }
346
+
347
+ // Simple YAML parser (basic key: value format only)
348
+ const parseSimpleYaml = (content) => {
349
+ const result = {};
350
+ content.split('\n').forEach(line => {
351
+ const match = line.match(/^(\w+):\s*(.*)$/);
352
+ if (match) {
353
+ const value = match[2].trim();
354
+ if (value === '[]') {
355
+ result[match[1]] = [];
356
+ } else if (value.startsWith('[')) {
357
+ try {
358
+ result[match[1]] = JSON.parse(value.replace(/'/g, '"'));
359
+ } catch (e) {
360
+ result[match[1]] = [];
361
+ }
362
+ } else {
363
+ result[match[1]] = value;
364
+ }
365
+ }
366
+ });
367
+ return result;
368
+ };
369
+
370
+ const metadata = parseSimpleYaml(fs.readFileSync(metadataFile, 'utf-8'));
371
+ const deps = metadata.dependencies || [];
372
+
373
+ if (deps.length === 0) {
374
+ console.log(`✅ ${name}: No dependencies`);
375
+ return;
376
+ }
377
+
378
+ console.log(`📦 ${name} depends on:`);
379
+ deps.forEach(dep => {
380
+ const depDir = path.join(skillsDir, dep);
381
+ if (fs.existsSync(depDir)) {
382
+ console.log(` ✅ ${dep}`);
383
+ checkSkill(dep, new Set(visited));
384
+ } else {
385
+ console.log(` ❌ ${dep} (missing)`);
386
+ }
387
+ });
388
+ };
389
+
390
+ if (skillName) {
391
+ checkSkill(skillName);
392
+ } else {
393
+ // Check all skills
394
+ const allSkills = fs.existsSync(skillsDir)
395
+ ? fs.readdirSync(skillsDir).filter(f => {
396
+ const dir = path.join(skillsDir, f);
397
+ return fs.statSync(dir).isDirectory() && f !== 'template' && f !== 'examples';
398
+ })
399
+ : [];
400
+
401
+ console.log(`Found ${allSkills.length} skills\n`);
402
+ allSkills.forEach(skill => checkSkill(skill));
403
+ }
404
+ },
405
+
406
+ // -------------------------------------------------------------------------
407
+ 'skill:install': (source) => {
408
+ if (!source) {
409
+ console.log('Usage: sumulige-claude skill:install <source>');
410
+ console.log('Example: sumulige-claude skill:install anthropics/skills');
411
+ return;
412
+ }
413
+ try {
414
+ execSync(`openskills install ${source} -y`, { stdio: 'inherit' });
415
+ execSync('openskills sync -y', { stdio: 'pipe' });
416
+ console.log('✅ Skill installed and synced');
417
+ } catch (e) {
418
+ console.log('❌ Failed to install skill');
419
+ }
420
+ },
421
+
422
+ // -------------------------------------------------------------------------
423
+ template: (targetPath) => {
424
+ const targetDir = targetPath ? path.resolve(targetPath) : process.cwd();
425
+
426
+ console.log('🚀 Initializing Claude Code project template...');
427
+ console.log(' Target:', targetDir);
428
+ console.log('');
429
+
430
+ // Check template directory exists
431
+ if (!fs.existsSync(TEMPLATE_DIR)) {
432
+ console.log('❌ Template not found at:', TEMPLATE_DIR);
433
+ console.log(' Please reinstall sumulige-claude');
434
+ process.exit(1);
435
+ }
436
+
437
+ // Create directory structure
438
+ console.log('📁 Creating directory structure...');
439
+ const dirs = [
440
+ path.join(targetDir, '.claude'),
441
+ path.join(targetDir, 'prompts'),
442
+ path.join(targetDir, 'development/todos/active'),
443
+ path.join(targetDir, 'development/todos/completed'),
444
+ path.join(targetDir, 'development/todos/backlog'),
445
+ path.join(targetDir, 'development/todos/archived')
446
+ ];
447
+
448
+ dirs.forEach(ensureDir);
449
+ console.log(' ✅ Directories created');
450
+
451
+ // Copy files
452
+ console.log('📋 Copying template files...');
453
+
454
+ const claudeTemplateDir = path.join(TEMPLATE_DIR, '.claude');
455
+ const targetClaudeDir = path.join(targetDir, '.claude');
456
+
457
+ // Files to copy
458
+ const filesToCopy = [
459
+ { src: 'CLAUDE-template.md', dest: 'CLAUDE.md' },
460
+ { src: 'README.md', dest: 'README.md' },
461
+ { src: 'settings.json', dest: 'settings.json' },
462
+ { src: 'boris-optimizations.md', dest: 'boris-optimizations.md' }
463
+ ];
464
+
465
+ filesToCopy.forEach(({ src, dest }) => {
466
+ const srcPath = path.join(claudeTemplateDir, src);
467
+ if (fs.existsSync(srcPath)) {
468
+ fs.copyFileSync(srcPath, path.join(targetClaudeDir, dest));
469
+ console.log(` ✅ .claude/${dest}`);
470
+ }
471
+ });
472
+
473
+ // Directories to copy recursively
474
+ const dirsToCopy = [
475
+ { src: 'hooks', overwrite: true },
476
+ { src: 'commands', overwrite: true },
477
+ { src: 'skills', overwrite: false },
478
+ { src: 'templates', overwrite: false },
479
+ { src: 'thinking-routes', overwrite: false },
480
+ { src: 'rag', overwrite: true }
481
+ ];
482
+
483
+ dirsToCopy.forEach(({ src, overwrite }) => {
484
+ const srcPath = path.join(claudeTemplateDir, src);
485
+ if (fs.existsSync(srcPath)) {
486
+ const count = copyRecursive(srcPath, path.join(targetClaudeDir, src), overwrite);
487
+ console.log(` ✅ .claude/${src}/ (${count} files)`);
488
+ }
489
+ });
490
+
491
+ // Copy prompts
492
+ const promptsDir = path.join(TEMPLATE_DIR, 'prompts');
493
+ if (fs.existsSync(promptsDir)) {
494
+ const count = copyRecursive(promptsDir, path.join(targetDir, 'prompts'), false);
495
+ console.log(` ✅ prompts/ (${count} files)`);
496
+ }
497
+
498
+ // Copy todos
499
+ const todosDir = path.join(TEMPLATE_DIR, 'development', 'todos');
500
+ if (fs.existsSync(todosDir)) {
501
+ const count = copyRecursive(todosDir, path.join(targetDir, 'development', 'todos'), false);
502
+ console.log(` ✅ development/todos/ (${count} files)`);
503
+ }
504
+
505
+ // Root files
506
+ const rootFiles = ['project-paradigm.md', 'thinkinglens-silent.md', 'CLAUDE-template.md'];
507
+ rootFiles.forEach(file => {
508
+ const src = path.join(TEMPLATE_DIR, file);
509
+ if (fs.existsSync(src)) {
510
+ fs.copyFileSync(src, path.join(targetDir, file));
511
+ console.log(' ✅ ' + file);
512
+ }
513
+ });
514
+
515
+ // Create memory files
516
+ console.log('📝 Creating memory files...');
517
+ if (!fs.existsSync(path.join(targetClaudeDir, 'MEMORY.md'))) {
518
+ fs.writeFileSync(path.join(targetClaudeDir, 'MEMORY.md'), '# Memory\n\n<!-- Project memory updated by AI -->\n');
519
+ }
520
+ if (!fs.existsSync(path.join(targetClaudeDir, 'PROJECT_LOG.md'))) {
521
+ fs.writeFileSync(path.join(targetClaudeDir, 'PROJECT_LOG.md'), '# Project Log\n\n<!-- Build history and decisions -->\n');
522
+ }
523
+ console.log(' ✅ Memory files created');
524
+
525
+ // Create ANCHORS.md
526
+ const anchorsContent = `# [Project Name] - Skill Anchors Index
527
+
528
+ > This file is auto-maintained by AI as a quick index for the skill system
529
+ > Last updated: ${new Date().toISOString().split('T')[0]}
530
+
531
+ ---
532
+
533
+ ## 🚀 AI Startup: Memory Loading Order
534
+
535
+ \`\`\`
536
+ 1. ANCHORS.md (this file) → Quick locate modules
537
+ 2. PROJECT_LOG.md → Understand build history
538
+ 3. MEMORY.md → View latest changes
539
+ 4. CLAUDE.md → Load core knowledge
540
+ 5. prompts/ → View tutorials
541
+ 6. .claude/rag/skills.md → RAG skill index ⭐
542
+ 7. Specific files → Deep dive into implementation
543
+ \`\`\`
544
+
545
+ ---
546
+
547
+ ## Current Anchor Mapping
548
+
549
+ ### Teaching Resources
550
+ | Anchor | File Path | Purpose |
551
+ |--------|-----------|---------|
552
+ | \`[doc:paradigm]\` | \`prompts/project-paradigm.md\` | General development paradigm ⭐ |
553
+ | \`[doc:claude-template]\` | \`.claude/CLAUDE.md\` | CLAUDE.md template for new projects |
554
+
555
+ ### RAG System
556
+ | Anchor | File Path | Purpose |
557
+ |--------|-----------|---------|
558
+ | \`[system:rag-index]\` | \`.claude/rag/skill-index.json\` | Dynamic skill index ⭐ |
559
+
560
+ ---
561
+
562
+ ## Add Your Anchors Here...
563
+
564
+ `;
565
+ fs.writeFileSync(path.join(targetClaudeDir, 'ANCHORS.md'), anchorsContent);
566
+ console.log(' ✅ .claude/ANCHORS.md');
567
+
568
+ // Initialize Sumulige Claude if installed
569
+ console.log('');
570
+ console.log('🤖 Initializing Sumulige Claude...');
571
+ try {
572
+ execSync('sumulige-claude sync', { cwd: targetDir, stdio: 'pipe' });
573
+ console.log(' ✅ Sumulige Claude synced');
574
+ } catch (e) {
575
+ console.log(' ⚠️ Sumulige Claude not available (run: npm i -g sumulige-claude)');
576
+ }
577
+
578
+ console.log('');
579
+ console.log('✅ Template initialization complete!');
580
+ console.log('');
581
+ console.log('📦 What was included:');
582
+ console.log(' • AI autonomous memory system (ThinkingLens)');
583
+ console.log(' • Slash commands (/commit, /test, /review, etc.)');
584
+ console.log(' • Skills system with templates');
585
+ console.log(' • RAG dynamic skill index');
586
+ console.log(' • Hooks for automation');
587
+ console.log(' • TODO management system');
588
+ console.log('');
589
+ console.log('Next steps:');
590
+ console.log(' 1. Edit .claude/CLAUDE.md with your project info');
591
+ console.log(' 2. Run: claude # Start Claude Code');
592
+ console.log(' 3. Try: /commit, /test, /review');
593
+ console.log('');
594
+ },
595
+
596
+ // -------------------------------------------------------------------------
597
+ kickoff: () => {
598
+ const projectDir = process.cwd();
599
+ const kickoffFile = path.join(projectDir, 'PROJECT_KICKOFF.md');
600
+ const hintFile = path.join(projectDir, '.claude', '.kickoff-hint.txt');
601
+
602
+ console.log('🚀 Project Kickoff - Manus 风格项目启动');
603
+ console.log('');
604
+
605
+ if (fs.existsSync(kickoffFile)) {
606
+ console.log('ℹ️ 项目已经完成启动流程');
607
+ console.log(' 文件:', kickoffFile);
608
+ console.log('');
609
+ console.log('如需重新规划,请先删除以下文件:');
610
+ console.log(' - PROJECT_KICKOFF.md');
611
+ console.log(' - TASK_PLAN.md');
612
+ console.log(' - PROJECT_PROPOSAL.md');
613
+ return;
614
+ }
615
+
616
+ // Run kickoff hook
617
+ const kickoffHook = path.join(projectDir, '.claude', 'hooks', 'project-kickoff.cjs');
618
+ if (fs.existsSync(kickoffHook)) {
619
+ try {
620
+ execSync(`node "${kickoffHook}"`, {
621
+ cwd: projectDir,
622
+ env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir },
623
+ stdio: 'inherit'
624
+ });
625
+ } catch (e) {
626
+ // Hook may output and exit, this is normal
627
+ }
628
+
629
+ // Show hint file if exists
630
+ if (fs.existsSync(hintFile)) {
631
+ const hint = fs.readFileSync(hintFile, 'utf-8');
632
+ console.log(hint);
633
+ }
634
+ } else {
635
+ console.log('⚠️ 启动 Hook 不存在');
636
+ console.log(' 请先运行: sumulige-claude template');
637
+ console.log(' 或: sumulige-claude sync');
638
+ }
639
+ }
640
+ };
641
+
642
+ // ============================================================================
643
+ // Helpers
644
+ // ============================================================================
645
+
646
+ function generateAgentsMd(config) {
647
+ const agentsList = Object.entries(config.agents)
648
+ .map(([name, agent]) => {
649
+ const model = agent.model || config.model;
650
+ return `### ${name}\n- **Model**: ${model}\n- **Role**: ${agent.role}`;
651
+ })
652
+ .join('\n\n');
653
+
654
+ return `# AGENTS
655
+
656
+ <skills_system priority="1">
657
+
658
+ ## Agent Orchestration
659
+
660
+ This project uses **Sumulige Claude** for multi-agent collaboration.
661
+
662
+ ${agentsList}
663
+
664
+ ## Usage
665
+
666
+ \`\`\`bash
667
+ # View agent status
668
+ sumulige-claude status
669
+
670
+ # Run agent task
671
+ sumulige-claude agent <task>
672
+
673
+ # List skills
674
+ sumulige-claude skill:list
675
+ \`\`\`
676
+
677
+ </skills_system>
678
+ `;
679
+ }
680
+
681
+ // ============================================================================
682
+ // Exports
683
+ // ============================================================================
684
+
685
+ /**
686
+ * Run a command
687
+ * @param {string} cmd - Command name
688
+ * @param {Array} args - Command arguments
689
+ */
690
+ function runCommand(cmd, args) {
691
+ const command = commands[cmd];
692
+ if (command) {
693
+ command(...args);
694
+ }
695
+ }
696
+
697
+ exports.runCommand = runCommand;
698
+ exports.commands = commands;