@optima-chat/dev-skills 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,377 @@
1
+ # /query-db - 查询数据库
2
+
3
+ 执行 SQL 查询,支持 CI/Stage/Prod 三个环境。
4
+
5
+ **版本**: v0.3.0
6
+
7
+ ## 使用场景
8
+
9
+ **开发者**: 快速查询数据验证功能
10
+ **调试**: 检查数据库状态、排查数据问题
11
+ **运维**: 查看生产数据、统计分析
12
+
13
+ ## 用法
14
+
15
+ ```
16
+ /query-db <service> <sql> [environment]
17
+ ```
18
+
19
+ ## 参数
20
+
21
+ - `service` (必需): 服务名称
22
+ - `commerce-backend` - 电商后端数据库
23
+ - `user-auth` - 用户认证数据库
24
+ - `mcp-host` - MCP 协调器数据库
25
+ - `agentic-chat` - AI 聊天服务数据库
26
+ - `sql` (必需): SQL 查询语句(用引号包裹)
27
+ - `environment` (可选): 环境,默认 ci
28
+ - `ci` - CI 持续集成环境(开发环境,默认)
29
+ - `stage` - Stage 预发布环境
30
+ - `prod` - Prod 生产环境(⚠️ 谨慎使用)
31
+
32
+ ## 示例
33
+
34
+ ```bash
35
+ /query-db commerce-backend "SELECT COUNT(*) FROM products" # CI 环境(默认)
36
+ /query-db user-auth "SELECT email FROM users LIMIT 5" # CI 环境
37
+ /query-db commerce-backend "SELECT * FROM orders WHERE status='pending'" ci # CI 环境
38
+ /query-db user-auth "SELECT COUNT(*) FROM users" stage # Stage 环境
39
+ /query-db commerce-backend "SELECT * FROM products LIMIT 10" prod # Prod 环境(只读)
40
+ ```
41
+
42
+ ## 特殊参数处理
43
+
44
+ 如果用户输入 `/query-db` 或 `/query-db --help`,显示此帮助文档,不执行查询。
45
+
46
+ ## Claude Code 执行步骤
47
+
48
+ **重要提示**:根据用户指定的 `environment` 参数选择执行方式:
49
+ - `ci` 或未指定 → 通过 SSH 连接 Docker Postgres(第 0 节,默认)
50
+ - `stage` → 通过 AWS RDS 端点连接(第 1 节)
51
+ - `prod` → 通过 AWS RDS 端点连接(第 2 节,⚠️ 只读)
52
+
53
+ ### 0. CI 环境(environment = "ci" 或默认)
54
+
55
+ **访问方式**: SSH + Docker Exec
56
+
57
+ **步骤**:
58
+ ```bash
59
+ # IMPORTANT: 使用单行命令
60
+
61
+ # 获取 CI 服务器配置
62
+ CI_USER=$(gh variable get CI_SSH_USER -R Optima-Chat/optima-dev-skills)
63
+ CI_HOST=$(gh variable get CI_SSH_HOST -R Optima-Chat/optima-dev-skills)
64
+ CI_PASSWORD=$(gh variable get CI_SSH_PASSWORD -R Optima-Chat/optima-dev-skills)
65
+
66
+ # 执行查询(根据服务选择不同的数据库)
67
+ sshpass -p "$CI_PASSWORD" ssh -o StrictHostKeyChecking=no ${CI_USER}@${CI_HOST} "docker exec commerce-postgres psql -U commerce -d commerce -c \"SELECT COUNT(*) FROM products\""
68
+ ```
69
+
70
+ **数据库配置映射**:
71
+ - `commerce-backend`:
72
+ - 容器: `commerce-postgres`
73
+ - 用户: `commerce`
74
+ - 密码: `commerce123`
75
+ - 数据库: `commerce`
76
+
77
+ - `user-auth`:
78
+ - 容器: `user-auth-postgres-1`
79
+ - 用户: `userauth`
80
+ - 密码: `password123`
81
+ - 数据库: `userauth`
82
+
83
+ - `mcp-host`:
84
+ - 容器: `mcp-host-db-1`
85
+ - 用户: `mcp_user`
86
+ - 密码: `mcp_password`
87
+ - 数据库: `mcp_host`
88
+
89
+ - `agentic-chat`:
90
+ - 容器: `optima-postgres`
91
+ - 用户: `postgres`
92
+ - 密码: `postgres123`
93
+ - 数据库: `optima_chat`
94
+
95
+ **完整命令示例**:
96
+ ```bash
97
+ # 获取配置
98
+ CI_USER=$(gh variable get CI_SSH_USER -R Optima-Chat/optima-dev-skills)
99
+ CI_HOST=$(gh variable get CI_SSH_HOST -R Optima-Chat/optima-dev-skills)
100
+ CI_PASSWORD=$(gh variable get CI_SSH_PASSWORD -R Optima-Chat/optima-dev-skills)
101
+
102
+ # commerce-backend
103
+ sshpass -p "$CI_PASSWORD" ssh -o StrictHostKeyChecking=no ${CI_USER}@${CI_HOST} "docker exec commerce-postgres psql -U commerce -d commerce -c \"SELECT COUNT(*) FROM products\""
104
+
105
+ # user-auth
106
+ sshpass -p "$CI_PASSWORD" ssh -o StrictHostKeyChecking=no ${CI_USER}@${CI_HOST} "docker exec user-auth-postgres-1 psql -U userauth -d userauth -c \"SELECT COUNT(*) FROM users\""
107
+
108
+ # mcp-host
109
+ sshpass -p "$CI_PASSWORD" ssh -o StrictHostKeyChecking=no ${CI_USER}@${CI_HOST} "docker exec mcp-host-db-1 psql -U mcp_user -d mcp_host -c \"SELECT COUNT(*) FROM sessions\""
110
+
111
+ # agentic-chat
112
+ sshpass -p "$CI_PASSWORD" ssh -o StrictHostKeyChecking=no ${CI_USER}@${CI_HOST} "docker exec optima-postgres psql -U postgres -d optima_chat -c \"SELECT COUNT(*) FROM conversations\""
113
+ ```
114
+
115
+ ### 1. Stage 环境(environment = "stage")
116
+
117
+ **访问方式**: 通过 EC2 SSH 隧道访问 RDS(通过 Infisical 获取密钥)
118
+
119
+ **前置条件**:
120
+ 1. 获取 `optima-ec2-key` SSH 密钥文件(联系 xbfool)
121
+ 2. 保存到 `~/.ssh/optima-ec2-key` 并设置权限: `chmod 600 ~/.ssh/optima-ec2-key`
122
+
123
+ **步骤**:
124
+ ```bash
125
+ # IMPORTANT: 使用单行命令
126
+
127
+ # 1. 获取 Infisical 配置
128
+ INFISICAL_URL=$(gh variable get INFISICAL_URL -R Optima-Chat/optima-dev-skills)
129
+ INFISICAL_CLIENT_ID=$(gh variable get INFISICAL_CLIENT_ID -R Optima-Chat/optima-dev-skills)
130
+ INFISICAL_CLIENT_SECRET=$(gh variable get INFISICAL_CLIENT_SECRET -R Optima-Chat/optima-dev-skills)
131
+ INFISICAL_PROJECT_ID=$(gh variable get INFISICAL_PROJECT_ID -R Optima-Chat/optima-dev-skills)
132
+
133
+ # 2. 获取 Infisical Access Token
134
+ INFISICAL_TOKEN=$(curl -s -X POST "${INFISICAL_URL}/api/v1/auth/universal-auth/login" \
135
+ -H "Content-Type: application/json" \
136
+ -d "{\"clientId\": \"${INFISICAL_CLIENT_ID}\", \"clientSecret\": \"${INFISICAL_CLIENT_SECRET}\"}" \
137
+ | python3 -c "import sys, json; print(json.load(sys.stdin)['accessToken'])")
138
+
139
+ # 3. 从 Infisical 获取数据库配置(以 commerce-backend 为例)
140
+ curl -s "${INFISICAL_URL}/api/v3/secrets/raw?workspaceId=${INFISICAL_PROJECT_ID}&environment=staging&secretPath=/infrastructure" \
141
+ -H "Authorization: Bearer ${INFISICAL_TOKEN}" | python3 -c "
142
+ import sys, json
143
+ secrets = {s['secretKey']: s['secretValue'] for s in json.load(sys.stdin)['secrets']}
144
+ print(f\"DATABASE_HOST={secrets['DATABASE_HOST']}\")
145
+ print(f\"COMMERCE_DB_USER={secrets['COMMERCE_DB_USER']}\")
146
+ print(f\"COMMERCE_DB_PASSWORD={secrets['COMMERCE_DB_PASSWORD']}\")
147
+ " > /tmp/stage_db_config.sh && source /tmp/stage_db_config.sh
148
+
149
+ # 4. 建立 SSH 隧道到 Stage EC2,通过隧道访问 RDS
150
+ ssh -i ~/.ssh/optima-ec2-key -f -N -L 15432:${DATABASE_HOST}:5432 ec2-user@54.179.132.102
151
+
152
+ # 5. 通过本地端口 15432 连接到 RDS
153
+ PGPASSWORD="${COMMERCE_DB_PASSWORD}" psql -h localhost -p 15432 -U "${COMMERCE_DB_USER}" -d optima_stage_commerce -c "SELECT COUNT(*) FROM products"
154
+
155
+ # 6. 关闭 SSH 隧道(可选)
156
+ pkill -f "ssh.*15432:${DATABASE_HOST}:5432"
157
+ ```
158
+
159
+ **完整示例(四个服务)**:
160
+ ```bash
161
+ # commerce-backend
162
+ # 使用 COMMERCE_DB_USER, COMMERCE_DB_PASSWORD, 数据库: optima_stage_commerce
163
+
164
+ # user-auth
165
+ # 使用 AUTH_DB_USER, AUTH_DB_PASSWORD, 数据库: optima_stage_auth
166
+
167
+ # mcp-host
168
+ # 使用 MCP_DB_USER, MCP_DB_PASSWORD, 数据库: optima_stage_mcp
169
+
170
+ # agentic-chat
171
+ # 使用 CHAT_DB_USER, CHAT_DB_PASSWORD, 数据库: optima_stage_chat
172
+ ```
173
+
174
+ **数据库配置映射**:
175
+ - `commerce-backend`:
176
+ - 数据库: `optima_stage_commerce`
177
+ - 用户: Infisical `COMMERCE_DB_USER`
178
+ - 密码: Infisical `COMMERCE_DB_PASSWORD`
179
+
180
+ - `user-auth`:
181
+ - 数据库: `optima_stage_auth`
182
+ - 用户: Infisical `AUTH_DB_USER`
183
+ - 密码: Infisical `AUTH_DB_PASSWORD`
184
+
185
+ - `mcp-host`:
186
+ - 数据库: `optima_stage_mcp`
187
+ - 用户: Infisical `MCP_DB_USER`
188
+ - 密码: Infisical `MCP_DB_PASSWORD`
189
+
190
+ - `agentic-chat`:
191
+ - 数据库: `optima_stage_chat`
192
+ - 用户: Infisical `CHAT_DB_USER`
193
+ - 密码: Infisical `CHAT_DB_PASSWORD`
194
+
195
+ **说明**:
196
+ - Infisical 配置从 GitHub Variables 获取
197
+ - 数据库密钥从 Infisical 动态获取(项目: optima-secrets, 环境: staging, 路径: /infrastructure)
198
+ - DATABASE_HOST: `optima-prod-postgres.ctg866o0ehac.ap-southeast-1.rds.amazonaws.com`
199
+ - Stage EC2 IP: `54.179.132.102`
200
+ - SSH 隧道: 本地端口 `15432` → EC2 → RDS `5432`
201
+ - Stage 和 Prod 共享同一个 RDS 实例,通过不同的数据库名隔离
202
+
203
+ ### 2. Prod 环境(environment = "prod")
204
+
205
+ **访问方式**: 通过 EC2 SSH 隧道访问 RDS(通过 Infisical 获取密钥)
206
+
207
+ **前置条件**:
208
+ 1. 获取 `optima-ec2-key` SSH 密钥文件(联系 xbfool)
209
+ 2. 保存到 `~/.ssh/optima-ec2-key` 并设置权限: `chmod 600 ~/.ssh/optima-ec2-key`
210
+
211
+ **步骤**:
212
+ ```bash
213
+ # IMPORTANT: 使用单行命令
214
+ # ⚠️ 生产环境谨慎操作
215
+
216
+ # 1. 获取 Infisical 配置
217
+ INFISICAL_URL=$(gh variable get INFISICAL_URL -R Optima-Chat/optima-dev-skills)
218
+ INFISICAL_CLIENT_ID=$(gh variable get INFISICAL_CLIENT_ID -R Optima-Chat/optima-dev-skills)
219
+ INFISICAL_CLIENT_SECRET=$(gh variable get INFISICAL_CLIENT_SECRET -R Optima-Chat/optima-dev-skills)
220
+ INFISICAL_PROJECT_ID=$(gh variable get INFISICAL_PROJECT_ID -R Optima-Chat/optima-dev-skills)
221
+
222
+ # 2. 获取 Infisical Access Token
223
+ INFISICAL_TOKEN=$(curl -s -X POST "${INFISICAL_URL}/api/v1/auth/universal-auth/login" \
224
+ -H "Content-Type: application/json" \
225
+ -d "{\"clientId\": \"${INFISICAL_CLIENT_ID}\", \"clientSecret\": \"${INFISICAL_CLIENT_SECRET}\"}" \
226
+ | python3 -c "import sys, json; print(json.load(sys.stdin)['accessToken'])")
227
+
228
+ # 3. 从 Infisical 获取数据库配置(以 commerce-backend 为例)
229
+ curl -s "${INFISICAL_URL}/api/v3/secrets/raw?workspaceId=${INFISICAL_PROJECT_ID}&environment=prod&secretPath=/infrastructure" \
230
+ -H "Authorization: Bearer ${INFISICAL_TOKEN}" | python3 -c "
231
+ import sys, json
232
+ secrets = {s['secretKey']: s['secretValue'] for s in json.load(sys.stdin)['secrets']}
233
+ print(f\"DATABASE_HOST={secrets['DATABASE_HOST']}\")
234
+ print(f\"COMMERCE_DB_USER={secrets['COMMERCE_DB_USER']}\")
235
+ print(f\"COMMERCE_DB_PASSWORD={secrets['COMMERCE_DB_PASSWORD']}\")
236
+ " > /tmp/prod_db_config.sh && source /tmp/prod_db_config.sh
237
+
238
+ # 4. 建立 SSH 隧道到 Prod EC2,通过隧道访问 RDS
239
+ ssh -i ~/.ssh/optima-ec2-key -f -N -L 15433:${DATABASE_HOST}:5432 ec2-user@18.136.25.239
240
+
241
+ # 5. 通过本地端口 15433 连接到 RDS
242
+ PGPASSWORD="${COMMERCE_DB_PASSWORD}" psql -h localhost -p 15433 -U "${COMMERCE_DB_USER}" -d optima_commerce -c "SELECT COUNT(*) FROM products"
243
+
244
+ # 6. 关闭 SSH 隧道(可选)
245
+ pkill -f "ssh.*15433:${DATABASE_HOST}:5432"
246
+ ```
247
+
248
+ **完整示例(四个服务)**:
249
+ ```bash
250
+ # commerce-backend
251
+ # 使用 COMMERCE_DB_USER, COMMERCE_DB_PASSWORD, 数据库: optima_commerce
252
+
253
+ # user-auth
254
+ # 使用 AUTH_DB_USER, AUTH_DB_PASSWORD, 数据库: optima_auth
255
+
256
+ # mcp-host
257
+ # 使用 MCP_DB_USER, MCP_DB_PASSWORD, 数据库: optima_mcp
258
+
259
+ # agentic-chat
260
+ # 使用 CHAT_DB_USER, CHAT_DB_PASSWORD, 数据库: optima_chat
261
+ ```
262
+
263
+ **数据库配置映射**:
264
+ - `commerce-backend`:
265
+ - 数据库: `optima_commerce`
266
+ - 用户: Infisical `COMMERCE_DB_USER`
267
+ - 密码: Infisical `COMMERCE_DB_PASSWORD`
268
+
269
+ - `user-auth`:
270
+ - 数据库: `optima_auth`
271
+ - 用户: Infisical `AUTH_DB_USER`
272
+ - 密码: Infisical `AUTH_DB_PASSWORD`
273
+
274
+ - `mcp-host`:
275
+ - 数据库: `optima_mcp`
276
+ - 用户: Infisical `MCP_DB_USER`
277
+ - 密码: Infisical `MCP_DB_PASSWORD`
278
+
279
+ - `agentic-chat`:
280
+ - 数据库: `optima_chat`
281
+ - 用户: Infisical `CHAT_DB_USER`
282
+ - 密码: Infisical `CHAT_DB_PASSWORD`
283
+
284
+ **说明**:
285
+ - Infisical 配置从 GitHub Variables 获取
286
+ - 数据库密钥从 Infisical 动态获取(项目: optima-secrets, 环境: prod, 路径: /infrastructure)
287
+ - DATABASE_HOST: `optima-prod-postgres.ctg866o0ehac.ap-southeast-1.rds.amazonaws.com`
288
+ - Prod EC2 IP: `18.136.25.239`
289
+ - SSH 隧道: 本地端口 `15433` → EC2 → RDS `5432` (注意 Prod 用 15433,Stage 用 15432)
290
+ - Stage 和 Prod 共享同一个 RDS 实例,通过不同的数据库名隔离
291
+
292
+ **⚠️ 生产环境安全规则**:
293
+ 1. **谨慎操作** - 生产数据库,避免误操作
294
+ 2. **避免 DELETE/UPDATE** - 除非明确需要
295
+ 3. **使用 LIMIT** - 防止查询过多数据
296
+ 4. **不查敏感数据** - 避免查询密码、密钥等
297
+
298
+ ## 安全注意事项
299
+
300
+ ### SQL 注入防护
301
+
302
+ **❌ 危险示例**:
303
+ ```bash
304
+ # 不要直接拼接用户输入
305
+ /query-db commerce-backend "SELECT * FROM products WHERE id=$USER_INPUT"
306
+ ```
307
+
308
+ **✅ 安全示例**:
309
+ ```bash
310
+ # 使用参数化查询或明确的值
311
+ /query-db commerce-backend "SELECT * FROM products WHERE id=123"
312
+ ```
313
+
314
+ ### 生产环境规则
315
+
316
+ 1. **只读查询**: 生产环境只允许 SELECT
317
+ 2. **限制返回行数**: 使用 LIMIT
318
+ 3. **避免全表扫描**: 使用 WHERE 条件
319
+ 4. **敏感数据**: 不查询密码、密钥等敏感字段
320
+
321
+ ### 常见安全查询
322
+
323
+ ```bash
324
+ # ✅ 统计查询
325
+ /query-db commerce-backend "SELECT COUNT(*) FROM orders WHERE created_at > NOW() - INTERVAL '1 day'" prod
326
+
327
+ # ✅ 限制行数
328
+ /query-db user-auth "SELECT id, email, created_at FROM users ORDER BY created_at DESC LIMIT 10" prod
329
+
330
+ # ✅ 聚合查询
331
+ /query-db commerce-backend "SELECT status, COUNT(*) FROM orders GROUP BY status" prod
332
+
333
+ # ❌ 危险:全表查询
334
+ # /query-db commerce-backend "SELECT * FROM orders" prod
335
+
336
+ # ❌ 危险:敏感字段
337
+ # /query-db user-auth "SELECT password_hash FROM users" prod
338
+ ```
339
+
340
+ ## 常见错误处理
341
+
342
+ ### 错误:Connection refused
343
+
344
+ **原因**: 数据库未运行或网络不通
345
+
346
+ **解决**:
347
+ ```bash
348
+ # CI: 检查容器状态
349
+ sshpass -p "$CI_PASSWORD" ssh ${CI_USER}@${CI_HOST} "docker ps | grep postgres"
350
+
351
+ # Stage/Prod: 检查安全组和网络配置
352
+ ```
353
+
354
+ ### 错误:Authentication failed
355
+
356
+ **原因**: 用户名或密码错误
357
+
358
+ **解决**: 检查 GitHub Variables 配置是否正确
359
+
360
+ ### 错误:Permission denied
361
+
362
+ **原因**: 生产环境使用了写操作
363
+
364
+ **解决**: 使用只读查询,移除 INSERT/UPDATE/DELETE
365
+
366
+ ## 最佳实践
367
+
368
+ 1. **默认使用 CI**: 开发调试优先用 CI 环境
369
+ 2. **生产只读**: Prod 环境只用于查看数据,不修改
370
+ 3. **添加 LIMIT**: 避免返回过多数据
371
+ 4. **使用聚合**: COUNT/SUM/AVG 比 SELECT * 更安全
372
+ 5. **索引查询**: 使用主键或索引字段提高性能
373
+
374
+ ## 相关资源
375
+
376
+ - PostgreSQL 文档: https://www.postgresql.org/docs/
377
+ - AWS RDS 最佳实践: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/
@@ -23,7 +23,12 @@
23
23
  "Bash(npm install:*)",
