OpenCode 非交互式模式完整指南:-p 参数、JSON 输出与工作流集成

OpenCode 非交互式模式完整指南:-p 参数、JSON 输出与工作流集成

【免费下载链接】termaiA powerful AI coding agent. Built for the terminal.项目地址: https://gitcode.com/gh_mirrors/te/termai

把 AI 助手写进脚本,第一件事就会被卡住:OpenCode 默认启动的是一个全屏的交互式界面,没有地方让你敲回车,也没有"打印一行结果就退出"的出口。解决办法是它的非交互式模式:带上-p参数传一个提示词,程序跑完就返回、进程退出,stdout 里只剩答案。下面直接围绕这个模式展开。

哪些任务适合切到非交互模式

判断标准很简单:这次调用需不需要人盯着屏幕。

  • 批量处理:对一整个目录的代码做重复操作(统一检查、统一改写注释),你不需要每次回答"是否允许修改文件"。
  • CI/CD 流水线:在持续集成构建里嵌入一个代码审查或文档生成步骤,流水线没有终端 UI,只需要一行命令加一个退出码。
  • 给其他程序当后端:Python、Node 或其他 Go 服务通过子进程调用它,拿回结构化文本。
  • 只要结构化日志:调用方是脚本而不是人,输出必须是可解析的 JSON 而不是终端花屏。

跑通第一条命令

最小可用命令长这样:

opencode -p "用 Go 写一个读取 JSON 文件的示例" opencode -p "分析这段代码的时间复杂度" -f json

用到的参数一共五个:

  • -p:提示词,也是触发非交互模式的开关(不带它就直接进交互界面)
  • -f:输出格式,text(默认)或json,写错值会直接报错退出
  • -q:隐藏运行中的转圈指示器(spinner 是任务执行时的等待动画),批量跑时输出更干净
  • -d:打开调试日志
  • -c:指定工作目录,等于先cd再执行,适合批处理时锁定项目路径

提示词本身建议写得像给同事的任务单:说清楚目标文件和期望输出,比一句"帮我看看代码"有用得多。

把输出变成可解析的 JSON

加上-f json后,成功时 stdout 是一个 JSON 对象,结构比很多文档吹的要简单——就一个字段:

{ "response": "时间复杂度为 O(n log n),排序发生在 merge 步骤……" }

AI 的回答放在response里,转义、缩进都由程序处理,你只管按这个结构去解包。

错误则走完全不同的路:不会输出一段"错误 JSON"。当 agent 处理失败时(模型不可用、请求被中断等),进程以非零退出码结束,错误信息打在 stderr,stdout 为空。所以程序化解析的完整判法是:先看退出码,等于 0 再解析response;非零就记为失败,别去 parse stdout。

接入你自己的工作流

Python 里当工具函数用

subprocess 调一下,拿到 JSON 再解包:

import subprocess, json r = subprocess.run( ["opencode", "-f", "json", "-q", "-p", "分析 requirements.txt 的依赖冲突"], capture_output=True, text=True, check=False, ) if r.returncode != 0: raise RuntimeError(r.stderr) print(json.loads(r.stdout)["response"])

注意-q别省:spinner 会往 stderr 写动画字符,混进日志很难看,关掉它 stdout 才是纯 JSON。

Shell 里批量扫文件

for f in $(find ./internal -name '*.go'); do opencode -f json -q -c . -p "检查 $f 的并发安全问题,只输出结论" done

配合-c固定工作目录,循环里就不用担心相对路径漂移。想落盘就重定向到文件,想即时看就让它直接打屏。

在 CI 里做审查门禁

在流水线里加一步:opencode -f json -q -p "审查本次 diff 的安全风险" > review.json。然后单独写一个校验步骤:退出码非零就exit 1让流水线失败,退出码为零再解析review.json发通知。关键习惯是把调用和校验拆成两步,别在一条命令里又跑又判。

内部到底发生了什么

理解这条链路后,排查问题会快很多。顺序是:

  1. cmd/root.go 的RunE读到-p非空,确认走非交互分支,同时校验-f的值是否合法
  2. 加载配置:环境变量(带OPENCODE_前缀)+ 项目根目录的.opencode.json+ 全局默认值,逐层合并
  3. 连本地数据库(SQLite,负责会话持久化),创建一个新会话;非交互模式下该会话的权限请求被自动批准,不会再弹"是否允许执行命令"
  4. internal/app/app.go 的RunNonInteractive起 spinner(-q时不起),把提示词交给 coder agent 执行
  5. 拿到回复后按-f格式输出到 stdout,进程退出

也就是说,即使没有界面,OpenCode 依然是完整的 agent:能读写文件、跑 shell,只是不再问你。

几个容易踩的坑

  • 参数优先级:命令行参数 >OPENCODE_前缀的环境变量 >.opencode.json> 内置默认。配置写在文件里又被环境变量覆盖时,用-d跑一次看日志加载的是哪个文件。
  • 编码:JSON 输出是 UTF-8,中文内容无需额外处理;终端乱码先检查终端 locale 是否为 UTF-8,而不是怀疑工具。
  • 长提示词:超过 shell 单条命令长度限制时,把提示词写进文件再$(cat prompt.txt)注入,比转义引号可靠。
  • .opencode.json里没有的输出格式项:output-format只能通过-f传,别往配置文件里写不存在的键,模型选择(agents)、API Key(providers)、contextPaths这些才是配置该管的事。

收尾:几条实践

  • 脚本里永远带-f json -q,给人看的调用才用默认文本模式
  • 先判退出码再解析 JSON,失败分支处理 stderr
  • 用contextPaths或opencode.md把项目约定沉淀下来,减少每条提示词里的重复背景
  • 批处理固定-c指定工作目录,避免路径漂移

【免费下载链接】termaiA powerful AI coding agent. Built for the terminal.项目地址: https://gitcode.com/gh_mirrors/te/termai

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考