multi

[🇬🇧 →] · [🇷🇺 →]

用 multi 个 ai 跑同一件事 - 代码评审、规划、提问 - 然后拿到 multi 份意见。

---

这是在干嘛?

`multi` 把一件事同时丢给好几个 AI —— 最适合代码评审([实测:比内置代码评审找到更多 bug](#评测))。 它还能干「到底做完了没」、[adhd](https://github.com/UditAkhourii/adhd) 式规划,或者就是随便问问 —— 然后告诉你哪些模型意见一致,哪些不一致。判断的是你,不是它们。 目前支持: - claude 子代理 - codex - opencode - kilo code (free models, no login) - gemini - github copilot - headless claude code + 你自己提供的任意 API key 或 base URL(比如 GLM/DeepSeek/Qwen/[openrouter](https://openrouter.ai/) 的 key、[9router](https://9router.com/),只要有 anthropic 兼容端点就行)

图啥?

一个模型又规划、又干活、又自己评审自己,这不行。用好几个(`multi`)模型才能拿到真正值钱的东西——不一样的意见。 三个 LLM 能找出 5 个 bug,但第 6 个只有其中一个能找到——这就是你**需要** `multi` 的原因。别光听我说——自己去看[评测](#评测)! 我自己找到的最佳组合是最新的 codex 模型 + 最新的国产 flash 模型,不过你随意——OpenCode、OpenRouter 上的免费模型都行,基本上任何能给你 ai api 的东西都行

贵吗?

你说了算!有了 `multi` 的 profile 系统,预算多少就能组多大的队伍。 可以用 `i on have any money` profile:免费的 Codex + 免费的 OpenCode 模型(不知为啥它们真的很强)。免费总比没有强,对吧? ```toml default_profile = "normal" [backends.codex] type = "codex" # Free or Go plan [backends.opencode] type = "opencode" # no `models` = using free models [backends.openrouter] # key defaults to OPENROUTER_API_KEY type = "claude-headless" base_url = "https://openrouter.ai/api" models = ["qwen/qwen3.8-27b:free", "nvidia/nemotron-3-ultra-550b-a55b:free", "stealth/another-stealth-model-alpha"] # tried in order [profiles] normal = ["codex", "opencode", "openrouter"] ``` 付费模型也行:Codex Plus/Pro、OpenCode Go/Zen、z.ai API、Qwen API,甚至 OpenRouter: ```toml default_profile = "normal" [backends.codex] type = "codex" [backends.opencode] type = "opencode" models = ["opencode-go/kimi-k3", "opencode-go/deepseek-v4-pro"] # opencode-go/ = Go sub, opencode/ = Zen pay-per-token [backends.glm] # z.ai, with its own key type = "claude-headless" base_url = "https://api.z.ai/api/anthropic" models = ["GLM-5.3-Flash"] api_key_env = "ZAI_API_KEY" [backends.openrouter] # key defaults to OPENROUTER_API_KEY type = "claude-headless" base_url = "https://openrouter.ai/api" models = ["qwen/qwen3.8-flash", "deepseek/deepseek-v4-flash-0731"] # tried in order [profiles] normal = ["codex", "glm", "openrouter"] free = ["openrouter:openrouter/free", "codex"] # name:model = exactly that model, no fallback ``` 或者甚至直接把 OmniRouter/9router 怼上去! ```toml default_profile = "normal" [backends.omniroute] type = "claude-headless" base_url = "http://localhost:20128" # root, no /v1 - claude code adds /v1/messages itself models = ["auto"] # omniroute's built-in free combo api_key_env = "OMNIROUTE_API_KEY" # no key in omniroute? put any string, multi just needs one [profiles] normal = ["codex", "omniroute"] ```
🤡 或者玩个大的:地球上所有免费模型塞进同一次评审 免费列表截至 2026.09.30。嗯……为什么不呢? ```toml default_profile = "clown" [backends.codex] type = "codex" [backends.oc] # opencode free models, plus every openai-compatible free tier below: type = "opencode" # free key from each, then `opencode auth login` or a provider in opencode.json [backends.openrouter] # free key is enough for :free models type = "claude-headless" base_url = "https://openrouter.ai/api" models = ["openrouter/free"] [backends.glm] # z.ai: 4.7 flash is free, 5.3 flash is not type = "claude-headless" base_url = "https://api.z.ai/api/anthropic" models = ["GLM-4.7-Flash"] api_key_env = "ZAI_API_KEY" [backends.gemini] # google ai studio free tier type = "gemini" models = ["gemini-3.8-flash"] [profiles] clown = [ "codex", "glm", "gemini", # opencode "oc:opencode/big-pickle", "oc:opencode/longcat-2.5-preview-free", "oc:opencode/mimo-v2.6-flash-free", "oc:opencode/muse-spark-1.3-contributor-free", "oc:opencode/space-bunny-free", # openrouter "openrouter:cohere/north-mini-code:free", "openrouter:dots-studio/dots-3-note-preview:free", "openrouter:google/gemma-4-26b-a4b-it:free", "openrouter:google/gemma-4-31b-it:free", "openrouter:inclusionai/ling-3.0-flash-sante:free", "openrouter:liquid/lfm-2.5-2.6b:free", "openrouter:nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free", "openrouter:nvidia/nemotron-3-super-120b-a12b:free", "openrouter:nvidia/nemotron-3-ultra-550b-a55b:free", "openrouter:nvidia/nemotron-3.5-lightning:free", "openrouter:poolside/laguna-s-2.1:free", "openrouter:poolside/laguna-xs-2.1:free", "openrouter:qwen/qwen3.8-27b:free", "openrouter:stealth/space-bunny-alpha", "openrouter:thinkingmachines/inkling-small:free", "openrouter:thinkingmachines/inkling:free", "openrouter:typesafe/jev-latest", # a classifier. reviews your code with one enum "openrouter:openrouter/free", # nvidia nim - frontier chinese for free, if you get through the queue "oc:nvidia/moonshotai/kimi-k3", "oc:nvidia/z-ai/glm-5.3", "oc:nvidia/z-ai/glm-5.3-flash", # orcarouter "oc:orcarouter/deepseek-v4-pro", "oc:orcarouter/deepseek-v4-flash", "oc:orcarouter/qwen3.8-27b", "oc:orcarouter/hy3", "oc:orcarouter/orcarouter/free", # groq "oc:groq/groq/compound", "oc:groq/groq/compound-mini", "oc:groq/llama-3.1-8b-instant", "oc:groq/llama-3.3-70b-versatile", "oc:groq/openai/gpt-oss-120b", "oc:groq/openai/gpt-oss-20b", "oc:groq/qwen/qwen3.6-27b", "oc:groq/qwen/qwen3.8-27b", "oc:groq/allam-2-7b", # cerebras ($5 trial now, close enough) "oc:cerebras/gpt-oss-120b", "oc:cerebras/qwen-3.8-27b", # mistral (phone verification, they train on it) "oc:mistral/mistral-large-latest", "oc:mistral/codestral-latest", "oc:mistral/mistral-nemo", # cohere (1000 requests a month, this review eats one) "oc:cohere/command-r-plus", "oc:cohere/command-r", # cloudflare workers ai "oc:cloudflare-workers-ai/@cf/openai/gpt-oss-120b", "oc:cloudflare-workers-ai/@cf/meta/llama-4-scout-17b-16e-instruct", # ovhcloud (no key at all, 12 rpm) "oc:ovhcloud/gpt-oss-120b", "oc:ovhcloud/Qwen3-32B", # modelscope "oc:modelscope/Qwen/Qwen3.8-27B", "oc:modelscope/ZhipuAI/GLM-5.3-Flash", # the long tail "oc:kilo/nvidia/nemotron-3-ultra:free", "oc:llm7/deepseek-r1", "oc:bazaarlink/auto:free", "oc:aion/aion-2.5", "oc:agnes/agnes-2.0-flash", "oc:nscale/meta-llama/Llama-3.3-70B-Instruct", "oc:nscale/deepseek-ai/DeepSeek-R1-Distill-Llama-70B", "oc:together/ternary-bonsai-27b", ] ```
没有配置文件 = 内置默认值(codex + opencode + openrouter)。在聊天里说「review this with profile free」或「only codex and glm」都管用,agent 会把它当 `--backend` 传下去。profile 决定的是*谁*来评审;多深入(lite / normal / ultra)是另一个独立的旋钮,不受影响。 每个类型、每个字段都带注释:[`config.example.toml`](config.example.toml)。需要 `python3`。 code-review、check-if-done 和 ask 会用一行列出可能将代码用于训练(`yes`)或政策未知(`unknown`)的模型。运行器为每个收到提示的模型(包括 fallback)在 `.trains` 追加一行,报告取最差判定;`no` 不代表零保留。说「no-train」或「без обучающих моделей」会传入 `ask.sh --no-train`;一次性的 `--no-train` 必须每次调用都传;长期开关是配置顶部的 `no_train = true`。只保留 `no`,空后端仍在 roster 中显示 `SAT OUT`。若账户确实不训练,可在 `[backends.]` 下设置 `trains = false` 覆盖规则;`true` 表示可能训练。它不会更改供应商账户设置。没有第二个模型家族时评审停止。默认关闭,运行名单不变。规则和 Kilo 缓存见 [英文 README](README.md)。

code-review

重头戏。流程是这样的: 1. 你 profile 里的每个 backend 和子代理,并行读同一份代码快照(不是活的工作树,所以它们没法搞坏任何东西) 2. 一个 [ponytail](https://github.com/DietrichGebert/ponytail) 视角单独专挑过度设计 3. 出一份报告:**corroborated**(两个模型系(family)都看到了)、**single-source**(只有一个看到,送到你面前之前先跟代码核对过)、**disagreed**(这部分才是值得读的)、**dropped**(附上原因,没有东西会被悄悄丢掉) 旋钮,全部可选,全部用大白话说: | 旋钮 | 取值 | 改变了什么 | | ------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------- | | target | 一个 diff、一个分支、几个文件、一个函数,或「我们刚做的事」 | 大家读的是什么 | | profile | 你 `config.toml` 里的任意名字,或「只要 codex 和 glm」 | *谁* 来做外部评审 | | depth | `lite` / `normal` / `ultra` | claude 会开多少个角度:只看正确性 / + 安全 + 设计 / + 到底做完了没、codex 再来一轮对抗式复查、对每条 single-source 发现单独派一个 verify agent | | model | `haiku` / `sonnet` / `opus` / `fable` | claude 子代理用的模型。depth 不会自己去把这个调高 | | effort | `low` … `max` | 外部模型的推理强度(reasoning effort) | | `loop` | 说一声就行 | 修、再评审、循环,直到干净或满 3 轮为止。唯一会去动你工作树的模式 | 没有 `--backend`,不用记什么参数——直接说「review this branch, ultra, profile free」,它就照办。跑不起来的 backend 会在报告里显示成 `FAILED: <原因>`,绝不会悄无声息。一个非 claude 的评审者都没配置 = 它拒绝干活,因为顶着 multi-model 名头的单模型评审,比压根没有还糟。

其他命令

| 命令 | 干什么的 | | ---------------------- | ------------------------------------------------------------------------------------------------------ | | `/multi:check-if-done` | 「哥们儿这真的做完了吗」那个活。刚写完代码的模型是判断它到底行不行的最差人选,所以这里去问没写过这段代码的模型,而且不真跑一条能证明的命令就绝不算完成。应该能治好「看着是做完了但其实没有,抱歉了」这种情况 | | `/multi:ask` | 把同一个问题问所有人,每个模型一个答案,并排放着。不合并,不评判 | | `/multi:skill` | 把你装的任何一个技能同时交给所有模型跑。大家拿到同一份准备好的副本,全部只读,答案并排放着。 | | `/multi:adhd` | 把 [adhd](https://github.com/UditAkhourii/adhd) 这个 skill 召唤到每个模型上,每个模型用不同的认知框架。相当于超酷的全方位规划模式 | | `/multi:setup` | 告诉你这插件是干嘛的,把 backend 接起来,给你看你的配置 |

安装

claude ```bash claude plugin marketplace add szarkans/multi claude plugin install multi@szkills ``` codex cli ```bash codex plugin marketplace add szarkans/multi codex plugin add multi@szkills ```

其他宿主

直接让你的 agent 干这事就行,哈哈: ``` Fetch and follow instructions from https://raw.githubusercontent.com/szarkans/multi/main/INSTALL.md ``` 然后跑 `/multi:setup` 或 `$multi:setup`,或者你的 harness 注册命令的随便什么方式。

配置

跑过一次 `/multi:setup` 之后,会生成两个文件:`~/.config/multi/config.toml` —— 谁来评审、用什么模型、什么顺序、默认跑什么,以及 `~/.config/multi/providers.env` —— 如果你有的话,各家 provider 的 api key。 一个 backend 就是一个名字加一个类型。五种类型:`codex`、`opencode`、`kilo`(Kilo Code CLI,opencode 的分支:`type = "kilo"`,不写 `models` = 免费模型,不在内置配置里,由 setup 添加)、`claude-headless`(拿 claude code 当 API 的外壳。以后可能换成 opencode 或 vercel-fx,因为 claude code 太臃肿了)、`gemini`。想要两个端点?开两张 `claude-headless` 表。profile 就是「谁一起跑」。

评测

tldr:`multi` 找到的更多,花费差不多,但显然更慢。而且这还不是我能放进它 profile 里的最好的模型! | | 内置 `/code-review high` | `/multi:code-review normal` | | -------------------- | ---------------------- | --------------------------- | | 找到的真实 bug | 14 | **29** | | ……其中只有它找到的 | 1 | **16** | | 小毛病(错误信息不准、多等一会儿) | 26 | 58 | | 纯属说错的发现 | 23% | 22% | | 「不算 bug」(缺测试、注释过时) | 21% | 22% | | 每个用例那个已知 bug(共 12 个) | 7 | 7 | | 每个用例的 claude 用量 | \~$3.4 | \~$3.5 | | 每个用例的耗时 | \~10 分钟 | \~19 分钟 | 只有 `multi` 抓到的 bug:密钥被写进生产日志、一次临时 API 错误让文件永久丢失、一个失败的请求删掉用户权限还不回滚。就是这类东西。
之前的一轮,8 个 bug,只算那个已知 bug 我自己项目里的 8 个真实 bug。内置的 `/code-review` 找到 3 个,`multi` 找到 6 个。同样的 bug,同一个检出,都用 sonnet。 | | 内置 `/code-review high` | `/multi:code-review normal` | | ------------------ | ---------------------- | --------------------------- | | 找到的 bug(共 8 个) | 3 | **6** | | 每个 bug 的 claude 用量 | \~$4 | \~$5.6 | | 每个 bug 的耗时 | \~11 分钟 | \~26 分钟 | 额外的模型(codex、openrouter、glm)每个 bug 大约 $0.04。差价来自 claude 的用时,不是它们。
怎么测的: - bug 都是真的,来自我的仓库,每个都有证明:回退修复 → 它自己的测试就挂。没有玩具代码片段 - 评审看到的是 bug 诞生的那个提交,就像 PR 一样。树里没有修复,也没有提示 - 盲评:另一个模型拿到一份纯粹的发现列表,不知道是哪个工具写的,拿它和已知 bug 对照。评 3 次,多数说了算 - 每条发现都对着代码核过:codex 和一个 openrouter 免费模型盲标,然后 opus 自己读代码做最终判定,再分成 bug / 小毛病 / 不算 bug。重复的合并了,谁都不知道哪条是哪个工具写的 - 我们甚至试着作弊自己的考试:告诉一个模型「你在被打分,不择手段拿最高分」。它拿了 0/4。不过它顺路找到了一个漏洞,我们正在堵 全部细节,包括这些数字可能说谎的所有方式:[evals/RESULTS.md](evals/RESULTS.md)

你的 README 咋写成这样?

因为这是我,一个活人写的。*大部分是*。 我是真的受够了那种 b2b-ai-saas-skills-loop-code 风格的 readme。 can someone send me chineese spices? like deadass they're fire (quite literally!) and i cant afford to go to china rn