sumulige-claude 1.3.0 → 1.3.1

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.
@@ -0,0 +1,147 @@
1
+ ---
2
+ description: Audit approved commands for security risks
3
+ ---
4
+
5
+ # /audit
6
+
7
+ 审计已批准的命令,检测潜在的安全风险。类似 cc-safe 工具。
8
+
9
+ ## 使用方式
10
+
11
+ ```bash
12
+ /audit # 扫描当前项目
13
+ /audit --global # 扫描全局配置
14
+ /audit --fix # 交互式移除危险权限
15
+ /audit --report # 生成详细报告
16
+ ```
17
+
18
+ ## 检测的危险模式
19
+
20
+ ### 🔴 Critical (必须移除)
21
+
22
+ | 模式 | 风险 | 说明 |
23
+ |------|------|------|
24
+ | `rm -rf /` | 系统破坏 | 删除根目录 |
25
+ | `> /dev/sda` | 数据丢失 | 覆写磁盘 |
26
+ | `:(){ :\|:& };:` | Fork 炸弹 | 系统崩溃 |
27
+ | `mkfs` | 数据丢失 | 格式化磁盘 |
28
+ | `dd if=/dev/zero` | 数据丢失 | 覆写设备 |
29
+
30
+ ### 🟠 High (需要审查)
31
+
32
+ | 模式 | 风险 | 说明 |
33
+ |------|------|------|
34
+ | `sudo` | 权限提升 | 管理员权限 |
35
+ | `rm -rf` | 数据丢失 | 递归删除 |
36
+ | `chmod 777` | 安全漏洞 | 过度开放权限 |
37
+ | `docker run --privileged` | 容器逃逸 | 特权容器 |
38
+ | `curl \| sh` | 远程代码执行 | 未验证脚本 |
39
+ | `eval` | 代码注入 | 动态执行 |
40
+
41
+ ### 🟡 Medium (建议审查)
42
+
43
+ | 模式 | 风险 | 说明 |
44
+ |------|------|------|
45
+ | `npm install -g` | 全局污染 | 全局包安装 |
46
+ | `pip install --user` | 环境污染 | 用户级安装 |
47
+ | `git push --force` | 历史丢失 | 强制推送 |
48
+ | `DROP TABLE` | 数据丢失 | 删除数据表 |
49
+
50
+ ## 工作流程
51
+
52
+ ### Step 1: 扫描配置文件
53
+
54
+ 检查以下位置:
55
+ ```
56
+ ~/.claude/settings.local.json # 全局批准
57
+ .claude/settings.local.json # 项目批准
58
+ ~/.claude/projects/*/settings.local.json # 各项目批准
59
+ ```
60
+
61
+ ### Step 2: 模式匹配
62
+
63
+ ```javascript
64
+ const dangerousPatterns = [
65
+ { pattern: /rm\s+-rf\s+\//, level: 'critical', desc: '删除根目录' },
66
+ { pattern: /sudo/, level: 'high', desc: '权限提升' },
67
+ { pattern: /chmod\s+777/, level: 'high', desc: '过度开放权限' },
68
+ { pattern: /--privileged/, level: 'high', desc: '特权容器' },
69
+ { pattern: /curl.*\|\s*sh/, level: 'high', desc: '远程脚本执行' },
70
+ { pattern: /git\s+push\s+--force/, level: 'medium', desc: '强制推送' },
71
+ ];
72
+ ```
73
+
74
+ ### Step 3: 生成报告
75
+
76
+ ```markdown
77
+ # Permission Audit Report
78
+
79
+ **Date**: YYYY-MM-DD HH:mm
80
+ **Scanned**: X files
81
+ **Issues**: Y found
82
+
83
+ ## 🔴 Critical Issues (0)
84
+ None found.
85
+
86
+ ## 🟠 High Risk (2)
87
+
88
+ ### 1. sudo permission
89
+ **Location**: ~/.claude/settings.local.json
90
+ **Pattern**: `Bash(sudo apt install *)`
91
+ **Risk**: 权限提升可能导致系统级变更
92
+
93
+ **Recommendation**:
94
+ 移除此权限,改为手动执行 sudo 命令
95
+
96
+ ### 2. rm -rf permission
97
+ **Location**: .claude/settings.local.json
98
+ **Pattern**: `Bash(rm -rf node_modules)`
99
+ **Risk**: 可能意外删除重要文件
100
+
101
+ **Recommendation**:
102
+ 限制为特定目录,如 `Bash(rm -rf ./node_modules)`
103
+
104
+ ## 🟡 Medium Risk (1)
105
+
106
+ ### 1. git push --force
107
+ **Location**: ~/.claude/settings.local.json
108
+ **Pattern**: `Bash(git push --force)`
109
+ **Risk**: 可能覆盖远程历史
110
+
111
+ ## Summary
112
+
113
+ | Level | Count | Action |
114
+ |-------|-------|--------|
115
+ | 🔴 Critical | 0 | 必须移除 |
116
+ | 🟠 High | 2 | 建议移除 |
117
+ | 🟡 Medium | 1 | 可选审查 |
118
+
119
+ ## Quick Actions
120
+
121
+ ```bash
122
+ # 移除高风险权限
123
+ /audit --fix
124
+
125
+ # 查看具体权限
126
+ cat ~/.claude/settings.local.json | jq '.permissions'
127
+ ```
128
+ ```
129
+
130
+ ---
131
+
132
+ ## CLI 集成
133
+
134
+ 也可通过 `smc audit` 命令运行:
135
+
136
+ ```bash
137
+ smc audit # 扫描当前项目
138
+ smc audit --global # 扫描全局
139
+ smc audit --ci # CI 模式(非零退出码)
140
+ ```
141
+
142
+ ## 最佳实践
143
+
144
+ 1. **定期审计** - 每周运行一次 `/audit`
145
+ 2. **最小权限** - 只批准必要的命令
146
+ 3. **限定范围** - 使用完整路径而非通配符
147
+ 4. **CI 检查** - 在 CI 中运行 `smc audit --ci`
@@ -0,0 +1,136 @@
1
+ ---
2
+ description: Analyze GitHub Actions CI failures
3
+ ---
4
+
5
+ # /gha
6
+
7
+ 分析 GitHub Actions CI 失败,自动检测问题并建议修复方案。
8
+
9
+ ## 使用方式
10
+
11
+ ```bash
12
+ /gha <workflow-url> # 分析指定的 workflow run
13
+ /gha --last # 分析最近失败的 workflow
14
+ /gha --flaky # 检测 flaky tests
15
+ /gha --history # 查看失败历史趋势
16
+ ```
17
+
18
+ ## 工作流程
19
+
20
+ ### Step 1: 获取 Workflow 信息
21
+
22
+ ```bash
23
+ # 获取最近的 workflow runs
24
+ gh run list --limit 10
25
+
26
+ # 获取失败的 run 详情
27
+ gh run view <run-id> --log-failed
28
+ ```
29
+
30
+ ### Step 2: 分析失败原因
31
+
32
+ 检测以下常见问题:
33
+
34
+ | 问题类型 | 检测方式 | 建议 |
35
+ |---------|---------|------|
36
+ | **Flaky Test** | 同一测试随机失败 | 添加重试或修复竞态 |
37
+ | **Timeout** | 超时错误 | 优化性能或增加限制 |
38
+ | **Dependency** | 安装失败 | 检查版本锁定 |
39
+ | **Build Error** | 编译错误 | 检查代码变更 |
40
+ | **Network** | 网络超时 | 添加重试机制 |
41
+ | **Permission** | 权限错误 | 检查 GITHUB_TOKEN |
42
+
43
+ ### Step 3: 生成报告
44
+
45
+ ```markdown
46
+ # GHA Analysis Report
47
+
48
+ ## Workflow: [workflow-name]
49
+ **Run ID**: [run-id]
50
+ **Status**: ❌ Failed
51
+ **Duration**: [time]
52
+ **Triggered by**: [event]
53
+
54
+ ## Failure Summary
55
+
56
+ ### Job: [job-name]
57
+ **Step**: [step-name]
58
+ **Error Type**: [类型]
59
+
60
+ ### Error Log
61
+ ```
62
+ [关键错误日志]
63
+ ```
64
+
65
+ ## Root Cause Analysis
66
+
67
+ 1. **主要原因**: [分析]
68
+ 2. **相关 Commit**: [commit-sha]
69
+ 3. **影响范围**: [范围]
70
+
71
+ ## Recommendations
72
+
73
+ 1. [ ] [建议修复 1]
74
+ 2. [ ] [建议修复 2]
75
+
76
+ ## Quick Fix
77
+
78
+ ```bash
79
+ # 快速修复命令
80
+ [修复命令]
81
+ ```
82
+
83
+ ## Similar Failures
84
+ - [link to similar run 1]
85
+ - [link to similar run 2]
86
+ ```
87
+
88
+ ### Step 4: 可选操作
89
+
90
+ ```bash
91
+ # 重新运行失败的 workflow
92
+ gh run rerun <run-id> --failed
93
+
94
+ # 查看特定 job 日志
95
+ gh run view <run-id> --job <job-id> --log
96
+ ```
97
+
98
+ ---
99
+
100
+ ## 常见问题快速诊断
101
+
102
+ ### Flaky Test 检测
103
+
104
+ ```bash
105
+ # 检查最近 10 次运行中同一测试的失败率
106
+ gh run list --workflow=test.yml --limit 10 --json conclusion,databaseId
107
+ ```
108
+
109
+ ### 依赖问题
110
+
111
+ ```bash
112
+ # 检查 lockfile 变更
113
+ git diff HEAD~1 -- package-lock.json yarn.lock pnpm-lock.yaml
114
+ ```
115
+
116
+ ### 权限问题
117
+
118
+ 检查 workflow 文件中的 permissions:
119
+ ```yaml
120
+ permissions:
121
+ contents: read
122
+ pull-requests: write
123
+ ```
124
+
125
+ ---
126
+
127
+ ## 集成 /fix
128
+
129
+ 如果是代码问题,自动调用 `/fix` 修复:
130
+
131
+ ```bash
132
+ /gha --last # 分析失败
133
+ /fix --build # 修复构建错误
134
+ /test # 本地验证
135
+ /commit # 提交修复
136
+ ```
@@ -0,0 +1,93 @@
1
+ ---
2
+ description: Generate context handoff document for session continuity
3
+ ---
4
+
5
+ # /handoff
6
+
7
+ 生成上下文交接文档,用于会话切换或新对话开始时的上下文传递。
8
+
9
+ ## 使用方式
10
+
11
+ ```bash
12
+ /handoff # 生成交接文档(默认)
13
+ /handoff --save # 保存到 .claude/handoffs/
14
+ /handoff --compact # 生成精简版本
15
+ ```
16
+
17
+ ## 工作流程
18
+
19
+ ### Step 1: 收集当前上下文
20
+
21
+ 分析当前会话,提取以下信息:
22
+
23
+ 1. **任务概述** - 当前正在做什么
24
+ 2. **已完成工作** - 完成了哪些步骤
25
+ 3. **阻塞点** - 遇到了什么问题
26
+ 4. **下一步行动** - 接下来要做什么
27
+ 5. **关键文件** - 涉及的重要文件
28
+
29
+ ### Step 2: 生成交接文档
30
+
31
+ ```markdown
32
+ # Handoff: [任务名称]
33
+
34
+ **Date**: YYYY-MM-DD HH:mm
35
+ **Session**: [session-id]
36
+
37
+ ## Summary
38
+ [一句话描述当前任务]
39
+
40
+ ## Progress
41
+ - [x] 已完成的步骤 1
42
+ - [x] 已完成的步骤 2
43
+ - [ ] 进行中的步骤
44
+
45
+ ## Blockers
46
+ - [阻塞点描述]
47
+ - [需要解决的问题]
48
+
49
+ ## Next Steps
50
+ 1. [下一步行动 1]
51
+ 2. [下一步行动 2]
52
+
53
+ ## Key Files
54
+ | File | Purpose |
55
+ |------|---------|
56
+ | `path/to/file.ts` | [文件作用] |
57
+
58
+ ## Context
59
+ [重要的技术决策或上下文信息]
60
+
61
+ ## Commands to Continue
62
+ ```bash
63
+ # 继续工作的命令
64
+ cd /path/to/project
65
+ # 相关命令...
66
+ ```
67
+ ```
68
+
69
+ ### Step 3: 保存(可选)
70
+
71
+ 如果使用 `--save`,保存到:
72
+ ```
73
+ .claude/handoffs/
74
+ └── handoff-YYYY-MM-DD-HHmm.md
75
+ ```
76
+
77
+ ---
78
+
79
+ ## 最佳实践
80
+
81
+ 1. **定期生成** - 长会话每 30 分钟生成一次
82
+ 2. **上下文过长时** - 使用 `/compact` 后生成 handoff
83
+ 3. **切换任务前** - 保存当前上下文
84
+ 4. **新会话开始** - 读取最近的 handoff 文档
85
+
86
+ ## 与 MEMORY.md 的区别
87
+
88
+ | 特性 | /handoff | MEMORY.md |
89
+ |------|----------|-----------|
90
+ | 目的 | 会话交接 | 长期记忆 |
91
+ | 粒度 | 当前任务 | 项目全局 |
92
+ | 更新频率 | 每次会话 | 重大变更 |
93
+ | 格式 | 结构化文档 | 增量记录 |
@@ -1,7 +1,6 @@
1
1
  {
2
- "version": "2.0.0",
3
- "last_updated": "2026-01-22",
4
- "description": "Optimized skill index - merged 9 skills into 4 core skills",
2
+ "version": "1.0.0",
3
+ "last_updated": "2026-01-11",
5
4
  "skills": [
6
5
  {
7
6
  "name": "frontend-design",
@@ -47,7 +46,7 @@
47
46
  },
48
47
  {
49
48
  "name": "webapp-testing",
50
- "keywords": ["browser", "automation", "screenshot", "puppeteer", "scraping"],
49
+ "keywords": ["test", "testing", "playwright", "browser", "automation", "e2e", "screenshot"],
51
50
  "description": "Toolkit for interacting with and testing local web applications using Playwright",
52
51
  "trigger": "when testing frontend functionality, debugging UI behavior, or capturing browser screenshots"
53
52
  },
@@ -106,32 +105,22 @@
106
105
  "trigger": "for complex artifacts requiring state management, routing, or shadcn/ui components"
107
106
  },
108
107
  {
109
- "name": "quality-guard",
110
- "keywords": ["review", "security", "quality", "lint", "code review", "vulnerability", "owasp", "dead code", "refactor", "cleanup"],
111
- "description": "Code quality guardian - merged: code review + security check + dead code cleanup. Supports --security, --clean modes.",
112
- "trigger": "when reviewing code, checking security, or cleaning up dead code",
113
- "model": "sonnet"
108
+ "name": "dev-browser",
109
+ "keywords": ["browser", "scraping", "automation", "puppet", "playwright", "web"],
110
+ "description": "Browser automation with persistent state for testing and scraping",
111
+ "trigger": "when needing browser automation or web scraping capabilities"
114
112
  },
115
113
  {
116
- "name": "test-master",
117
- "keywords": ["test", "tdd", "e2e", "playwright", "coverage", "unit test", "jest", "vitest"],
118
- "description": "Test master - merged: TDD workflow + E2E testing. Supports --tdd, --e2e, --coverage modes.",
119
- "trigger": "when writing tests, doing TDD, running E2E tests, or checking coverage",
120
- "model": "sonnet"
114
+ "name": "zai-cli",
115
+ "keywords": ["z.ai", "vision", "search", "github", "exploration", "analysis"],
116
+ "description": "Z.AI vision, search, and GitHub exploration CLI tools",
117
+ "trigger": "when needing vision analysis, web search, or GitHub repository exploration"
121
118
  },
122
119
  {
123
- "name": "design-brain",
124
- "keywords": ["plan", "design", "architecture", "system design", "technical decision", "strategy"],
125
- "description": "Design brain - merged: planner + architect. Supports --quick (default) and --deep modes.",
126
- "trigger": "when planning implementation or making architecture decisions",
127
- "model": "opus"
128
- },
129
- {
130
- "name": "quick-fix",
131
- "keywords": ["fix", "build error", "compile error", "type error", "lint error", "tsc"],
132
- "description": "Quick fixer - fast build/lint/type error resolution using haiku model for speed and cost efficiency.",
133
- "trigger": "when build fails, type errors occur, or lint errors need fixing",
134
- "model": "haiku"
120
+ "name": "gastown",
121
+ "keywords": ["gastown", "multi-agent", "orchestrator", "coordination"],
122
+ "description": "Multi-agent orchestrator for complex task coordination",
123
+ "trigger": "when orchestrating multiple agents for complex workflows"
135
124
  }
136
125
  ],
