sumulige-claude 1.3.0 → 1.3.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 (38) hide show
  1. package/.claude/MEMORY.md +9 -0
  2. package/.claude/commands/audit.md +147 -0
  3. package/.claude/commands/gha.md +136 -0
  4. package/.claude/commands/handoff.md +93 -0
  5. package/.claude/handoffs/INDEX.md +21 -0
  6. package/.claude/handoffs/LATEST.md +76 -0
  7. package/.claude/handoffs/handoff_2026-01-22T13-07-04-757Z.md +76 -0
  8. package/.claude/hooks/auto-handoff.cjs +353 -0
  9. package/.claude/hooks/memory-loader.cjs +208 -0
  10. package/.claude/hooks/memory-saver.cjs +268 -0
  11. package/.claude/rag/skill-index.json +15 -34
  12. package/.claude/sessions/session_2026-01-22T13-07-26-625Z.json +23 -0
  13. package/.claude/settings.json +40 -0
  14. package/.claude/settings.local.json +10 -1
  15. package/.claude/skills/api-tester/SKILL.md +61 -0
  16. package/.claude/skills/api-tester/examples/basic.md +3 -0
  17. package/.claude/skills/api-tester/metadata.yaml +30 -0
  18. package/.claude/skills/api-tester/templates/default.md +3 -0
  19. package/.claude/skills/code-reviewer-123/SKILL.md +61 -0
  20. package/.claude/skills/code-reviewer-123/examples/basic.md +3 -0
  21. package/.claude/skills/code-reviewer-123/metadata.yaml +30 -0
  22. package/.claude/skills/code-reviewer-123/templates/default.md +3 -0
  23. package/.claude/skills/my-skill/SKILL.md +61 -0
  24. package/.claude/skills/my-skill/examples/basic.md +3 -0
  25. package/.claude/skills/my-skill/metadata.yaml +30 -0
  26. package/.claude/skills/my-skill/templates/default.md +3 -0
  27. package/.claude/skills/template/SKILL.md +6 -0
  28. package/.claude/skills/template/metadata.yaml +30 -0
  29. package/.claude/skills/test-skill-name/SKILL.md +61 -0
  30. package/.claude/skills/test-skill-name/examples/basic.md +3 -0
  31. package/.claude/skills/test-skill-name/metadata.yaml +30 -0
  32. package/.claude/skills/test-skill-name/templates/default.md +3 -0
  33. package/CHANGELOG.md +45 -0
  34. package/cli.js +4 -0
  35. package/development/todos/.state.json +3 -1
  36. package/lib/commands.js +51 -0
  37. package/lib/permission-audit.js +255 -0
  38. package/package.json +1 -1
