| name | tui-test |
| description | Test TUI applications using tu (terminal-use). Launch apps in virtual terminals, take screenshots, type text, press keys, wait for conditions, and verify output. Use for smoke testing terminal UIs, interactive CLIs, and TUI apps. Trigger on phrases like "test the TUI", "terminal test", "tu test", "test in terminal", "smoke test the editor", "verify the UI". |
TUI Testing with tu (terminal-use)
Use tu CLI to test TUI applications in headless virtual terminals. Run all commands via the Bash tool.
Core Workflow
1. Build the app
2. Launch in virtual terminal with `tu run`
3. Wait for UI to load with `tu wait`
4. Interact: type text, press keys
5. Screenshot and verify output
6. Clean up with `tu kill`
Commands
tu run --name <id> --size 120x40 -- <command> [args]
tu kill --name <id>
tu list
tu status --name <id>
tu screenshot --name <id>
tu type --name <id> "text"
tu press --name <id> <key> [key...]
tu paste --name <id> "text"
tu wait --name <id> --text "pattern" --timeout 5000
tu cursor --name <id>
tu scrollback --name <id>
tu resize --name <id> --size 80x24
Key Names for tu press
ctrl+y ctrl+p ctrl+j ctrl+k ctrl+c ctrl+d
up down left right home end pageup pagedown
enter escape tab backspace space delete
f1 f2 f3 ...
tu press --name test ctrl+y enter escape
Reading Screenshots
Screenshots return JSON. Extract the content field:
tu screenshot --name <id> | python3 -c "import sys,json; print(json.load(sys.stdin)['content'])"
tu screenshot --name <id> | python3 -c "
import sys,json
c = json.load(sys.stdin)['content']
for line in c.split('\n')[:30]:
print(line[62:])
"
Environment Variables
Pass env vars to the subprocess with --env:
source ~/.secrets/env 2>/dev/null
tu run --name test --env "GROQ_API_KEY=$GROQ_API_KEY" -- ./app
Waiting for State
Always wait for the app to be ready before interacting:
tu wait --name test --text "EDITOR" --timeout 5000
tu wait --name test --text "ready" --timeout 5000 && tu type --name test "hello"
tu wait --name test --text "AI:" --timeout 20000
Example: Testing a TUI Editor
make editor.build
cat > /tmp/test-article.md << 'EOF'
---
title: Test Article
status: draft
---
Some content here.
EOF
source ~/.secrets/env 2>/dev/null
tu run --name editor-test --size 120x40 \
--env "GROQ_API_KEY=$GROQ_API_KEY" \
-- ./target/release/devtui /tmp/test-article.md
tu wait --name editor-test --text "EDITOR" --timeout 5000
tu screenshot --name editor-test | python3 -c "import sys,json; print(json.load(sys.stdin)['content'])"
tu press --name editor-test ctrl+y
tu wait --name editor-test --text "Ask" --timeout 3000
tu type --name editor-test "what is this article about?"
tu press --name editor-test enter
tu wait --name editor-test --text "AI:" --timeout 20000
tu screenshot --name editor-test | python3 -c "import sys,json; print(json.load(sys.stdin)['content'])"
tu kill --name editor-test
Example: Testing vim Keybindings
tu run --name vim-test --size 80x24 -- vim /tmp/test.txt
tu wait --name vim-test --text "~" --timeout 3000
tu press --name vim-test i
tu type --name vim-test "Hello, world!"
tu press --name vim-test escape
tu type --name vim-test ":wq"
tu press --name vim-test enter
cat /tmp/test.txt
Tips
- Always
tu wait before interacting. The app needs time to render.
- Use
--timeout generously. LLM calls can take 10-20 seconds.
- Kill sessions when done. Leftover sessions consume resources.
- Use
tu list to check for orphaned sessions.
- Sleep is not allowed. Use
tu wait --text instead of sleep.
- Split pane apps: Parse specific columns from the screenshot to read each pane independently.
- Debug with scrollback:
tu scrollback --name <id> shows the full buffer history, useful for finding text that scrolled off screen.