乐于分享
好东西不私藏

给 AI 发工具的一周:从浏览器桥到表格打印

给 AI 发工具的一周:从浏览器桥到表格打印

翻了下 GitHub 的提交记录,8 月中下旬这十来天,我几乎每天都在往不同的仓库推代码,粗看很散:浏览器扩展、MCP 服务器、Go CLI、Python 性能优化。但串起来其实只有一条主线:

与其替 AI 写流程,不如给 AI 发趁手的工具。

具体就是五个项目,正好构成一个小闭环:AI 用 browser-bridge 看真实网页,用 mcp-coding 改代码;我用 ai-sessions 复盘 AI 干得怎么样,用 ai-models 挑该用哪个模型;最后所有输出交给 printable 打印得整整齐齐。

一、browser-bridge:把我的浏览器借给 AI

这个项目的深层成果是,知道了如何从外部和浏览器通信交互,不再让浏览器成为不可触碰的孤岛。

普通的爬虫:

  • 没有登录态,每个站点都得想办法塞 cookie;
  • 反爬一抓一个准,Cloudflare 盾页都过不去;
  • 验证码只能干瞪眼。

换个思路呢?别造假浏览器,直接用我正在用的这个。 登录态天然就有,验证码我顺手点一下就行,指纹就是真人的指纹。

于是有了 browser-bridge,三层结构:

  1. 浏览器扩展:注入页面拿 DOM 快照,监听指令;
  2. Native Host:扩展和本机进程之间的桥,Chrome官方开的口子;
  3. MCP Server:对上暴露标准 MCP 协议,任何 MCP 客户端(Claude Code、Codex、curl)都能连。

AI 拿到的是 browser_snapshot / browser_click / browser_type / browser_extract 这样一组工具,操作的就是我眼前这个真实的浏览器标签页。

之前 Claude、Codex的浏览器扩展配合 App工作,估计也是这个原理,但是它不开放呀,只能它自己用。

设计里我最得意的是跟随模式:不指定目标时,AI 自动控制当前激活的标签页。我在哪个页面上,AI 就在哪个页面上,零配置。想让它去别的页,切过去就行——控制权和知情权始终在我手里。

两个省 token 的细节:

  • browser_extract 把正文抽出来转成 Markdown,读文章比全量 snapshot 便宜一个量级;
  • 截图落到本地缓存目录返回路径,AI 按需再读,而不是每步都塞一张图进上下文。

为了便于其他可能感兴趣的用户,配置 Github CI 矩阵出各平台压缩包,用户解压跑一个 install-host.sh 就完事。目前 v0.1.2,开源在 GitHub。

二、mcp-coding:一次调用改十个文件

第二个项目解决的是另一个日常摩擦:AI 改代码太"碎"。

内置的编辑工具基本是"一次一处",跨五个文件的重构就是五轮工具调用,五次往返、五次上下文膨胀。更难受的是失败恢复——改到第三个文件发现第一处匹配错了,前面已经落盘的怎么办?

mcp-coding 是我的答案:一个 MCP 服务器,只暴露一个工具 edit_files,吃一种自定义的行导向文本协议

一个 patch 同时覆盖:删文件(!)、移动重命名(=>)、文本锚点(@)、行号跳转(:42)、删改块(-/+)、上下文消歧行(空格开头)、行内替换(~)、尾部追加($ 后接 +)、新建并全文重写(*)。关键性质有三条:

  • 原子性:整个 patch 先全部验证,任何一行匹配失败就整体拒绝、零修改,报错里带文件名、行号和当前内容;
  • 模糊降级:auto 模式下精确匹配失败会依次尝试忽略尾空白、忽略首尾空白、Unicode 归一,降级了会明说,膨胀行直接拒绝;
  • 歧义拒绝:锚点命中多处时不猜,列出所有候选行号让你消歧。

协议本身写了 ABNF 规范,配了单元、回归和 stdio 冒烟测试。现在我日常写代码就挂着它。

三、ai-sessions:随时查看 agent 对话历史

工具发出去之后,新问题来了:AI 用这些工具干活的完整过程,散落在各家客户端自己的存储里——Codex 是 sqlite,Claude 和 Qoder 是 JSONL,格式互不相通,出了问题根本没法回看。

ai-sessions 把它们统一解析掉:

最有用的其实是 token 统计:Claude/Qoder 从 usage 字段汇总,Codex 能算出缓存命中率。哪类任务烧钱、哪个 prompt 让 AI 绕了远路,数据说话。

四、ai-models:选模型不拍脑袋

复盘之后自然要选型。新模型层出不穷,榜单满天飞,但榜单和我实际的编程场景经常对不上。

ai-models 直接拉 OpenRouter 的实时数据,按编程评分(coding_index)筛:

-aa 选项还可以拉 artificialanalysis.ai 的评分交叉验证。选模型从"听说很强"变成"查一下再定"。

亮点是,我让 AI 设计了公式来计算总分,用于排名。其中有些常量,我用 ai-sessions 输出我的日常使用统计,喂给 AI 之后定出来的,也算更贴近真实使用情况。

这个命令的表格输出,使用了 go-column,和接下我要讲的 printable 共享了c底层实现。

五、printable:老项目焕发新春

前四个都是新项目,最后这个是个老朋友:printable,一个打印表格数据的 Python 库 + CLI(pip install printable),支持中英文混排对齐。

这周回头性能优化了一波。思路是把宽度计算和渲染下沉到 C,编成共享库:

engine
input
median (ms)
speedup
Python
rows
80.32
1.00x
Python + C width
rows
28.37
2.83x
Go column
[]byte
14.10
5.70x

5000×6 中英混合行,纯 Python 80ms,Go 走 C 实现只要 14ms。有意思的地方在于一份 C 实现喂三家人:Python 走 ctypes,Go 通过 cgo binding 复用同一个 .so,谁也不用重新实现一遍 UTF-8 宽度计算。

而不带线框的表格渲染使用的 linux 上的 column 命令底层实现 util-linux,借力打力。

打包也顺带清理了:wheel 里不再带 .c/.h 源码、输入走内存文件、为各个平台输出单独的更小体积的 wheel 包。现在 PyPI printable v0.5.0。

效果如下,

写在最后

回头看这五个项目,没有一个是"AI 应用"——没有 prompt 工程,没有 agent 框架,全是朴素的小工具。但它们共同回答了一个问题:怎么让 AI 在我的环境里干活更顺手?

  • 它要看网页 → 给它 browser-bridge;
  • 它要改代码 → 给它 mcp-coding;
  • 我要检查它的活 → ai-sessions;
  • 我要挑模型 → ai-models;
  • 结果要给人看 → printable。

AI 的能力上限是模型厂商的事,我能做的是把它脚下的路铺平一点。工具配置对了,同样的模型干出的活就会不一样。