跳转到内容

fx — JSON 的交互式查看器(jq 的 TUI 表亲)

是什么

fx 是 Anton Medvedev 在 2018 年发布、2022 年用 Go 重写的终端交互式 JSON 查看器。日常类比:

  • jq:JSON 的 sed/awk —— 一条命令吐出过滤后的结果,不交互
  • fx:JSON 的 less + 文件树 —— 在终端里打开一个大 JSON,方向键展开/折叠,斜杠搜索,回车跳转
  • btop : top/htop = fx : jq —— 都是给原本一次性输出的命令行工具加一层”可以点、可以滚、可以折”的 TUI 皮

最小例子:

Terminal window
curl -s https://api.github.com/repos/antonmedv/fx | fx

fx 立刻打开一个全屏 TUI:左边是可折叠的 JSON 树,方向键导航,e 展开全部,/ 搜索,q 退出。无参数时它就是 JSON 版的 less。

为什么重要

fx 在 19k+ stars 的位置不是偶然,原因有几层:

  • 大 JSON 时代缺个交互入口:API 响应、kubectl、AWS CLI 输出动辄 100KB ~ 几 MB,jq 一行命令打出来全是滚动屏幕的瀑布;fx 让你先折叠看结构、再展开看细节,认知负担直接降一档
  • jq / yq 是搭档不是替代:jq/yq 是管道里的 filter,fx 是终点的 viewer —— 三者关系类似 grep + less 的关系,没有 fx 时人们用 jq . | less,但 less 不懂 JSON 结构
  • 零配置上手brew install fxcat x.json | fx,5 秒学会,比学 jq 的 DSL 门槛低 10 倍 —— 是 jq 的”前置入口工具”
  • 单 Go 二进制 + 跨平台 —— 老版 Node.js 的发行包袱在 2022 重写后甩掉

如果说 jq 是从无到有造了”shell 里处理 JSON”这个场景,fx 是把这个场景人性化 —— 让不会 jq 的人也能先看清 JSON 长什么样。

核心要点

fx 的心智模型可以拆成 三层

  1. TUI viewer(默认模式):把 JSON 当文件树渲染。空格折叠/展开节点,e 展开所有,E 全部折叠,/ 搜索,g/G 跳到首尾 —— 键位刻意抄 vim/less,老用户零迁移成本。

  2. filter 模式(按 . 进入):在底部输入栏写 jq 风格的过滤表达式,输入一个字符就实时刷新上方视图。这是它最杀手的功能 —— 写 jq 你得”猜对一次跑一次”,写 fx 你”边写边看”。

  3. 管道模式(无 TTY 时):检测到输出被重定向(fx ... > out.json)时自动切非交互,行为退化成 jq .。这让 fx 在脚本里也能当 JSON pretty-printer 用,不会破坏 pipeline。

三层叠加,让 fx 既能在调试场景做”打开看看”的 viewer,又能在 jq 表达式开发阶段做”实时 REPL”,还能在 CI 脚本里当透明的 pretty-printer。

实践案例

案例 1:打开一个大 API 响应

Terminal window
gh api repos/antonmedv/fx | fx

打开后是可折叠的 JSON 树。方向键浏览,看到 owner 是个对象,按空格展开,再看到 permissions,再展开 —— 全程不需要写任何 jq 表达式。这是 fx 替代 jq . | less 的标准用法。

案例 2:和 jq 互补 —— fx 当前置探索器

实际工作流是这样:

Terminal window
# 第一步:先用 fx 探索结构
kubectl get pods -o json | fx
# 第二步:心里有数后,写 jq 一行抓字段
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, status: .status.phase}'

fx 解决”我不知道这个 JSON 长什么样”的问题,jq 解决”我已经知道结构、要批量提字段”的问题。先 fx 后 jq 是最高效的组合。

案例 3:和 yq 联动看 K8s YAML

yq 把 YAML 转 JSON 后灌给 fx 交互浏览:

Terminal window
yq -o=json deployment.yaml | fx

K8s 的 manifest 嵌套深,YAML 直接读眼花,转成 JSON 用 fx 的折叠树看更清楚。这是 yq 文档里推荐的 debugging 模式之一。

案例 4:在 fx 内写 jq 过滤器(实时 REPL)

Terminal window
cat huge-config.json | fx

. 进入 filter 模式,输入 .users | map(.email) —— 每按一个字符上方视图都重渲染。写错语法立刻看到错误,写对就看到结果。开发完再 Ctrl+S 保存表达式,或退出后把表达式贴给 jq 跑批。

案例 5:和 fzf / ripgrep 搭管道

ripgrep 找出含敏感字段的 ndjson 行,fx 逐条展开看细节:

Terminal window
rg --json "password" logs/ | fx

ndjson 的多文档场景 fx 也支持 —— 它把每行当独立 JSON 加载,方向键在多文档之间切换。这是审查日志/审计的常见模式。

