Skill(技能):遇到对应任务才加载的一套做法
Skill:按需加载
Skill 是 .claude/skills/名字/SKILL.md。description 写"做什么 + 用户会怎么说",Claude 据此判断要不要读正文,所以平时不占上下文。游客可以看到下面 5 个 Skill 的完整内容。
.claude/skills/acceptance-criteria/SKILL.md 下载---
name: acceptance-criteria
description: "写需求/功能的『验收条件』(怎样算做完、做对)时使用:用 Given-When-Then 把要求写成可测试的是/否条款,每组最多约5条,覆盖正常路径+出错+边界+权限,并写明怎么验证。用户说『验收条件』『怎样算完成』『写测试用例』『需求写清楚』时触发。"
---
# 验收条件写法
## 原则
- 好的验收条件:清楚、具体、可测试;两个人读了会得出同样的"通过/没通过"。
- 格式 Given-When-Then:Given=动作之前的状态,When=用户做的动作,Then=应该看到的变化。
- 每条必须能回答"怎么测?";不能测就改写。把"要快"写成"普通网络下 3 秒内打开"。
- 每组大约 5 条为止;更多就是多个功能,拆开。
- 要覆盖:正常路径、出错状态、边界情况、权限规则。每条独立、有明确的是/否。
- 从用户或业务角度写结果,不写实现方式。
## 额外补充(踩过的坑)
1. 每条后面写「验证方式」:自动测试 / 浏览器自动化(手机与电脑两种宽度)/ 需要人眼 / 需要真机;做不到的如实写"未验证"。
2. 涉及"A 看不到 B / A 不影响 B"(多用户、语言隔离)必须有"反向用例":真的用 B 的身份去试。
3. 能数字化就数字化:页面不横向溢出 = `scrollWidth <= clientWidth`;上线后用 `curl` 确认 200。
4. 能自动化的写进测试脚本,每次改动后顺手跑。
## 模板
```
功能:<名字>
验收条件(≤5条):
1. Given <状态> When <动作> Then <结果> 验证:<方式>
2.(出错)Given … When … Then …
3.(边界)…
4.(权限/隔离)Given 用户甲和乙 When 乙登录 Then 看不到甲的数据 验证:自动测试(两个会话)
```
## 例子:多用户
1. Given 用户甲有收藏 When 乙登录 Then 乙的收藏为空 验证:自动测试
2. Given 乙修改了自己的设置 When 甲刷新 Then 甲的设置不变 验证:自动测试
3. Given 未登录 When 访问他人数据接口 Then 返回 401 验证:自动测试
.claude/skills/deploy-verify/SKILL.md 下载---
name: deploy-verify
description: "把网站/服务改动部署到自己的服务器并验证的固定流程:先备份→语法检查→上传→重启→线上 curl 确认→浏览器实点→写记录。用户说『部署』『上线』『发到服务器』『回滚』『服务重启』时使用。拿不准就先别部署,先问用户。"
---
# 部署 + 验证流程(每步都做,别跳)
先在项目 `CLAUDE.md` 里写清楚:服务器地址、部署目录、服务名、域名。没有就先问用户,不要猜。
1. **备份**:`ssh <服务器> "mkdir -p <目录>/.bak_<日期> && cp <要改的文件> <目录>/.bak_<日期>/"`。回滚 = 拷回来 + 重启。
2. **语法检查**:Node 用 `node --check <文件>`,Python 用 `python -m py_compile <文件>`。前端 JS 改了,把页面里引用它的 `?v=` 版本号加 1(避免缓存),引用它的父文件也要跟着升。
3. **上传**:`scp` 到对应目录。改 nginx 前先备份,`nginx -t` 通过再 `systemctl reload nginx`,只加自己的 server/location,不动别人的。
4. **重启**(只有后端改了才需要):`systemctl restart <服务名> && systemctl is-active <服务名>`。
5. **线上验证**:`curl -s -o /dev/null -w "%{http_code}" <网址>` 检查关键网址(首页、API、新增的图片和静态文件;发现 1 个 404,顺手查同目录其它文件);再用浏览器自动化真的点一遍。
6. **汇报**:写清楚"没测到"的部分(手机真机、并发等),不要把没测的写成"已验证"。
7. **记录**:在项目 `CLAUDE.md` 记 3-5 行(改了什么、备份目录、没测到什么)。
## 红线
- 线上数据只删**自己造的**测试记录,禁止整表 DELETE / 清空。
- 不碰别的项目的 nginx 配置。
- 不把密码/令牌写进 skill、回复、git;密钥放 `secrets/*.env`(加入 `.gitignore`),运行时以服务器上的环境变量为准。
- 重活(视频转码、大下载)一次只跑一个,先看内存 `free -m`。
- 拿不准、怀疑有问题 → 先不部署,跟用户确认。
.claude/skills/skill-writer/SKILL.md 下载---
name: skill-writer
description: "写新 skill 或改进现有 skill 的流程:判断该不该写、怎么拆分(入口 SKILL.md + 按需读取的子文件)、description 怎么写触发词、控制体积。用户说『写一个skill』『把这个做成skill』『skill没触发』『skill太大』时使用。"
---
# 写 skill
## 0. 先判断值不值得写
值得:同一类事做过 ≥2 次且步骤固定;踩过的坑能写成检查清单;有可复用脚本。
不值得:只做一次;已有 rule 或命令覆盖;光是一堆链接(链接没法被搜索和触发,要点必须写进正文)。
## 1. 结构
- 一个 skill = 一个文件夹,入口 `SKILL.md`,开头 `name`(与文件夹同名)+ `description`。
- 简单的只要一个 SKILL.md。复杂的:入口只放"路由 + 关键规则",细节拆到 `references/*.md`,固定动作放 `scripts/*.py`,正文里写"什么时候读哪个文件"。
- 脚本当黑盒用:正文写"先 --help,不读源码"。
## 2. description 决定会不会被触发
- 一段话,写"做什么 + 用户会怎么说":把用户真实会说的词列进去。
- 也写不该触发的场景。
- 不超过约 600 字符。
## 3. 体积
入口 SKILL.md 目标 ≤5KB,硬上限 12KB;超了就拆 references。
## 4. 写完必做
1. 找一个真实任务让它触发一次,看是否按预期走。
2. 在项目 `CLAUDE.md` 记一行,注明 skill 名。
3. 不存密钥/密码进 skill(路径可以写,值不写)。
## 5. 放在哪里
- 个人通用:`~/.claude/skills/<名字>/SKILL.md`
- 只给某个项目:项目里的 `.claude/skills/<名字>/SKILL.md`
.claude/skills/web-standards/SKILL.md 下载---
name: web-standards
description: "做或改任何网站/网页前先读:以行业通用做法为准(可访问性 WCAG、响应式、表单、性能、设置页惯例),偏离通用做法要写进设计文档。用户说『做个网页』『改网站』『界面不好看』『手机显示不对』『设置页放哪』时使用。"
---
# 网站/网页通用标准(精简版)
默认用行业通用做法;要偏离时,在项目 `DESIGN.md` 写明"为什么这样设计"。
## 布局与响应式
- `<meta name="viewport" content="width=device-width, initial-scale=1">` 必须有。
- 不用固定像素宽度做容器;flex 子元素加 `min-width:0` 防止撑爆;长文本 `overflow-wrap:anywhere`。
- 表格、代码块放进可横向滚动的容器,别让整页出现横向滚动条。
- 改完用两个宽度(约 390 和 1400)实测 `scrollWidth <= innerWidth`。
## 可访问性(WCAG 2.2 的常用要点)
- 正文对比度 ≥ 4.5:1;不要只靠颜色表达状态。
- 所有可点元素能用键盘到达,有可见焦点;点击目标 ≥ 24px(手机建议 44px)。
- 图片有 alt;表单输入有 label;错误提示说明原因和怎么改。
- 弹窗:能用 Esc 关闭,打开时焦点进入,关闭后焦点回到触发处。
## 表单与交互
- 一页一个主操作;危险操作(删除)要二次确认并说明后果。
- 不要在用户输入时清空已填内容;提交时禁用按钮防重复提交。
## 设置页惯例
- 顺序:常用 → 外观/语言 → 账号/数据 → 关于(版本与更新)。
- "关于"里放版本号和更新入口。
## 性能与缓存
- 图片压缩、懒加载;静态资源 URL 带 `?v=` 版本号,改了就升版本。
- 部署后用 `curl` 确认关键资源返回 200。
.claude/skills/webapp-testing/SKILL.md 下载---
name: webapp-testing
description: "改完网页前端/后端后,验证『线上真的能用』:双视口(手机约 390 / 电脑约 1400)是否横向溢出、控制台有无 JS 报错、点一遍关键流程、截图存到项目文件夹。用户说『测一下』『验证』『手机显示有问题』『改完看看线上』『Playwright』『截图』时使用。"
---
# 网页验证(线上优先)
## 做法
用 Playwright(`pip install playwright && playwright install chromium`,或 Node 版)对**真实网址**跑:
1. 两个视口各打开一次:`390×844`(手机)和 `1400×900`(电脑)。
2. 等页面稳定(`wait_for_load_state('networkidle')`)。
3. 量横向溢出:`document.documentElement.scrollWidth > innerWidth` 就是溢出。
4. 收集 `console` 的 error,列出条数和前 5 条。
5. 点一遍关键流程(登录、提交、切换语言等),选择器优先用 id 或文本。
6. 截图,保存到**项目自己的文件夹**,用完整绝对路径。
最小示例(Python):
```python
from playwright.sync_api import sync_playwright
URL = "https://你的网址/"
with sync_playwright() as p:
b = p.chromium.launch(headless=True)
for name, w, h in [("phone", 390, 844), ("pc", 1400, 900)]:
pg = b.new_page(viewport={"width": w, "height": h})
errs = []
pg.on("console", lambda m: errs.append(m.text) if m.type == "error" else None)
pg.goto(URL); pg.wait_for_load_state("networkidle")
sw = pg.evaluate("document.documentElement.scrollWidth")
print(name, "scrollWidth", sw, "viewport", w, "overflow" if sw > w else "ok", "errors", len(errs))
pg.screenshot(path=f"/完整/绝对/路径/{name}.png")
b.close()
```
## 必须遵守
1. 截图用完整绝对路径,存项目文件夹,不要丢在根目录。
2. 不改用户真实数据:测试数据自己造、自己删,禁止整表 DELETE。
3. 本地通过 ≠ 线上可用:部署后对真实网址再跑一遍;新增图片等二进制,用 `curl` 逐个确认 200。
4. 手机真机的手感、麦克风、方向锁定脚本测不到,汇报里写"没测到:…",不要写"已验证"。