Vinay-O/slopscore
GitHub: Vinay-O/slopscore
slopscore 是一个零依赖的代码质量扫描 CLI,通过 85 个确定性检测器和 181 种模式协议来识别并治理 AI 生成代码中的安全隐患与质量问题。
Stars: 2 | Forks: 0
# 🩺 slopscore
### 扫描代码库中的 AI slop。获取 Slop Score。交付干净的代码。
**一个零依赖的 CLI + 一套面向 AI 编程代理的 181 种模式协议。**
vibe-coded 软件的解药:将*生成*转化为*治理*。
[](https://github.com/Vinay-O/slopscore/actions/workflows/ci.yml)
[](LICENSE)
[](https://nodejs.org)
[](package.json)
[](#it-passes-its-own-scan)
```
npx slopscore
```
就这样。无需安装,无需配置,无需 API key。将它指向一个代码库,它会用一个数字告诉你——你即将交付多少 AI slop,以及如何准确地修复每个问题。
## 问题所在
在 2026 年,**46% 的新代码是由 AI 生成的**,并且 **92% 的开发者每天使用 AI 工具**——但对这些代码的信任度却从 **77% 下降到了 60%**。GitClear 对 2.11 亿行代码的分析发现,重复代码增加了 **4–8 倍**,重构骤降了 **60%**,并且 AI PR 携带的**问题多出约 1.7 倍**。大约 **45% 的 AI 生成代码带着安全弱点**交付。
来源:GitHub / Stack Overflow 2025–26 开发者调查(采用率、信任度);[GitClear, *AI Copilot Code Quality 2025*](https://www.gitclear.com/ai_assistant_code_quality_2025_research)(2.11 亿行代码——重复率、重构减少);CodeRabbit(AI PR 中的问题多出约 1.7 倍);[Veracode, *2025 GenAI Code Security Report*](https://www.veracode.com/resources/analyst-reports/2025-genai-code-security-report/)(45% 的任务引入了漏洞,涵盖 100 多个模型)。完整的归属说明见 [`ANTI_SLOP_PROTOCOL.md` §8](ANTI_SLOP_PROTOCOL.md)。
工具并没有制造这个问题。它们只是揭示了一开始就少得可怜的结构。
AI slop 之所以隐蔽,是因为它看起来已经*完工了*——命名一致、测试通过、一个精心打磨的紫色英雄区块——但在架构上却空洞无物。你无法仅凭一眼就看穿它。**slopscore 替你揪出它。**
## 查看运行效果
```
$ npx slopscore examples/slop.tsx
slopscore · 1 files · 0.03 kLOC
slop.tsx
:5 🔴 CRIT [058] Hardcoded secret / API key
const API_KEY = "sk-proj-abc123def456ghi789jkl012mno345";
fix: Move to an env var / secret manager. A committed secret is COMPROMISED — rotate it now.
:12 🔴 CRIT [073] Auth token in localStorage
localStorage.setItem("auth_token", "ey.some.jwt");
fix: Store auth in httpOnly, Secure, SameSite cookies — not localStorage (XSS-readable).
:13 🔴 CRIT [072] SQL injection via template literal
const q = `SELECT * FROM users WHERE id = ${data.id}`;
fix: Use parameterized queries / prepared statements. Never interpolate input into SQL.
:15 🔴 CRIT [053] Empty catch block (silent error swallowing)
} catch (e) {}
fix: At minimum log with context; better, handle or rethrow and surface a real message.
:29 🔴 CRIT [071] dangerouslySetInnerHTML / .innerHTML without sanitization
fix: Render as text, or sanitize with DOMPurify + an allowlist before injecting.
… and 16 more
╔══════════════════════════════════════════╗
║ S L O P S C O R E ║
╚══════════════════════════════════════════╝
84 weighted (33 lines scanned)
5 critical 9 major 7 minor
by rule: 105 ×1 · 176 ×1 · 058 ×1 · 054 ×1 · 070 ×1 · 099 ×1
▶ Vibe-coded. Audit before anyone depends on it.
```
每个发现都有一个**严重程度**、一个**目录 ID**、一个**置信度**、**确切位置**和一个**修复建议**。没有模糊的“代码异味”——而是一份你可以立即采取行动的待办清单。
## 快速开始
```
npx slopscore # scan the current directory
npx slopscore scan src --fail-on minor
npx slopscore examples/slop.tsx # watch a sloppy file score 84
npx slopscore . --markdown > slop.md
```
或者安装它:
```
npm i -g slopscore && slopscore
```
## 两种使用方式
slopscore 提供了**同一理念的两半**:一个由你运行的确定性扫描器,以及一份你交给 AI 的协议。
### 1. 扫描器(确定性,零依赖)
在几毫秒内在本地运行 **85 个检测器**——一次强化的**安全扫描**(密钥、SQL/命令注入、禁用的 TLS 验证、弱哈希、不安全的随机数、硬编码的私钥、不安全的反序列化、通配符 CORS、`eval`、未验证的 JWTs、明文 HTTP),以及空 catch 块、`any`、幻觉 API、缺失的 `alt`、VibeCode 紫色渐变、AI 流行语文案和超大混杂文件(god files)。没有 LLM,没有网络请求,没有依赖项。
使用 `slopscore scan . --category security` 运行一次专注的安全审计。
### 2. 协议(面向你的编程代理)
[`ANTI_SLOP_PROTOCOL.md`](ANTI_SLOP_PROTOCOL.md) 是一份面向 AI 代理的**181 种模式操作手册**。把它交给 Claude Code、Cursor、Codex CLI、Aider、Copilot、Windsurf 或 Cline,然后说:
代理会运行一个定义好的循环——定向 → 扫描 → 评分 → 分诊 → **修复** → 验证 → 报告——其中每个模式都包含 `DETECT`、`FIX` 和**修复权限**(🟢 自动修复 · 🟡 提议 · 🔴 标记给人类),这样它就知道哪些可以自行更改,哪些需要你来决定。**CLI 已经自动化的 85 种模式在目录中直接标记为 `⚙️ slopscore scan`**(根据扫描器自身的规则表生成,因此这两半永远不会产生偏差)——未标记的模式正是代理发挥价值的地方。
```
slopscore protocol | pbcopy # copy the protocol to paste into your agent
slopscore scan . --format agent # compact, context-window-friendly output for an agent
slopscore explain 058 # look up any one pattern + its fix, by id
```
**让代理自动使用它。** 你不应该每次会话都得提醒你的代理。`slopscore init` 会写入一个 **`AGENTS.md`**(这是 Cursor、Codex、Claude Code、Aider、Windsurf 和 Cline 都会读取的跨工具标准),告诉代理加载 `npx slopscore protocol`,遵循它,并在宣布完成之前以 `npx slopscore scan` 作为门禁——这样协议就会自行被采用,无需复制粘贴。如果你已经有 `AGENTS.md` 或 `CLAUDE.md`,它会(以幂等方式)追加该部分,而不是覆盖它。
扫描器负责发现问题。协议负责修复问题。CI 门禁负责将其拒之门外。而 `AGENTS.md` 让你的代理在无需提醒的情况下完成这三件事。
## Slop Score
一个数字,按严重程度加权,每 1,000 行代码进行标准化,这样大型代码库就不会仅仅因为代码量大而显得更糟:
```
SLOP SCORE = (🔴 critical × 10) + (🟠 major × 3) + (🟡 minor × 1)
SLOP DENSITY = weighted findings per 1,000 lines (kLOC)
```
| 密度 (加权 / kLOC) | 结论 |
|:--|:--|
| 0 | **纯净。直接交付。** |
| ≤ 2 | 干净。人类级别。 |
| 2–6 | 轻度 slop。通过一次专注的检查即可修复。 |
| 6–12 | 严重 slop。需要真正下功夫。 |
| > 12 | Vibe-coded。在任何人依赖它之前进行审计。 |
### 该分数反映的是*生产*风险
测试运行器中的 `console.log` 不是生产环境中的 SQL 注入——所以它们不应该获得相同的分数。slopscore 默认具有上下文感知能力:
- **生成的和 vendored 文件会被跳过**——压缩后的 bundle (`*.min.js`)、包含超长单行的文件,以及带有 `@generated` 头的文件不是你编写的代码,因此它们不会污染分数。
- **测试和工具代码会被报告,但不参与评分**——在 `test/`、`e2e/`、`scripts/`、`__tests__/`、`*.spec.*` 等目录中的发现仍会显示,但它们不会抬高标题中的 Slop Score(`5 个严重问题 … (生产环境) · + 12 个在 测试 / 工具 中 — 已报告,不参与评分`)。
你看到的数字就是你实际交付的风险。
## 它通过了自身的扫描
一个旨在防止交付 slop 的 linter 绝不能*自身就是* slop。因此 slopscore 对自己也坚持同样的标准:
- **零运行时依赖。** 整个工具完全基于 Node 内置模块。
- **此代码库上的 `slopscore scan .` 返回 `0`——“纯净”。**
- 其自身的 CI 会在其源代码上以 `--fail-on minor` 运行扫描器,如果有任何漏网之鱼,则会导致构建失败。
```
npm run selfcheck # → Pristine. Ship it. (exit 0)
```
*(规则定义文件和示例 fixture 被排除在外——它们必然包含 slopscore 正在寻找的特定字符串,就像 ESLint 排除它自己的 fixture 一样。参见 [`.slopscoreignore.md`](.slopscoreignore.md)。)*
## 将其引入 CI
```
slopscore init # writes .slopscore.json + a GitHub Action PR gate
```
或者粘贴这段代码:
```
# .github/workflows/anti-slop.yml
name: anti-slop
on: [pull_request]
jobs:
slopscore:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npx slopscore scan . --fail-on major
```
**想在 PR diff 中内联显示发现的问题?** 导出 SARIF 并将其上传到 GitHub 代码扫描:
```
- run: npx slopscore scan . --sarif --fail-on never > slopscore.sarif
- uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: slopscore.sarif }
```
**想在每个 PR 上发布 Slop Score?** 从 Markdown 报告中添加一条置顶评论:
```
- run: npx slopscore scan . --markdown > slop.md || true
- uses: marocchino/sticky-pull-request-comment@v2
with: { path: slop.md }
```
**Pre-commit hook**(在代码被提交之前就捕获 slop——仅扫描你暂存的内容):
```
# .git/hooks/pre-commit (对其执行 chmod +x)
files=$(git diff --cached --name-only --diff-filter=ACM)
[ -z "$files" ] || npx slopscore $files --fail-on major
```
### 在杂乱的代码库中采用它——棘轮模式
一个真实的代码库在第一天不会得 0 分,而首次运行就出现“严重 slop”往往会导致一个工具被关闭和遗忘。所以**把已经存在的问题作为基线,并且只针对_新的_ slop 进行拦截:**
```
slopscore scan . --baseline # first run: snapshots current findings, exits 0
slopscore scan . --baseline # from now on: passes unless you ADD slop
slopscore scan . --update-baseline # accept the current state as the new floor
```
基线是按内容而不是行号来记录发现结果的——所以四处移动代码永远不会被记录为新的 slop。提交 `.slopscore-baseline.json`,你的 CI 门禁今天就能变绿,同时问题计数只会永远下降。
## 自动修复安全的内容
有些 slop 只有一个正确的修复方法,不需要主观判断——一个多余的 `console.log`,一个缺失了 `alt` 的 `` · 带有 `outline:none` 但没有焦点样式 |
| 🎨 视觉 slop | VibeCode 紫色渐变 · 锥形/网格渐变 · 毛玻璃拟态 · 渐变裁切文本 · Sparkle/Wand 图标 · 被滥用的 AI 字体 · 彩纸/礼花特效——跨越 **Tailwind classes 和 CSS-in-JS**(MUI `sx`, styled, emotion)进行匹配 |
| ✍️ 文案 | AI 流行语(“supercharge”、“seamlessly”) · 带感叹号的 CTA · “Coming soon” · “Oops!” 错误提示 · “Submit” 按钮 · “Click here” 链接 · lorem ipsum(无意义占位文本) |
| 🏗️ 架构 / API | 硬编码的 localhost · SPA 中的 `window.location` 导航 · 使用 `location.reload()` 进行故障恢复 · HTTP 200 返回的错误 · 破坏性 GET 请求 · `z-index: 9999` · `alert()`/`confirm()` |
运行 `slopscore rules` 查看包含严重程度和修复权限的完整列表。
## 横向对比
| | slopscore | ESLint | vibecop | Semgrep |
|:--|:--:|:--:|:--:|:--:|
| 专针对 AI slop 的模式 | ✅ | ❌ | ✅ | ⚠️ |
| 视觉 / 设计 / 文案特征 | ✅ | ❌ | ❌ | ❌ |
| Slop Score(单一数值) | ✅ | ❌ | ❌ | ❌ |
| 面向代理的协议(修复权限) | ✅ | ❌ | ❌ | ❌ |
| 零安装(`npx`,无需配置) | ✅ | ⚠️ | ⚠️ | ⚠️ |
| 零依赖 | ✅ | ❌ | ❌ | ❌ |
此表的范围限定为**专门针对 AI slop 检测**——它不是质量排名。ESLint 和 Semgrep 在它们专门构建的领域(正确性规则、污点分析)表现出色,slopscore 绝不能替代它们;这里的 `❌` 仅仅意味着“不是为了捕获 slopscore 针对的那些 AI 特征而设计的”。slopscore 有意定位为一种**快速、透明、零依赖的第一道防线**——基于正则表达式/启发式检测,而非深层数据流分析。对于 AST 级别的分析(真正的圈复杂度、跨文件重复、污点追踪),请**将其与** [vibecop](https://github.com/bhvbhushan/vibecop)、Semgrep 或 CodeQL **结合使用**——协议([`ANTI_SLOP_PROTOCOL.md`](ANTI_SLOP_PROTOCOL.md))会准确地告诉你的代理何时该求助于这些工具。它是对你的 linter 的补充;而不是替代品。
## 常见问题解答
**仅靠正则表达式足以捕获所有 AI slop 吗?** 不够,slopscore 从未声称如此。它能快速且低误报地搞定那些可确定性检测的子集,然后将重度依赖判断和 AST 级别的模式推迟给协议和专用工具处理。诚实胜过花架子。
**它会修改我的代码吗?** CLI 仅用于*报告*。修复由你完成,或者由遵循协议修复权限规则的 AI 代理完成。
**它支持 Python / Go / Rust 吗?** 是的——每种语言都有专门的检测器(Python:可变默认参数、`== None`、`eval`/`exec`、f-string SQL、`pickle`、`print`;Go:被忽略的 error、`fmt.Print`、`panic`、命令注入;Rust:`.unwrap()`、`panic!`、`unsafe`、`dbg!`)。注释/字符串屏蔽机制具有语言识别能力(Python 的 `#` 注释和文档字符串不会被当作代码扫描),并且 `test_*.py` / `*_test.go` 被正确地视作测试区域。安全和文案检测器在所有源代码上运行;JS/TS 的检测面最深,因为那是 vibe-coded slop 最集中的地方。
**它的准确性如何 / 误报率?** 在设计上误报率很低,并经过了严格测试:干净、符合语言习惯的代码能稳定获得零分。扫描器具备注释和字符串识别能力(它不会标记文档字符串中的 `eval()`、注释中的 `console.log`,或将 `firstName + " and " + lastName` 标记为 SQL),遵循你的 `eslint-disable`,跳过测试文件,豁免 ORM 的 `Column == None` 和带日期固定的模型 id,并附带了 **150 多个测试**,包括一组干净代码测试组。在成熟的代码库中,高频出现的模式(例如设计系统的重复标签)会被**聚类**为一行,这样它就不会淹没真正重要的发现,而单个嘈杂的检测器永远不会决定最终结论(评分限制了每条规则的权重)。`slopscore fix` 经过验证不会破坏代码——它永远不会删除会破坏结构的行,也不会在字符串内部进行重写。发现了错误的检测结果?[提交一个 issue。](../../issues)
## 许可证
MIT——参见 [LICENSE](LICENSE)。使用它,fork 它,把它构建到你的 pipeline 中。
**如果 slopscore 帮助你避免了交付 slop,请点一个 ⭐——这有助于下一个人发现它。**
*从生成到治理。*
标签:AI辅助编程, GNU通用公共许可证, MITM代理, Node.js, 代码安全审计, 文档结构分析, 自定义脚本, 错误基检测, 静态代码分析