24
24
  "Bash(optima-dev-skills:*)",
25
25
  "Bash(gh variable set:*)",
26
- "Bash(npm publish:*)"
26
+ "Bash(npm publish:*)",
27
+ "Bash(curl -s \"https://secrets.optima.onl/api/v3/secrets/raw?workspaceId=f2415dc2-f79d-4e41-90bb-cd3d2631ec71&environment=staging&secretPath=/infrastructure\" -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eUlkIjoiMjZiNmYxMmItZjNjYy00OTE2LTliMTItNWFiYzZhMTlmNGI0IiwiY2xpZW50U2VjcmV0SWQiOiIxZjRhM2I0Ni03NTZmLTQwNmItOGQ1OS0yODI0YjUzOGFlMmMiLCJpZGVudGl0eUFjY2Vzc1Rva2VuSWQiOiJlMDQ1Y2MyOC02Nzk5LTRhODYtYWEwNy02YTQ4NmZkYzczODgiLCJhdXRoVG9rZW5UeXBlIjoiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImlhdCI6MTc2MzkxMzAxNywiZXhwIjoxNzY2NTA1MDE3fQ.xkPyv9MwXKLg3t-h1C_6mHSV5-cFuuvHnrkOoaGtuaQ\")",
28
+ "Bash(python3:*)",
29
+ "Bash(curl -s \"https://secrets.optima.onl/api/v1/folders?workspaceId=f2415dc2-f79d-4e41-90bb-cd3d2631ec71&environment=prod\" -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eUlkIjoiMjZiNmYxMmItZjNjYy00OTE2LTliMTItNWFiYzZhMTlmNGI0IiwiY2xpZW50U2VjcmV0SWQiOiIxZjRhM2I0Ni03NTZmLTQwNmItOGQ1OS0yODI0YjUzOGFlMmMiLCJpZGVudGl0eUFjY2Vzc1Rva2VuSWQiOiJlMDQ1Y2MyOC02Nzk5LTRhODYtYWEwNy02YTQ4NmZkYzczODgiLCJhdXRoVG9rZW5UeXBlIjoiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImlhdCI6MTc2MzkxMzAxNywiZXhwIjoxNzY2NTA1MDE3fQ.xkPyv9MwXKLg3t-h1C_6mHSV5-cFuuvHnrkOoaGtuaQ\")",
30
+ "Bash(curl -s \"https://secrets.optima.onl/api/v3/secrets/raw?workspaceId=f2415dc2-f79d-4e41-90bb-cd3d2631ec71&environment=prod&secretPath=/infrastructure\" -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eUlkIjoiMjZiNmYxMmItZjNjYy00OTE2LTliMTItNWFiYzZhMTlmNGI0IiwiY2xpZW50U2VjcmV0SWQiOiIxZjRhM2I0Ni03NTZmLTQwNmItOGQ1OS0yODI0YjUzOGFlMmMiLCJpZGVudGl0eUFjY2Vzc1Rva2VuSWQiOiJlMDQ1Y2MyOC02Nzk5LTRhODYtYWEwNy02YTQ4NmZkYzczODgiLCJhdXRoVG9rZW5UeXBlIjoiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImlhdCI6MTc2MzkxMzAxNywiZXhwIjoxNzY2NTA1MDE3fQ.xkPyv9MwXKLg3t-h1C_6mHSV5-cFuuvHnrkOoaGtuaQ\")",
31
+ "Bash(gh api:*)"
27
32
  ],