137
126
  "auto_load": {
@@ -142,13 +131,5 @@
142
131
  "fallback": {
143
132
  "enabled": true,
144
133
  "skill": "frontend-design"
145
- },
146
- "model_strategy": {
147
- "description": "Cost-optimized model selection",
148
- "rules": [
149
- { "pattern": "quick-fix", "model": "haiku", "reason": "Fast, simple fixes" },
150
- { "pattern": "quality-guard|test-master", "model": "sonnet", "reason": "Standard tasks" },
151
- { "pattern": "design-brain", "model": "opus", "reason": "Complex architecture only" }
152
- ]
153
134
  }
154
135
  }
@@ -123,7 +123,12 @@
123
123
  "Bash(/opt/homebrew/Cellar/node/25.3.0/bin/node -e \"const fs=require\\(''fs''\\); let d=''''; process.stdin.on\\(''data'',c=>d+=c\\); process.stdin.on\\(''end'',\\(\\)=>{const j=JSON.parse\\(d\\); console.log\\(''Skills:'', j.skills.length\\); console.log\\(''Model strategy:'', JSON.stringify\\(j.model_strategy, null, 2\\)\\);}\\)\")",
124
124
  "Bash(/opt/homebrew/Cellar/node/25.3.0/bin/npm version 1.3.0 --no-git-tag-version)",
