$npx -y skills add virgo777/buddyme --skill plankton-code-quality使用 Plankton 实现编写时代码质量强制执行 —— 通过钩子在每次文件编辑时进行自动格式化、代码检查,并由 Claude 驱动自动修复。
| 1 | # Plankton 代码质量技能(Plankton Code Quality Skill) |
| 2 | |
| 3 | Plankton(感谢 @alxfazio)的集成参考,这是一个针对 Claude Code 的编写时(Write-time)代码质量强制执行系统。Plankton 通过工具调用后钩子(PostToolUse hooks)在每次文件编辑时运行格式化程序和 Linter,然后启动 Claude 子进程(Subprocess)来修复智能体(Agent)未捕捉到的违规项。 |
| 4 | |
| 5 | ## 适用场景 |
| 6 | |
| 7 | - 你希望在每次文件编辑时(而不只是提交时)自动进行格式化和代码检查。 |
| 8 | - 你需要防御智能体通过修改 Linter 配置来绕过检查,而不是真正修复代码。 |
| 9 | - 你希望针对修复任务进行分级模型路由(Haiku 用于简单样式,Sonnet 用于逻辑,Opus 用于类型)。 |
| 10 | - 你使用多种语言进行开发(Python, TypeScript, Shell, YAML, JSON, TOML, Markdown, Dockerfile)。 |
| 11 | |
| 12 | ## 工作原理 |
| 13 | |
| 14 | ### 三阶段架构 |
| 15 | |
| 16 | 每当 Claude Code 编辑或写入文件时,Plankton 的 `multi_linter.sh` 工具调用后钩子(PostToolUse hook)就会运行: |
| 17 | |
| 18 | ``` |
| 19 | 阶段 1: 自动格式化 (静默) |
| 20 | ├─ 运行格式化程序 (ruff format, biome, shfmt, taplo, markdownlint) |
| 21 | ├─ 静默修复 40-50% 的问题 |
| 22 | └─ 不向主智能体输出任何内容 |
| 23 | |
| 24 | 阶段 2: 收集违规项 (JSON) |
| 25 | ├─ 运行 Linter 并收集无法自动修复的违规项 |
| 26 | ├─ 返回结构化 JSON: {line, column, code, message, linter} |
| 27 | └─ 仍不向主智能体输出任何内容 |
| 28 | |
| 29 | 阶段 3: 委派 + 验证 |
| 30 | ├─ 启动带有违规 JSON 的 claude -p 子进程 |
| 31 | ├─ 根据违规复杂性路由到不同层级的模型: |
| 32 | │ ├─ Haiku: 格式化、导入、样式 (E/W/F 代码) — 120s 超时 |
| 33 | │ ├─ Sonnet: 复杂性、重构 (C901, PLR 代码) — 300s 超时 |
| 34 | │ └─ Opus: 类型系统、深度推理 (unresolved-attribute) — 600s 超时 |
| 35 | ├─ 重新运行阶段 1+2 以验证修复结果 |
| 36 | └─ 如果清理完成则 Exit 0,如果仍存在违规项则 Exit 2(报告给主智能体) |
| 37 | ``` |
| 38 | |
| 39 | ### 主智能体看到的内容 |
| 40 | |
| 41 | | 场景 | 智能体看到的内容 | 钩子退出码 | |
| 42 | |----------|-----------|-----------| |
| 43 | | 无违规项 | 无 | 0 | |
| 44 | | 子进程修复了所有问题 | 无 | 0 | |
| 45 | | 子进程处理后仍存在违规 | `[hook] N violation(s) remain` | 2 | |
| 46 | | 建议性信息 (重复、旧工具) | `[hook:advisory] ...` | 0 | |
| 47 | |
| 48 | 主智能体只看到子进程无法修复的问题。大多数质量问题都会被透明地解决。 |
| 49 | |
| 50 | ### 配置保护 (防御规则博弈) |
| 51 | |
| 52 | LLM 有时会尝试修改 `.ruff.toml` 或 `biome.json` 来禁用规则,而不是修复代码。Plankton 通过三层防护来阻止这种情况: |
| 53 | |
| 54 | 1. **工具调用前钩子(PreToolUse hook)** — `protect_linter_configs.sh` 在修改发生前阻止对所有 Linter 配置的编辑。 |
| 55 | 2. **停止钩子(Stop hook)** — `stop_config_guardian.sh` 在会话结束时通过 `git diff` 检测配置更改。 |
| 56 | 3. **受保护文件列表** — 包括 `.ruff.toml`, `biome.json`, `.shellcheckrc`, `.yamllint`, `.hadolint.yaml` 等。 |
| 57 | |
| 58 | ### 包管理器强制执行 |
| 59 | |
| 60 | Bash 上的工具调用前钩子(PreToolUse hook)会阻止使用旧版包管理器: |
| 61 | - `pip`, `pip3`, `poetry`, `pipenv` → 已阻止 (请使用 `uv`) |
| 62 | - `npm`, `yarn`, `pnpm` → 已阻止 (请使用 `bun`) |
| 63 | - 允许的例外情况: `npm audit`, `npm view`, `npm publish` |
| 64 | |
| 65 | ## 设置 |
| 66 | |
| 67 | ### 快速开始 |
| 68 | |
| 69 | ```bash |
| 70 | # 将 Plankton 克隆到你的项目(或共享位置) |
| 71 | # 注: Plankton 由 @alxfazio 开发 |
| 72 | git clone https://github.com/alexfazio/plankton.git |
| 73 | cd plankton |
| 74 | |
| 75 | # 安装核心依赖 |
| 76 | brew install jaq ruff uv |
| 77 | |
| 78 | # 安装 Python linter |
| 79 | uv sync --all-extras |
| 80 | |
| 81 | # 启动 Claude Code — 钩子将自动激活 |
| 82 | claude |
| 83 | ``` |
| 84 | |
| 85 | 无需安装命令,无需插件配置。当你向在 Plankton 目录中运行 Claude Code 时,`.claude/settings.json` 中的钩子会自动被加载。 |
| 86 | |
| 87 | ### 针对单个项目的集成 |
| 88 | |
| 89 | 要在你自己的项目中使用 Plankton 钩子: |
| 90 | |
| 91 | 1. 将 `.claude/hooks/` 目录复制到你的项目。 |
| 92 | 2. 复制 `.claude/settings.json` 中的钩子配置。 |
| 93 | 3. 复制 Linter 配置文件 (`.ruff.toml`, `biome.json` 等)。 |
| 94 | 4. 为你的语言安装相应的 Linter。 |
| 95 | |
| 96 | ### 特定语言的依赖项 |
| 97 | |
| 98 | | 语言 | 必需 | 可选 | |
| 99 | |----------|----------|----------| |
| 100 | | Python | `ruff`, `uv` | `ty` (类型), `vulture` (死代码), `bandit` (安全) | |
| 101 | | TypeScript/JS | `biome` | `oxlint`, `semgrep`, `knip` (死导出) | |
| 102 | | Shell | `shellcheck`, `shfmt` | — | |
| 103 | | YAML | `yamllint` | — | |
| 104 | | Markdown | `markdownlint-cli2` | — | |
| 105 | | Dockerfile | `hadolint` (>= 2.12.0) | — | |
| 106 | | TOML | `taplo` | — | |
| 107 | | JSON | `jaq` | — | |
| 108 | |
| 109 | ## 与 ECC 配合使用 |
| 110 | |
| 111 | ### 互补而非重叠 |
| 112 | |
| 113 | | 关注点 | ECC | Plankton | |
| 114 | |---------|-----|----------| |
| 115 | | 代码质量强制执行 | 工具调用后钩子 (Prettier, tsc) | 工具调用后钩子 (20+ Linter + 子进程修复) | |
| 116 | | 安全扫描 | AgentShield, security-reviewer 智能体 | Bandit (Python), Semgrep (TypeScript) | |
| 117 | | 配置保护 | — | 工具调用前钩子阻止 + 停止钩子检测 | |
| 118 | | 包管理器 | 检测 + 设置 | 强制执行 (阻止旧版包管理器) | |
| 119 | | CI 集成 | — | 用于 git 的 Pre-commit 钩子 | |
| 120 | | 模型路由 | 手动 (`/model opus`) | 自动 (违规复杂性 → 相应层级) | |
| 121 | |
| 122 | ### 推荐组合 |
| 123 | |
| 124 | 1. 安装 ECC 作为你的插件(智能体、技能、命令、规则)。 |
| 125 | 2. 添加 Plankton 钩子用于编写时质量强制执行。 |
| 126 | 3. 使用 AgentShield 进行安全审计。 |
| 127 | 4. 使用 ECC 的验证循环(verification-loop)作为 PR 前的最终门控。 |
| 128 | |
| 129 | ### 避免钩子冲突 |
| 130 | |
| 131 | 如果同时运行 ECC 和 Plankton 钩子: |
| 132 | - ECC 的 Prettier 钩子和 Plankton 的 biome 格式化程序可能会在 JS/TS 文件上发生冲突。 |
| 133 | - 解决方法:在使用 Plankton 时禁用 ECC 的 Prettier 工具调用后钩子(Plankton 的 biome 更全面)。 |
| 134 | - 两者可以在不同文件类型上共存(ECC 可以处理 Plankton 未涵盖的内容)。 |
| 135 | |
| 136 | ## 配置参考 |
| 137 | |
| 138 | Plankton 的 `.claude/hooks/config.json` 控制所有行为: |
| 139 | |
| 140 | ```json |
| 141 | { |
| 142 | "languages": { |
| 143 | "python": true, |
| 144 | "shell": true, |
| 145 | "yaml": true, |
| 146 | "json": true, |
| 147 | "toml": true, |
| 148 | "dockerfile": true, |
| 149 | "markdown": true, |
| 150 | "typescript": { |
| 151 | "enabled": true, |
| 152 | "js_runtime": "auto", |
| 153 | "biome_nursery": "warn", |
| 154 | "semgrep": true |
| 155 | } |
| 156 | }, |
| 157 | "phases": { |
| 158 | "auto_format": true, |
| 159 | "subprocess_delegation": true |
| 160 | }, |
| 161 | "subprocess": { |
| 162 | "tiers": { |
| 163 | "haiku": { "timeout": 120, "max_turns": 10 }, |
| 164 | "sonnet": { "timeout": 300, "max_turns": 10 }, |
| 165 | "opus": { "timeout": 600, "max_turns": 15 } |
| 166 | }, |
| 167 | "volume_threshold": 5 |
| 168 | } |
| 169 | } |
| 170 | ``` |
| 171 | |
| 172 | **关键设置:** |
| 173 | - 禁用你不使用的语言以加快钩子运行速度。 |
| 174 | - `volume_threshold` — 违规数超过此值将自动升级到更高级别的模型。 |
| 175 | - `subprocess_delegation: false` — 完全跳过阶段 3(仅报告违规项)。 |
| 176 | |
| 177 | ## 环境变量覆盖 |
| 178 | |
| 179 | | 变量 | 用途 | |
| 180 | |----------|---------| |
| 181 | | `HOOK_SKIP_SUBPROCESS=1` | 跳过阶段 3,直接报告违规项 | |
| 182 | | `HOOK_SUBPROCESS_TIMEOUT=N` | 覆盖模型层级的超时时间 | |
| 183 | | `HOOK_DEBUG_MODEL=1` | 记录模型选择决策 | |
| 184 | | `HOOK_SKIP_PM=1` | 绕过包管理器强制执行 | |
| 185 | |
| 186 | ## 参考资料 |
| 187 | |
| 188 | - Plankton (感谢 @alxfazio) |
| 189 | - Plankton REFERENCE.md — 完整架构文档 (感谢 @alxfazio) |
| 190 | - Plankton SETUP.md — 详细安装指南 (感谢 @alxfazio) |