28
33
  "deny": [],
29
34
  "ask": []
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: "query-db"
3
+ description: "当用户请求查询数据库、执行SQL、查看数据、统计数据、检查数据库、查询表、数据库查询时,使用此技能。支持 CI、Stage、Prod 三个环境的 commerce-backend、user-auth、mcp-host、agentic-chat 服务的数据库查询。"
4
+ allowed-tools: ["Bash", "SlashCommand"]
5
+ ---
6
+
7
+ # 查询数据库
8
+
9
+ 当你需要执行 SQL 查询检查数据时,使用这个场景。
10
+
11
+ ## 🎯 适用情况
12
+
13
+ - 验证数据是否正确插入/更新
14
+ - 统计数据(用户数、订单数等)
15
+ - 排查数据问题
16
+ - 检查数据库状态
17
+ - 开发调试时查看数据
18
+
19
+ ## 🚀 快速操作
20
+
21
+ ### 1. 查询 CI 环境数据库(默认)
22
+
23
+ ```
24
+ /query-db commerce-backend "SELECT COUNT(*) FROM products"
25
+ /query-db user-auth "SELECT email FROM users LIMIT 5"
26
+ ```
27
+
28
+ **说明**:
29
+ - 查询 CI 开发环境数据库
30
+ - 默认环境,不需要指定 `ci` 参数
31
+ - 通过 SSH + Docker Exec 访问
32
+ - 可以执行任何 SQL 语句
33
+
34
+ ### 2. 查询 Stage 环境数据库
35
+
36
+ ```
37
+ /query-db commerce-backend "SELECT COUNT(*) FROM orders" stage
38
+ ```
39
+
40
+ **说明**:
41
+ - 查询 Stage 预发布环境
42
+ - 通过 AWS RDS 直连
43
+
44
+ ### 3. 查询 Prod 环境数据库
45
+
46
+ ```
47
+ /query-db commerce-backend "SELECT status, COUNT(*) FROM orders GROUP BY status" prod
48
+ ```
49
+
50
+ **说明**:
51
+ - 查询生产环境数据库
52
+ - ⚠️ **只读查询**,不能修改数据
53
+ - 使用只读用户连接
54
+
55
+ **常用服务**:
56
+ - `commerce-backend` - 电商数据库
57
+ - `user-auth` - 用户认证数据库
58
+ - `mcp-host` - MCP 协调器数据库
59
+ - `agentic-chat` - AI 聊天数据库
60
+
61
+ ### 4. 常用查询示例
62
+
63
+ ```
64
+ # 统计查询
65
+ /query-db commerce-backend "SELECT COUNT(*) FROM products WHERE status='active'"
66
+
67
+ # 查看最新数据
68
+ /query-db user-auth "SELECT id, email, created_at FROM users ORDER BY created_at DESC LIMIT 10"
69
+
70
+ # 聚合统计
71
+ /query-db commerce-backend "SELECT status, COUNT(*) as count FROM orders GROUP BY status"
72
+
73
+ # 检查特定记录
74
+ /query-db user-auth "SELECT * FROM users WHERE email='user@example.com'"
75
+ ```
76
+
77
+ ## 📋 常见使用场景
78
+
79
+ ### 场景 1:验证新功能
80
+
81
+ **步骤**:
82
+ 1. 创建数据后查询:`/query-db commerce-backend "SELECT * FROM products WHERE title='新商品'"`
83
+ 2. 检查关联数据:`/query-db commerce-backend "SELECT * FROM product_variants WHERE product_id=123"`
84
+
85
+ ### 场景 2:数据统计
86
+
87
+ **步骤**:
88
+ 1. 统计总数:`/query-db user-auth "SELECT COUNT(*) FROM users"`
89
+ 2. 分组统计:`/query-db commerce-backend "SELECT DATE(created_at), COUNT(*) FROM orders GROUP BY DATE(created_at)"`
90
+
91
+ ### 场景 3:排查问题
92
+
93
+ **步骤**:
94
+ 1. 查找异常数据:`/query-db commerce-backend "SELECT * FROM orders WHERE status IS NULL"`
95
+ 2. 检查重复数据:`/query-db user-auth "SELECT email, COUNT(*) FROM users GROUP BY email HAVING COUNT(*) > 1"`
96
+
97
+ ## ⚠️ 安全提示
98
+
99
+ ### 生产环境规则
100
+
101
+ 1. **只读查询**: 只使用 SELECT,不能 INSERT/UPDATE/DELETE
102
+ 2. **限制返回**: 使用 LIMIT 限制返回行数
103
+ 3. **避免全表**: 使用 WHERE 条件
104
+ 4. **不查敏感数据**: 避免查询密码、密钥等
105
+
106
+ ### 安全查询示例
107
+
108
+ ```
109
+ # ✅ 好的查询
110
+ /query-db commerce-backend "SELECT COUNT(*) FROM orders WHERE created_at > NOW() - INTERVAL '1 day'" prod
111
+ /query-db user-auth "SELECT id, email FROM users LIMIT 10" prod
112
+
113
+ # ❌ 不好的查询
114
+ # /query-db commerce-backend "SELECT * FROM orders" prod (全表扫描)
115
+ # /query-db user-auth "SELECT password_hash FROM users" prod (敏感数据)
116
+ ```
117
+
118
+ ## 💡 最佳实践
119
+
120
+ 1. **开发用 CI**: 调试和验证优先用 CI 环境
121
+ 2. **生产只读**: Prod 环境只查看,不修改
122
+ 3. **使用聚合**: COUNT/SUM/AVG 比 SELECT * 更好
123
+ 4. **添加限制**: 总是使用 LIMIT
124
+ 5. **指定列名**: 避免 SELECT *
125
+
126
+ ## 🌐 环境对比
127
+
128
+ ### CI 环境
129
+
130
+ ```
131
+ /query-db commerce-backend "SELECT COUNT(*) FROM products"
132
+ ```
133
+
134
+ **特点**:
135
+ - 开发环境,可以任意查询和修改
136
+ - 数据可以随时重置
137
+ - 通过 Docker 容器访问
138
+
139
+ ### Stage 环境
140
+
141
+ ```
142
+ /query-db commerce-backend "SELECT COUNT(*) FROM orders" stage
143
+ ```
144
+
145
+ **特点**:
146
+ - 预发布环境
147
+ - 数据接近生产
148
+ - 通过 AWS RDS 访问
149
+
150
+ ### Prod 环境
151
+
152
+ ```
153
+ /query-db commerce-backend "SELECT status, COUNT(*) FROM orders GROUP BY status" prod
154
+ ```
155
+
156
+ **特点**:
157
+ - 生产环境,只读访问
158
+ - 真实用户数据
159
+ - ⚠️ 谨慎使用
160
+
161
+ ## 🔗 相关命令
162
+
163
+ - `/query-db` - 查询数据库(详细使用方法请查看 `/query-db --help`)
package/README.md CHANGED
@@ -23,11 +23,12 @@ Optima Dev Skills 让 Claude Code 能够直接在 **CI、Stage、Prod** 三个
23
23
  - **任务驱动** - 基于具体任务场景(查看日志、调用 API),不是抽象分类
