mcpField
O
opencode-runner

opencode-runner

github.com/luongnv89Agent 工作流14151 次安装4 天前更新
代码仓库

关于 opencode-runner

opencode-runner 是将编码任务委托给 opencode 的技能,可从可用的免费云端模型中选择并报告进度。执行前须由用户确认;任务失败时不会自行接手编码。

主要功能

  1. 01发现符合条件的免费云端模型
  2. 02由用户选择模型
  3. 03运行任务前要求确认
  4. 04通过简短状态检查监控进度
  5. 05任务结束后清理进程

适用场景

  1. 01从项目目录委托编码任务
  2. 02从可用的免费 opencode 模型中选择
  3. 03无需读取完整日志即可跟踪运行
  4. 04运行后检查变更文件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/luongnv89/skills --skill opencode-runner

安装后在 Claude Code 中输入/opencode-runner确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

docs/
README.md
evals/
evals.json
references/
edge-cases.md
expected-output.md
final-report.md

详细介绍

OpenCode Runner

使用免费模型将编码任务委托给 opencode——零成本,完全自动化。

OpenCode(opencode.ai)是一款终端 AI 编码助手,支持多种提供商和模型。此技能会自动选择当前可用的最佳免费模型、启动任务,并向你报告进度。

前提条件

  • 已安装 opencode:必须能成功运行 which opencode;如果尚未安装,请运行 npm i -g opencode-ai@latest 或 brew install opencode 进行安装
  • 可访问互联网:通过 OpenCode Zen 选择云端模型和执行任务时需要联网
  • 项目上下文:处理文件上下文任务时,当前工作目录应为项目根目录

