spotworkers0.3.0
Outsource bounded coding tasks to cheap agent workers. Your main agent keeps architecture, verification and commit rights — and you stop burning your quota.
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
spotworkers
不再把 Claude Code / Codex 的额度,消耗在便宜模型也能完成的工作上。
spot把有边界的实现任务派给便宜的 Agent Worker(Pi / Qwen / DeepSeek / Kimi / Qoder / CodeBuddy),随后自行重跑你的测试、校验 diff 哈希,所有闸门通过才合并。架构、审查与提交权始终留在主控端 Agent 手里。
主控端不必让用户去为不是自己写的代码背书。把 Worker 视为不可信方:它拿不到 Bash、extensions、Skills 与项目信任,也无法对测试结果撒谎 —— verification.json 由 wrapper 生成,而非 Worker 自身。
原项目名
pi-delegate,现已更名。pi-worker命令仍可作为spot的别名使用。
特性
闭环委托 + 独立验证
doctor → prepare → run → verify → self-review → approve → integrate → report → cleanup。wrapper 会自己重跑你的验证命令(不依赖 Pi 的自述),并且每个闸门都校验 diff 哈希 —— 哈希一变就阻断审批。
防作弊 self-review(主控端 token 省钱)
主控端读完整 diff 之前,可选的第二个 worker 回合会重读自己的产出,吐出紧凑的 self-review.json(约 50 行 vs 数千行)。防作弊机制:
verification.json由 wrapper 生成,不是 worker —— 它无法对测试结果撒谎。diffSha256Mismatch=true(回错哈希)→ 主控端升级为全量审查。fallbackRecommended=true(自报unmet/uncertain或任意 P0–P2)→ 主控端升级。approve会再扫一次 diff,哈希变了就拒。- 高危任务永远到不了 self-review(
HIGH_RISK_BLOCKED)。
self-review 永远不会卡住闭环 —— worker 失败、JSON 解析失败、diff 小于 minDiffBytes、或审查面(diff + 改动文件体积)小于 minSurfaceBytes 时,它会自动降级到 reviewing 并标 skipped:true。minSurfaceBytes(默认 4000)的理由是:报告约每条约 700 字节,而小 diff 直接读更便宜。用 selfReview.enabled=false 完全关闭;selfReview.spotCheckRatio(默认 0.34)调整按比例的抽查量。
硬性闸门与安全
- 审批前必须:wrapper 验证通过、diff 哈希不变、安全扫描通过、有验收证据、零未解决 P0–P2 问题。
- worker 不能改给它打分的装置:契约
lockedPaths、配置alwaysLockedPaths(CI 与测试运行器配置)、以及package.json里决定执行方式的键(scripts、jest、vitest、mocha、ava、nyc、c8、workspaces、packageManager)全部冻结;依赖仍可改。违反即LOCKED_PATH_CHANGED/VERIFICATION_SCRIPT_CHANGED阻断。 - worker 被当作不可信:永不开 Bash、extensions、Skills、prompt templates、context files、项目 auto-trust。
- 永不 push、建 PR、改 remote,也不会把 worktree 隔离说成 OS 沙箱。
- 永不绕过鉴权错误或能力不匹配 —— setup/凭证失败就是真 blocker。
崩溃安全恢复
进程组超时、SIGINT/SIGTERM 清理、过期锁回收。中断后 spot recover --id <run-id> 原地重开 run:有部分 diff 送 verify,没 diff 送回 run。活动锁永远不会被抢 —— 只有 owner 进程已不在的锁才会被回收。
多主控端调度
通过 PARENT_AGENT / PI_WORKER_CALLER 环境变量追踪调用方(trae、codex、claude-code、cursor、pi-recursive、cli),面板可归因、list --caller <name> 可过滤。
并行执行
多个主控端会话可并发 —— 每个 run 有独立的 Git worktree、state 目录、per-run 文件锁,不同 run 互不碰撞,同一 run 不会被两个进程同时推进。maxConcurrentRuns(默认 4,范围 1–16)限制活动 run 数;超限 prepare 返回 CONCURRENCY_LIMIT。面板读 state.json 时容忍 JSON 解析失败,并发写入时快照不会崩。
按难度自动选模型
在契约里直接声明 difficulty(low/medium/high)即按声明路由。不声明时由 risk 与 domain 主导(medium 风险 + backend/systems/algorithm 领域即判 medium),而验收条数、验证数、约束数、tool-use 这类规模信号最多贡献 +2。难度再选 cheap/standard/premium profile;同档内 task.domain 软匹配 profile.strengths。用 --profile <name> 强制;不写 costTier 即关闭自动选择。
多 CLI 后端
除默认 Pi 后端外,profile 可设 adapter: kimi | trae | qoder | opencode | codebuddy | zcode 驱动其他编码 CLI(Kimi Code CLI、Trae CLI、Qoder CLI、OpenCode、CodeBuddy Code CLI、ZCode CLI)。跨 adapter fallback 无缝工作。详见 references/provider-configuration.md。
成本与节省指标
头号指标是主模型少花的 token:worker 侧要么免费、要么有折扣、要么单价低一个数量级,所以判断值不值得委派,看的是主模型那一边。每次 run 都会记录两件事——委派模式下父级实际读的内容(self-review 报告,或完整审查面),以及反事实:自己动手要读 diff + 改动文件(按 1.5 轮算)并写出新增的那些行。两个口径都报:纯 token 比例,和按价格加权的比例(输出 token 约为输入的 4 倍)。计算依据与被排除项都写进 metrics.json,数字可复核而不是凭信。
单次明细还记录 token 用量(输入/输出/缓存)、worker 侧 provider 上报的用量,以及——仅当父级 backend 配了费率卡时——折算 credits 与订阅额度占比。按 credits 计费的后端(Qoder CN 只报 total_credits,不报 token 数)会把这个值单独暴露,credit 口径的节省率降级为 null,绝不编造。
实时监控面板
HTTP 服务,带刷新按钮、汇总卡片、可过滤 run 表(按 caller、状态、自由文本)、可展开详情行、亮/暗主题,以及 "Connection status" tab 展示 CLI adapter 与 profile 凭证健康度。
最近更新
v0.1.0 发布的是闭环主干。此后(未发布,位于 main):
- 免费档位路由。
model: "free"(别名qoder-free、cheapest)在派发时解析为账户可达的最低price_factor模型,profile 无需硬编码模型名,避免模型下架后失效。Qoder 当前有两个0x档位:DeepSeek-Flash与Qwen3.8-Flash。 - 带定价的模型目录。
spot detect逐行输出倍率、上下文档位与合法 effort 档位 ——12 model(s) (2 free),其后每个模型标注[free]/[0.1x]/[1.4x]。目录缓存 30 分钟;离线时降级为「无目录」而非中断 run。 - 按模型校验能力参数。 不支持的
reasoningEffort或maxContextSize会吸附到该模型最近的合法档位,并记为worker_warning事件与worker.log的[warn]行。调整可见,不会静默改写。 - CodeBuddy CLI adapter。 第六个后端,与 Pi、Kimi、Trae、Qoder、OpenCode 并列(
adapter: codebuddy)。 - 所有 adapter 统一计量。 非流式后端回显
message_end用量事件,readPiUsage统一聚合 token 与时长;面板标签不再绑定 Pi("Token"、"duration"、"call count")。 - 修复:
EXCESSIVE_DELETION会拦截所有纯修改。 原守卫按删除行 / (新增 + 删除)计算,单行修改恒为0.5,必被拦下 —— 而这恰是最常见的委托形态。现改为对照原文件行数,并以limits.maxDeletedLines(默认300)作为绝对上限兜底。 - 修复:Qoder 以交互模式启动并挂起。 CN 版本现显式传入
-p/--print;缺此参数时 worker 会打开 TUI 并卡到超时。鉴权失败也归类为auth而非permanent,凭证问题不再被误报为代码问题。 - 面板。 60 秒自动刷新(存于 localStorage,标签页获得焦点时刷新);
workbuddy作为来源被识别;新增worker.log与scripts/pi-tmux-monitor,可并发监视多个 run。
前置条件
- Node.js
>=22.19.0 - 至少一个 Worker CLI 在
PATH中 —— Pi(默认),或 Kimi / Trae / Qoder / OpenCode / CodeBuddy,并在 profile 中配置对应的adapter。PI_WORKER_PI_BIN仅对 Pi adapter 生效,其余后端不会调用pi。 - Git(worker 需要 Git 仓库)
- 环境变量中的 provider 凭证(如
VOLCENGINE_API_KEY)
运行 spot detect 可查看本机已安装哪些 Worker CLI。
安装 Worker CLI
默认后端为 Pi CLI(项目主页:https://pi.dev/)。Pi 是一个独立的开源项目,需单独安装。若你打算使用其他后端,可直接跳到 adapter 并安装对应 CLI —— 只需确保你所选的 adapter 在 PATH 上。
方式 A — npm 全局安装(跨平台)
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
pi --version # 验证;spotworkers 要求 >= 0.80.10
方式 B — 一行安装脚本(macOS / Linux)
curl -fsSL https://pi.dev/install.sh | sh
pi --version
首次配置 Pi:在任意目录启动 pi,然后在 Pi 内执行 /login 配置模型 provider(API key 或订阅登录)。完整 provider 列表(Anthropic、OpenAI、Google、Volcengine、DeepSeek、Kimi、MiniMax、GLM、Qwen、OpenRouter、Ollama 等)见 Pi 官方文档。
spotworkers 只会非交互式地调用 Pi(
pi -p),所以交互式 TUI 仅用于首次/login和模型配置。委托任务你永远不需要手动驱动 Pi。
安装
方式 1 — npm 全局安装(推荐)
npm install -g spotworkers
spot --help
方式 2 — npx(免安装)
npx -p spotworkers spot serve
包内提供两个可执行入口(spot 与 pi-worker 别名),npx 无法自行判断该执行哪一个,需显式指定。
方式 3 — 作为 Pi package 安装
pi install npm:spotworkers
该方式会把包内的 SKILL.md 注册到 Pi,使 /skill:spotworkers 在 Pi 会话中可用。它不会把 spot 放进 PATH;若两者都要,请用方式 1。
方式 4 — 本地 link(开发 / 发布前验证用)
git clone https://github.com/hLxiao9/spotworkers.git
cd spotworkers
npm install # 仅在后续添加依赖时需要;当前零运行时依赖
npm link # 把 `spot` 暴露到 PATH
spot --help
路线图:首个 npm 版本发布后,会增加 Homebrew tap(
brew tap hLxiao9/spotworkers && brew install spotworkers)与curl | sh一行安装脚本。
首次配置
npm install -g spotworkers 会通过 postinstall 钩子自动运行 node scripts/install-config.mjs,把默认配置合并进 ~/.config/pi-worker/config.json,并把 Volcengine provider 合并进 ~/.pi/agent/models.json。合并是幂等的 —— 你已有的 profile、rate card、subscription 都会保留。
如果自动配置没有跑(比如 npm install --ignore-scripts、沙箱包管理器或 tarball 安装),手动执行:
node scripts/install-config.mjs # 合并默认配置;绝不覆盖用户已有改动
spot init # 交互式选择 provider + 凭证状态报告
apiKeyEnv契约警告:~/.config/pi-worker/config.json里的apiKeyEnv字段与~/.pi/agent/models.json里的$VAR引用必须指向同一个环境变量名。名字不一致(例如 config 里写apiKeyEnv: VOLCENGINE_API_KEY,但 models.json 里写$API_KEY)会在运行时静默 401。spot doctor会检测这种情况并给出正确名字的建议。
快速开始
# 1. 预检(校验 Pi、模型、凭证、配置 —— 不会创建 run)
spot doctor --task ./task.json
# 2. 准备隔离的 worker 分支 + worktree
spot prepare --task ./task.json --usage-start ./usage-start.json
# 3. 在隔离 worktree 上运行 Pi
spot run --id <run-id>
# 4. 验证真实 diff(不依赖 Pi 的自述)
spot verify --id <run-id>
# 5. 审批 + 集成回源分支
spot approve --id <run-id> --review ./review.json --message "feat: ..."
spot integrate --id <run-id>
# 6. 持久化 metrics + 清理
spot report --id <run-id>
spot cleanup --id <run-id>
如果终端或主控进程被中断,检查已持久化的 run,重新进入同一闭环,而不是创建新 run:
spot inspect --id <run-id>
spot recover --id <run-id>
recover 只重开被中断或超时的 run。如果 worker 留下了部分 diff,它会送到 verify;如果没有 diff,会送回 run。活动锁永远不会被抢占;只有锁的 owner 进程已不在时才会被回收。
完整的主控端工作流、硬性闸门与路由规则见 SKILL.md。
与主控端 Agent 集成
spotworkers 是一个 skill:由你的主控端 Agent(Codex / Claude Code / Trae / Cursor / 另一个 Pi)读取 SKILL.md,然后调用 spot CLI 来驱动。主控端保留架构、审查、提交权限;Pi 只实现被分配的有边界任务。
第 1 步 —— 把 skill 装载给主控端
用主控端支持的方式把 SKILL.md 加载进它的上下文:
| 主控端 | 加载 SKILL.md 的方式 |
|---|---|
| Pi | pi install path/to/spotworkers(作为本地 Pi skill 包加载) |
| Codex (OpenAI) | 把 SKILL.md(或软链接)放到 ~/.codex/skills/ 后重启 Codex,或把内容粘进项目的 AGENTS.md |
| Claude Code | 加到 ~/.claude/skills/,或把内容写进 .claude/CLAUDE.md |
| Trae | 把 SKILL.md 内容加到 Trae 项目规则 / 指令中 |
| Cursor | 把 SKILL.md 内容加到 .cursor/rules/(项目规则) |
| 临时 shell | 直接 node scripts/spot.mjs <命令> ... —— 不需要加载 skill |
SKILL.md 是自包含的:它告诉主控端完整闭环流程(doctor → prepare → run → verify → self-review → approve → integrate → report → cleanup)、硬性闸门、路由规则,以及精确的 spot 命令。主控端之后通过它正常的 shell/bash 工具调用 spot。
第 2 步 —— 标识调用方
在调用 spot prepare 的环境里设置 PARENT_AGENT(或 PI_WORKER_CALLER),这样用量追踪和面板才能正确归因:
export PARENT_AGENT=codex # 可选值: codex | claude-code | trae | cursor | pi-recursive | cli
第 3 步 —— 跑一个委托任务
skill 装载好后,用自然语言告诉主控端,比如:
"委托给 Pi:给
utils.js加一个slugify函数,要小写、trim、把空白折叠成连字符、剔除非字母数字。test.js里的测试必须通过。"
主控端会自己构造符合 schemas/task-contract.schema.json 的 task.json,然后自己驱动整个闭环。你不需要手动调用 spot。
第 4 步 —— 看面板
主控端干活时,另开一个终端:
spot serve # http://localhost:7317/
面板按 caller 分组显示 runs,所以你能实时看到哪个 agent 在委托什么。
关于
trae和cursor调用方:这两个的用量计量尚未实现 —— 面板对它们的用量数字会报available: false。如果你需要用量统计,请改用PARENT_AGENT=codex或claude-code。
监控
每个 run 都持久化在 ~/.local/state/pi-worker/runs/<run-id>/(state.json、pi-events.jsonl、metrics.json、report.md)。无需触碰 worker 即可查询:
| 命令 | 用途 |
|---|---|
spot list [--status <s>] [--caller <c>] |
runs 的 JSON 数组 |
spot inspect --id <run-id> |
完整 state + metrics + 验证 + 审查 + Pi 用量 |
spot recover --id <run-id> |
安全重开被中断/超时的 run |
spot dashboard [--output <file>] |
静态单页 HTML 快照 |
spot serve [--port <port>] [--no-open] |
实时 HTTP 面板,带刷新按钮 |
实时面板
最快方式:双击启动
仓库根目录的 start-dashboard.command 是一个一键启动器(macOS 双击即可):
- 自动检测
spot命令;未安装时给出npm install -g spotworkers或npm link提示 - 启动本地 HTTP 服务并自动打开浏览器
- 浏览器里的"刷新"按钮实时拉取最新用量,或直接 F5
Ctrl+C停止服务- 端口可用
PI_WORKER_PORT环境变量覆盖(默认 7317)
Linux / 通用环境:
bash start-dashboard.command
# 或直接
spot serve
命令行直接调用:
spot serve # http://localhost:7317/
spot serve --port 8080 # 自定义端口
spot serve --no-open # 不自动打开浏览器
GET /— HTML 面板GET /api/fragment— 渲染后的 HTML 片段("刷新"按钮使用)GET /api/runs— state + metrics 的原始 JSONGET /health— 健康检查
"刷新"按钮(以及普通的 F5)会重新读取 ~/.local/state/pi-worker/runs/,所以你看到的永远是最新的 runs。静态打开的 dashboard.html(file://)只是快照 —— 实时监控请用 serve。
调用方识别
在调用 spot prepare 的环境里设置 PARENT_AGENT(或 PI_WORKER_CALLER):
PARENT_AGENT=codex spot prepare --task ./task.json # → caller: codex
PARENT_AGENT=trae spot prepare --task ./task.json # → caller: trae
PARENT_AGENT=cli spot prepare --task ./task.json # → caller: cli
面板按 caller 分组显示 runs;list --caller <name> 可按调用方过滤。
配置
文件位置
- 默认配置:
fixtures/default-config.json - 用户配置:
~/.config/pi-worker/config.json - 模型注册表:
~/.config/pi-worker/models.json - 通过环境变量覆盖路径:
PI_WORKER_CONFIG、PI_WORKER_MODELS_FILE、PI_WORKER_STATE_DIR、PI_WORKER_CACHE_DIR、PI_WORKER_PI_BIN
配置模型
spotworkers 不自己管理模型凭证 —— 那是 Pi 的职责。流程是:
先在 Pi 里配置 provider。 启动
pi,运行/login,添加你的 API key / 订阅。Pi 会把它们存到~/.pi/agent/models.json。完整 provider 列表和配置步骤见 Pi 官方文档。列出 Pi 能看到的模型,确认你在 spotworkers profile 里能引用哪些:
pi --no-extensions --no-skills --no-prompt-templates --no-themes --no-context-files --no-approve --list-models把这些模型映射成 spotworkers profile,写到
~/.config/pi-worker/config.json。每个 profile 从 Pi 的注册表里挑一个provider+model,并打上costTier(cheap/standard/premium)、strengths(领域)、modalities标签。默认带 9 个 profile(volcengine、deepseek、kimi、minimax-m3、gemini-vision、gpt-image、kimi-cli、trae-cli、qoder-cli)—— 完整表格和添加自定义 profile 的可复制 JSON 片段见references/provider-configuration.md。用
spot doctor校验 —— 它一次过检查 Node、Git、Pi、凭证、模型可用性、task schema。
提示:spotworkers 会按任务难度自动选 profile(
low → cheap、medium → standard、high → premium)。如果想强制用某个 profile(比如你只有 MiniMax 凭证),给doctor/prepare传--profile minimax-m3。
个人路由偏好(callerProfiles)
「从哪个模型起跳」是个人喜好,不该写死在共享仓库的 Agent 规则里。把它写在你自己的 ~/.config/pi-worker/config.json,按调用方区分:
{
"callerProfiles": {
"claude-code": "qoder-qwen-flash",
"codex": "minimax-m3"
}
}
不传 --profile 时的选择顺序:--profile → callerProfiles[<调用方>] → 按难度自动路由 → defaultProfile。调用方取自 PARENT_AGENT(见调用方识别);键必须是已知调用方、值必须是已有 profile,否则配置校验失败。首选 profile 沿用它自己的 fallbackProfiles,所以免费模型接力链(如 Qoder 免费 → CodeBuddy flash)每台机器配一次即可。首选 profile 缺任务所需能力/模态时自动跳过,且永远不会放行 risk: high 任务。不带 --profile 运行 spot doctor 会显示 profileSource: caller-preference 和将要使用的接力链。包自带的默认配置不设任何偏好。
多 CLI 后端(Pi / Kimi / Trae / Qoder)
除了默认的 Pi 后端,profile 还可以设置 adapter: kimi | trae | qoder 来驱动其他编码 CLI。详见 references/provider-configuration.md 中的 "Multi-CLI Adapter Support" 段落。
开发
npm test # node:test 测试套件
npm run check:syntax # 对所有入口执行 node --check
npm run check # 语法 + 测试
测试位于 tests/*.test.mjs,用 node --test --test-concurrency=1 运行。
项目结构
spotworkers/
├── scripts/
│ ├── spot.mjs # CLI 入口(bin)
│ ├── install-config.mjs # 一次性配置引导
│ └── parent-meter.mjs # 主控端用量快照
├── lib/
│ ├── cli.mjs # 参数解析 + 分发
│ ├── dashboard.mjs # HTML 渲染 + 汇总逻辑
│ ├── server.mjs # `serve` HTTP 服务
│ ├── state.mjs # run 状态机 + 持久化
│ ├── pi-runner.mjs # Pi 调用
│ ├── verification.mjs # 独立验证闸门
│ ├── review.mjs # 主控端审查 / 审批
│ ├── integration.mjs # 分支集成 + 清理
│ ├── report.mjs # metrics + report.md
│ └── ...
├── schemas/ # JSON schema(task、review)
├── fixtures/ # 默认配置 + provider 模板
├── references/ # provider-configuration.md、review-policy.md
├── agents/ # 主控端 adapter
└── tests/ # node:test 测试套件
协议
本项目基于 GNU Affero General Public License v3.0 or later(AGPL-3.0-or-later)授权。
如需闭源商业使用,需另行购买商业授权 —— 请提 issue 联系。