踩过的坑

  1. 同名工具混淆:GitHub 上至少有 3 个叫 fx 的工具 —— Anton Medvedev 的这个 JSON viewer、一个前端 effects 库、一个 functional extensions 库。认准 antonmedv/fx —— Homebrew brew install fx 默认就是它,但 npm 上其他同名包多到要小心。

  2. Node 版和 Go 版并存:2018-2022 是 Node.js 写的(npm 安装),2022 后官方主推 Go 版(brew/binary)。两版功能基本一致但启动速度差 10 倍(Go 二进制冷启 30ms,Node 版要起 V8 引擎要 200ms+)。建议直接装 Go 版。

  3. 没 TTY 自动退化:在 CI 或者输出被重定向时,fx 检测到没 TTY 就不进 TUI,行为变成 jq . —— 这点设计合理但会让”为什么我看不到 UI”的初学者困惑半天。检查 tty -s 状态。

  4. JS 表达式模式有安全风险:fx 支持用 JS 函数当 filter(fx 'x => x.users.length')。这意味着 JSON 文件里的内容如果跟你的 filter 拼起来形成 JS 注入面,理论上能跑任意代码。处理不可信 JSON 时尽量用 jq 模式或只读 viewer。

  5. 大文件仍然一次性加载:默认把整个 JSON 读进内存才开始渲染。打开 5GB JSON 会卡几秒甚至 OOM —— 流式打开要看 ndjson 模式或外部预处理(jq --stream 切片后再 fx)。

适用 vs 不适用场景

适用

  • 探索陌生 JSON 结构(API 响应、kubectl 输出、配置文件)
  • jq 表达式开发期的实时 REPL(边写边看)
  • ndjson 日志逐条交互查看
  • 临时 pretty-print(管道末端 ... | fx 在脚本里也能用)
  • 教学场景 —— 比 jq 友好太多,新人 5 分钟会用

不适用

  • CI/CD 自动化里抽字段 → 用 jq,无 TUI 开销
  • YAML 直接处理 → 用 yq(先 yq 转 JSON 再 fx 也行,但多一步)
  • 多 GB 流式处理 → fx 不擅长,用 jq --stream
  • 需要 schema 校验 → 用 jsonschema / ajv
  • 远程服务器无 TTY → 用 jq . | less 替代

历史小故事(可跳过)

  • 2018:Anton Medvedev 在 GitHub 发布 fx 1.0,Node.js 写的,配一个 30 秒的 GIF 演示 cat data.json | fx。HN 首页爆,第一周就 5k stars。
  • 2019-2021:稳定迭代,加 themes、搜索、JS 表达式 filter,10k+ stars。
  • 2022:官方宣布完全用 Go 重写,理由是单二进制、启动快、不依赖 Node runtime。Node 版仍可用但进入维护模式。
  • 2023:进入 Homebrew、apt、scoop、nix 默认仓库,K8s 圈口口相传”调试 JSON 用 fx”。
  • 2024-2026:19k+ stars,是 jq 之后最常被推荐的 JSON 工具;Anton 开始做 fx Pro(带 schema 推断的付费版)。

学到什么

  1. 给老 CLI 加 TUI 是一个反复出现的成功 pattern —— top → htop → btop,jq → fx,git → lazygit,docker → lazydocker。每个 CLI 工具都值得问一句”它的 TUI 在哪”。

  2. filter 实时反馈 = 学习曲线砍半 —— jq 的 DSL 老有人学不会,是因为反馈周期长(写、跑、看错误、改);fx 让反馈降到键击级别,新人上手指数级变快。这是 REPL 思想在 CLI 工具里的胜利。

  3. 同生态做”探索版 + 批量版”组合 —— fx 不试图替代 jq,而是当它的前置入口。这种”互补不替代”的定位让两者都活得很好,比正面竞争健康。

  4. Node → Go 的重写代价值不值 —— 2022 重写后用户从 npm 迁到 brew 经历了一次小阵痛,但启动速度从 200ms 降到 30ms,长期收益远大于一次性迁移成本。这是工具类项目”语言换跑道”的成功案例。

延伸阅读

  • 官方站:fx.wtf(一页文档全在这,5 分钟看完)
  • GitHub README:antonmedv/fx(GIF 演示直观)
  • 作者博客:medv.io(Anton 写的 fx 设计反思和重写故事)
  • 同类对比:jless(Rust 写的 fx 对手,键位更 vim)

关联

  • jq —— 心智模型同源;fx 是 jq 的 TUI 前置入口,先 fx 探索再 jq 批量
  • yq —— yq -o=json | fx 是看复杂 K8s manifest 的标准管道
  • btop —— 同属”给老 CLI 加 TUI”的设计模式
  • fzf —— ripgrep + jq + fzf + fx 是 DevOps 的 JSON 探索四件套
  • ripgrep —— rg --json | fx 把搜索结果交互化
  • claude-code —— Claude Code 在调试 API 响应时常推荐先 fx 探索再写 jq 表达式

反向链接

  • btop —— btop — bashtop 三代 C++ 版,五面板一屏的彩色资源监控器
  • claude-code —— Claude Code — Anthropic 终端编程助手
  • curlie —— curlie — curl 的能力 + HTTPie 的语法
  • dasel —— dasel — 一把刀同时切 JSON / YAML / TOML / XML / CSV
  • fzf —— fzf — 命令行模糊查找
  • gron —— gron — 把 JSON 拍平成 grep 能吃的赋值行
  • httpie —— HTTPie — curl 的人话版本
  • jc —— jc — 把 100+ Unix 命令的输出一键 JSON 化
  • jq —— jq — JSON 的 sed/awk
  • ripgrep —— ripgrep — Rust 写的现代 grep