@@ -0,0 +1,61 @@
1
+ # My Skill
2
+
3
+ > 简短描述这个技能的作用(一句话)
4
+
5
+ **版本**: 1.0.0
6
+ **作者**: @username
7
+ **标签**: [category1, category2]
8
+ **难度**: 初级/中级/高级
9
+
10
+ ---
11
+
12
+ ## 概述
13
+
14
+ 详细描述这个技能的功能和用途。
15
+
16
+ ## 适用场景
17
+
18
+ - 场景 1
19
+ - 场景 2
20
+ - 场景 3
21
+
22
+ ## 触发关键词
23
+
24
+ ```
25
+ keyword1, keyword2, "exact phrase"
26
+ ```
27
+
28
+ ## 使用方法
29
+
30
+ ### 基础用法
31
+
32
+ ```bash
33
+ # 示例命令
34
+ your-command-here
35
+ ```
36
+
37
+ ### 高级用法
38
+
39
+ ```yaml
40
+ # 配置示例
41
+ key: value
42
+ ```
43
+
44
+ ## 输出格式
45
+
46
+ 描述这个技能的输出结果格式。
47
+
48
+ ## 注意事项
49
+
50
+ - 注意事项 1
51
+ - 注意事项 2
52
+
53
+ ## 相关技能
54
+
55
+ - [related-skill](../related-skill/)
56
+ - [another-skill](../another-skill/)
57
+
58
+ ## 更新日志
59
+
60
+ ### 1.0.0 (YYYY-MM-DD)
61
+ - 初始版本
@@ -0,0 +1,3 @@
1
+ # Basic Example for my-skill
2
+
3
+ Replace this with your actual example.
@@ -0,0 +1,30 @@
1
+ # Skill Metadata
2
+ # 这个文件定义技能的基本信息,用于自动发现和索引
3
+
4
+ name: my-skill
5
+ version: 1.0.0
6
+ author: @username
7
+ description: 简短描述技能功能
8
+
9
+ tags:
10
+ - category1
11
+ - category2
12
+
13
+ triggers:
14
+ - keyword1
15
+ - keyword2
16
+ - "exact phrase"
17
+
18
+ dependencies: [] # 依赖的其他技能
19
+
20
+ difficulty: beginner # beginner | intermediate | advanced
21
+
22
+ # 模板文件
23
+ templates:
24
+ - name: default
25
+ file: templates/default.md
26
+
27
+ # 示例文件
28
+ examples:
29
+ - name: basic
30
+ file: examples/basic.md
@@ -0,0 +1,3 @@
1
+ # Default Template for my-skill
2
+
3
+ Replace this with your actual template.
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: template-skill
3
+ description: Replace with description of the skill and when Claude should use it.
4
+ ---
5
+
6
+ # Insert instructions below
@@ -0,0 +1,30 @@
1
+ # Skill Metadata
2
+ # 这个文件定义技能的基本信息,用于自动发现和索引
3
+
4
+ name: skill-name
5
+ version: 1.0.0
6
+ author: @username
7
+ description: 简短描述技能功能
8
+
9
+ tags:
10
+ - category1
11
+ - category2
12
+
13
+ triggers:
14
+ - keyword1
15
+ - keyword2
16
+ - "exact phrase"
17
+
18
+ dependencies: [] # 依赖的其他技能
19
+
20
+ difficulty: beginner # beginner | intermediate | advanced
21
+
22
+ # 模板文件
23
+ templates:
24
+ - name: default
25
+ file: templates/default.md
26
+
27
+ # 示例文件
28
+ examples:
29
+ - name: basic
30
+ file: examples/basic.md
@@ -0,0 +1,61 @@
1
+ # Test Skill Name
2
+
3
+ > 简短描述这个技能的作用(一句话)
4
+
5
+ **版本**: 1.0.0
6
+ **作者**: @username
7
+ **标签**: [category1, category2]
8
+ **难度**: 初级/中级/高级
9
+
10
+ ---
11
+
12
+ ## 概述
13
+
14
+ 详细描述这个技能的功能和用途。
15
+
16
+ ## 适用场景
17
+
18
+ - 场景 1
19
+ - 场景 2
20
+ - 场景 3
21
+
22
+ ## 触发关键词
23
+
24
+ ```
25
+ keyword1, keyword2, "exact phrase"
26
+ ```
27
+
28
+ ## 使用方法
29
+
30
+ ### 基础用法
31
+
32
+ ```bash
33
+ # 示例命令
34
+ your-command-here
35
+ ```
36
+
37
+ ### 高级用法
38
+
39
+ ```yaml
40
+ # 配置示例
41
+ key: value
42
+ ```
43
+
44
+ ## 输出格式
45
+
46
+ 描述这个技能的输出结果格式。
47
+
48
+ ## 注意事项
49
+
50
+ - 注意事项 1
51
+ - 注意事项 2
52
+
53
+ ## 相关技能
54
+
55
+ - [related-skill](../related-skill/)
56
+ - [another-skill](../another-skill/)
57
+
58
+ ## 更新日志
59
+
60
+ ### 1.0.0 (YYYY-MM-DD)
61
+ - 初始版本
@@ -0,0 +1,3 @@
1
+ # Basic Example for test-skill-name
2
+
3
+ Replace this with your actual example.
@@ -0,0 +1,30 @@
1
+ # Skill Metadata
2
+ # 这个文件定义技能的基本信息,用于自动发现和索引
3
+
4
+ name: test-skill-name
5
+ version: 1.0.0
6
+ author: @username
7
+ description: 简短描述技能功能
8
+
9
+ tags:
10
+ - category1
11
+ - category2
12
+
13
+ triggers:
14
+ - keyword1
15
+ - keyword2
16
+ - "exact phrase"
17
+
18
+ dependencies: [] # 依赖的其他技能
19
+
20
+ difficulty: beginner # beginner | intermediate | advanced
21
+
22
+ # 模板文件
23
+ templates:
24
+ - name: default
25
+ file: templates/default.md
26
+
27
+ # 示例文件
28
+ examples:
29
+ - name: basic
30
+ file: examples/basic.md
@@ -0,0 +1,3 @@
1
+ # Default Template for test-skill-name
2
+
3
+ Replace this with your actual template.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,48 @@
1
+ ## [1.3.2](https://github.com/sumulige/sumulige-claude/compare/v1.3.1...v1.3.2) (2026-01-22)
2
+
3
+ ### ✨ New Features
4
+
5
+ - **Official Hooks Integration**: Claude Code lifecycle auto-sync
6
+ - `SessionStart` → `memory-loader.cjs`: Auto-load MEMORY.md, ANCHORS.md, restore TODO state
7
+ - `SessionEnd` → `memory-saver.cjs`: Auto-save session summary, archive session, sync TODO
8
+ - `PreCompact` → `auto-handoff.cjs`: Auto-generate handoff before context compression
9
+ - **Context Preservation**: Automatic handoff documents in `.claude/handoffs/`
10
+ - Includes active TODOs, recently modified files, recovery commands
11
+ - `LATEST.md` always points to most recent handoff
12
+
13
+ ### 🔧 Improvements
14
+
15
+ - Session state tracking via `.session-state.json`
16
+ - Automatic session archiving to `.claude/sessions/`
17
+ - Memory entries kept for 7 days with auto-cleanup
18
+
19
+ ---
20
+
21
+ ## [1.3.1](https://github.com/sumulige/sumulige-claude/compare/v1.3.0...v1.3.1) (2026-01-22)
22
+
23
+ ### ✨ New Features
24
+
25
+ - **System Prompt Optimization**: Token savings via MCP lazy-loading
26
+ - `ENABLE_TOOL_SEARCH=true` - MCP tools loaded on demand
27
+ - `DISABLE_AUTOUPDATER=1` - Reduce startup overhead
28
+ - ~50% token reduction for system prompts
29
+ - **New Commands**:
30
+ - `/handoff` - Generate context handoff documents for session continuity
31
+ - `/gha` - Analyze GitHub Actions CI failures
32
+ - `/audit` - Security audit for approved commands (cc-safe style)
33
+ - **Permission Audit**: Detect dangerous patterns in approved commands
34
+ - Critical: `rm -rf /`, disk overwrite, fork bombs
35
+ - High: `sudo`, `chmod 777`, privileged containers
36
+ - Medium: global installs, force push
37
+
38
+ ### 📝 Documentation
39
+
40
+ - Add `/handoff` command guide
41
+ - Add `/gha` CI analysis guide
42
+ - Add `/audit` security audit guide
43
+
44
+ ---
45
+
1
46
  ## [1.3.0](https://github.com/sumulige/sumulige-claude/compare/v1.2.1...v1.3.0) (2026-01-22)
