TUI应用AI代理工具包

Spectatty是一个用于构建TUI应用的AI代理工具包,支持代理生成真实终端会话、交互式调试和实时会话共享。

  • by dayvidwang
  • TypeScript
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 dayvidwang/pty-mcp

使用说明

spectatty(spectate tty)

使用AI代理构建TUI应用程序的工具包。代理可以生成真实的终端会话,像人类一样与它们交互,对渲染的输出进行截图,并与您共享实时会话——这样他们就可以在构建UI时实际查看和调试UI,而不是从原始文本中猜测。

暴露为 MCP服务器 (和CLI),因此任何支持MCP的代理都可以开箱即用。

的问题

如今,每个人都在用人工智能构建终端应用程序(包括我自己),但很常见的情况是陷入以下循环:提示更改->手动测试UI->告诉代理出了什么问题->重复。代理人基本上是盲目的。

在构建web应用程序时,这不是问题——像这样的工具 剧作家 让代理在构建渲染的UI时检查并与之交互。TUI应用程序没有等效的工具。这就是为什么这很难。

哪些代理当前可以访问以查看终端输出:

tmux capture-pane -剥离所有颜色和样式,返回原始文本:

htop 开放代码

与此同时,从人类的角度来看,UI实际上是这样的:

htop 开放代码

spectatty为代理商提供了什么:

使用spectatty,代理实际上可以从人类的角度渲染和截图UI,包括间距、颜色、字体等。这允许它调试在纯文本视图中甚至不可见的UI错误(例如,您可能正在使用颜色来指示UI中的边界,或者组件之间的间距可能会微妙地偏离)。

htop 开放代码

演示

给代理人的提示:

我的CLI目前显示暗淡和不暗淡的文本,用于思考和非思考输出。请将此更改为使用蓝色表示思考,使用绿色表示文本。记录mp4前后的变化,显示变化的全部范围。

代理进行代码更改,然后自主记录MP4前后的结果。在下面的视频中,左侧终端是在Claude Code中工作的代理。右侧终端是代理的spectatty会话的实时视图,通过 spectatty attach --所有的输入都是由代理完成的,而不是用户。

https://github.com/user-attachments/assets/0a76b7f6-4b0a-4bf3-a650-4cd0517cc7a1

在MP4之前和之后,该试剂产生了:

之前 之后

