文章

CurlGo CLI:空的 --out-dir 先失败,curl 选项不再被静默丢掉(附可跑命令)

· 12 分钟阅读 · 本文以中文撰写

11 月 12 日,CurlGo 桌面端发到 v0.2.1,独立 CLI 发到 cli-v0.1.1。两件事同一天,升级通道是分开的。桌面客户端有自己的版本;CLI 和完整指南的版本写在 internal/cli/VERSION 里。

如果你让 Agent 用命令行测接口,最怕两件事。输出目录写错了,请求已经打出去了;从聊天里复制的 curl 带了一些旗标,工具既没有告诉你不支持,也没有按你以为的方式执行。

CurlGo CLI 用 schemaVersion: 1 的 JSON 说话。帮助、预检、正式请求,各自对「成功」有不同含义。显式传入空的 --out-dir "" 时,它会在发请求之前以 OUTPUT_ERROR、退出码 3 失败。省略这个旗标,才继续用私有临时目录。

先跑通一条预检

独立 CLI 不启动图形界面。仓库里可以这样编出一个本地可执行文件:

CGO_ENABLED=0 go build -o /tmp/curlgo-api-test ./cmd/curlgo

也可以直接下载 独立 CLI 0.1.1。下面的命令把 curlgo 理解成这个可执行文件即可。先确认它在 PATH 里:

command -v curlgo

本地服务已经在 8080 端口时,把最小请求存成 request.json:

{
  "schemaVersion": 1,
  "request": {
    "method": "GET",
    "url": "http://127.0.0.1:8080/health",
    "followRedirects": true,
    "timeoutSeconds": 30
  }
}

先预检,不发请求:

curlgo run --request request.json --dry-run

也支持从标准输入读,或改走 curl 文本。--request 和 --curl 互斥:

curlgo run --request - --dry-run <request.json
curlgo run --curl imported.curl --dry-run

预检通过时,stdout 是一份 schemaVersion: 1、ok: true 的 JSON,带 validation,没有 result。bodyMode: "" 表示原始正文模式,计数是准备后的请求头和表单项数,不是响应信息。

成功只表示本地准备通过。它不代表目标可达,也不代表 TLS 证书链可信,更不代表登录或业务成功。确认请求和目标都没问题之后,再去掉 --dry-run 发送。

当前版本的字段和选项,也可以直接问 CLI 自己:

curlgo skill cli-reference

skill 输出 Markdown,最后一行是 [curlgo:skill] end of guide。它不启动界面,不读标准输入,也不访问目标接口。其他帮助、预检和请求命令继续输出 JSON。

三种成功不是一回事

ok: true 和退出码 0,要先看你跑的是哪种模式。

模式退出码 0 / ok: true 的含义
帮助帮助 JSON 输出成功,不是一次接口检查
--dry-run本地准备和预检 JSON 输出成功,没有发送请求
普通 run响应捕获、已配置的断言、适用的提取和输出都成功;只验证你列出来的规则

没有断言时,HTTP 401、404、500 也可以退出 0。这时必须再看 result.statusCode 和正文,不能把退出码 0 直接当成业务通过。

JSON 输入缺省是 GET、HTTP、30 秒超时、跟随重定向。你写了 false 就按 false 留着;超时写成 0 会被拒绝。从 curl 导入时,只有带了 -L 才跟随重定向。

CLI 不加载图形界面的工作区。变量来自 JSON 里的 settings.environments 和 environment,不读操作系统环境变量。CA、Cookie、代理分别通过 --ca-file、--cookie-jar、--proxy 显式提供,不读 HTTP_PROXY、HTTPS_PROXY、NO_PROXY。凭证放在权限为 0600 的私有文件里,或走标准输入,不要放在命令行参数上。

空的 —out-dir,在发请求前失败

请求发出前的四步:读入、预检、空目录先失败,再决定是否真的发送

图 1:显式传入空的输出目录时,失败发生在预检这一段。请求还没有离开这台机器。

显式指定 --out-dir 或 --cookie-jar 时,它们的父目录必须已经存在,而且必须是目录。预检只检查存在和类型,不检查写权限或剩余空间,也不会替你 mkdir。这条检查失败,就是 OUTPUT_ERROR,退出码 3。

更需要盯住的是空字符串。普通执行里,--out-dir "" 同样以 OUTPUT_ERROR、退出码 3 失败,而且发生在发送请求之前。它不会悄悄退回临时目录。只有省略这个旗标时,才使用私有临时目录。

这个区别对 Agent 很要紧。如果把空字符串和「没传」当成同一回事,工具可能已经打到生产接口,调用方却以为只是路径没设好。CLI 0.1.1 把这条写死:空值就是失败,失败在发送之前,和 --dry-run 走同一段路径检查。

正文怎么落盘,也和这个目录有关。小文本放在 result.body.text 里;二进制,或超过默认 262144 字节内联阈值的正文,会写到 body.path,需要再读那个文件。--inline-body-bytes 范围是 0 到 4194304,写成 0 会让所有非空正文都写文件。捕获上限是 4 MiB,truncated 为真时,不能声称响应完整,也不能直接拿不完整的 JSON 去解析。输出文件权限是 0600,默认临时目录是 0700,留给调用方读取和清理。--out-dir 必须指向已有目录,调用方不应删除用户目录或无关文件。

