
今天我给自己的博客写了一个命令行工具 blog-cli,纯玩具,除了能消耗一下我的 token,其实没别的卵用。
为什么要做 blog-cli
我的博客是一个 Astro 静态站点,源码放在 GitHub 私有仓库里,线上通过 Vercel 部署。这个结构很稳定,也足够简单,但它有一个小问题:内容管理还是偏“开发者工作流”。
如果只是在主力电脑上写文章,这不算麻烦。但我不想在公司电脑里 clone 我的整个 blog repo。每次发博客切到博客仓库、创建文件、提交、推送。
我希望能有一个跨设备使用的小工具,可以把单独一个 blog 文件,或者文件夹 push 到我的博客里。
- 不需要每台电脑都 clone 博客仓库。
- 不需要在每台电脑上配置完整的 Node/Astro 开发环境。
- 不需要记住博客项目里的目录结构。
- 最好能先 dry-run,看清楚会写入哪些路径,再真正发布。
于是 blog-cli 的目标就变得很明确:它是一个只服务于我这个博客的小工具。
目前支持的功能
现在 blogctl 已经支持这些命令:
blogctl login
blogctl status
blogctl list
blogctl view <slug>
blogctl publish <path>
login 用来配置 GitHub token 和博客仓库信息。
status 用来查看当前配置、认证状态和缓存状态。
list 会读取公开站点的 RSS,列出已经发布的文章。
view 会通过 GitHub API 读取私有仓库里的 Markdown 源文件,并在终端里显示正文。
publish 是最核心的命令,可以发布两种文章:
my-post.md
或者:
my-post/
index.md
image.png
单文件文章适合纯文字内容。文件夹文章适合带图片、附件或其他本地资源的内容。
发布前可以先执行:
blogctl publish ./my-post.md --dry-run
确认输出路径、slug、URL 都没问题,再真正发布:
blogctl publish ./my-post.md
如果目标文章已经存在,需要显式加上:
--replace
技术栈
blog-cli 是用 Go 写的。
选择 Go 的原因很直接,AI 推荐的,它说:
- 可以编译成单个二进制文件。
- 安装后不依赖 Node.js。
- 标准库里已经有 HTTP、XML、文件遍历等能力。
- 很适合做这种跨设备使用的小工具。
目前它的主要实现思路是:
- 用 RSS 读取公开文章列表。
- 用 GitHub API 读取私有仓库里的文章源码。
- 用 GitHub Git Data API 写入文章。
- 用本地配置文件保存 token 和默认仓库信息。
- 用 GitHub Actions 自动构建 macOS、Linux、Windows 的 release 二进制。
比较重要的一点是,发布文件夹文章时,它不会一张图一张图单独提交,而是把整篇文章和资源打包成一次 commit。这样历史记录会更干净,也更符合“发布一篇文章”这个动作本身。
做的过程中踩到的小坑
第一个坑是认证。
我一开始当然也希望能像网页登录一样输入 GitHub 账号密码,再输入 2FA 验证码。但 GitHub 现在已经不允许命令行或 API 使用账号密码认证了。最后还是回到了 token。
不过想明白之后,token 也没那么可怕。它更像是每台设备单独配置的一把钥匙,只要权限给得足够小,使用起来反而很清晰。
第二个坑是安装路径。
一开始我把 README 写成把二进制放到 /usr/local/bin。后来发现有些设备上根本没有这个目录。最后改成了更通用的用户级安装:
~/.local/bin
这样不需要 sudo,也不依赖系统目录,更适合个人工具。
第三个坑是发布前校验。
比如文件夹文章里可能会混入 .DS_Store,Markdown 图片路径可能带 query,frontmatter 里的 tags 可能写成 inline list。这些都不是什么大问题,但如果不处理,真正使用时就会很烦。
所以我给它补了一批测试,把这些边界都固定下来。
后面可能会继续做什么
目前 blog-cli 已经有了第一个 release,接下来我可能会继续补这些功能:
delete:删除文章。edit:拉取文章到本地临时文件,编辑后再发布。search:搜索已发布文章。doctor:检查 token、配置、网络和仓库权限。- 更好的安装脚本或 Homebrew 支持。
如果一个工具能对我有一丁点用,那它就已经有价值了。
这篇文章就是用 blog-cli 发布的。