spectatty解决的其他问题

  1. 生成一个真正的终端 -bash工具通常是带有管道stdio的子进程,而不是完整的PTY。依赖于终端大小、交替屏幕、鼠标输入或原始按键的TUI应用程序会在bash工具中崩溃。spectatty生成了一个由无头终端模拟器支持的真正的PTY,因此您可以测试全套终端行为。

  2. 在适当的抽象层次上进行交互 -编写原始转义序列是灵活的,但不可读。如果探员告诉你它跑了 \x1b[A\x1b[Acontinue\r 你不知道它做了什么。斯佩克蒂揭露了离散的类人行为(terminal_type, terminal_key, terminal_ctrl等等),因此代理痕迹是可读和可再现的。原始逃生通道仍可通过 terminal_write 作为最后的手段-如果代理必须使用它,这通常意味着操作集存在缺口或应用程序存在问题。

  3. 人类合作 -两部分。首先,用户如何看到代理正在做什么? spectatty attach <sessionId> 允许您在自己的终端中实时观看实时代理驱动的会话。 terminal_screenshot 接受a savePath 因此用户可以编写和查看PNG。第二,用户如何共享上下文?自己跳到附件中的会话 spectatty attach <sessionId>,再现一个错误,代理下次截图时会看到结果。

运作原理

bun-pty (spawn process in a real PTY)
  -> @xterm/headless (parse escape sequences into virtual screen buffer)
  -> @napi-rs/canvas (render cell grid to PNG)
  -> MCP server (expose as tools over stdio)

MCP服务器委托给拥有PTY会话的长时间运行的守护进程。程序写入的每个字节都经过 xterm.js 进程中,因此渲染的屏幕始终是最新的,无需轮询。每个会话的Unix套接字允许人类连接并实时观看。

工具

输入

工具 说明
terminal_type 键入文本,就像用户一样。添加 submit: true 之后按Enter键。优先选择 terminal_write 用于文本输入。
terminal_key 按指定键: enter, backspace, tab, escape, up/down/left/right, page_up/page_down, home/end, f1--f12.支持 times 重复。
terminal_ctrl 发送Ctrl+组合键: c (中断), d (EOF), z (暂停), l (清晰)等。
terminal_send_scroll 向上或向下发送滚动输入。
terminal_mouse 在特定列/行位置发送鼠标事件(单击、移动、向下、向上)。
terminal_write 发送带有转义序列的原始输入(\r, \x03, \e).最后手段-首选上述工具。

观察

工具 说明
terminal_screenshot 将当前屏幕捕获为PNG、纯文本或两者兼而有之。 savePath 将PNG写入磁盘。 viewportTop 在捕获之前滚动到特定行
terminal_wait_for 等待正则表达式模式出现在终端文本中。投票,直到匹配或超时。
terminal_list 列出所有活动会话及其维度和退出状态。

会话生命周期

工具 说明
terminal_spawn 生成一个新的终端会话。返回a sessionId 以及连接插座的路径。
terminal_resize 将会话调整为新尺寸。
terminal_kill 终止一个会话并清理所有资源。

录制

工具 说明
terminal_record_start 开始将终端输出记录为 asciicast v2 .cast 文件。
terminal_record_stop 停止录制。保存 .cast 文件并自动写入sidecar .tape.json 沿着它(相同的路径, .cast 扩展名替换为 .tape.json).
terminal_to_gif 转换a .cast 录制为动态GIF(需要 agg).
terminal_to_mp4 转换a .cast 录制为MP4视频(需要 ffmpeg).
terminal_export_tape 将会话的交互日志导出为可回放 .tape.json 文件。
terminal_replay_tape 重播a .tape.json 并返回实时会话ID

命令行界面

spectatty <subcommand>
子命令 描述
mcp 在stdio上启动MCP服务器
server start/stop/status 管理后台守护进程
ctl <subcommand> 控制终端会话(镜像所有MCP工具-见下文)
attach <sessionId> 将您的终端连接到实时会话。用途 Ctrl+A 作为控制命令的前缀键-按Ctrl+a,然后: d 为了分离, l 获取代理锁(阻止代理写入,以便您可以自由键入), u 为了解锁, s 在锁定状态下进行屏幕截图。按Ctrl+a两次发送文字Ctrl+a。如果你卡住了,按Ctrl+A d 总是退出。
tail <file.cast> 实时跟踪正在编写的asciicast录音
to-gif <input.cast> <output.gif> 将录制转换为动态GIF(需要 agg)
to-mp4 <input.cast> <output.mp4> 将录音转换为MP4(需要 ffmpeg)
replay-cast <file.cast> 播放a .cast 当前终端中具有原始定时的文件
replay-tape <file.tape.json> 重放磁带文件。产生a .cast 默认情况下; --live 回放到当前终端。

spectatty ctl 将每个MCP工具作为脚本和调试的子命令公开: spawn, list, type, key, ctrl, write, screenshot, resize, kill, scroll, mouse, wait-for, record-start, record-stop, export-tape, replay-tape.

安装

需要 包子 (v1.0+)。这 to-gif 和 to-mp4 命令还需要 agg 和 ffmpeg 分别。

bun install -g spectatty
spectatty mcp

用法

MCP客户端配置

添加到您的MCP客户端配置中(例如Claude Desktop、Cursor等):

{
  "mcpServers": {
    "spectatty": {
      "command": "spectatty",
      "args": ["mcp"]
    }
  }
}

注: 如果 spectatty 如果不在MCP客户端的PATH中,请使用完整路径(例如。 ~/.bun/bin/spectatty).

发展

git clone https://github.com/dayvidwang/spectatty
cd spectatty
bun install
bun run src/cli.ts mcp

交互示例

1. terminal_spawn(cols: 220, rows: 50)                        -> { sessionId: "term-1", attachSocket: "/tmp/spectatty-*.sock" }
2. terminal_type(sessionId: "term-1", text: "vim file.txt", submit: true)
3. terminal_wait_for(sessionId: "term-1", pattern: "vim")
4. terminal_screenshot(sessionId: "term-1")                   -> PNG + text of vim loaded
5. terminal_key(sessionId: "term-1", key: "i")               -> enter insert mode
6. terminal_type(sessionId: "term-1", text: "hello world")
7. terminal_key(sessionId: "term-1", key: "escape")
8. terminal_type(sessionId: "term-1", text: ":wq", submit: true)
9. terminal_screenshot(sessionId: "term-1")                   -> confirm file saved
10. terminal_kill(sessionId: "term-1")

与此同时,人类可以奔跑 spectatty attach term-1 观看会议直播。

堆栈

层 包
PTY 包子pty
终端仿真 @xterm/无头
PNG渲染 @纳帕/帆布
HTML序列化 @xterm/addon序列化
MCP服务器 @模型上下文协议/sdk

设计说明

为什么不组合tmux+asciinema?

显而易见的替代方案是使用现有的工具:tmux用于会话管理,asciinema用于录制,VHS作为脚本交互的参考。

核心问题: tmux capture-pane 仅为快照(您轮询它)。 tmux pipe-pane 流式传输原始PTY字节,但要从这些字节中生成屏幕截图,您仍然需要自己通过终端模拟器解析它们。无论如何,您最终都会重新实现渲染管道,在中间会有一个额外的子流程跃点。

所需的基本属性是 渲染状态始终为最新,零轮询。这需要直接拥有PTY,这样xterm.js就可以在每个字节到达时处理它。

家用录像系统 是最接近的精神前身——它驱动一个无头终端并呈现输出。不同之处在于,VHS是一个批处理工具(脚本输入->视频输出),而spectatty是交互式的(代理实时驱动会话,在任意点截图,等待模式,无限期保持会话活动)。

许可证

麻省理工学院