curl 选项分三种下场

从聊天或文档里复制一行 curl,最怕的是「看起来收下了,其实没按这个旗标做」。CurlGo 把选项分成三类:导入、接受但忽略、明确拒绝。未列出的参数不会被静默丢掉。

三列:导入的 curl 选项、接受但忽略的选项、明确拒绝的选项

图 2:接受但忽略,和明确拒绝,是两种不同的回答。前者是故意不生效,后者会让这次导入失败。

会导入的包括:--request、--header、--data、--data-raw、--data-binary、--json、--user、--cookie(只接受 name=value)、--oauth2-bearer、--user-agent、--referer、--url、--location、--head、--max-time,以及文本形式的 --form-string。短参数是 -X、-H、-d、-u、-b、-A、-e、-m、-L、-I,也支持 --参数=值 这种写法。

接受但忽略的是输出和传输层习惯用法:--compressed、-s / --silent、-S / --show-error、-sS、-i / --include、-N / --no-buffer。它们常出现在从终端复制出来的命令里,忽略它们是为了不改变这次请求本身的含义。

明确拒绝的包括 -F / --form、--data-urlencode,以及上面没列出的其他参数。上传文件要在图形界面里选择,或在获授权的 CLI JSON 里提供 multipart 的绝对路径。curl 文本只被解析,不会拿去执行 shell,也不会展开系统变量,更不会按隐式 @file 去读文件或 Cookie 文件。

你可以先把准备导入的命令存成 imported.curl,用 --dry-run 看它落在哪一类。被拒绝时,退出码和 error.code 会告诉你是 INVALID_CURL 这类输入问题,而不是已经打到了服务器。

看退出码和 error.code,不要匹配提示文本

退出码 0 到 4 的含义:0 随模式变化,1 是构造错误,2 是执行失败,3 是输出失败,4 是断言失败

图 3:分类看 error.code 和退出码。error.message 只提供安全提示,不回显原始凭证、输入或底层错误。

  • 退出码 1:用法、输入、配置或请求构造错误。例如 INVALID_USAGE、INVALID_INPUT、INVALID_CURL、UNRESOLVED_VARIABLE、MISSING_SECRET、INVALID_SECRETS、INVALID_REQUEST、REQUEST_BUILD_ERROR。
  • 退出码 2:执行或提取失败。例如 CONNECT_ERROR、REDIRECT_ERROR、TLS_ERROR、TIMEOUT、CANCELED、BODY_READ_ERROR、EXTRACTION_ERROR。
  • 退出码 3:输出路径、正文落盘或 Cookie 保存失败,也就是 OUTPUT_ERROR。stdout 本身写入失败也是 3,此时 JSON 可能不完整,标准错误里是固定提示 CurlGo: 无法写入结果 JSON。
  • 退出码 4:响应断言失败,ASSERTION_FAILED。失败仍保留响应,并阻止变量提取。

把 Agent 的重试策略挂在这些码上会比较稳。输入问题不要换个目标再打一遍;输出路径问题不要改成「先发出去再说」;断言失败要读完整报告,而不是把同一条请求循环发送。

v1 还不包含脚本断言、集合运行器,也没有无界面的 SSE 或 WebSocket。这些能力在图形界面里可用,不要假设 CLI 0.1.1 也能做同一件事。

用这几步验收

把下面几条在同一台机器上跑完,就能核对这份契约。目标建议用本地服务,不要一上来打到生产接口。

  1. curlgo help 和 curlgo run --help 输出 schemaVersion: 1、ok: true 的帮助 JSON,没有 result。
  2. 对前面的 request.json 跑 --dry-run,得到 validation.dryRun: true,网络上不应出现对应请求。
  3. 再跑 curlgo run --request request.json --out-dir "",应在发送前以退出码 3、OUTPUT_ERROR 失败。把同一条命令改成省略 --out-dir,才会走私有临时目录。
  4. 准备一个带 -s、--compressed 的 curl 文件,--dry-run 应能通过;再准备一个带 -F 或 --data-urlencode 的文件,预检应失败,且请求未发出。
  5. 给普通 run 配一条必定失败的断言,退出码应是 4;去掉断言再打一个会返回 404 的地址,退出码可以是 0,这时要靠 result.statusCode 判断。

五条都对上,空输出目录、curl 选项分类和成功含义就没有混在一起。当前版本的完整选项列表,以 curlgo skill cli-reference 当场打出来的为准。

材料与时效

本文以 2026-11-13 可读的公开材料为准,对应桌面端 v0.2.1 与独立 CLI cli-v0.1.1:

  • 仓库 README 中的 Agent 与 CLI 说明、退出码表,以及「当前边界」里的 curl 选项清单
  • CLI 指南入口 curlgo skill、curlgo skill workflows、curlgo skill cli-reference
  • internal/cli/CHANGELOG.md

我没有在写作时对着生产接口做完整回归;文中的命令和失败约定以 README 与 CLI 指南为准。后续版本以 GitHub 仓库和 curlgo skill cli-reference 的当场输出为准。

继续阅读

相关文章

讨论

审核后公开 · 支持 Markdown

读到这里时加载讨论。