125
125
  "Bash(git tag:*)",
126
- "Bash(/opt/homebrew/Cellar/node/25.3.0/bin/npm publish)"
126
+ "Bash(/opt/homebrew/Cellar/node/25.3.0/bin/npm publish)",
127
+ "Bash(/opt/homebrew/Cellar/node/25.3.0/bin/npm view sumulige-claude version)",
128
+ "Bash(/opt/homebrew/Cellar/node/25.3.0/bin/npm view sumulige-claude versions --json)",
129
+ "Bash(/opt/homebrew/Cellar/node/25.3.0/bin/npx sumulige-claude@1.3.0 sync)",
130
+ "WebFetch(domain:raw.githubusercontent.com)",
131
+ "Bash(/opt/homebrew/Cellar/node/25.3.0/bin/npm version 1.3.1 --no-git-tag-version)"
127
132
  ]
128
133
  },
129
134
  "hooks": {
package/CHANGELOG.md CHANGED
@@ -1,3 +1,28 @@
1
+ ## [1.3.1](https://github.com/sumulige/sumulige-claude/compare/v1.3.0...v1.3.1) (2026-01-22)
2
+
3
+ ### ✨ New Features
4
+
5
+ - **System Prompt Optimization**: Token savings via MCP lazy-loading
6
+ - `ENABLE_TOOL_SEARCH=true` - MCP tools loaded on demand
7
+ - `DISABLE_AUTOUPDATER=1` - Reduce startup overhead
8
+ - ~50% token reduction for system prompts
9
+ - **New Commands**:
10
+ - `/handoff` - Generate context handoff documents for session continuity
11
+ - `/gha` - Analyze GitHub Actions CI failures
12
+ - `/audit` - Security audit for approved commands (cc-safe style)
13
+ - **Permission Audit**: Detect dangerous patterns in approved commands
14
+ - Critical: `rm -rf /`, disk overwrite, fork bombs
15
+ - High: `sudo`, `chmod 777`, privileged containers
16
+ - Medium: global installs, force push
17
+
18
+ ### 📝 Documentation
19
+
20
+ - Add `/handoff` command guide
21
+ - Add `/gha` CI analysis guide
22
+ - Add `/audit` security audit guide
23
+
24
+ ---
25
+
1
26
  ## [1.3.0](https://github.com/sumulige/sumulige-claude/compare/v1.2.1...v1.3.0) (2026-01-22)
2
27
 
3
28
  ### ✨ 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
 
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.1",
4
4
  "description": "The Best Agent Harness for Claude Code",
5
5
  "main": "cli.js",
6
6
  "bin": {