2
47
 
3
48
  ### ✨ New Features
package/cli.js CHANGED
@@ -175,6 +175,10 @@ const COMMANDS = {
175
175
  notebooklm: {
176
176
  help: 'NotebookLM browser automation',
177
177
  args: '<auth|ask|status|clear> [args...]'
178
+ },
179
+ audit: {
180
+ help: 'Audit approved commands for security risks',
181
+ args: '[--global] [--ci] [--report]'
178
182
  }
179
183
  };
180
184
 
@@ -13,5 +13,7 @@
13
13
  "notified": true
14
14
  }
15
15
  },
16
- "transitions": []
16
+ "transitions": [],
17
+ "lastSynced": "2026-01-22T13:07:26.625Z",
18
+ "sessionId": "unknown"
17
19
  }
package/lib/commands.js CHANGED
@@ -3332,6 +3332,57 @@ All notable changes to this project will be documented in this file.
3332
3332
  } = require("../.claude/workflow/notebooklm/browser");
3333
3333
  await handleNotebookLMCommand(args);
3334
3334
  },
3335
+
3336
+ // ==========================================================================
3337
+ // Security Audit Commands
3338
+ // ==========================================================================
3339
+
3340
+ audit: async (...args) => {
3341
+ const { audit, generateReport, passes } = require("./permission-audit");
3342
+
3343
+ const isGlobal = args.includes("--global");
3344
+ const isCi = args.includes("--ci");
3345
+ const isReport = args.includes("--report");
3346
+
3347
+ console.log("🔍 Running permission audit...\n");
3348
+
3349
+ const results = audit({ global: isGlobal });
3350
+
3351
+ if (isReport) {
3352
+ console.log(generateReport(results));
3353
+ } else {
3354
+ const { issues } = results;
3355
+ const total = issues.critical.length + issues.high.length + issues.medium.length;
3356
+
3357
+ if (total === 0) {
3358
+ console.log("✅ No security issues found!\n");
3359
+ console.log(`Scanned ${results.scanned} settings file(s)`);
3360
+ } else {
3361
+ console.log(`Found ${total} potential issue(s):\n`);
3362
+
3363
+ if (issues.critical.length > 0) {
3364
+ console.log(`🔴 Critical: ${issues.critical.length}`);
3365
+ issues.critical.forEach(i => console.log(` - ${i.desc}: ${i.permission}`));
3366
+ }
3367
+
3368
+ if (issues.high.length > 0) {
3369
+ console.log(`🟠 High: ${issues.high.length}`);
3370
+ issues.high.forEach(i => console.log(` - ${i.desc}: ${i.permission}`));
3371
+ }
3372
+
3373
+ if (issues.medium.length > 0) {
3374
+ console.log(`🟡 Medium: ${issues.medium.length}`);
3375
+ issues.medium.forEach(i => console.log(` - ${i.desc}: ${i.permission}`));
3376
+ }
3377
+
3378
+ console.log("\nRun 'smc audit --report' for detailed analysis.");
3379
+ }
3380
+ }
3381
+
3382
+ if (isCi && !passes(results)) {
3383
+ process.exit(1);
3384
+ }
3385
+ },
3335
3386
  };