24
24
  - **跨环境协作** - 统一的命令在 CI、Stage、Prod 三个环境中使用
25
25
 
26
- ## 📋 任务场景(1 个)
26
+ ## 📋 任务场景(2 个)
27
27
 
28
28
  当 Claude Code 识别到以下任务时,会自动加载对应的 Skill:
29
29
 
30
30
  - **logs** - 查看 CI/Stage/Prod 的服务器日志
31
+ - **query-db** - 查询 CI/Stage/Prod 的数据库
31
32
 
32
33
  ## 👤 用户故事
33
34
 
@@ -69,12 +70,13 @@ Claude:
69
70
 
70
71
  | 命令 | 说明 | 示例 | 跨环境 |
71
72
  |------|------|------|--------|
72
- | `/logs` | 查看服务日志 | `/logs commerce-backend 100 stage` | ✅ |
73
+ | `/logs` | 查看服务日志 | `/logs commerce-backend 100` | ✅ |
74
+ | `/query-db` | 查询数据库 | `/query-db user-auth "SELECT COUNT(*) FROM users"` | ✅ |
73
75
 
74
76
  **说明**:
75
77
  - 命令支持 CI、Stage、Prod 三个环境
76
- - Claude Code 会根据上下文自动选择环境
77
- - 命令提供信息和入口,具体操作由 Claude Code 智能完成
78
+ - 默认使用 CI 环境,适合日常开发
79
+ - Claude Code 会根据上下文自动选择环境和执行方式
78
80
 
