在 opencode 中使用 opencode-plugin-loop 插件完全指南

让 AI 编码代理像 Claude Code 一样定时重复执行任务 ------ /loop 命令的中文实战手册


一、插件简介

opencode-plugin-loop 是为 opencode 量身打造的 /loop 调度插件,灵感来源于 Claude Code 的同名命令。它能让 opencode 按照固定间隔、自适应间隔,或按 .opencode/loop.md 中的维护脚本,周期性地重新发起同一个 prompt

核心特性一览:

  • /loop 5m <prompt> ------ 固定间隔(支持 s/m/h/d
  • /loop <prompt> ------ 自适应间隔(1 分钟~1 小时,由 LLM 自行决定下一次触发时间)
  • /loop ------ 不带参数:读取 .opencode/loop.md 或执行内置维护流程
  • 会话级隔离 :每个任务绑定创建它的 sessionID,不会跨 session 串扰
  • 子命令list | status | cancel | pause | resume | stop-all(默认仅作用于当前 session,加 --all 可跨 session)
  • 15 秒内部 ticker 驱动调度,不再依赖 session.idle 事件
  • 双层防重入 :ticker 与 fireTask 双重 guard,即使插件热重载也不会重复触发
  • 持久化 :任务可跨 session 重启存活,自动迁移(无 sessionID 的旧任务加载时丢弃)
  • session.deleted 自动清理 :会话被删除时,其所有 /loop 任务自动取消
  • 抖动(Jitter):基于 taskId 的确定性偏移,与 Claude Code 算法一致
  • 自动过期:超过 7 天的任务在加载时被清理
  • 最多 50 个并发任务
  • LLM 可调用的工具loop_scheduleloop_status(默认会话绑定)
  • 交互式 Loop 结果对话框:结果展示在原生对话框中,不再覆盖 prompt 输入区
  • 剪贴板操作:一键复制任务 ID 或完整结果
  • 响应式布局:在窄终端下对话框自适应缩放,结果区与操作区独立滚动
  • 简单关闭 :点 Close 、按 q 或原生对话框的 Esc 即可退出

二、环境要求

组件 版本要求
OpenCode >= 1.17.18(用于交互式 TUI 伴侣)
Node.js >= 18

调度服务端插件仍有原生 toast 兜底,而支持的 OpenCode 版本会自动安装 package 的两个入口点。


三、安装方法

方式 1:通过 OpenCode 插件安装器安装(推荐)

bash 复制代码
opencode plugin opencode-plugin-loop --global --force

该命令会同时识别 npm 包中的 server 与 TUI 入口点,并把无版本号的包名写入全局 opencode.jsontui.json,后续升级无需手动修改版本号。

如果 /loop 还没有在你的 OpenCode 配置中定义,请把下面「手动配置」一节中的 command.loop 段手动添加到 opencode.json 中。OpenCode 会自动发现 npm 包的两个插件入口点,但目前并不会把包内的 commands/loop.md 拷贝到你的配置目录。

升级到最新版本

bash 复制代码
opencode plugin opencode-plugin-loop --global --force

--force 会替换已安装的插件版本,并刷新全局配置中的两项。命令执行完后 重启 OpenCode

方式 2:手动配置

把包名分别加入两个配置文件的 plugin 数组即可。

服务端配置 ~/.config/opencode/opencode.json

json 复制代码
{
  "plugin": ["opencode-plugin-loop"],
  "command": {
    "loop": {
      "description": "定时重复执行 prompt。可选间隔: s/m/h/d。子命令: list | status | cancel <id> | pause <id> | resume <id> | stop-all(加 --all 跨 session)",
      "template": "$ARGUMENTS",
      "agent": "build"
    }
  }
}

TUI 配置 ~/.config/opencode/tui.json

json 复制代码
{
  "$schema": "https://opencode.ai/tui.json",
  "plugin": ["opencode-plugin-loop"]
}

方式 3:从源码安装(开发者)

bash 复制代码
git clone https://github.com/jkrandom-sudo/opencode-plugin-loop.git
cd opencode-plugin-loop
npm install
npm run build
opencode plugin "file:///absolute/path/to/opencode-plugin-loop" --global --force

修改 src/ 后重新执行 npm run build,然后重启 OpenCode 即可加载新版本。


四、命令使用方法

4.1 固定间隔模式

rust 复制代码
/loop 5m check if the deploy finished
/loop 30s ping the health endpoint
/loop 2h look for failing CI runs

支持 s(秒)、m(分钟)、h(小时)、d(天) 四种单位。

4.2 自适应间隔模式(LLM 决定下一次触发时间)

arduino 复制代码
/loop check whether CI passed and address any review comments

LLM 每次执行都会收到 prompt,并通过 loop_schedule 工具自主选择下一次间隔(1~60 分钟)。

4.3 裸 /loop ------ 自定义默认维护任务

在项目根目录新建 .opencode/loop.md(项目级)或 <user>/.opencode/loop.md(用户级):

markdown 复制代码
Check the release branch PR. If CI is red, pull the failing log,
diagnose, and push a minimal fix. If new review comments have arrived,
address each one. If everything is green, say so in one line.

下次直接输入 /loop 即可按该脚本执行维护任务。

4.4 子命令

所有子命令默认仅作用于当前会话,加上 --all 可跨会话操作。

bash 复制代码
/loop list                              # 显示当前会话的任务
/loop list --all                        # 显示所有会话的任务(带 [s:xxxx] 标签)
/loop status                            # list 的别名
/loop cancel <taskId>                   # 取消当前会话中的指定任务
/loop cancel <taskId> --all             # 强制跨会话取消
/loop pause <taskId>                    # 暂停任务
/loop resume <taskId>                   # 恢复任务(重新启用固定间隔)
/loop stop-all                          # 取消当前会话所有任务
/loop stop-all --all                    # 取消所有会话的全部任务

如果尝试取消属于其他会话的 taskId,会收到拒绝提示并提示添加 --allloop_scheduleloop_status 工具同样遵循严格的 session 隔离。

4.5 交互式结果对话框

每次 /loop 命令的结果都会在独立的 OpenCode 原生对话框中打开,与 prompt 输入区完全隔离。它提供:

  • Copy ID: <taskId> ------ 复制结果中出现的每个任务 ID
  • Copy all ------ 复制完整的结果文本
  • Close ------ 关闭对话框

用鼠标或方向键选择操作后按 EnterSpace。复制成功后会显示确认并自动关闭对话框;若剪贴板访问失败,对话框保持打开并显示错误信息。长结果文本可用 Page Up / Page Down 滚动,按 qEsc 关闭。在窄终端下对话框会自动缩放到可视区域,结果区与操作列表保持独立滚动。新的 Loop 结果会替换上一个 Loop 对话框,而不会叠加多个。

4.6 程序化调用(LLM 工具)

插件注册了两个 LLM 可调用的工具,默认都绑定当前会话,传 all: true 即可跨会话。

typescript 复制代码
loop_schedule({
  action: "create",
  prompt: "check the deploy",
  intervalMs: 300_000,
  // sessionID 会从 ctx 自动绑定
})

loop_schedule({
  action: "cancel",
  taskId: "abc12345",
  // 若 taskId 属于其他会话会拒绝(传 all: true 可绕过)
})

loop_schedule({
  action: "reschedule",
  taskId: "abc12345",
  nextDueAtMs: Date.now() + 5 * 60_000,
})

loop_status({})               // 仅当前会话
loop_status({ all: true })     // 跨所有会话

五、配置选项

可在 opencode.json 中传入插件选项:

json 复制代码
{
  "plugin": ["opencode-plugin-loop"],
  "opencode-plugin-loop": {
    "maxTasks": 50,
    "taskTtlDays": 7,
    "defaultAdaptiveMinMs": 60000,
    "defaultAdaptiveMaxMs": 3600000,
    "tickerIntervalMs": 15000
  }
}
字段 默认值 说明
maxTasks 50 最大并发任务数
taskTtlDays 7 任务过期时间(天),加载时自动清理
defaultAdaptiveMinMs 60000 自适应模式下最小间隔(毫秒)
defaultAdaptiveMaxMs 3600000 自适应模式下最大间隔(毫秒)
tickerIntervalMs 15000 内部调度器检查间隔(毫秒)

六、会话隔离架构

每个 /loop 任务都携带 sessionID 字段:

生命周期事件 行为
用户在 session A 中执行 /loop 任务创建,sessionID = A
Ticker 每 15 秒扫描 仅触发 sessionID === activeSessionID 的任务(通过 chat.message hook 追踪)
用户在 session B 中执行 /loop B 变为活跃会话,A 的任务挂起等待
session A 触发 session.deleted A 的所有任务自动取消
插件热重载 老 ticker 停止、新 ticker 启动;in-flight 任务由 inflight Set 守护
没有 sessionID 的旧 tasks.json 加载时丢弃并打日志

任务持久化到 .opencode/cache/loop/tasks.json(项目级)。触发历史记录在同级目录的 history.log


七、常见问题排查

7.1 0.2.6 版本的双入口点

0.2.6 起插件暴露独立的 opencode-plugin-loop/serveropencode-plugin-loop/tui 入口点,让 OpenCode 分别加载调度器与响应式对话框。根导出仍保持 v1 兼容的 server 模块以兼容旧版本。程序化调用请使用命名工厂:

typescript 复制代码
import { LoopPlugin } from "opencode-plugin-loop"

7.2 任务行覆盖到输入区

0.2.4 之前的版本会把 /loop 结果直接写入终端,而 OpenCode 自己负责重绘 UI,可能造成任务 ID 与 prompt 串行。建议升级到 0.2.6+,它使用响应式交互对话框;运行期诊断信息会写入 OpenCode 的结构化应用日志。

同时确保插件 仅从一处来源 安装。OpenCode 会分别从 opencode.json 中的 npm 插件目录和 ~/.config/opencode/plugins/ 下拷贝的插件加载,即使包名相同也会重复加载。

如果 opencode.json 中已经有 "plugin": ["opencode-plugin-loop"],请检查是否残留了旧的拷贝安装:

bash 复制代码
ls ~/.config/opencode/plugins/opencode-plugin-loop

若该目录存在,把它移出自动加载目录后重启 OpenCode:

bash 复制代码
mv ~/.config/opencode/plugins/opencode-plugin-loop \
  ~/.config/opencode/plugins/opencode-plugin-loop.backup

验证 npm 安装工作正常后再删除备份目录。

7.3 任务没有触发

  1. 确认 OpenCode 版本 >= 1.17.18
  2. /loop list 检查任务是否已注册
  3. 检查 tickerIntervalMs 是否被改得过大
  4. 查看 .opencode/cache/loop/history.log 中是否有调度记录

7.4 想清理所有历史任务

直接删除持久化文件即可:

bash 复制代码
rm -rf .opencode/cache/loop

下次启动时插件会重建空目录。


八、最佳实践

  1. CI 巡检 :用 /loop 10m check the latest CI run for my branch,让 AI 自动分析失败用例。
  2. 部署观察/loop 30s curl the staging health endpoint and report status
  3. Review 自动化 :在 .opencode/loop.md 中写入 PR review 流程,对重要仓库做轮询检查。
  4. 谨慎使用自适应模式:自适应间隔由 LLM 决定,可能产生不可预测的频率,建议在 prompt 中给出明确的最长间隔提示。
  5. 及时清理 :对短期任务在完成后用 /loop cancel <taskId> 主动清理,避免堆积超过 maxTasks

九、参考资源


相关推荐
谭光志14 小时前
Vibe Coding 时代,程序员该何去何从
前端·后端·ai编程
GoGeekBaird15 小时前
我用 BeeWeave 跑完了一次完整写作闭环
后端·github
仿生狮子16 小时前
别再说“全栈”了,AI 时代团队只认这 5 种人
前端·人工智能·后端
Reart19 小时前
Leetcode 213.打家劫舍2(内含闲谈,打劫真是技术活,好题,716)
后端·算法
触底反弹19 小时前
🔥 RAG 到底是怎么工作的?掰开揉碎了给你讲明白!
javascript·人工智能·后端
techdashen19 小时前
Go 1.26 新增 `bytes.Buffer.Peek`:只看数据,不移动读取位置
开发语言·后端·golang
Reart19 小时前
Leetcode 198.打家劫舍(716)
后端·算法
Java编程爱好者20 小时前
Spring6.0+Boot3.0:秒级启动、万级并发的开发新姿势
后端
YYYing.20 小时前
【C++大型项目之高性能服务器框架 (七) 】Socket与ByteArray模块
服务器·c++·后端·框架·高性能·c/c++
青山木20 小时前
一把 Redis 分布式锁,踩透四个坑:锁争抢、僵尸锁、锁过期、锁丢失
java·数据库·redis·后端