3336
3387
 
3337
3388
  // ============================================================================
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Permission Audit - Security scanner for approved commands
3
+ * Inspired by cc-safe from ykdojo/claude-code-tips
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const os = require('os');
9
+
10
+ // Dangerous patterns with severity levels
11
+ const DANGEROUS_PATTERNS = [
12
+ // Critical - Must remove
13
+ { pattern: /rm\s+-rf\s+\/(?!\w)/, level: 'critical', desc: 'Delete root directory' },
14
+ { pattern: />\s*\/dev\/sd[a-z]/, level: 'critical', desc: 'Overwrite disk device' },
15
+ { pattern: /mkfs/, level: 'critical', desc: 'Format disk' },
16
+ { pattern: /dd\s+if=\/dev\/zero/, level: 'critical', desc: 'Overwrite with zeros' },
17
+ { pattern: /:\(\)\s*\{\s*:\|:&\s*\}\s*;:/, level: 'critical', desc: 'Fork bomb' },
18
+
19
+ // High - Should review
20
+ { pattern: /sudo/, level: 'high', desc: 'Privilege escalation' },
21
+ { pattern: /rm\s+-rf/, level: 'high', desc: 'Recursive force delete' },
22
+ { pattern: /chmod\s+777/, level: 'high', desc: 'World-writable permissions' },
23
+ { pattern: /--privileged/, level: 'high', desc: 'Privileged container' },
24
+ { pattern: /curl.*\|\s*(sh|bash)/, level: 'high', desc: 'Remote script execution' },
25
+ { pattern: /wget.*\|\s*(sh|bash)/, level: 'high', desc: 'Remote script execution' },
26
+ { pattern: /eval\s/, level: 'high', desc: 'Dynamic code execution' },
27
+ { pattern: /--no-verify/, level: 'high', desc: 'Skip verification hooks' },
28
+
29
+ // Medium - Optional review
30
+ { pattern: /npm\s+install\s+-g/, level: 'medium', desc: 'Global npm install' },
31
+ { pattern: /pip\s+install/, level: 'medium', desc: 'Python package install' },
32
+ { pattern: /git\s+push\s+--force/, level: 'medium', desc: 'Force push' },
33
+ { pattern: /git\s+reset\s+--hard/, level: 'medium', desc: 'Hard reset' },
34
+ { pattern: /DROP\s+(TABLE|DATABASE)/i, level: 'medium', desc: 'Drop database objects' },
35
+ { pattern: /TRUNCATE/i, level: 'medium', desc: 'Truncate table' },
36
+ ];
37
+
38
+ /**
39
+ * Find all settings files to scan
40
+ */
41
+ function findSettingsFiles(projectDir) {
42
+ const files = [];
43
+ const homeDir = os.homedir();
44
+
45
+ // Global settings
46
+ const globalSettings = path.join(homeDir, '.claude', 'settings.local.json');
47
+ if (fs.existsSync(globalSettings)) {
48
+ files.push({ path: globalSettings, scope: 'global' });
49
+ }
50
+
51
+ // Project settings
52
+ if (projectDir) {
53
+ const projectSettings = path.join(projectDir, '.claude', 'settings.local.json');
54
+ if (fs.existsSync(projectSettings)) {
55
+ files.push({ path: projectSettings, scope: 'project' });
56
+ }
57
+ }
58
+
59
+ // All project settings in ~/.claude/projects/
60
+ const projectsDir = path.join(homeDir, '.claude', 'projects');
61
+ if (fs.existsSync(projectsDir)) {
62
+ try {
63
+ const projects = fs.readdirSync(projectsDir);
64
+ for (const proj of projects) {
65
+ const projSettings = path.join(projectsDir, proj, 'settings.local.json');
66
+ if (fs.existsSync(projSettings)) {
67
+ files.push({ path: projSettings, scope: `project:${proj}` });
68
+ }
69
+ }
70
+ } catch (e) {
71
+ // Ignore read errors
72
+ }
73
+ }
74
+
75
+ return files;
76
+ }
77
+
78
+ /**
79
+ * Extract permissions from settings file
80
+ */
81
+ function extractPermissions(settingsPath) {
82
+ try {
83
+ const content = fs.readFileSync(settingsPath, 'utf-8');
84
+ const settings = JSON.parse(content);
85
+
86
+ const permissions = [];
87
+
88
+ // Check permissions.allow array
89
+ if (settings.permissions?.allow) {
90
+ permissions.push(...settings.permissions.allow);
91
+ }
92
+
93
+ // Check allowedTools (older format)
94
+ if (settings.allowedTools) {
95
+ permissions.push(...settings.allowedTools);
96
+ }
97
+
98
+ return permissions;
99
+ } catch (e) {
100
+ return [];
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Scan a permission string for dangerous patterns
106
+ */
107
+ function scanPermission(permission) {
108
+ const issues = [];
109
+
110
+ for (const { pattern, level, desc } of DANGEROUS_PATTERNS) {
111
+ if (pattern.test(permission)) {
112
+ issues.push({ level, desc, pattern: pattern.toString(), match: permission });
113
+ }
114
+ }
115
+
116
+ return issues;
117
+ }
118
+
119
+ /**
120
+ * Run full audit
121
+ */
122
+ function audit(options = {}) {
123
+ const { projectDir = process.cwd(), global: scanGlobal = true } = options;
124
+
125
+ const results = {
126
+ scanned: 0,
127
+ issues: {
128
+ critical: [],
129
+ high: [],
130
+ medium: [],
131
+ },
132
+ files: [],
133
+ };
134
+
135
+ const files = findSettingsFiles(scanGlobal ? projectDir : null);
136
+ results.scanned = files.length;
137
+ results.files = files.map(f => f.path);
138
+
139
+ for (const { path: filePath, scope } of files) {
140
+ const permissions = extractPermissions(filePath);
141
+
142
+ for (const perm of permissions) {
143
+ const issues = scanPermission(perm);
144
+
145
+ for (const issue of issues) {
146
+ const entry = {
147
+ ...issue,
148
+ file: filePath,
149
+ scope,
150
+ permission: perm,
151
+ };
152
+
153
+ results.issues[issue.level].push(entry);
154
+ }
155
+ }
156
+ }
157
+
158
+ return results;
159
+ }
160
+
161
+ /**
162
+ * Generate markdown report
163
+ */
164
+ function generateReport(results) {
165
+ const { scanned, issues, files } = results;
166
+ const totalIssues = issues.critical.length + issues.high.length + issues.medium.length;
167
+
168
+ let report = `# Permission Audit Report
169
+
170
+ **Date**: ${new Date().toISOString().split('T')[0]}
171
+ **Scanned**: ${scanned} files
172
+ **Issues**: ${totalIssues} found
173
+
174
+ `;
175
+
176
+ // Critical issues
177
+ report += `## 🔴 Critical Issues (${issues.critical.length})\n\n`;
178
+ if (issues.critical.length === 0) {
179
+ report += 'None found.\n\n';
180
+ } else {
181
+ issues.critical.forEach((issue, i) => {
182
+ report += `### ${i + 1}. ${issue.desc}
183
+ **Location**: ${issue.file}
184
+ **Pattern**: \`${issue.permission}\`
185
+ **Risk**: ${issue.desc}
186
+
187
+ `;
188
+ });
189
+ }
190
+
191
+ // High risk
192
+ report += `## 🟠 High Risk (${issues.high.length})\n\n`;
193
+ if (issues.high.length === 0) {
194
+ report += 'None found.\n\n';
195
+ } else {
196
+ issues.high.forEach((issue, i) => {
197
+ report += `### ${i + 1}. ${issue.desc}
198
+ **Location**: ${issue.file}
199
+ **Pattern**: \`${issue.permission}\`
200
+ **Risk**: ${issue.desc}
201
+
202
+ `;
203
+ });
204
+ }
205
+
206
+ // Medium risk
207
+ report += `## 🟡 Medium Risk (${issues.medium.length})\n\n`;
208
+ if (issues.medium.length === 0) {
209
+ report += 'None found.\n\n';
210
+ } else {
211
+ issues.medium.forEach((issue, i) => {
212
+ report += `### ${i + 1}. ${issue.desc}
213
+ **Location**: ${issue.file}
214
+ **Pattern**: \`${issue.permission}\`
215
+
216
+ `;
217
+ });
218
+ }
219
+
220
+ // Summary
221
+ report += `## Summary
222
+
223
+ | Level | Count | Action |
224
+ |-------|-------|--------|
225
+ | 🔴 Critical | ${issues.critical.length} | Must remove |
226
+ | 🟠 High | ${issues.high.length} | Should review |
227
+ | 🟡 Medium | ${issues.medium.length} | Optional review |
228
+
229
+ `;
230
+
231
+ return report;
232
+ }
233
+
234
+ /**
235
+ * Check if audit passes (for CI)
236
+ */
237
+ function passes(results, options = {}) {
238
+ const { allowMedium = true, allowHigh = false } = options;
239
+
240
+ if (results.issues.critical.length > 0) return false;
241
+ if (!allowHigh && results.issues.high.length > 0) return false;
242
+ if (!allowMedium && results.issues.medium.length > 0) return false;
243
+
244
+ return true;
245
+ }
246
+
247
+ module.exports = {
248
+ audit,
249
+ generateReport,
250
+ passes,
251
+ DANGEROUS_PATTERNS,
252
+ findSettingsFiles,
253
+ extractPermissions,
254
+ scanPermission,
255
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sumulige-claude",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "The Best Agent Harness for Claude Code",
5
5
  "main": "cli.js",
6
6
  "bin": {