79
81
  ## 🏗️ 项目结构
80
82
 
@@ -82,10 +84,13 @@ Claude:
82
84
  optima-dev-skills/
83
85
  ├── .claude/
84
86
  │ ├── commands/
85
- │ │ └── logs.md # /logs - 查看服务日志
87
+ │ │ ├── logs.md # /logs - 查看服务日志
88
+ │ │ └── query-db.md # /query-db - 查询数据库
86
89
  │ │
87
90
  │ └── skills/
88
- └── logs/ # 日志查看 skill
91
+ ├── logs/ # 日志查看 skill
92
+ │ │ └── SKILL.md
93
+ │ └── query-db/ # 数据库查询 skill
89
94
  │ └── SKILL.md
90
95
 
91
96
  └── docs/
@@ -157,14 +162,15 @@ Claude:
157
162
 
158
163
  ## 🛠️ 开发状态
159
164
 
160
- **当前版本**: 0.2.1
165
+ **当前版本**: 0.3.0
161
166
 
162
167
  **已完成**:
163
- - ✅ 1 个跨环境命令:`/logs`
164
- - ✅ 1 个任务场景:`logs` skill
168
+ - ✅ 2 个跨环境命令:`/logs`、`/query-db`
169
+ - ✅ 2 个任务场景:`logs` skill、`query-db` skill
165
170
  - ✅ 支持 CI、Stage、Prod 三个环境
