给终端输出截图,听起来很简单对吧?截图、粘贴,完事。
但如果你需要把截图放进技术博客、在 CI 里验证 TUI 界面、或者把终端输出喂给 AI 做结构化解析,普通截图的像素点根本不够用。
这篇文章会实测一个 Rust 写的终端截图工具 cellshot(仓库已更名为 kitlangton/terminal-control),它能对正在运行的 TUI 程序截图,输出 SVG/JSON/PNG 格式,还支持通过会话管理做自动化。我会把安装、常用命令、踩坑、和同类工具怎么选都过一遍。
为什么需要专门的终端截图工具?
普通的终端截图方案各有各的短板:
- 手动截屏(PrtSc/微信截图等)— 每次分辨率、字体、主题都不一样,放在文章里很难看
script命令回放— 只能录文本,不能生成图片- asciinema— 录制功能好,但是生成 SVG/PNG 需要额外步骤,不支持交互式控制
- freeze/termshot— 只能处理管道输入(
ls -la | freeze),没法对正在运行的 TUI 程序(比如htop、ranger、各种 CLI 菜单工具)截图
cellshot 的差异点在于它的 PTY-first 架构:工具启动一个伪终端(PTY)来运行目标程序,然后把终端输出解析成结构化帧模型,每个字符的坐标、颜色、样式属性都单独存储。配合命名会话的 start/send/wait/stop 四步生命周期,你可以编写脚本来自动化截图流程。

安装
前提是系统装了 Rust 工具链(rustc ≥ 1.93),直接 cargo 安装:
cargo install cellshot --locked
这条命令会拉取并编译 89 个依赖包,总耗时约 2 分钟。如果你的终端默认 120 秒超时,可以用后台运行的方式:
# 放后台跑,别等它
# 等提示符重新出现后再检查版本
cellshot --version
# → cellshot 0.7.0
如果你不想装 Rust 工具链,或者介意编译耗时,同类工具也有 npm/pip/go 的安装方式(后面竞品对比会提到)。
基础截图:cellshot show
最常用的子命令 show,截取一条命令的输出:
cellshot show --cols 80 --rows 15 -- ls -la
--cols 和 --rows 参数控制虚拟终端的视口大小。-- 后面的内容是要执行的程序和参数。
你也可以用它启动其他程序而不只是一条命令,具体看后面的会话管理部分。
SVG/JSON 输出:cellshot save
想同时拿到 SVG 图片和结构化数据,用 save 子命令:
cellshot save --format svg --format json --out terminal-output \
--cols 80 --rows 12 -- ls -la ~
这条命令会产生两个文件:
terminal-output.svg— 32.5KB,SVG 矢量图。背景色#0d1117(GitHub Dark),字体 JetBrains Mono,ANSI 颜色映射完整terminal-output.json— 310.5KB,17,326 行,逐单元的结构化数据
JSON 输出值得细说。每个单元格(cell)包含:
坐标 (x, y) → 文本字符 → 宽度 → 前景色 → 背景色 → 样式属性
用这个数据你可以对终端输出做精确的 diff 比较、或者直接喂给 AI 做结构化解析。JSON 输出了 17K+ 行的数据量,虽然不是每个场景都需要,但在需要机器处理的场景里,这个精细度是普通截图完全给不到的。
交互式会话管理:核心能力
cellshot 最特别的功能是命名会话管理,分为四个步骤:
启动会话
cellshot start demo --cols 40 --rows 10 -- bash
这会创建一个名为 demo 的持久终端会话。查看会话状态:
cellshot status demo
# demo running
# cwd: /path/to/current
# command: bash
# viewport: 40x10
发送指令
⚠️ 这里有一个要留意的点:send 子命令不支持裸文本,必须用类型前缀:
# ❌ 这样会报错
cellshot send demo 'echo "hello"'
# Error: unsupported input event...
# ✅ 正确写法
cellshot send demo 'text:echo "=== CELLSHOT TEST ==='
cellshot send demo 'enter'
cellshot send demo 'text:ls -la /tmp'
cellshot send demo 'enter'
支持的输入类型包括:text:<value>(普通文本)、enter、ctrl-a 到 ctrl-z、方向键、escape、tab、backspace 等。
等待指定文本(CI 自动化核心)
这是把会话管理串进自动化流程的关键命令。wait 会阻塞直到终端中出现指定文本:
cellshot send demo 'text:echo "===READY==="'
cellshot send demo 'enter'
cellshot wait demo '===READY===' --timeout 5
超时参数 --timeout 5 防止无限等待。配合 send 使用,可以在脚本里控制截图时机:

