关于 anti-koshary
anti-koshary 是面向现有代码库的独立审计技能,识别架构混杂、重复逻辑及安全和依赖问题。它先提交按影响排序的报告,只有用户批准后才进行修复。
主要功能
- 01检查分层混杂与重复逻辑
- 02审视过长或难读的代码
- 03查找死代码与明显重构点
- 04检查安全问题和过时依赖
- 05修复前征求用户批准
适用场景
- 01评估现有代码库的维护风险
- 02定位重复验证逻辑和层级混杂
- 03审查凭据、认证及依赖漏洞
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ismail9k/ skills --skill anti-koshary安装后在 Claude Code 中输入/anti-koshary确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/security-checks.mdstructural-decay.mdscripts/dep_audit.sh详细介绍
反糊涂炖
Koshary 是将米饭、意面和扁豆放在一个碗里。每种食材都不错;但混在一起后,就再也分不开了。Koshary 代码也是同样的问题——原本结构良好的代码栈,层层混杂,最终没有任何部分能独立拆出来。
这项技能就是用来找出这种混杂的症状:
- 业务逻辑写在控制器、组件和路由处理程序中
- 相同的验证或格式化代码在多个文件中反复复制粘贴
- 函数和文件不断膨胀,已经大到没人愿意读
- 抽象从未体现出价值,反而让本应彼此独立的调用方相互耦合
报告后面还会指出一些往往也会堆在同一碗里的问题,不过用户来这里并不是为了处理这些问题:
- 没人重新检查过的密钥、缺失的身份验证检查,以及未经验证的输入
- 多年前就锁定版本、却一直悄悄携带 CVE 的依赖项
专为独立运行而设计
这项技能不依赖任何其他内容。没有配套技能、配置文件、问题跟踪器或预先设置步骤——它能直接在任何仓库、任何技术栈中运行。编辑时也要保持这一点:所需的一切都放在它自己的目录中。
适用情形
用户想知道现有代码库有什么问题,或想要清理代码库时,适用此技能。当用户要求你开发新功能时,不适用——那是向前推进的工作,在功能开发过程中进行审查只会增加噪音。同样,用户要求“重构这个函数”时也不适用,因为这是让你直接动手,而不是检查一遍。
两轮规则
第一轮只报告。第二轮才修复。用户说开始之前,不得进行第二轮的任何操作。
即使修复显而易见,而且只需一行代码,也要坚持这一原则。报告才是用户真正要付费获取的交付物:用户没看到的问题,就没机会评估;未经审查就应用的修复,则需要用户从差异中逆向推断。用户批准报告时,也会决定哪些发现确实成立——你有些判断会出错,而第一轮能以较低成本发现这些问题。
步骤 0——开始检查前先了解情况
用几句话向用户明确回答以下四个问题:
- 技术栈是什么? 语言、框架、包管理器(读取锁定文件,而不只是清单文件——它能告诉你实际使用的是哪个包管理器)。
- 审查范围有多大? 整个仓库、某个目录,还是最近的差异。对于较大的范围,开始前先商定边界——不设边界的检查要么范围失控,要么悄悄抽样;而悄悄抽样看起来就像代码库完全没有问题。
- 有没有测试,测试是否通过? 运行测试。这决定了之后可以做出哪些结论。
- 工作树是否干净? 运行
git status --porcelain。如果工作树不干净,明确说明,并请用户在第二轮之前先提交或暂存更改——用户能否运行git reset,是修复阶段唯一的安全保障。
如果没有测试,要明确说明,并在整个审查过程中贯彻这一点:不要将任何更改描述为“安全”或“功能等效”。 没有测试,“仍然可以构建”只能证明代码能解析、导入能解析——无法证明行为正确。应改为指出风险最高的两三项更改,并说明在着手修改之前,在哪些地方添加一项快速测试就能恢复大部分信心。
第 1 轮 — 查找并报告
按以下七个部分的顺序逐一检查,并将每项结果整理成一个小表格。每项发现都要说明:是什么、位置(文件 + 行号,使用可点击路径)、为何重要,以及你会如何修复。
每项发现只报告一次,放在最早适用的部分。重复的验证器同时属于第 2、4 和 5 部分;把它列三次,只是在用表格充数。
按后果而非发现难易程度排序:
| 优先级 | 含义 |
|---|---|
| 严重 | 有效凭据,或目前可被利用的漏洞。这是唯一仍高于其他所有问题的类别。 |
| 高 | 同一条规则在多个地方实现,迟早会出现偏差;或者逻辑已经坍塌,导致相同逻辑必须在别处重写——虽然尚未发生,但终究会出现的 bug。也包括真实存在的漏洞。 |
| 中 | 每次修改都会耗费维护时间,或掩盖 bug——杂烩本身。 |
| 低 | 整洁度问题。反正已经在改这个文件,顺手处理即可。 |
一项发现只有在你能说清楚后果时才值得列出。“这个函数很长”不算发现;“这个 400 行的处理程序混杂了身份验证、验证和数据库写入,因此编辑时很容易漏掉第 210 行的身份验证检查”才算。如果你无法补完“这意味着……”这句话,就删掉它——一份充数的报告会让用户习惯性地略读整份报告。
阅读 references/structural-decay.md,然后再检查第 1–5 部分。该文档包含用于区分会造成成本的重复与偶然重复的测试,以及判断分层是否已坍塌的迹象。
1. 分层坍塌 — 真正的大杂烩
这是该技能名称所指的问题。检查是否有单个文件或函数同时处理以下多项工作:传输(解析请求、状态码)、业务规则(允许什么、计算什么)、持久化(查询、写入、缓存)、呈现(渲染、格式化)。
迹象包括:在 React 组件或路由处理程序中调用 ORM;本应是纯规则的函数却接收请求对象,因此无法再从任务或测试中调用;UI 中包含业务规则,导致 API 接受 UI 禁止的内容;一个所有模块都会导入的 utils 模块反过来又导入所有模块。
报告具体后果:"价格规则写在结账组件中,因此移动客户端和管理面板都各自重新实现了这条规则" 才算。 "这违反了关注点分离原则" 不算。
2. 重复逻辑
判断标准不是“看起来相似”,而是:如果这条规则发生变化,需要同时修改多少处?会不会有人漏改? 三份相同的验证正则表达式会制造 bug。两个函数都恰好循环遍历数组则不算问题。
量化说明——“这个正则表达式出现在 4 个文件中;更改规则意味着要编辑全部 4 个文件”——并参照文档区分偶然重复与相互耦合的重复。这是模型最常判断错误的地方。
3. 已经无人阅读的函数和文件
长度是症状,不是发现。需要检查的情况包括:有多个修改原因;嵌套超过三层;通过布尔参数切换行为;注释标出了一个本应独立成函数的边界。
参考文档中提供了检查大小和变更频率的命令。先报告两者重叠的部分——经常变动的大文件最容易造成麻烦,而两年都没人动过的大文件通常不值得冒险。
4. 死代码和显而易见的重构
未使用的导入和局部变量、不可达代码、具有误导性的名称。删除前先核实:字符串键查找、反射、DI 容器、路由清单和库的公开导出,都可能让实际在用的代码看起来像是未使用。只报告显而易见的改进——如果一项发现需要讨论设计,就应该作为提示放在第 6 部分,而不是在这里作为修复项。
5. 可复用组件——仅在确有必要时
只有当 UI 或逻辑的重复频率足够高,提取为一个组件、钩子或函数明显能带来好处时,才这样做。如果你还得为此辩解,那就跳过。过早抽象本身也是一种 koshary:它会让原本没有理由一起变动的调用方产生耦合。
6. 快速健康检查
检查网络和 I/O 调用周围是否缺少错误处理。检查明显的性能陷阱——N+1 查询、未分页的列表端点,以及本应放在循环外却写在循环内的操作。然后检查其他你注意到的真正风险,每项用一行说明。
7. 安全与依赖项
放在最后,而且这是有意安排的——但有效凭据仍然是严重问题,第二轮会优先修复。分别报告这两方面;它们是不同的决策。
安全。 首先阅读 references/security-checks.md。其中包含值得运行的 grep 模式、会让简单密钥扫描失去意义的误报,以及针对不同技术栈要检查的内容。涵盖:代码或已提交配置中的硬编码密钥;用户输入未经转义便到达解释器的注入路径;缺失或可绕过的身份验证;日志、localStorage 或 URL 中的敏感数据;不安全的执行方式和完全开放的 CORS。既要检查 Git 历史,也要检查工作树——即使密钥在最近一次提交中已被删除,它仍然是有效密钥。
依赖项。 运行随附脚本;它会根据锁文件检测包管理器,并运行过时依赖报告和漏洞扫描:
bash scripts/dep_audit.sh [project-dir]
路径相对于此技能自身的目录——也就是你加载 SKILL.md 的目录,而不是被审计的项目目录。项目目录是可选参数,默认使用当前目录,因此你可以从任何位置运行。如果脚本无法识别技术栈,会以状态码 2 退出,说明它检查了哪些内容,并且不会更改任何内容——此时请改用该生态系统自带的过时依赖和审计命令,并在报告中说明你这么做了。
报告前先对漏洞扫描结果分级。扫描器统计的是安全公告数量,而不是实际暴露风险:区分哪些依赖会随产品部署到生产环境,哪些只在构建或测试链中运行,并说明具体情况。运行时依赖中的 CVE 是需要限期处理的问题;构建工具链深处的 12 条安全公告通常不是。把它们同等对待,真正的问题就会被忽略。落后 3 个次要版本根本不算安全问题。
第一轮收尾
最后给出简短摘要,列出各优先级的问题数量,并询问用户希望修复哪些部分。不要因为用户没有回应或只说一句“看起来不错”就继续操作。
第 2 轮——获批后修复
按以下顺序修复,每完成一组后就停下来确认项目仍能构建和运行(如果有测试,也要确认测试仍能通过)。每组单独提交,这样有问题的修复可以撤销,而不影响其他有效修复。 如果某组导致构建或测试失败,就撤销该组,说明出了什么问题,然后停止——不要在代码状态不明的情况下,继续排查后续事项。
- 任何严重问题。 无论报告中的位置如何,先处理有效凭据或可利用的漏洞。这些修复会有意改变行为——这正是修复的目的,因此要明确说明现在有哪些行为发生了变化,并从用户关心的角度描述:哪些请求会开始失败,哪些用户会被登出,需要轮换哪些凭据。
- 结构性清理。 合并层级、消除重复、清理死代码、提取代码——也就是 koshary 本身,也是用户寻求帮助的原因。只处理用户批准的项目。这些改动不得改变行为。逐项展示修改前后的对比,并优先拆分为多个小提交,而不是一个大提交;合并层级通常需要分步进行。
- 依赖项。 可自由升级补丁和次要版本;更新锁文件;然后构建并测试。不要升级主要版本——将每项主要版本升级单独列出,附上一行迁移说明,并交由用户决定。
- 其余安全修复。 高危和中危问题,规则与第 1 步相同:说明每项修复会带来哪些行为变化。
最后给出总结:清理了哪些内容、修复了哪些安全问题、更新了哪些软件包(旧版本 → 新版本),以及还有哪些事项需要用户决定。
规则
- 优先采用能解决问题的最小改动。
- 未经询问,不要改动业务逻辑——你能看出代码做了什么,却不知道它本应做什么。
- 如果修复需要重写代码或进行不兼容升级,请标明建议并在此处停止。
- 不要添加用户未要求的抽象、配置或工具。目标是让代码库更易于修改,而不是让它看起来更厉害。
不要做的事
- 第 1 轮期间不要修复任何问题,无论它看起来多么微不足道。
- 不要把这变成安全审计。安全问题排在第 7 节,是因为用户问的是代码结构;如果在用户真正需要的发现前面堆上一页依赖项安全公告,那并不是更全面的报告,反而更糟。
- 不要为了显得全面而凑报告——没有实际后果的发现只会制造噪音,并分散用户对真正问题的注意力。
- 不要因为某个发现适用于多个章节,就在三个章节里重复报告。
- 对于没有测试的代码库,不要把改动称为“安全”或“功能等效”。请说明实际验证了什么。
- 不要因为不合个人风格就重写运行正常的代码。
- 不要合并仅仅偶然相似的重复代码——那样只会制造下一个 koshary。
- 不要主动升级主要版本依赖项。
- 不要在总结中复述密钥的值——请指出文件和行号,并告知用户应轮换该密钥。
非 Claude-Code 版本(普通提示词)
对于不支持技能发现的工具,请在已提交的仓库中粘贴一次以下内容:
请扮演一名资深工程师,审查一个已变得难以修改的代码库。分两轮进行审查,在我批准之前不要做任何改动。
首先告诉我技术栈(语言、框架、包管理器)、审查范围,以及是否有测试。如果没有测试,不要将任何改动称为“安全”——请指出风险最高的改动,以及在哪里添加快速测试会有帮助。
第 1 轮——仅报告。 按类别列出优先级表,每项发现只列一次,并说明问题是什么、文件和行号、为何重要,以及建议的修复方案:(1) 层级混杂——业务规则、查询、传输或渲染逻辑混在同一个文件或函数中;(2) 重复逻辑,但仅限于修改一条规则就会迫使你同时修改多个地方的情况;(3) 无人能读懂的函数和文件——有多个变更原因、嵌套过深、布尔模式标记——按其变更频率排序;(4) 无用代码和明显的重构机会——未使用的导入、无法到达的代码、容易误解的命名;需对照反射和动态查找进行验证;(5) 可复用部分,仅限明显的情况;(6) 网络/IO 相关错误处理缺失,以及 N+1 查询或未分页列表等明显的性能陷阱;(7) 最后,检查安全和依赖项——硬编码的密钥(也要检查 git 历史)、注入漏洞、缺少身份验证、日志/localStorage/URL 中的敏感数据、
eval/dangerouslySetInnerHTML/开放的 CORS,以及过时的软件包和适用于我的包管理器的漏洞扫描结果,并分别列出运行时和仅构建时的安全公告。对于无法指出后果的问题,一律跳过。
第 2 轮——我确认后再进行。 首先修复所有严重问题——例如有效凭据泄露或可被利用的漏洞——并说明行为会有哪些变化。然后进行我已批准的结构清理,这些清理不得改变行为。接着处理依赖项(仅限补丁版/次要版本升级——主要版本升级需单独列出,并附上迁移说明)。最后处理其余安全修复。每组改动后确认应用仍能构建和运行,并分别提交;如果某组改动导致问题,则回滚该组并停止。优先选择能奏效的最小改动;未经询问不要改动业务逻辑;需要重写的部分请标记出来,不要直接动手。