关于 sidecrew
sidecrew 是一个 MCP 服务,在 Mac 上将代码修改和单元测试任务交给本地 MLX 模型。Claude Opus 负责规划和审查,自动检查则在应用变更前进行把关。
主要功能
- 01将代码修改交给本地 MLX 模型
- 02由 Claude Opus 规划并审查工作
- 03通过差异、TypeScript 和测试检查把关
- 04使用变异杀死门槛运行单元测试任务
- 05报告检查失败并升级未通过的任务
适用场景
- 01在 Mac 上执行规划好的源代码修改
- 02对单元测试任务进行自动验证
- 03拒绝无法通过编译或现有测试的编辑
- 04查看任务结果和验证报告
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
10收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| port | integer | 否 | worker 端口;默认值为 8000 |
| project | string | 否 | 正在验证的项目——tsc/vitest/stryker 从其 node_modules 中报告,而非 sidecrew 的 node_modules |
详细介绍
sidecrew
你提出源代码变更需求,就能获得改好的代码——在你的 Mac 上完成,由不会消耗 Claude tokens 的模型处理,而且只有在机器检查通过后才会交给你。
Claude Opus 负责规划工作并审查结果。运行在本地的小型模型(MLX,不联网)负责范围明确的部分。两者之间设有一道机器可执行的关卡——对于代码变更:差异没有超出指定范围,tsc 检查通过,之前通过的所有测试依然通过。未经这道关卡放行的内容,Claude 绝不会看到。
$ sidecrew fix change_plan.json
fix 2026-09-20T09-14-02Z-rename: 1 step, 12 tasks, 13.0 GB free ÷ 6.5 GB per slot = 2; 1 worker up
step 1/1 "rename the helper": capturing the baseline
rename-01: survived (src/util/asset.util.ts)
rename-02: survived (src/util/asset.util.ts, src/util/asset.util.spec.ts)
…
multi-06: failed at compile · escalating — renamed the symbol 7 times over, 5 compile errors
11/12 survived · 0 → 0 tsc errors · .sidecrew/runs/2026-09-20T09-14-02Z-rename/result.json
仅为示意,并非实际捕获的对话记录——这是实际的输出格式,计数取自下方的 React 测量,且不包含任何客户端的文件名。12 项中有 11 项通过,95 % 区间为 [0.615, 0.998];上方那行展示的是运行时的样子。
单元测试是工作负载 #1——格式相同,但采用变异测试杀死率关卡——两种工作负载的数据及各自的区间都列在下方。
**sidecrew 需要 24 GB 的已安装内存。**低于这个容量,7B 模型无法与正常工作集并存(已测量),因此 sidecrew 会拒绝运行,并说明原因,而不是悄悄变成另一个工具(ADR-0073)。sidecrew doctor 会在你规划之前告诉你这一点。
**账目中的另一半,测量于 2026 年 9 月 19–20 日:**工作模型免费,但协调并非如此。Opus 规划每项任务需花费 8,400–22,100 tokens,几乎完全取决于计划中的任务数量——详见下方的运行成本。如果页面只说“工作是免费的”却不说明这一点,那说的就只是账目的一半。
阅读以下数字前:如何解读它们
本页的所有比率都以区间呈现,从不只给出单点值,这有实测依据。将前沿模型自己生成、且关卡未发现缺陷的差异重新通过关卡检查时,19 个候选项中有 2 个前后判断不一致:D = 0.105,95 % 区间 [0.013, 0.331](experiments/gate-error-rate/,使用在首次重放前冻结的规则)。根据该规则自身的判定,D > 0.10 即为不可接受,因此我们采取了以下做法:这里的通过率不会只以单独的分数形式发布;每个通过率旁边都会标出 D;比较任意两个比率时,都会先确认它们的差异是否足以经受这一误差的影响。
这会、也不会影响什么。 D 统计的是关卡拒绝本来没问题的变更。这并不能证明关卡放行了任何有问题的内容。因此:
关卡不会放行任何未通过的内容——依然成立。 关卡只会拒绝未通过的内容——测量结果已证伪,约每十次评估就有一次不符,且更严格的范围尚未得到证实。
已知的三个原因中,有两个现在会记录在每项判定中——内存压力(ADR-0066)和基线采集日期不同(ADR-0069)。第三个原因尚未查明,而且两次测量到的判断不一致都发生在机器空闲时,因此并非前两种原因导致。D 是在工作负载 #2a 的关卡上测得的;它对工作负载 #1 的变异测试关卡没有说明作用,因为后者使用的是另一种判定机制(规则 §4.4)。
工作负载 #2a — 保持行为不变的变更,实测
依据一项在工具给出任何判定之前就已冻结的决策规则(experiments/go-no-go-2a/results/REPORT.md)。S 表示存活,A 表示盲审人员对差异的认可。每个单元格均为 k/n,并附有精确的 95 % 区间;D = 0.105 [0.013, 0.331] 适用于所有 S。
| 输入 | S,本地 7B | S,Haiku 对照组 | A,本地 7B | A,对照组 |
|---|---|---|---|---|
| 夹具 | 3/3 [0.292, 1.000] | 3/3 [0.292, 1.000] | 1/3 [0.008, 0.906] | 3/3 [0.292, 1.000] |
| 一个商业 Nest/jest 代码库 | 12/12 [0.735, 1.000] | 12/12 [0.735, 1.000] | 9/10 [0.555, 0.997] | 10/10 [0.692, 1.000] |
| 一个商业 React/jest 代码库 | 11/12 [0.615, 0.998] | 12/12 [0.735, 1.000] | 9/10 [0.555, 0.997] | 10/10 [0.692, 1.000] |
请看区间,而不是分数:在这些样本量下,12/12 和 11/12 无法区分,7B 与对照组在 A 上的结果也无法区分。两个真实项目都刚好以零余量通过了冻结规则,样本量为 10。存活率没有说明任何问题——六个可测单元格中有五个不低于 0.917,因此规则中的比率条款没有起作用;本地 7B 与网络模型之间唯一的区别因素就是认可率。
实测结果表明,这一认可率反映的是:本地模型会进行未被要求的外观调整——删除文档块注释、改写注释、无故插入空行——在抽样的存活者中有 4/23 [0.050, 0.388],而对照组为 0/23 [0.000, 0.148]。confined ∧ compiles ∧ tests pass 无法发现这些问题,这正是关键所在。
相比只询问 Opus,你能获得什么
2026 年 9 月 18—19 日进行测量,对比的是同事今天实际采用的方式——直接逐项询问前沿模型,不做计划,也不设置门槛。相同的 19 个手写任务、相同的两个代码库,四组对照。
| 仅 Opus | 仅 Sonnet | sidecrew | |
|---|---|---|---|
| Nest 代码库中 19 个任务的 token 数 | 80,131 | 88,820 | 0 |
| React 代码库中 19 个任务的 token 数 | 95,335 | 88,680 | 0 |
| 相较 Opus 的输出,Nest 代码库 | — | 19/19 完全相同 | 18/19 完全相同 |
| 已交付并验证的变更,Nest | 19(未经验证) | 19(未经验证) | 19/19 [0.824, 1.000] 通过验证 |
| 已交付并验证的变更,React | 19(未经验证) | 19(未经验证) | 15/19 [0.544, 0.939] 通过验证;4 个升级处理 |
token 列是计数,数值精确。通过率行是比率,因此附带区间;两行都适用 D = 0.105 [0.013, 0.331]。
第四组对照对 Opus 自己生成的差异运行了相同的门槛检查,以区分门槛和工作者各自的贡献:Nest 代码库中 19/19 [0.824, 1.000],React 代码库中 18/19 [0.740, 0.999]。由此得出两点,第二点更有用。
门槛检查没有发现前沿模型的工作有问题。 它唯一拒绝的一项,是 tsc 脆弱性;它对两组都拒绝了这项变更——因此,在这些任务上,门槛检查并未在 Opus 的基础上增加安全性。它的全部价值在于让免费的工作者变得可用,而不是对昂贵的模型进行二次审查。
它还能区分工作者缺陷和项目缺陷。 React 的四个失败中,有三个在由 Opus 编写差异时消失——这是真正的工作者缺陷;另一个则原样复现,因为 7B 模型对此任务的输出与 Opus 逐字节相同。因此,归因于工作者的通过率是 15/18 [0.586, 0.964],而不是 15/19。没有这项对照,小模型会被归咎于比实际造成的失败多三分之一——并且请注意,两组区间几乎完全重叠,因此修正改变的是归因,而不是数量。
这能带来三点好处,也有一项代价。
- 工作免费。 不是更便宜——工作者 token 用量为零。Opus 负责规划并审查通过验证的变更;编辑工作在你的 Mac 上完成。
- 对于编译器和测试套件能够检查的工作,你不必为此牺牲任何东西。 19 个差异中有 18 个与 Opus 生成的结果逐字节相同。这不是“质量相当”——而是同一个文件。
- 出现错误时,你会收到明确警告,而且不会应用任何变更。 React 的四个失败分别是:一个符号被重命名七次(5 个编译错误);一次重命名同时改到了一个类型、一个模块路径和一个公共属性键(122 个编译错误);一次变更重命名了它接收到的文件;以及一次前沿模型也原样生成的变更。每项都显示为
escalated,并附带确切错误信息,没有任何一项被合并。直接询问 Opus,你会得到一个差异以及“其他内容没有变化”这句话——在这里它确实准确,但未经验证。 - 它会耗费实际时间。 交互式使用 Opus 每项任务约 25 秒;使用 sidecrew 则为 216—271 秒(生成用时 15 秒,运行项目自己的测试套件和
tsc用时 200—255 秒)。它免费且无需值守,但速度不快。
未作出的主张。 冻结规则的结论是 WITHHELD:这些运行中的任务全部都是重命名,而规则要求空值保护、API 迁移或死代码删除至少占一半,才会给出结论。这次测量非但没有推翻这一条款,反而证实了它的合理性——两个前沿模型和一个 7B 模型在 19 个 Nest 任务中有 18 个输出了完全相同的字节,因此这组任务无法对任何方案进行排名。experiments/status-quo/ 中包含各组对照、运行前冻结的协议,以及缺陷记录。
系统要求
| 操作系统 | Apple 芯片上的 macOS。 本地工作进程使用 MLX,这是 Apple 的技术。这不是移植,而是不同的推理栈。 |
| 内存 | 已安装内存至少 24 GB,适用于本地层级以及本页测量的所有内容。阈值按已安装内存计算,而不是可用内存,因此能够运行工作进程的机器绝不会悄悄降级。 |
| Node | ≥ 20。若项目自身的 engines 要求更高版本,则遵从项目要求——在项目所用的 Node 版本下运行 sidecrew(ADR-0049 让我花了一晚上才弄明白)。 |
| Python | mlx-lm,由你安装:pip install mlx-lm。刻意不打包——外部能力通过 Shell 命令调用,并由 doctor 报告,不会随附打包。 |
| 磁盘空间 | 7B 模型约需 4 GB(首次运行 sidecrew serve 时下载,并固定版本),每个验证沙箱在运行期间另需约 500 MB。 |
| 项目 | 使用 TypeScript,tsc 基本无错误,且测试套件能够运行。工作负载 #1 还会运行 Swift/XCTest。 |
内存低于 24 GB:sidecrew 仍可运行,但会使用 api 层级,由 Haiku 作为工作进程并向你的密钥计费——本页的所有数字都不适用于该层级,因为尚未对其进行测量
(Phase 13 §5)。受支持,但未定价。如果这对你很重要,24 GB 就是门槛。
Windows 和 Linux:不支持。TypeScript 验证器可以移植,但工作进程不行,而且内存和压力检测依赖 sysctl/vm_stat。sidecrew doctor 会告诉你原因,而不是莫名其妙地失败。
在你的机器上会是什么情况
检查的是已安装的 RAM,而不是可用 RAM——打开 Xcode 后,可用 RAM 会波动 8 GB;如果一个工具会因此改变自身行为,那你就无法推断它的表现。最低要求是 24 GB,低于此值 sidecrew 会拒绝运行(ADR-0073)。
| 已安装 | 档位 | Worker | 正在运行的 gate 数 | 对你意味着什么 |
|---|---|---|---|---|
| 低于 24 GB | — | 无:sidecrew 会拒绝运行 | — | 这里无法在正常工作负载旁运行 7B(实测如此),强行尝试会导致交换内存——这会让 gate 拒绝原本正常的更改(ADR-0066)。系统会告知你的 RAM、最低要求和原因。有一个不受支持的逃生通道(SIDECREW_TIER=api,通过网络调用 Haiku,费用计入你的密钥,从未测量);本页上的任何数字都不适用于它。 |
| 24–32 GB | local | Mac 上的 7B | 1 | 本页上的所有数据都在此配置下测得。Worker token 为零。一次一个任务:每个约 4 分钟,因此 19 个任务的计划需要约 70 分钟,可无人值守运行。内存是限制因素——见下方的假阴性说明。 |
| 48–64 GB | local | 7B,或轻松运行 14B | ~3 (估算) | gate 不再与模型争抢内存。同一个 19 个任务的计划预计耗时接近约 25 分钟 (估算),而且 ADR-0066 中整个由资源不足导致 gate 默认拒绝的假阴性类别也不再适用。你可以继续使用这台机器。 |
测量值与估算值的区别在这里很重要。 24–32 GB 这一行是实测数据:在一台 32 GB 的 M2 Pro 上,每个任务生成需要 15 秒,项目自身的 tsc 和测试套件需要 200–255 秒。48–64 GB 这一行是根据两个实测数据得出的估算值——上述每个任务的 gate 耗时,以及单个 gate 实际占用的内存(大型 React 项目中,tsc 最多占用 8 GB,jest worker 另占 7–10 GB)。没人用 64 GB 运行过 sidecrew。并发计算采用工具自身的公式(slot_gb = model.ram_gb + headroom),因此 doctor 会告诉你这台机器能做什么。
更多 RAM 提升的是运行时间和可靠性,而不是更改质量。 gate 在 React 代码库上发现的四个问题中,没有一个能通过增加内存来避免:一个符号被重命名了七次,一个文件被重命名,一个改动涉及 Worker 从未看到的文件中声明的类型,还有一个与 Opus 生成的内容逐字节相同。前两个问题出在模型;第三个需要的是检索,而不是 RAM。
本页所有存活率数字都应谨慎解读,这一点在本页顶部——D = 0.105 [0.013, 0.331],gate 对自身结果存在分歧。这里不再重复,是因为它影响下文的所有比率,而不仅仅是这张表。
另外两个缺陷改变了 gate 本身(ADR-0067、ADR-0068),因此上方的 Phase 11 表格是在一个后来经过两项修复的 gate 上测得的。
两个真实项目都未经修改,且都不属于我们,上文的每个组都在本地档位下运行,Worker token 为零。api 档位没有自己的存活率、批准率或费用数据——Phase 13 §5 从未运行,本页的任何内容都不适用于它。
experiments/go-no-go-2a/results/REPORT.md 包含漏斗、冻结规则,以及为得到任何数字而付出的六项缺陷。
这不是测试框架。Vitest、Jest 和 XCTest 运行测试;StrykerJS/Muter 修改代码。sidecrew 负责协调。runner 是一道接口:相同计划、相同种子,Vitest 和 Jest 会返回完全相同的判定(ADR-0028)。
运行成本
Worker 是免费的。协调不是,而这里的数字说明了成本有多高。
数据测量于 2026 年 9 月 19 日至 20 日,使用未经修改的商用 Nest/jest 代码库,依据在规划器出现前冻结的规则(experiments/planner-cost/):
| 计划规模 | 规划所用 Opus token 数 | 每项任务 | 相比每项任务付费使用模型 |
|---|---|---|---|
| 12 项任务 | 265,607 | 22,134 | 2.84× |
| 41 项任务 | 343,144 | 8,369 | 1.07× |
工作量增加 3.4×,规划成本几乎没变——仅为 1.29×。成本主要是较大的固定成本(读取代码库,约 233k token),加上较小的单项任务成本(约 2,700)。因此:
对于十几项任务,sidecrew 的协调不值得花钱;工作规模越大,经济效益就越明显地向它倾斜。
两行的数值都高于 1.0,因此按照冻结的规则,两者都未通过——规划成本仍高于把每项任务交给付费模型的成本。诚实的解读是上面那句话,而不是“它没通过”:只看一种计划规模,本可以得出严苛得多、也不符合事实的结论,这正是规则要求使用两种规模的原因。
引用每项任务的成本时,务必注明计划规模。 同一个规划器、同一个项目、同一周,数值却相差 2.6×。
纠错轮已关闭,而且也经过了测量。 在免费重试之后(那次重试已经包含编译器自己的错误信息),给失败的 Worker 一条由 Opus 编写的说明,挽救了 0/29 项任务 [0.000, 0.119];其中 29 项里有 27 项最终停留在与免费重试完全相同的关卡阶段(experiments/correction-round/)。对于 Worker 直接原样返回文件的任务,明确指出原样返回就是失败后,17 项里有 16 项再次如此。对于适合这类工作的任务——添加 null 防护——本地 7B 模型仅在 30 项任务中的 1 项 [0.001, 0.172] 上成功,并在其中 17 项里原样返回文件。改写指令并不能改变这一结果,因此 sidecrew fix 默认关闭了这一轮。
不过,这并不是能力上限,之后的测量也证实了这一点。 Phase 14b 对同样的 30 项任务使用了 14B 模型,并在另一轮将要求缩小到单个指定函数。两种方法都大幅减少了“原样返回”的失败:14B 模型从 17 项降至 3 项,缩小要求后从 17 项降至 10 项;但两者都没有提升成功率,结果仅从 1 项变为 2 项 [0.008, 0.221]。Worker 能完成工作;关卡却无法认可它。请参阅下文 v0.1.0 尚不具备的功能。
为什么工作负载 #1(测试)值得这样做
| Claude 编写每项测试 | sidecrew | |
|---|---|---|
| 每项测试的 token 数 | 每个函数都完整生成 | 规划 + 每种形态一个示例 + 审查通过的测试 |
| 延迟限制 | API | 你的硬件——每个 7B Worker 40 tok/s,下文有测量数据 |
| Claude 读取的内容 | 原始输出 | 仅限已编译、通过且杀死 ≥ 1 个变异体的测试 |
| 生成是否需要联网 | 是 | 否 |
token 和成功率两列的测量数据来自 Phase 6,结果并非明确肯定:experiments/go-no-go/results/REPORT.md 中记录了完整流程、运行前冻结的决策规则,以及无法命名的单元格。TypeScript 有条件可行;Swift 不可行。 速度列:
M2 Pro、32 GB、macOS 26.6.2、mlx_lm 0.31.3,Xcode 和模拟器均已打开——
experiments/go-no-go/results/bench-2026-09-11.json 中所有字段均为 "measured": true:
| 模型 | 解码速度 | 首 token 延迟(热启动) | 峰值 RSS | 交换空间 | 相同提示词运行 5× |
|---|---|---|---|---|---|
| Qwen2.5-Coder-7B-Instruct-4bit | 40.5 tok/s | 159 ms | 4.4 GB | 0 | 字节完全一致 |
| Qwen2.5-Coder-14B-Instruct-4bit | 21.1 tok/s | 199 ms | 8.1 GB | 0 | 字节完全一致 |
在空闲机器上,速度分别为 42.3 和 21.2 tok/s——完整的 Xcode 工作集会让 7B 模型慢约 4%,对 14B 模型几乎没有影响。Xcode 影响的是内存,而非速度:可用内存为 9.1 GB 时,14B 模型使用了 3.2 GB 交换空间。这就是默认使用 7B 模型,以及启动 Worker 前要检查当时的可用 RAM(ADR-0011)的原因。
安装
要求:配备至少 24 GB 已安装内存的 Apple Silicon Mac。 低于这个配置,7B 模型无法与正常工作集并存(ADR-0009,已实测),sidecrew 会拒绝启动,并说明你的内存容量、最低要求和原因。sidecrew doctor 可以在你规划之前解答这个问题。
拒绝启动是有意为之,并非偷懒。强行运行意味着交换内存,而交换内存会导致这个门槛拒绝原本没问题的更改,且无法从自身的判定中区分这种情况与真正的缺陷(ADR-0066,已实测)。把这种问题丢给最难发现它的用户,比直接说不更糟。
有一个应急选项,但不受支持。 SIDECREW_TIER=api 会通过 Anthropic API 使用 claude-haiku-4-5 运行工作进程,并经过同一道门槛,费用由你的密钥承担。该模式已构建并测试,但其稳定性和每项任务的费用从未测量过,本页的任何数字都不适用于它(ADR-0073)。doctor 会将其标记为不受支持,已选择启用。
除生成(规划、验证、核验)外,其他所有功能都可以在任何能运行 node 的环境中使用。
npm install -g sidecrew
sidecrew doctor
doctor 会分别检查每项能力:
ok platform darwin/arm64
ok node v20.20.0
ok tier 32.0 GB installed → local tier · qwen2.5-coder-7b-4bit
ok mlx_lm python3 -m mlx_lm server available
MISSING worker nothing on http://localhost:8000/v1 — start one with: sidecrew serve
ok memory 32.0 GB total · 12.5 GB free
ok tsc Version 5.9.3
ok vitest vitest/2.1.9 darwin-arm64 node-v20.20.0
MISSING stryker stryker 8.7.1 is not in sidecrew's tool cache — run: sidecrew tools install (~62 MB, never into a project)
ok swift Apple Swift version 6.3.3
MISSING muter not installed — brew install muter-mutation-testing/formulae/muter
ok line-ranges from the TypeScript compiler's own tree (ADR-0076)
DEGRADED tsconfig-include sidecrew writes candidates to test/, and no file there is in the program
tsconfig.json builds — every candidate would be compiled by a stage that
never opens it (ADR-0037)
ok ts-jest ts-jest does not resolve here — the shim is not needed
ok tsc-heap this project's own scripts ask for no extra heap
ok jest-tests jest does not resolve here — not this project's runner
最值得看的,是最下面五行;每一行都对应一次失败的运行,或更糟——一次悄无声息地成功的运行。“是否已安装”的答案对它们全都是“是”;缺陷出在更底层,具体取决于某个项目的布局方式。tsconfig-include 是六个真实阻碍因素中最严重的一个,也是唯一一次以放行方式失败的情况:编译阶段对项目进行了类型检查,却从未打开候选项,还对一个包含三个类型错误的文件报告 compile ok。
Claude Code
claude mcp add --scope user sidecrew -- npx -y sidecrew mcp
然后,claude mcp list 应显示 sidecrew: … ✔ Connected,并且可以在新的 Claude Code 会话中调用 sidecrew_status。安装技能和 Agent 后,还会添加 /sidecrew plan|run|review|escalate:
cp -r $(npm root -g)/sidecrew/claude/skills/sidecrew ~/.claude/skills/
cp $(npm root -g)/sidecrew/claude/agents/*.md ~/.claude/agents/
这些文件同样构成一个 Claude Code 插件——claude/.claude-plugin/plugin.json 是它的清单,其版本会与 package.json 和 server.json 一起更新。
该技能负责确保生成工作由本地工作进程完成:Claude Code 子 Agent 在会话端点上只能选择 haiku/sonnet/opus,因此工作进程不能作为子 Agent 运行;技能会明确说明这一点(ADR-0001)。
其他 MCP 客户端
{ "mcpServers": { "sidecrew": { "command": "npx", "args": ["-y", "sidecrew", "mcp"] } } }
各项能力彼此独立
| 能力 | 依赖项 | 缺少依赖项时 |
|---|---|---|
| 规划、验证和核验 TypeScript | node,以及项目自身的 tsc 和 vitest 或 jest。Stryker 属于 sidecrew:sidecrew tools install | — |
| 核验 Swift | Xcode CLT、muter | 仅 TS |
| 本地工作进程 | pip install mlx-lm(Apple Silicon) | 仅验证;由 Claude 自行编写测试 |
pip install mlx-lm # workers
brew install muter-mutation-testing/formulae/muter # Swift mutation
sidecrew tools install # sidecrew's own pinned Stryker, once per machine
不会向正在测试的项目中安装任何内容。 Stryker 属于 sidecrew,固定在 ~/.sidecrew/tools 中的 8.7.1 版本;每次运行都会使用它的临时副本,并接入项目自身的编译器和测试运行器。每次 run 和 fix 都会在前后对项目进行指纹检查(git status、package.json、所有锁文件、node_modules),如果有任何更改就会明确报错(ADR-0088)。sidecrew doctor --project <dir> 会报告项目是否自带测试运行器——jest 或 vitest——因为这部分由项目负责。
工具
| 工具 | 功能 |
|---|---|
sidecrew_status | Worker 是否运行?使用哪个模型、哪个修订版、剩余 RAM 有多少、有哪些可用的验证器。 |
sidecrew_generate | 一个 WorkerTask → 本地模型生成一个候选测试。绝不会调用 Anthropic API。 |
sidecrew_verify | 编译 → 运行 → 修改一个文件 → Verdict。 |
sidecrew_run_batch | 执行完整计划:生成 → 验证 → 使用错误重试一次 → 升级处理。仅返回存活项和升级处理项。 |
sidecrew_plan_validate | 在计划花费任何资源之前验证计划:检查架构、行范围、source_sha,并让每个示例实际通过验证器运行。 |
sidecrew_escalate | 列出 Worker 无法完成的任务,以及它们收到的示例和规则,还有两次尝试的错误。会从磁盘读取已完成的运行记录。 |
sidecrew_review | 判断哪些存活项值得阅读:低于各语言变异分数阈值的项,以及确定性审计样本;按令牌上限分批处理。 |
sidecrew_fix_plan_validate | 在变更计划花费任何资源之前验证计划;根据规则拒绝任何 Worker 都无法通过的任务。 |
sidecrew_fix | 工作负载 #2a:在项目自身测试套件和 tsc 的门控下进行保持行为不变的变更。速度较慢——每个候选项都要运行一次测试套件。 |
sidecrew_fix_escalate | 列出 Worker 无法完成的变更,以及每次尝试的判定结果。 |
sidecrew_recon | 检查项目按当前配置有多少 tsc 错误,以及每个更严格的标志会额外带来什么;分别统计源码和测试。不提供修复建议。 |
sidecrew_query | 针对规划器谓词提出的问题,由项目自身的编译器作答:refs、unreferenced、sizes、diagnostics。不使用 Worker。 |
sidecrew_read | 本地 Worker 最多读取 10 个文件并回答一个问题;只有机器在所引位置找到引文的主张才会返回。获准返回不等于事实正确。 |
工作原理
Claude (Opus) sidecrew local worker (mlx_lm.server)
reads module ──► test_plan.json + one exemplar/shape
for each function × shape ──► prompt = source + exemplar ──► candidate
verifier: tsc/swift build → vitest/swift test → stryker/muter
survive? ── yes ──► survivors (Claude reviews low mutation-score ones)
── no ──► retry once with error ──► escalate to Claude
- 验证器才是产品。 存活 ⇔ 编译通过 ∧ 测试通过 ∧ 至少杀死 1 个变异 ∧ 非同义反复。
- Worker 具有确定性。 temperature 为 0,使用固定 seed,并锁定模型修订版。seed 还会
让请求避开
mlx_lm.server的批处理——它通过is_batchable and args.seed is None判定能否批处理,因此发送 seed 会从根本上让请求串行化(ADR-0003)。 - Worker 是独立进程,不是 Claude Code 子 Agent。 子 Agent 在会话端点只能选择 haiku/sonnet/opus,因此本地路由必须通过 MCP。参见
docs/research/。 - 内存感知,分两种不同含义。 已安装 RAM 决定档位——24 GB 及以上可运行本地
Worker。低于 24 GB 时,sidecrew 会拒绝运行,并说明你的 RAM、最低要求和原因(ADR-0073)。为这类机器设计的
api档位 ADR-0009 曾在 Phase 13 中实现,之后从受支持路径中移除,因为没有任何存活率、审批或价格数据; 它仅以SIDECREW_TIER=api的形式保留,并由doctor标记为不受支持。可用 RAM 决定此刻是否可以启动: 如果可用 RAM 低于模型占用量 + 2 GB,serve就会拒绝启动,因为在交换空间中启动的 Worker 不只是运行缓慢, 还会污染之后测得的每一个数值。它还会查询内核自身的内存压力级别,因为处于内存压力下时,macOS 会压缩内存, 使可用内存数值上升,但机器状况却会恶化(ADR-0026)——--wait会排队等待内存,而不是拒绝启动。
CLI
sidecrew doctor what this machine can do
sidecrew models [--pin [KEY]] pinned revisions, what is downloaded, this machine's tier
sidecrew serve [--model qwen2.5-coder-7b-4bit] [--port 8000] [--force] [--wait N] [--allow-unpinned]
sidecrew status / stop
sidecrew bench [--determinism] tok/s, TTFT, peak RSS → experiments/go-no-go/results/
sidecrew plan test_plan.json [--quick] validate a plan; non-zero if it is not valid
sidecrew run test_plan.json [--concurrency N] [--dry-run] whole plan, survivors out
sidecrew verify <test-file> --plan test_plan.json one file, one Verdict, non-zero if it failed
sidecrew generate --plan P --function F --shape S one candidate, for looking at
sidecrew escalate [RUN_ID] what the workers could not do, for Claude
sidecrew review [RUN_ID] which survivors are worth Claude's eyes
sidecrew fix change_plan.json [--validate | --dry-run] workload #2a: behaviour-preserving changes
sidecrew recon [DIR] [--flags --strictNullChecks,…] tsc errors as configured, and what each flag adds
sidecrew query refs|unreferenced|sizes|diagnostics … predicate questions, the project's own compiler
sidecrew read --question "…" --file F [--file …] a local worker reads; answers admitted by citation
sidecrew mcp
doctor、status 和 verify 都会针对指定的项目作答,而非针对 sidecrew 自身的目录:sidecrew doctor --project fixtures/ts-fixture 会报告该软件包的 tsc、vitest 和 stryker,判定结果取决于这些工具。
一次运行
sidecrew serve # one 7B worker, gated on free RAM
sidecrew run fixtures/ts-fixture/plans/strings/test_plan.json --dry-run # tasks, concurrency, stale check — no tokens
sidecrew run fixtures/ts-fixture/plans/strings/test_plan.json
run 2026-09-14T10-24-26Z-strings: 6 tasks, 13.0 GB free ÷ 6.5 GB per slot = 2; 1 worker up, so 1 in flight and 2 test processes each
titleCase:happy_path:0: survived (score 0.88)
…
6/6 survived · 0 escalated · .sidecrew/runs/2026-09-14T10-24-26Z-strings/result.json
并发数由运行条件决定,而非由设置决定:已安装 RAM 决定档位,运行开始时的可用 RAM 决定可同时进行多少个候选项,而 --concurrency 只是上限,不能让机器凭空拥有更多内存。
固定模型版本
mlx_lm 没有 --revision,所以仓库 ID 表示“当前 main 分支的内容”。sidecrew models --pin 会将 Hugging Face 缓存中实际使用的提交写入
src/models.json,随后 serve 会传入快照路径——对应一个无法访问网络的不可变提交(ADR-0010)。
sidecrew serve # downloads on first run
sidecrew models --pin # writes the commit it downloaded
sidecrew bench --determinism # 5× the same prompt: byte-identical, or non-zero exit
状态
在 main 上,自 v0.2.0 发布以来尚未发布: sidecrew recon(每个更严格的标志会增加多少个 tsc 错误),
sidecrew query(引用计数、未引用的导出、重写规模、带位置的诊断信息——均来自项目自身的编译器),
sidecrew read(本地模型读取内容,仅接受经验证引用支持的声明),拒绝修改任何通过反射可达内容的门禁规则、收紧后的测试编写门禁,以及针对大型测试套件的记忆准入控制。第 14d 阶段测量了让规划器使用这些内容,是否能让小型任务的规划成本足够低:
规划 token 减少了约 23%,但仍然不够——详见路线图。
v0.2.0——触达范围(2026 年 9 月 24 日)。 任务可以指定单个声明,而非整个文件;评估时也以该声明为单位:声明内部零错误、外部没有更严重的问题,并且所有测试仍然通过(ADR-0086)。所有数据都在未经修改的商业 Nest 代码库(2,174 个源文件)上测得,所依据的规则在数据产生前就已冻结:
| 测量结果 | 位置 | |
|---|---|---|
| 工作者可以被要求修改的代码占比 | 按字节计为 0.519 → 0.911 | experiments/reach/ |
| 每项任务修改一个声明,且该文件过去会被拒绝 | 15/41 = 0.37 [0.22, 0.53] | docs/plan/prompts/phase-14c-prime.md |
| 同上,但文件一直都在可触达范围内 | 10/42 = 0.24 [0.12, 0.40] | 同上 |
| 同样的 27 个文件,每个文件一项任务(旧的任务单位) | 1/27 | docs/plan/prompts/phase-14c-the-reach.md |
**应将其视为一个趋势:**两个区间有重叠,而大文件区间的下限低于本项目称为可用的 0.30 线。表现形式是 --strictNullChecks 的空值保护,这是测量中最难的一项。**尚未奏效的部分:**工作者在修改之前自行编写测试(ADR-0082)的成功率为
2/20,因为它还无法构建能针对真实 NestJS 服务运行的测试。测试编写门禁中还发现了一个漏洞(ADR-0089):仅针对类型的断言可以通过门禁。自 v0.2.0 起已在 main 上修复——现在测试要通过,必须能在不依赖移除函数体或程序崩溃的情况下杀死变异。
在此之前,第 14 阶段——首个公开版本。 对于两种工作负载,流水线都能端到端运行:规划、由本地工作者生成、验证、重试一次、升级处理;sidecrew fix 也会以同样方式处理保持行为不变的代码修改。依据事先冻结的规则,已完成五项测量;坦率地说,其中三项的结果是否定的:
| 结论 | 位置 | |
|---|---|---|
| 工作负载 #1,TypeScript | 有条件通过——在夹具上达到 Haiku 的 0.85,工作者 token 为零,延迟减半(ADR-0020) | experiments/go-no-go/ |
| 工作负载 #1,Swift | 不通过——即使修复提示词后结果提升了一倍以上,仍只有 Haiku 的 0.64(ADR-0021) | experiments/go-no-go/ |
| 工作负载 #2a | 在两个真实项目上均通过,优势恰好为零,但不适用于该任务组合(所有任务都是重命名) | experiments/go-no-go-2a/、experiments/status-quo/ |
规划成本 R | 两种规划规模下均未通过——12 项任务时为 2.84,41 项时为 1.07 | experiments/planner-cost/ |
门禁自身的错误率 D | 不可接受——0.105 [0.013, 0.331] | experiments/gate-error-rate/ |
这个 0.85 是固定样本的数字,高估了 2 倍多。 随后在未修改的真实项目上测得,工作负载 #1 的存活率在 Nest 代码库上为 3/8
[0.085, 0.755]和 4/8[0.157, 0.843],在 React 代码库上为 4/10[0.122, 0.738]。这些区间彼此重叠,也与固定样本的区间重叠,因此不能据此对任何项目进行排名;它们能排除的是基于 0.85 制订计划。固定样本中的函数规模小、彼此独立,而且没有真实代码中常见的导入、共享类型和框架脚手架。D是在工作负载 #2a 的门槛上测得的,不适用于这些情况——变异测试是另一种评判标准,有不同的失败模式。
根据这些证据,14B 从来都不是合适的权衡选择——它在 TypeScript 上与 7B 表现相同,在 Swift 上表现更差,而且生成时间是 2.2 倍。
v0.1.0 尚不具备的能力。 处理半个真实代码库仍遥不可及:一个项目中 3.3 % 的文件占其字节数的 48.1 %,而所有超过 1,000 行的文件都会被拒绝,因为 worker 会返回整个文件,而整个文件必须能够容纳(ADR-0075 — 提议的解决方案是按符号范围返回,但此版本尚未实现)。
它实际适用的改动类型。 在五种保持行为不变的改动类型中,只有一种——重命名和移除无用导入——能以可用的成功率完成。 null_guard 则不行,而 Phase 14b 测出了原因,这改变了应对方式:S₁₄ = 2/30 [0.008, 0.221],是 14B worker 和单函数请求中表现最佳的。** 模型大小和任务大小都不是障碍——两次探测都改变了各自的目标。**worker 每额外正确修复一个文件,任务就会多出一个无人能通过**,一一对应:+6 个正确修复 → +6 个不可满足任务,+9 → +9。原因就在门槛自身的字段中——导致这些任务失败的错误,在 **21/21** 个案例中出现在**测试文件**里,在非测试源码中则为 **0**。空值保护会收窄类型,收窄后的类型会传播到测试夹具和模拟对象中,而 sidecrew` 不能编辑测试,因为测试就是门槛**。
因此,诚实的说法不是“小模型做不到”。而是:在启用了严格性标志、且项目测试会涉及被收窄类型的项目中,无论 worker 有多出色,这种改动类型都无法通过——而且 worker 越出色,情况越糟(三个实验组中不可满足任务数依次为 12 → 18 → 21)。
api_migration 和 dead_code 仍未测量。ADR-0077 记录了各种选项,负责人选择了先测量反事实,再从中作出决定。
docs/plan/PHASES.md 展示了接下来的路线,并说明了每一步的价值。
在相信上面的宣传之前,值得先读的一项测量结果。 设计认为,示例是让小模型变得可用的关键(研究 §B)。但我们自己的消融实验表明并非如此:不提供额外信息时得分为 4/20,而且 15 次编译失败全都是缺少 import { describe, it, expect } from "vitest"。加上一句关于该导入的说明——不提供示例——得分就达到 16/20,比完整示例还高一分。保留示例,是因为它能提升幸存者的变异分数(1.00,对比 0.93),并降低成本(150 个补全 token,对比 258 个),而不是因为它能让候选结果通过门槛。ADR-0017 列出了数据表和注意事项,其中最需要强调的是:在 n = 1 时,16/15/17 的差异只相当于一两个任务。
一次长时间运行会如何影响机器,以及 sidecrew 如何应对
第 7 阶段的加固措施,每项都附有相关 ADR:
- 只有在重试可能有帮助时,才会用掉唯一一次重试。 对于由变更 工具 导致的失败、完全没有变异体的函数,以及提示词与首次尝试逐字节相同的重试,都会升级处理,而不是重试(ADR-0012、ADR-0005、ADR-0022)。重试提示词使用独立的模板。
- 升级事件发生时就会写入记录,写入
.sidecrew/runs/<id>/escalations.jsonl,这样即使运行在第 40 分钟被终止,也仍有记录说明各次尝试取得了什么(ADR-0023)。某项任务抛出异常时会被升级处理,其他 19 项仍会继续运行;设置错误仍会使所有任务停止。 - Claude 只会检查表现最差的幸存者,而不是全部幸存者——低于各语言的分数阈值,并加上确定性的 10 % 审计抽样;按批处理且受令牌上限约束(ADR-0024)。TypeScript 的阈值为 0.6,Swift 为 1.0,因为 Swift 的判定基于 1 或 2 个变异体,而 TypeScript 基于 6 到 12 个。
- 工作器不会在内存交换压力下启动。 同时检查可用 RAM 和内核自身的内存压力级别,因为 macOS 在内存压力下会压缩内存,导致可用内存计数上升,但机器状况却在恶化(ADR-0026)。
--wait会排队等待资源,而不是直接拒绝。 - 机器性能下降时会减少一个并发槽位。 如果解码速率连续两分钟比
sidecrew bench的基线低 30 % 以上,工作器并发数就会减少 1;如果没有基准测试结果,则不启用保护机制,而不是凭空猜测(ADR-0025)。 - 未固定版本的修订会被拒绝,而不是仅发出警告,因为同一仓库两个提交的存活率无法比较,下游也无法辨别(ADR-0027)。
sidecrew run --dry-run 会写出每项任务 以及 每条渲染后的提示词,并在生成第一个令牌前停止。
路线图
按照所有者的说法,sidecrew 正在努力实现这一目标:"我们能做到 Claude Opus 所做的事,但采用不同且更便宜的方式"——任何用户都可以在自己的代码上获得同样的结果。 每个版本都会准确说明这一目标已实现多少,并将数据标注为 实测 或 估算,绝不夸大 (ADR-0093)。
| 版本 | 含义 | 状态 |
|---|---|---|
| 0.x | 每个版本都会增加下方阶梯中的一个台阶,且只有经过实测后才会宣称达成 | 已发布 v0.2.0;main 上还有更多内容 |
| 1.0 | 在包含真实请求的基准测试中,sidecrew 的成功率达到 Opus 单独运行时的 ≥ 80–90 %——包括功能和错误修复——而批处理任务的成本**≤ 50 %**(以根据任务规模拟合的公式表示,并附上误差范围,绝不只给出单一数字);以 Opus 单独运行的结果为基准,并且能在 sidecrew 并非针对其构建的项目上复现 | 尚未达成 |
| 2.0 | 速度达到或超过 Opus 单独运行时的水平 | — |
| 3.0 | 质量达到或超过 Opus 单独运行时的水平 | — |
能力阶梯
大多数功能和 bug 并非独一无二,因此工作会归入不同类别,每类都有一套机器可运行的门槛。只有经过测量,才会认定某个类别已达标。最后一级——任意请求——就是 1.0。
| 级别 | 类别 | 门槛 | 状态 |
|---|---|---|---|
| 1 | 为现有代码编写单元测试 | 可编译 ∧ 测试通过 ∧ 能杀死一个既非删除函数体也非崩溃的变异体 ∧ 非恒真测试 | 已实现;在真实项目中测得 3/8、4/8、4/10(正在根据收紧后的门槛重新评分) |
| 2 | 保持行为不变的清理——重命名、死代码、未使用的导入 | 差异范围不越界 ∧ tsc 无错误 ∧ 所有原本通过的测试仍然通过 ∧ 不删除反射机制可触及的内容 | 已实现,已测量 |
| 3 | lint 和编译器标志修复 | 满足第 2 级门槛 + 标志或规则通过检查 | 已测量的范围(在一个真实 Nest 代码库中新增 282 项,其中 95 % 位于源代码中);尚未运行 |
| 4 | 静态分析发现的问题(Sonar 风格规则) | 满足第 3 级门槛 + 分析器规则通过检查 | 已提出 |
| 5 | 严格性迁移(--strictNullChecks) | 满足第 2 级门槛,测试文件中的类型错误降级处理 | 83 项中完成 25 项,逐项声明处理(仅供参考) |
| 6 | 分类 bug 修复 | 可复现的测试由失败转为通过 ∧ 无回归 | 尚未实现 |
| 7 | 分类功能 | 智能模型编写且用户批准的规格测试由失败转为通过 ∧ 对变异敏感 ∧ 一项留出测试通过 | 尚未实现 |
| 8 | 任意 bug、任意功能、完整的新模块 | 满足第 7 级门槛,不分类 | 1.0 |
如何分配工作——优先选择能力足够且按预期单位成功成本最低的方案
先使用能给出确定答案的机械工具(编译器、语言服务、codemod),然后是本地模型、较便宜的 Claude 模型,最后是用户当前使用的模型——每项工作都按预期单位成功成本分配,而非只看价格;根据门槛的判定逐级升级,并用同一门槛评估每一级(ADR-0092、ADR-0094)。请求会先经过分诊:规模(要修改多少处)决定成本,复杂度(结果需要多少判断)决定级别,而且一个请求可以拆分为不同级别的部分(ADR-0095)。
当前进展:已测量
| 衡量内容 | 当前值 | 目标 | |
|---|---|---|---|
| 覆盖范围 | 任务可能触及的真实代码库字节占比 | 0.911(已测量) | ≥ 0.90 ✓ |
| 成本 | 规划开销 | 小型任务目前还不比 Opus 便宜:规划约 12 项任务需花费 Opus 5.5 $2.39–3.31(每项任务约 $0.22–0.30);约 40 项任务需花费 $2.67–3.48(每项任务约 $0.07–0.08)。大部分开销都花在规划器反复读取自身上下文上,而非思考(已测量) | 在批量任务中低于仅使用 Opus 成本的 50 %;前提是已测量仅使用 Opus 的对照组 |
| 类型 | 以可用速度完成的行为保持型任务类型 | 重命名和死代码可以;严格性迁移正在改进;正式重新评分待定 | ≥ 4/5 |
| 可信度 | 门槛前后判定不一致的频率 | 已确定源于项目测试套件自身的不稳定率,并通过重新读取仅回归失败的结果进行缓解(ADR-0084) | 已确定 ✓ |
接下来的工作(docs/plan/HANDOFF.md 中有当前清单):基于来自开源项目外部的真实请求开展基准测试,以测量 1.0;进行所需的仅使用 Opus 对比;分诊;引入中间档模型;以及加快门槛检查。设计仍在调整期间,项目会用短探测进行测量,只有针对将要公布的数值才进行长时间运行(ADR-0091)。docs/research/2026-09-25-v1-independent-analysis.md 中提供了关于迈向 1.0 的独立分析。
开发 sidecrew 本身
npm i && npm run lint && npm test
fixtures/ 下的夹具具有各自的依赖项,且不包含在仓库中——它们是构建产物。因此,干净克隆后运行测试套件时,少数依赖夹具的测试会被跳过,每条跳过提示都会说明运行哪条命令可以启用该测试。要运行全部测试:
for f in fixtures/*/; do [ -f "$f/package.json" ] && npm --prefix "$f" i; done
需要真实工具链的测试——例如运行中的 worker、Stryker、Muter 或项目自身的测试套件——文件名均为 *.slow.test.ts,且仅在设置 SIDECREW_SLOW=1 时运行。CI 运行快速测试集。
发布
与 simframe 相同:同时更新 package.json、server.json 和 claude/.claude-plugin/plugin.json 中的版本号,打标签并推送;CI 会检查这三者是否一致,发布工作流则会将其发布到 npm 和 MCP Registry。
许可证
MIT。worker 模型和工具各自有其许可证;候选名单中仅包含 Apache-2.0 / MIT 许可证的项目。
docs/research/licences.md 是审计记录——其中说明了哪些内容会被打包、哪些会被下载,以及哪些仅为推荐项,所有信息均依据已安装的产物核实,而非网站内容。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。