Logo极客杰尼知识库

Go CLI 工具开发实践

用 Go 构建零依赖的 Agent 友好 CLI 工具 — 从项目结构到自动发布

Go CLI 工具开发实践

我用 Go 构建了 4 个 CLI 工具(gcli、imgcli、jina-cli、md2wechat-lite)。这篇文章总结构建过程中的工程选择和踩过的坑。

为什么选 Go

三个理由:

  1. 单二进制分发 — 编译后一个文件,curl | bash 就能安装。不需要运行时。
  2. 零 CGO — 交叉编译简单,一条命令出 linux/darwin/windows 三个平台。
  3. 性能够用 — CLI 工具不需要极致性能,但 Go 的启动速度和内存占用都很克制。

项目结构

以 gcli(Gmail CLI)为例:

gcli/
├── cmd/               # cobra 命令定义
│   ├── root.go        # 根命令 + 全局 flag
│   ├── auth.go        # gmail auth 子命令
│   ├── list.go        # gmail list 子命令
│   └── read.go        # gmail read 子命令
├── internal/          # 内部实现(不导出)
│   ├── gmail/         # Gmail API 封装
│   ├── auth/          # OAuth + PKCE 流程
│   └── output/        # JSON/Table 输出格式化
├── scripts/
│   └── install.sh     # 一键安装脚本
├── main.go
├── go.mod
└── .goreleaser.yaml   # 自动发布配置

关键选择

  • cobra 做命令行框架 — 成熟稳定,子命令模式适合 CLI 工具
  • internal/ 放所有业务逻辑 — 强制不导出,避免被意外依赖
  • scripts/install.sh — 检测平台 + 下载对应二进制 + 放到 PATH

Agent 友好设计

CLI 工具的真正用户不只是人,还有 AI Agent。Agent 友好意味着:

1. 结构化输出

# 人类友好
gcli list --limit 5

# Agent 友好
gcli list --limit 5 --output json

永远提供 --output json 选项。Agent 解析 JSON 比解析表格容易 100 倍。

2. 明确的退出码

// 成功 = 0,用户错误 = 1,系统错误 = 2
os.Exit(0)  // 一切正常
os.Exit(1)  // 参数错误、认证失败等
os.Exit(2)  // 网络错误、文件系统错误等

3. 静默模式

gcli auth --quiet  # 只输出结果,不输出过程

Agent 不需要看 spinner 和进度条。--quiet 模式只输出最终结果。

跨平台发布

使用 GoReleaser 自动化:

# .goreleaser.yaml 核心配置
builds:
  - env: [CGO_ENABLED=0]
    goos: [linux, darwin, windows]
    goarch: [amd64, arm64]

release:
  github:
    owner: geekjourneyx
    name: gcli

每次打 tag,GitHub Actions 自动编译 6 个平台二进制,发布到 GitHub Releases。

安装脚本设计

一键安装脚本的核心逻辑:

# 1. 检测平台
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)

# 2. 下载对应二进制
curl -fsSL "$DOWNLOAD_URL" -o /tmp/gcli.tar.gz

# 3. 解压到 PATH
tar -xzf /tmp/gcli.tar.gz -C /usr/local/bin/

关键:脚本要幂等。多次执行不会出错。

踩过的坑

CGO 和图片处理

imgcli 处理图片但不用 CGO。怎么做到的?

  • golang.org/x/image 替代需要 CGO 的图片库
  • PNG/JPEG 编解码用纯 Go 实现
  • 牺牲少量性能,换来零依赖的交叉编译

OAuth PKCE 在 CLI 中的实现

gcli 需要 OAuth 认证。在无浏览器的服务器上怎么办?

  1. 生成 PKCE code_verifier + code_challenge
  2. 打印授权 URL,让用户在别的设备打开
  3. 启动本地 HTTP server 等待回调
  4. 用 authorization_code + code_verifier 换 token

安装脚本在 CI 中失败

CI 环境可能没有 /usr/local/bin 写权限。解决:

INSTALL_DIR="${HOME}/.local/bin"
mkdir -p "$INSTALL_DIR"
# 安装到用户目录,不需要 sudo

总结

Go CLI 工具的核心优势是分发简单。一个二进制文件,什么环境都能跑。

对于 Agent 工具,最重要的不是功能多丰富,而是接口多清晰。JSON 输出、明确退出码、静默模式 — 这三件事做好,Agent 就能顺畅使用你的工具。