166
- - ✅ CI 环境通过 SSH + Docker Compose 访问
167
- - ✅ Stage/Prod 通过 AWS CloudWatch Logs 访问
171
+ - ✅ CI 环境通过 SSH + Docker 访问
172
+ - ✅ Stage/Prod 通过 AWS 服务访问
173
+ - ✅ 数据库查询支持只读模式(Prod)
168
174
 
169
175
  **设计原则**:
170
176
  - 命令提供信息(URL、路径、凭证位置),不实现复杂逻辑
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optima-chat/dev-skills",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "description": "Claude Code Skills for Optima development team - cross-environment collaboration tools",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -7,7 +7,8 @@ const os = require('os');
7
7
  const CLAUDE_DIR = path.join(os.homedir(), '.claude');
8
8
  const SKILLS_SOURCE = path.join(__dirname, '..', '.claude');
9
9
  const COMMANDS_DEST = path.join(CLAUDE_DIR, 'commands');
10
- const SKILLS_DEST = path.join(CLAUDE_DIR, 'skills', 'logs');
10
+ const LOGS_SKILL_DEST = path.join(CLAUDE_DIR, 'skills', 'logs');
11
+ const QUERY_DB_SKILL_DEST = path.join(CLAUDE_DIR, 'skills', 'query-db');
11
12
 