# 一套完整的自动化截图流程
cellshot start ci-session --cols 80 --rows 24 -- bash
cellshot send ci-session 'text:./run-tests.sh'
cellshot send ci-session 'enter'
cellshot send ci-session 'text:echo "===DONE==="'
cellshot send ci-session 'enter'
cellshot wait ci-session '===DONE===' --timeout 30
cellshot save --format png --format json --out ci-result
cellshot stop ci-session
其他常用操作
# 查看会话当前屏幕内容
cellshot show demo
# 调整视口大小(实时生效)
cellshot resize demo --cols 60 --rows 15
# 查看会话日志
cellshot logs demo
# 停止会话
cellshot stop demo
踩坑汇总
实测中碰到几个具体问题:
send 指令必须有类型前缀
上面已经提到了。send 不支持裸文本字符串,每条输入都需要用 text: 或 ctrl-x 指定类型。这不算 bug,但初次使用时很容易忘记。
-- 分隔符不能漏
cellshot 子命令的参数和传给目标程序的参数之间必须用 -- 分隔:
# 正确
cellshot show --cols 80 -- my-app
# 错误:my-app 被 cellshot 当成自己的参数
cellshot show my-app --cols 80
-- 之前是 cellshot 的参数,之后是传给目标程序的参数。
视口设置在启动时决定
命名会话的 viewport 在 start 时指定(--cols/--rows),save 时不能重新设置。如果截完后发现尺寸不对,需要先 resize 再重新 save。不过一次性命令 show/save 可以直接在命令后加 --cols/--rows,不受这个限制。
SVG 字体依赖
生成的 SVG 默认使用 JetBrains Mono 字体。系统如果没有安装这套字体,浏览器会自动 fallback 到系统等宽字体,渲染效果在不同系统上可能有细微差异。
仓库改名
原仓库 kitlangton/cellshot 已更名为 kitlangton/terminal-control,CLI 命令也在逐步迁移到 termctrl。crates.io 上两个包同时存在但内容不同。本文使用的是 cellshot v0.7.0。
同类工具怎么选
| 维度 | cellshot | freeze | termshot | asciinema |
|---|---|---|---|---|
| 核心定位 | TUI 截图+自动化 | 输出转 SVG | 输出转图片 | 录制+回放 |
| 交互式截图 | ✅ start/send/wait | ❌ | ❌ | ❌ |
| TUI 应用支持 | ✅ 完整 PTY | ❌ 仅文本 | ❌ 仅管道 | 部分支持 |
| 输出格式 | SVG,PNG,TXT,JSON,ANSI | SVG,PNG | PNG,SVG | JSON,SVG |
| 结构化数据 | ✅ JSON(逐单元格) | ❌ | ❌ | JSON(时间戳流) |
| CI 自动化 | ✅ 原生 wait 命令 | 有限 | 有限 | 需额外脚本 |
| 安装方式 | cargo install | npm/pip | go install | pip |
按场景选:
- 对 TUI 应用做截图或自动化测试 → cellshot,它是目前唯一能处理运行中 TUI 程序截图的选择
- 日常命令输出转好看的 SVG → freeze,渲染效果更精美,社区更大
- 录制终端操作过程分享 → asciinema,生态最成熟
- 终端录制转 GIF/视频 → terminalizer
总结
cellshot 的差异化在于:它不只是一个截图工具,而是一个终端会话的 结构化采集框架。别的工具把终端输出转成一张图,它把输出拆成了每一个字符的位置、颜色、样式——这种数据精细度让它在以下场景里很有价值:
- 技术写作:生成风格统一的终端截图放进文章或 README
- TUI 测试:在 CI 里启动应用→发送命令→等待输出→截图→对比 JSON diff
- AI 数据采集:把结构化终端输出喂给模型做训练或推理
当然它也不是完美的。社区很小(~76 星),文档示例不多,recording/video 功能依赖 FFmpeg。如果你只是偶尔截个终端图放博客,freeze 可能更省事。但如果你需要在自动化流程里处理 TUI 界面,cellshot 是这个细分领域唯一的选择。