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.
- package/.claude/commands/audit.md +147 -0
- package/.claude/commands/gha.md +136 -0
- package/.claude/commands/handoff.md +93 -0
- package/.claude/rag/skill-index.json +15 -34
- package/.claude/settings.local.json +6 -1
- package/CHANGELOG.md +25 -0
- package/cli.js +4 -0
- package/lib/commands.js +51 -0
- package/lib/permission-audit.js +255 -0
- package/package.json +1 -1
|
@@ -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": "
|
|
3
|
-
"last_updated": "2026-01-
|
|
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": ["
|
|
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": "
|
|
110
|
-
"keywords": ["
|
|
111
|
-
"description": "
|
|
112
|
-
"trigger": "when
|
|
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": "
|
|
117
|
-
"keywords": ["
|
|
118
|
-
"description": "
|
|
119
|
-
"trigger": "when
|
|
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": "
|
|
124
|
-
"keywords": ["
|
|
125
|
-
"description": "
|
|
126
|
-
"trigger": "when
|
|
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
|
+
};
|