12
13
  // 颜色输出
13
14
  const colors = {
@@ -50,34 +51,47 @@ function install() {
50
51
  }
51
52
 
52
53
  // 安装命令
53
- const commandsSource = path.join(SKILLS_SOURCE, 'commands', 'logs.md');
54
- const commandsDest = path.join(COMMANDS_DEST, 'logs.md');
55
- if (fs.existsSync(commandsSource)) {
56
- if (!fs.existsSync(COMMANDS_DEST)) {
57
- fs.mkdirSync(COMMANDS_DEST, { recursive: true });
58
- }
59
- fs.copyFileSync(commandsSource, commandsDest);
60
- log(`✓ Installed /logs command to ${commandsDest}`, 'green');
61
- } else {
62
- log(`✗ Commands not found at ${commandsSource}`, 'red');
54
+ if (!fs.existsSync(COMMANDS_DEST)) {
55
+ fs.mkdirSync(COMMANDS_DEST, { recursive: true });
63
56
  }
64
57
 
65
- // 安装 skills
66
- const skillsSource = path.join(SKILLS_SOURCE, 'skills', 'logs');
67
- if (fs.existsSync(skillsSource)) {
68
- copyRecursive(skillsSource, SKILLS_DEST);
69
- log(`✓ Installed logs skill to ${SKILLS_DEST}`, 'green');
70
- } else {
71
- log(`✗ Skills not found at ${skillsSource}`, 'red');
58
+ // 安装 /logs 命令
59
+ const logsCommandSource = path.join(SKILLS_SOURCE, 'commands', 'logs.md');
60
+ const logsCommandDest = path.join(COMMANDS_DEST, 'logs.md');
61
+ if (fs.existsSync(logsCommandSource)) {
62
+ fs.copyFileSync(logsCommandSource, logsCommandDest);
63
+ log(`✓ Installed /logs command`, 'green');
64
+ }
65
+
66
+ // 安装 /query-db 命令
67
+ const queryDbCommandSource = path.join(SKILLS_SOURCE, 'commands', 'query-db.md');
68
+ const queryDbCommandDest = path.join(COMMANDS_DEST, 'query-db.md');
69
+ if (fs.existsSync(queryDbCommandSource)) {
70
+ fs.copyFileSync(queryDbCommandSource, queryDbCommandDest);
71
+ log(`✓ Installed /query-db command`, 'green');
72
+ }
73
+
74
+ // 安装 logs skill
75
+ const logsSkillSource = path.join(SKILLS_SOURCE, 'skills', 'logs');
76
+ if (fs.existsSync(logsSkillSource)) {
77
+ copyRecursive(logsSkillSource, LOGS_SKILL_DEST);
78
+ log(`✓ Installed logs skill`, 'green');
79
+ }
80
+
81
+ // 安装 query-db skill
82
+ const queryDbSkillSource = path.join(SKILLS_SOURCE, 'skills', 'query-db');
83
+ if (fs.existsSync(queryDbSkillSource)) {
84
+ copyRecursive(queryDbSkillSource, QUERY_DB_SKILL_DEST);
85
+ log(`✓ Installed query-db skill`, 'green');
72
86
  }
73
87
 
74
88
  log('\n✨ Installation complete!\n', 'green');
75
89
  log('Available commands:', 'blue');
76
90
  log(' /logs <service> [lines] [environment]', 'yellow');
91
+ log(' /query-db <service> <sql> [environment]', 'yellow');
77
92
  log('\nExamples:', 'blue');
78
- log(' /logs commerce-backend # Stage, 50 lines', 'yellow');
79
- log(' /logs user-auth 100 # Stage, 100 lines', 'yellow');
80
- log(' /logs mcp-host 200 prod # Prod, 200 lines', 'yellow');
93
+ log(' /logs commerce-backend # CI logs', 'yellow');
94
+ log(' /query-db commerce-backend "SELECT COUNT(*) FROM orders" # CI query', 'yellow');
81
95
  log('\nDocumentation: https://github.com/Optima-Chat/optima-dev-skills\n', 'blue');
82
96
  }
83
97