AI Agent 写代码时,真正拖后腿的经常不是模型能力,而是项目上下文已经变脏了。
代码已经从 SQLite 切到了 PostgreSQL,但项目说明里还写着 SQLite;接口新增了 5 个路由,CLAUDE.md 里有记录,docs/integration-guide.md 里却没有;环境变量换了名字,部署手册仍然沿用旧字段。Agent 每次启动都会读这些材料,一旦材料过期,它就会把错误信息当成事实,然后基于错误前提继续写代码。
洁癖 Skill 解决的就是这个问题:在一次任务结束时,让 Agent 自动审查项目文档、项目约束和记忆文件,把过期、重复、冲突的信息清掉,把新事实沉淀到该去的位置。
它不是让模型“参数变聪明”,而是让 Agent 每次工作时拿到更准确的项目事实。
仓库地址:
https://github.com/KKKKhazix/khazix-skills
它可以用于 Claude Code、Codex、OpenCode、OpenClaw 这类 AI 编程 Agent。最常见的使用方式是在任务结束后输入:
/neat
也可以直接用自然语言说:
审查一下项目文档和记忆,把需要同步的地方整理干净。
为什么 Agent 会越用越乱
一次对话里的上下文,只是 Agent 看到的信息之一。真实项目里,Agent 还会读取很多持久化材料:
- README
docs/目录CLAUDE.md- Agent 自己的记忆文件
- 任务记录、约束说明、运行手册
- 接口文档、部署文档、架构说明
这些内容本来是为了帮助 Agent 理解项目,但它们有一个前提:必须是准确的。
如果文档不维护,项目就会出现“上下文腐败”:
flowchart TD
A[代码持续迭代] --> B[功能、接口、依赖、架构发生变化]
B --> C[文档和记忆没有同步更新]
C --> D[Agent 读取过期信息]
D --> E[基于错误前提生成代码]
E --> F[出现莫名其妙的 bug]
F --> C
很多 Vibe Coding 项目尤其容易遇到这个问题。前期通过对话快速做功能,速度很快;项目变大后,如果没有工程化的文档维护习惯,README、运行手册、项目约束和 Agent 记忆就会逐渐分裂。到最后,Agent 不是“不理解项目”,而是同时读到了多份互相矛盾的项目说明。
典型例子是数据库迁移。
假设项目一开始使用 SQLite,后面切到 PostgreSQL。代码迁移完成后,如果文档没有同步更新,Agent 下次可能仍然写出 SQLite 风格的 SQL,或者继续建议使用本地文件数据库。这个问题不是模型不会 PostgreSQL,而是项目材料告诉它“这里用 SQLite”。
项目知识应该分成三层维护
AI 编程项目里的知识,不应该全部塞进一个记忆文件,也不应该全部写进 README。不同材料服务的对象不同,承载的信息也不同。
| 层级 | 典型文件 | 主要读者 | 应该记录什么 | 不适合记录什么 |
|---|---|---|---|---|
| Agent 记忆 | Agent memory、会话摘要 | Agent 自己 | 项目当前状态、长期约定、已经确认的事实 | 大段接口文档、完整操作手册 |
| 项目约束 | CLAUDE.md 或同类规则文件 | AI 编程工具 | 编码规范、目录结构、禁用做法、关键红线、常用命令 | 面向外部使用者的接入教程 |
| 项目文档 | README.md、docs/ | 人、Agent、协作者、下游系统 | 架构说明、接入指南、部署手册、API 文档、运维说明 | 只对当前 Agent 有意义的临时偏好 |
这三层不能互相替代。
比如新增了 5 个 API 路由:
CLAUDE.md里需要提醒 Agent:这些路由已经存在,不要重复创建,新增接口要遵循同一风格。docs/integration-guide.md里需要告诉调用方:每个路由怎么请求、参数是什么、返回结构是什么。- 记忆文件里可以留下摘要:当前项目已完成某模块的 API 扩展,后续开发要基于新版路由。
如果只更新记忆,项目文档仍然是旧的;如果只更新 README,Agent 的项目约束可能仍然缺关键红线;如果只更新 CLAUDE.md,协作者和下游调用方还是不知道怎么接入。
洁癖 Skill 的价值就在于,它不是只整理单点记忆,而是把这三层一起纳入审查范围。
核心原则:合并优于追加,删除优于保留
很多人维护文档时,会下意识保留所有信息,理由是“万一以后用得上”。在 AI 协作场景里,这个习惯很危险。
对 Agent 来说,过期信息比没有信息更糟糕。
没有信息时,Agent 可能会问你;读到过期信息时,它会以为那是真的,并继续执行。尤其是数据库、鉴权、路由、部署命令、环境变量这类事实,一旦新旧版本同时存在,Agent 很容易选错。
洁癖 Skill 遵循两个清理原则:
| 原则 | 含义 | 例子 |
|---|---|---|
| 合并优于追加 | 同一件事不要散落在多个重复段落里,要合并成一个清晰版本 | 同一个 API 的说明在 3 个文档里各写一半,应合并成一份权威说明,再在其他地方引用 |
| 删除优于保留 | 明确过期的信息要删除,不要留着“备查” | 数据库已迁移到 PostgreSQL,就不要继续保留“项目使用 SQLite”的约束 |
这不是为了让文档更短,而是为了让文档里的事实更唯一。
理想状态下,Agent 读完项目材料后,不会看到两个互相冲突的答案。
洁癖 Skill 的工作流程
运行 /neat 后,Skill 会按固定流程处理项目知识。它做的不是简单总结对话,而是把本次变更映射到整个项目文档体系里。
flowchart TD
A[运行 /neat] --> B[盘点所有 Markdown 文档]
B --> C[识别本次对话产生的新事实]
C --> D[使用变更影响矩阵判断哪些文件受影响]
D --> E[更新 docs 和 README]
E --> F[更新 CLAUDE.md 或同类项目约束]
F --> G[整理 Agent 记忆]
G --> H[执行自检清单]
H --> I[输出变更摘要]
1. 盘点项目里的 Markdown 文件
清理文档不能只改眼前那一个文件。很多项目的问题就在于:某个关键说明藏在一个旧文档里,Agent 没有读到,最后新旧信息并存。
所以洁癖 Skill 的第一步是机械式盘点,把项目中所有相关 Markdown 文件列出来并读取,包括:
README.md
CLAUDE.md
docs/**/*.md
runbook/**/*.md
architecture/**/*.md
integration/**/*.md
如果平台使用的不是 CLAUDE.md,而是其他项目规则文件,也应该纳入同一类扫描。
这一步的目标是避免漏改。只要旧信息还留在某个文档里,它就有机会在未来被 Agent 读到。
2. 用变更影响矩阵判断该改哪里
一次开发对话里可能产生很多新事实,但不是每个事实都需要写进所有文件。洁癖 Skill 会根据变更类型判断影响范围。
| 变更类型 | README | docs | CLAUDE.md | 记忆文件 | 需要重点检查 |
|---|---|---|---|---|---|
| 新增 API | 可能需要 | 需要更新接入文档 | 需要记录路由约束 | 记录模块状态 | 参数、返回值、鉴权、错误码 |
| 数据库迁移 | 需要更新依赖说明 | 需要更新架构和部署文档 | 需要删除旧数据库约束 | 删除旧记忆并写入新事实 | SQL 方言、连接串、迁移命令 |
| 新增环境变量 | 需要更新启动说明 | 需要更新部署手册 | 需要提醒 Agent 使用新变量 | 可记录配置变化 | 示例值不能泄露密钥 |
| 删除功能 | 需要移除入口说明 | 需要删除旧教程 | 需要禁止继续调用旧模块 | 删除旧记忆 | 是否仍有旧路由、旧命令 |
| 跨项目依赖变化 | 可能需要 | 依赖方文档也要更新 | 记录联动关系 | 记录上下游状态 | 项目 A 改动是否影响项目 B |
这个矩阵解决的是“波及范围”问题。
例如项目 A 改了接口返回结构,项目 B 依赖这个接口。只更新项目 A 的接口文档还不够,项目 B 的接入说明、类型定义、运行手册也可能要同步更新。跨项目依赖是文档维护里很容易漏掉的部分。
3. 按顺序更新 docs、项目约束和记忆
洁癖 Skill 的更新顺序是:
docs/ 和 README
↓
CLAUDE.md 或同类项目约束
↓
Agent 记忆
这样做有一个好处:先把面向人和项目的权威文档修正,再把 Agent 的工作约束对齐,最后把长期记忆整理成摘要。
如果反过来先改记忆,Agent 可能只是记住“某件事变了”,但项目正式文档仍然没有更新。下一次换一个 Agent、换一个会话、换一个协作者,问题还会回来。
4. 执行自检清单
文档更新后,还需要检查新旧事实是否完全对齐。洁癖 Skill 会用自检清单找常见遗漏。
常见检查项包括:
| 检查项 | 为什么重要 |
|---|---|
| 新增环境变量是否同时出现在启动说明、部署手册和项目约束中 | 避免本地能跑、部署失败 |
| 数据库类型、连接方式、迁移命令是否一致 | 避免 Agent 写错 SQL 或使用旧依赖 |
| 新增路由是否有参数、返回值、错误码说明 | 避免调用方只能看代码猜接口 |
| 删除功能后是否残留旧文档、旧命令、旧记忆 | 避免 Agent 继续调用不存在的模块 |
| 是否存在“昨天、最近、当前版本”这类相对时间 | 相对时间会随时间失效,最好改成明确状态 |
| 跨项目依赖是否同步更新 | 避免上游变了,下游文档仍然指向旧协议 |
| 是否保留了互相冲突的说法 | 冲突信息会让 Agent 随机选一个相信 |
自检的目的不是追求文档数量,而是让项目里只保留当前准确的事实。
5. 输出变更摘要
整理结束后,Skill 会给出一份摘要,让使用者知道它改了哪些东西。一个比较理想的摘要结构类似这样:
## Neat 变更摘要
### 已更新
- docs/database.md:将数据库说明从 SQLite 更新为 PostgreSQL。
- docs/deployment.md:补充 POSTGRES_URL 环境变量。
- CLAUDE.md:移除 SQLite 相关约束,新增 PostgreSQL 查询约定。
- memory:删除旧数据库记忆,记录当前数据库架构状态。
### 已删除
- docs/legacy-sqlite-setup.md 中过期启动说明。
- CLAUDE.md 中“使用本地 SQLite 文件”的旧规则。
### 需要人工确认
- 生产环境 PostgreSQL 备份策略尚未写入 runbook。
- 旧版本迁移脚本是否仍需保留,需要确认兼容范围。
这份摘要很关键。自动整理文档不能变成黑盒,尤其是删除旧信息时,最好让人能快速确认修改范围。
一个数据库迁移场景
假设项目完成了一次数据库迁移:
旧状态:SQLite
新状态:PostgreSQL
相关变化:连接串、依赖包、SQL 方言、部署配置、迁移命令
如果只改代码,不整理文档,项目里可能出现这种冲突:
| 文件 | 残留问题 |
|---|---|
README.md | 安装步骤仍然说无需启动数据库 |
docs/deployment.md | 没有 POSTGRES_URL 环境变量 |
docs/architecture.md | 架构图仍然画成本地 SQLite 文件 |
CLAUDE.md | 仍然要求 Agent 使用 SQLite 语法 |
| 记忆文件 | 仍然记录“项目使用轻量级 SQLite” |
运行 /neat 后,应该把这些内容统一到 PostgreSQL 版本:
flowchart LR
A[数据库迁移完成] --> B[README 更新依赖和启动方式]
A --> C[部署文档新增 PostgreSQL 配置]
A --> D[架构文档更新存储层说明]
A --> E[CLAUDE.md 删除 SQLite 约束]
A --> F[记忆文件替换为新数据库事实]
这样新会话启动后,Agent 看到的是统一上下文:
项目当前使用 PostgreSQL。
新增查询必须使用 PostgreSQL 兼容语法。
本地开发需要配置 POSTGRES_URL。
旧 SQLite 说明已删除,不再作为参考。
这比在对话里反复提醒“别用 SQLite”稳定得多。对话会关闭,文档会留下。
适合哪些场景
洁癖 Skill 对“项目会持续迭代、Agent 会反复参与开发”的场景更有价值。
| 场景 | 是否适合 | 原因 |
|---|---|---|
| Vibe Coding 做出来的中长期项目 | 适合 | 文档维护习惯往往弱,功能增长后容易上下文混乱 |
| 多次会话持续开发同一个项目 | 适合 | 每次收尾都能把对话信息沉淀到文档 |
| 多个 Agent 或多个人协作 | 适合 | 需要统一的项目事实来源 |
| 接口、部署、数据库频繁变化的项目 | 适合 | 这些变化最容易造成旧文档误导 |
| 一次性脚本或临时 Demo | 不一定需要 | 没有长期上下文维护成本 |
| 文档已经由严格工程流程维护的团队 | 可作为补充 | 仍然可以用于检查遗漏,但不能替代代码评审和测试 |
| 对自动修改文档完全不放心的项目 | 谨慎使用 | 可以只让它输出建议,不直接写文件 |
它尤其适合任务收尾阶段,而不是任务刚开始的时候。比较自然的节奏是:
做功能 / 修 bug
↓
跑测试或手动验证
↓
运行 /neat
↓
检查变更摘要和 git diff
↓
提交代码与文档
上手方式
仓库可以直接克隆:
git clone https://github.com/KKKKhazix/khazix-skills.git
不同 Agent 平台的 Skill 或 Command 安装方式不完全一样,可以按平台自己的规则导入仓库中的洁癖 Skill。通用流程是:
1. 克隆或下载 skills 仓库
2. 找到洁癖 Skill 对应目录
3. 按 Claude Code、Codex、OpenCode、OpenClaw 的导入方式安装
4. 重启或刷新 Agent 的 Skill 列表
5. 在项目任务结束时运行 /neat
使用时不需要写复杂提示词。最短命令就是:
/neat
如果想让它更明确,可以这样说:
/neat
请全面审查本次对话产生的项目变化,同步更新 docs、README、CLAUDE.md 和记忆文件。
需要删除过期信息,合并重复说明,并输出变更摘要。
在没有斜杠命令的环境里,也可以直接写成自然语言:
请整理项目文档和记忆:
- 盘点所有 Markdown 文档
- 根据本次变更更新 docs、README 和项目约束文件
- 删除过期记忆,合并重复事实
- 检查是否存在新旧冲突
- 最后输出变更摘要
使用时要注意的坑
不要把它当测试工具
洁癖 Skill 主要整理项目知识,不负责证明代码正确。功能是否能跑,仍然要靠测试、类型检查、人工验证或 CI(持续集成)。
更稳妥的顺序是先验证代码,再整理文档:
# 示例:按项目实际命令调整
npm test
npm run lint
确认功能没问题后,再运行:
/neat
删除信息前最好看 diff
“删除优于保留”不等于无脑删除。运行后建议查看版本差异:
git diff
重点看三类修改:
- 是否误删仍然需要保留的兼容说明
- 是否把未确认的事实写成了确定结论
- 是否在文档里暴露了密钥、内部地址、私有配置
敏感配置只能写示例
环境变量、连接串、Token、内部域名这类内容要谨慎。文档里可以写变量名和示例格式,不应该写真实密钥。
推荐写法:
POSTGRES_URL=postgresql://user:password@localhost:5432/app_db
不推荐写法:
POSTGRES_URL=postgresql://real_user:real_password@prod-db.example.internal:5432/prod
记忆文件不要变成垃圾堆
记忆不是越多越好。适合进入记忆的是长期有效的项目事实,例如:
项目当前使用 PostgreSQL。
后端 API 统一放在 src/routes。
新增接口必须补充 integration guide。
不适合进入记忆的是临时过程:
刚才尝试了方案 A,但是失败了。
今天先临时注释掉某段代码。
这个 bug 可能明天再看。
这些内容如果没有长期价值,就不应该污染后续会话。
更好的使用节奏:把 /neat 当成存档
AI 编程会话越长,上下文越容易变得臃肿。与其把所有细节都堆在一个长对话里,不如在一个阶段结束时把真正有价值的信息写回项目文档,然后新开会话继续。
推荐节奏是:
sequenceDiagram
participant U as 使用者
participant A as AI Agent
participant D as 项目文档
participant M as 记忆文件
U->>A: 开发功能或修复 bug
A->>U: 完成代码修改
U->>A: 运行 /neat
A->>D: 更新 README、docs、项目约束
A->>M: 合并新事实,删除旧记忆
A-->>U: 输出变更摘要
U->>U: 检查 diff 后提交
U->>A: 新会话继续开发
这样做的关键变化是:项目知识不再依赖某一次对话,而是沉淀在持久化文档里。对话可以关闭,窗口可以重开,但 README、docs、CLAUDE.md 和记忆文件仍然能把 Agent 带回正确状态。
洁癖 Skill 的核心价值可以概括成一句话:
过期的就删,重复的就合,模糊的就改,让项目里只保留当前最准确的事实。
对 AI Agent 来说,干净的上下文就是稳定的工作环境。文档越准确,Agent 越不容易被旧信息带偏;记忆越克制,新会话越容易快速进入状态。