TUI ツールを Vibe coding で作ることが最近多く、その際の動作確認として tuistory というツールを使っていて便利だったので紹介する。
tuistory はどんなツールか
簡単に言うと Terminal 版の Playwright。
playwright-cli や agent-browser みたいなインターフェイスで、仮想ターミナルの起動や操作、内容の取得が出来る。
$ tuistory launch "nvim" -s nvim --cols 80 --rows 40
Session "nvim" started
$ tuistory -s nvim snapshot --trim
buffers
__
___ ___ ___ __ __ /\_\ ___ ___
/ _ `\ / __`\ / __`\/\ \/\ \\/\ \ / __` __`\
/\ \/\ \/\ __//\ \_\ \ \ \_/ |\ \ \/\ \/\ \/\ \
\ \_\ \_\ \____\ \____/\ \___/ \ \_\ \_\ \_\ \_\
\/_/\/_/\/____/\/___/ \/__/ \/_/\/_/\/_/\/_/
[e] New file •
MRU /Users/tomoya/.ghq/github.com/tomoasleep/navigator.nvim
[0] .envrc
[1] AGENTS.md
[2] denops/navigator/action.ts
[3] denops/navigator/ui.ts
[4] .gitignore
MRU
[10] ~/.ghq/github.com/tomoasleep/dotfiles/config/nvim/lua/lsp.lua
[11] ~/.ghq/github.com/tomoasleep/dotfiles/config/nvim/lua/git-gem.lua
[12] ~/.ghq/github.com/tomoasleep/dotfiles/config/nvim/lua/config/init.lu
[13] ~/.ghq/github.com/tomoasleep/dotfiles/config/nvim/lua/config/lsp-col
[14] ~/.ghq/github.com/tomoasleep/dotfiles/config/nvim/lua/config/airline
[15] ~/.ghq/github.com/tomoasleep/dotfiles/config/nvim/lua/start.lua
[16] ~/.ghq/github.com/tomoasleep/dotfiles/config/nvim/lua/yoda.lua
[17] ~/.ghq/github.com/tomoasleep/dotfiles/config/nvim/lua/plugins.lua
[18] ~/.ghq/github.com/tomoasleep/dotfiles/config/nvim/lua/core.lua
[19] ~/.ghq/github.com/tomoasleep/dotfiles/config/nvim/init.vim
[q] Quit
~
~
~
~
NORMAL [Scratch][-] alp… [unix] 30% ㏑:10/33≡ ℅ :5
$ tuistory -s nvim press e i
OK
$ tuistory -s nvim type 'Hello, world!'
OK
$ tuistory -s nvim snapshot --trim
[No Name]+ buffers
1 Hello, world! •
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
INSERT [No Name][+] [unix] 100% ㏑: 1/1≡ ℅ :14
-- INSERT -
Node.js のインターフェイスも提供されている
CLI 以外にも Node.js 用のインターフェイスも用意されている。(※ Bun とかでも動く)
import { launchTerminal } from 'tuistory' const session = await launchTerminal({ command: 'my-cli', args: ['--flag'], cols: 120, rows: 36, cwd: '/path/to/dir', env: { MY_VAR: 'value' }, }) // observe const text = await session.text() // full terminal text const text = await session.text({ trimEnd: true }) // trimmed const bold = await session.text({ only: { bold: true } }) // style filter // act await session.type('hello world') // type character by character await session.press('enter') // single key await session.press(['ctrl', 'c']) // key chord await session.click('Submit') // click on text // wait await session.waitForText('Ready', { timeout: 10000 }) await session.waitForText(/Loading\.\.\./, { timeout: 5000 }) // screenshot to image const data = session.getTerminalData() const { renderTerminalToImage } = await import('ghostty-opentui/image') const image = await renderTerminalToImage(data, { format: 'jpeg', devicePixelRatio: 2 }) // cleanup session.close()from: https://github.com/remorses/tuistory/blob/main/SKILL.md#jsts-api-library
こちらは実際に E2E を書くのに有効。自分もこれを使って実際に TUI ツールのテストなどを書いている。
Agent Skills も提供されている
最近のツールらしく、 Agent Skills (SKILL.md) もきちんと用意されている。入れておくと AI に Vibe Coding させるときの動作確認に便利。