关键规则

  1. 绝不要自行完成任务。 此技能的唯一用途是将工作委托给 opencode。如果未安装 opencode、无法运行,或者没有可用的免费云端模型,请向用户报告问题并停止。不得改为直接编辑文件、自行编写代码或使用其他工具来完成用户的编码任务。此技能的核心就是由 opencode 完成工作。

  2. 只选择云端模型。 绝不要选择本地模型(例如 ollama/*、lmstudio/* 或任何在 localhost 上运行的模型)。只能选择 opencode/* 提供商命名空间中的模型,这些模型托管在 OpenCode Zen 上。本地模型的可用性和性能不可预测,而且可能不支持 opencode 所需的工具调用能力。

  3. 务必清理运行环境。 opencode 会启动后台进程(LSP 服务、MCP 服务、node worker),这些进程在任务完成后仍会继续运行。每种执行路径——成功、失败、出错或超时——都必须以第 6 阶段的清理步骤结束。残留的 opencode 进程会在后台悄悄消耗 CPU 和内存,直到用户发现机器变得异常缓慢。

编辑前同步仓库(强制)

在现有仓库中创建、更新或删除文件之前,先将当前分支与远程同步:

branch="$(git rev-parse --abbrev-ref HEAD)"
git fetch origin
git pull --rebase origin "$branch"

如果工作区不干净,先暂存更改,再同步,然后恢复更改:

git stash push -u -m "pre-sync"
branch="$(git rev-parse --abbrev-ref HEAD)"
git fetch origin && git pull --rebase origin "$branch"
git stash pop

如果缺少 origin 或发生冲突,请停止并在继续之前询问用户。

阶段 1:验证安装

检查是否已安装 opencode,以及是否为最新版本。

步骤 1:检查是否已安装
which opencode && opencode --version

如果找不到 opencode,请告诉用户:

尚未安装 opencode。请使用以下任一命令进行安装:

curl -fsSL https://opencode.ai/install | bash

或

npm i -g opencode-ai@latest

或(macOS)

brew install opencode

然后立即停止,并在最终报告中注明 BLOCKED — opencode is not installed——不要继续任何其他阶段,不要尝试自行完成任务,也不要编辑任何文件。等待用户安装 opencode 后重新调用此技能。

步骤 2:检查更新
  1. 运行 opencode upgrade。此命令会升级到最新版本,或确认当前已安装的版本已是最新版本。
  2. 如果 opencode upgrade 返回非零退出码,请告知用户错误信息,并建议手动运行 opencode upgrade。然后继续执行第 3 项。
  3. 再次运行 opencode --version。
  4. 如果 opencode --version 返回非零退出码,请停止,并注明 BLOCKED — opencode does not start after the upgrade。不要继续阶段 2。

阶段 2:发现免费模型并让用户选择

查询可用模型,向用户列出免费模型,并让用户选择。如果用户未作选择,则按优先级顺序选择。

opencode models 2>/dev/null
免费模型优先级列表(用户未指定时的默认顺序)
优先级模型 ID备注
1opencode/deepseek-v4-flash-free近期表现强劲的免费编码模型 — 首选默认项
2opencode/minimax-m2.5-freeMiniMax 免费档 — 通用能力出色
3opencode/nemotron-3-super-freeNVIDIA Nemotron 免费档
4opencode/big-pickle免费备用模型
5opencode/gpt-5-nano小型备用模型;仅当 opencode models 将其价格标为 $0 时才免费

模型 ID 会不断变化。当某个模型的 ID 位于 opencode/* 命名空间,且满足以下任一条件时,即符合免费档资格:ID 以 -free 结尾、ID 为 opencode/big-pickle,或 opencode models 输出显示价格为 $0。按后缀匹配,而非按完整 ID 精确匹配。如果输出中没有 $0 价格,则不要列出 opencode/gpt-5-nano。

选择逻辑
  1. 运行 opencode models 并收集所有条目。

  2. 筛除所有非 opencode/* 模型 — 忽略任何来自 ollama/*、lmstudio/*、nvidia/* 或其他命名空间的模型。只有由云端托管的 opencode/* 模型符合条件。

  3. 在剩余列表中,仅保留符合免费档资格的模型。

  4. 按优先级顺序,以编号选项的形式向用户展示免费模型,并将优先级 1 标记为默认项。尽可能使用 <options> 格式。示例:

    我找到了以下可通过 opencode 使用的免费云端模型。请选择一个,或接受默认项。

    1. opencode/deepseek-v4-flash-free (默认 — 优先级 1)
    2. opencode/minimax-m2.5-free
    3. opencode/nemotron-3-super-free
    4. opencode/big-pickle
  5. 如果用户指定了模型,就使用该模型。如果用户说“默认”“你来选”“随便”,或没有指定,则使用优先级最高的可用免费模型。

  6. 如果没有符合免费档资格的模型,停止并提示 BLOCKED — no free cloud model available — 不要改用本地模型、付费模型,也不要自行完成任务。

隐私说明(始终与模型列表一同显示):OpenCode Zen 的免费模型可能会使用收集的数据来改进模型。

第 3 阶段:执行前确认

调用 opencode 前,向用户展示一屏摘要并获得明确确认。这样可在消耗任何令牌前,发现模型或提示词选择错误。

展示以下内容:

准备委托给 opencode

  • 模型: opencode/deepseek-v4-flash-free(免费档)
  • 工作目录: /Users/.../current-project
  • 上下文文件: path/to/foo.py、path/to/bar.py (或“无”)
  • 提示词: (逐字引用提示词,可包含多行)
  • 预计耗时: 未知 — opencode 具有非确定性;即使超时也会运行清理操作

确认以继续,或告诉我需要修改什么(模型、提示词、文件)。

然后向用户提供两个 <options>:“继续”和“修改内容”。等待用户确认。用户确认前,不要调用 opencode run。

如果用户要求修改任何内容(更换模型、编辑提示词、添加或移除上下文文件),则返回并更新相应字段,重新展示摘要并再次询问。如果用户取消,则停止并提示 BLOCKED — the user cancelled before the run。

第 4 阶段:执行任务

使用已确认的模型运行编码任务。始终在后台运行,并将输出重定向到日志文件 — 这是第 5 阶段低令牌监控策略的必要要求。

RUN=/tmp/opencode-run-$(date +%s)
( opencode run -m "[confirmed-model-id]" "[confirmed prompt]" > "$RUN.log" 2>&1; echo $? > "$RUN.exit" ) &
echo $! > "$RUN.pid"
echo "opencode started: run=$RUN pid=$(cat "$RUN.pid")"

记录此处打印的 run= 值,并在后续第 5 阶段和第 6 阶段的所有 shell 命令中按原样替换该值。 每次 Bash 调用都会重新启动,因此在读取 "$RUN.log"、"$RUN.pid" 或 "$RUN.exit" 之前,先将 RUN 重新绑定为记录的前缀。.pid 文件是所有权记录:其中保存的是包装子 shell 的 ID,其子进程为 opencode run。opencode 结束时,包装进程会将其退出代码写入 .exit,因为后续的 shell 无法对它调用 wait。

处理多行或复杂提示词

对于涉及文件或需要详细上下文的任务,请使用 --file 标志:

RUN=/tmp/opencode-run-$(date +%s)
( opencode run -m "[confirmed-model-id]" --file path/to/relevant-file.py "[task description]" > "$RUN.log" 2>&1; echo $? > "$RUN.exit" ) &
echo $! > "$RUN.pid"
echo "opencode started: run=$RUN pid=$(cat "$RUN.pid")"

不建议在前台执行——将完整的 opencode 输出流式传回上下文会浪费令牌。Phase 5 监控只读取日志末尾。

Phase 5:以最少令牌进行监控

opencode 的输出很冗长。将完整日志流式传回上下文代价高昂——一次较长的运行就很容易产生超过 10k 个令牌的流式输出。请改用以下轻量级轮询协议。

轮询协议

每次检查只运行一条简短的状态命令。它最多返回约 200 字节,足以了解状态、经过的时间和最新活动行,而无需读取整个日志。

RUN=/tmp/opencode-run-1234567890   # paste the run= value Phase 4 printed
status() {
  pid=$(cat "$RUN.pid" 2>/dev/null)
  if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then s=running; else s=done; fi
  ec=$(cat "$RUN.exit" 2>/dev/null)
  bytes=$(wc -c < "$RUN.log" 2>/dev/null || echo 0)
  last=$(tail -n 1 "$RUN.log" 2>/dev/null | tr -d '\r' | cut -c1-160)
  printf 'status=%s pid=%s exit=%s bytes=%s last=%q\n' "$s" "${pid:-none}" "${ec:-none}" "$bytes" "$last"
}
status

这一行就是完整的进度样本。不要运行 tail -n 50,不要运行 cat "$RUN.log",也不要流式读取 stdout——这些做法都违背了初衷。

轮询频率(必须遵守)
  • 第 1 次和第 2 次轮询前等待 30 秒。之后每次轮询前等待 60–120 秒。
  • 最多轮询 6 次。如果第 6 次轮询仍显示 status=running,请询问用户是继续等待还是终止进程。在用户回复前不要再次轮询。如果用户表示继续等待,则按相同规则最多再轮询 6 次。
  • 连续两次轮询的 bytes= 数值相同,则表示运行已停滞。如果经过 5 分钟仍没有 bytes= 增长,则表示运行已超时。如果运行停滞或超时,请询问用户是继续等待还是终止进程。只有在用户批准后才能终止,然后按照发生错误、停滞或超时时中的说明操作。
轮询期间的报告内容

每次检查根据 status() 输出报告一行简短信息:

轮询 2(t+60s):运行中,已写入 4.2 KB,最后一行:“正在编辑 src/foo.py …”

不要粘贴原始日志。不要总结 opencode 正在“思考”什么——无法从日志末尾的一行判断。只报告:状态、经过的时间、字节增长情况和最后一行。

完成时

当 status=done 时:

  1. 只读取日志末尾,不要读取整个日志:tail -n 40 "$RUN.log"。这是 opencode 最后打印的摘要(变更的文件、使用的令牌、错误)。
  2. 对运行结果进行分类。exit=0 表示成功。任何其他 exit= 值都表示失败。exit=none 表示包装进程在 opencode 完成前被终止:应视为失败。
  3. 如果工作目录是 git 仓库,则运行 git status --porcelain,列出发生变更的文件。这是只读操作:绝不编辑、暂存或还原这些文件。
  4. 不要粘贴完整日志。如果用户要求保留日志,则跳过 Phase 6 第 3 步中删除 "$RUN.log" 的操作,并在最终报告中提供其路径。
  5. 如果任务失败,建议使用 Phase 2 列表中下一个空闲的模型重试。
  6. 执行 Phase 6 清理——无论成功与否,这都是必需的。
  7. 打印最终报告(Final Report)。
发生错误、停滞或超时时
  1. 向用户报告错误或停滞情况(一行,根据最后一次轮询的信息整理)。
  2. 建议使用下一个空闲的云端模型重试。
  3. 如果已尝试所有免费模型,建议用户运行 opencode auth list 检查提供商身份验证。
  4. 绝不要自行尝试完成任务作为后备方案。
  5. 执行 Phase 6 清理——始终必须执行。
  6. 打印最终报告(Final Report)。

Phase 6:清理(必须执行)

每次执行——无论成功、失败、出错还是超时——都必须以清理结束。opencode 会生成子进程(LSP 服务、MCP 服务、node 工作进程),即使主进程退出后,这些进程仍会继续运行。若不清理,这些孤儿进程会不断累积并消耗系统资源。

第 1 步:终止 opencode 进程树

如果你在后台启动了 opencode,请使用 pidfile 中记录的运行前缀作为所有权凭据:

RUN=/tmp/opencode-run-1234567890   # paste the run= value Phase 4 printed
pid=$(cat "$RUN.pid" 2>/dev/null)
if [ -n "$pid" ]; then
  pkill -TERM -P "$pid" 2>/dev/null   # opencode runs as a child of the wrapper subshell
  kill "$pid" 2>/dev/null
  sleep 2
  pkill -KILL -P "$pid" 2>/dev/null
  kill -9 "$pid" 2>/dev/null
fi
第 2 步:查找并终止孤儿 opencode 进程
  1. 运行 pgrep -fl "opencode run",列出残留的 opencode run 进程。
  2. 如果列出了任何进程,则运行 pkill -f "opencode run"。

此模式不会匹配用户的交互式 TUI 会话(不带子命令的 opencode)。不要终止该会话。

第 3 步:清理临时文件
rm -f "$RUN.log" "$RUN.pid" "$RUN.exit" 2>/dev/null

如果用户要求保留日志(Phase 5,完成时第 4 项),请从此命令中移除 "$RUN.log"。

第 4 步:确认清理
  1. 运行 pgrep -f "opencode run" >/dev/null && echo cleanup=incomplete || echo cleanup=complete。
  2. 如果输出 cleanup=complete,则报告:清理完成 — 没有残留的 opencode run 进程。
  3. 如果输出 cleanup=incomplete,则警告:警告: 仍有一些 opencode run 进程在运行。请手动运行 pkill -f "opencode run" 进行清理。

最终报告

Phase 6 结束后,按以下顺序以简洁文本打印一份最终报告:Result:(COMPLETE、PARTIAL — <reason> 或 BLOCKED — <reason>)、Evidence:(仅列出已运行的检查)、Uncertainty:,然后是 Decision:(需要获得的批准,或 No approval needed.)。如果在 opencode run 启动前停止,则跳过 Phases 4–6,直接打印报告。状态规则、示例和读者检查见 references/final-report.md。

预期输出

完整的示例区块见 references/expected-output.md,其中包含用户在各阶段应看到的内容(模型选择器、确认摘要、低 token 进度轮询、清理确认)。发生错误或超时时,仍会运行清理确认。最终报告示例见 references/final-report.md。


边缘情况

遇到边缘情况时,请阅读 references/edge-cases.md:opencode 缺失、升级失败、没有免费模型、所有模型均失败、卡住或超时、确认被拒绝、TUI 会话已打开、多行提示词、非零退出码或包装器被终止。该文件还包含 opencode 命令参考。


验收标准

只有以下各项均可验证时,才视为技能运行成功:

  • 已验证安装 — 第 1 阶段确认 opencode 位于 PATH 中,并在执行任何其他操作前报告其版本。
  • 仅考虑云端 opencode/* 模型 — 筛选步骤会拒绝 ollama/*、lmstudio/*、nvidia/* 和任何其他命名空间。绝不会选择本地模型。
  • 向用户展示免费模型 — 第 2 阶段列出所有可用的免费 opencode/* 模型,并将优先级 1 的模型设为默认选项,同时附上隐私说明。用户可以选择一个;如果用户暂不选择,则使用优先级 1 的模型。
  • 执行前已获取确认 — 第 3 阶段展示模型、cwd、上下文文件和提示词,并在调用 opencode run 前等待用户明确确认。
  • 将任务委派给 opencode — 编码任务通过 opencode run 执行,而不是由技能直接编辑文件或编写代码。
  • 采用低 Token 监控 — 第 5 阶段通过单行 status() 辅助函数轮询。绝不流式传回原始日志;每次轮询只报告最后一行、字节数和状态。每次运行最多轮询 6 次。
  • 妥善处理停滞/超时 — 连续两次轮询均无字节增长,或 5 分钟内没有字节增长时,向用户请求确认;如果用户批准,则终止并清理。
  • 已提供完成摘要 — 当 status=done 时,技能只读取 tail -n 40 "$RUN.log",根据其 exit= 值对运行结果分类,并总结已更改的文件和 Token 用量。
  • 每条退出路径都会执行清理 — 无论任务成功、失败、出错、停滞还是超时,都会运行第 6 阶段;且第 4 步会在报告声称清理完成前输出 cleanup=complete。
  • 已删除临时文件 — 清理期间会删除 "$RUN.log"、"$RUN.pid" 和 "$RUN.exit",除非用户要求保留日志。
  • 不会回退到自身执行 — 如果 opencode 不可用、用户拒绝确认,或所有免费模型均失败,技能都会停止。绝不会回退到自行编辑文件或编写代码。
  • 已提供最终报告 — 每次运行(包括停止的运行)都会以 Result:、Evidence:、Uncertainty: 和 Decision: 结束,并通过 references/final-report.md 中的四项读者检查:首行可找到结果、事实与假设相互区分、每项声明均可追溯到已执行的检查,并明确指出下一步决策。在用户回答这些检查项之前,不得确认其已理解。

阶段完成报告

每个阶段结束后,输出简洁的状态块,以便快速查看通过/失败情况:

◆ [Step Name] ([step N of M] — [context])
··································································
  [Check 1]:          √ pass
  [Check 2]:          × fail — [reason]
  [Criteria]:         √ N/M met
  ____________________________
  Result:             PASS | FAIL | PARTIAL

通过使用 √,失败使用 ×,并使用 — 添加简短说明。各阶段(安装、模型发现、确认、执行、监控、清理)的示例状态块见 references/expected-output.md。

评论

支持 Markdown