Sequenced screen capture for Textual TUI applications. Enables AI assistants to review and test TUIs.
Project description
textual-capture
Sequenced screenshot capture for Textual TUI applications
textual-capture automates UI interactions in your Textual apps and captures screenshots at key moments. Define sequences of key presses, clicks, and delays in simple TOML files.
Perfect for:
- 🤖 LLM-driven TUI review and testing (AI can generate configs and analyze output)
- 📸 Documentation screenshots (consistent, reproducible captures)
- 🎬 Demo creation (step-through your app automatically)
- ✅ Visual regression prep (capture baseline states)
Quick Start
Installation
pip install textual-capture
Your First Capture
Create demo.toml:
app_module = "my_app"
app_class = "MyApp"
[[step]]
type = "press"
keys = ["tab", "tab", "enter"]
[[step]]
type = "capture"
output = "my_screenshot"
Run it:
textual-capture demo.toml
This creates:
my_screenshot.svg(visual)my_screenshot.txt(text representation)my_screenshot_tooltips.txt(widget tooltips)
Core Features
Multi-Step Sequences
Chain actions together:
[[step]]
type = "press"
keys = ["ctrl+n"] # Open new dialog
[[step]]
type = "delay"
seconds = 0.5 # Wait for animation
[[step]]
type = "click"
label = "Submit" # Click button
[[step]]
type = "capture" # Take screenshot
Auto-Sequencing
Omit output names for automatic numbering:
[[step]]
type = "capture"
# Creates: capture_001.svg, capture_001.txt, capture_001_tooltips.txt
[[step]]
type = "press"
keys = ["down"]
[[step]]
type = "capture"
# Creates: capture_002.svg, capture_002.txt, capture_002_tooltips.txt
Keyboard Shortcuts
Full modifier support:
[[step]]
type = "press"
keys = ["ctrl+s", "ctrl+shift+p", "alt+f4"]
Smart Tooltips
Tooltips captured automatically with every screenshot (opt-out if not needed):
# Enabled by default - just works!
[[step]]
type = "capture"
# Disable if not needed
[[step]]
type = "capture"
capture_tooltips = false
# Capture only tooltips (fast!)
[[step]]
type = "capture"
formats = [] # Skip SVG/TXT
capture_tooltips = true
Organized Output
output_dir = "./screenshots" # All files go here
formats = ["svg"] # Only generate SVG (faster)
Validation
Check your config before running:
textual-capture demo.toml --dry-run
Shows planned steps, validates imports, catches errors.
Common Use Cases
Documentation Screenshots
output_dir = "./docs/screenshots"
formats = ["svg"]
[[step]]
type = "capture"
output = "main_menu"
[[step]]
type = "press"
keys = ["tab", "enter"]
[[step]]
type = "capture"
output = "settings_dialog"
LLM UI Analysis
output_dir = "./llm_review"
formats = ["txt"] # Text for AI analysis
capture_tooltips = true # Include tooltip data
[[step]]
type = "capture"
# AI can read the text files and tooltips
Then: cat llm_review/*.txt | claude analyze-ui
Accessibility Audit
formats = [] # Skip visuals
capture_tooltips = true
tooltip_include_empty = true # Show missing tooltips
[[step]]
type = "capture"
output = "tooltip_audit"
Review tooltip_audit_tooltips.txt for widgets with (no tooltip).
Keyboard Workflow Testing
[[step]]
type = "press"
keys = ["ctrl+o"] # Open file
[[step]]
type = "delay"
seconds = 0.5
[[step]]
type = "press"
keys = ["t", "e", "s", "t"]
pause_between = 0.1 # Slow typing
[[step]]
type = "press"
keys = ["enter"]
[[step]]
type = "capture"
output = "file_opened"
Configuration Reference
Required Fields
app_module = "path.to.module" # Python module with your app
app_class = "MyApp" # Textual App class name
Global Settings
# Screen size
screen_width = 100 # Default: 80
screen_height = 40 # Default: 40
# Timing
initial_delay = 1.0 # Wait before first action (default: 1.0)
# Behavior
scroll_to_top = true # Press "home" at start (default: true)
module_path = "." # Add to sys.path (optional)
# Output
output_dir = "./screenshots" # Where to save files (default: ".")
formats = ["svg", "txt"] # Formats to generate (default: both)
# Tooltips
capture_tooltips = true # Capture tooltips (default: true)
widget_selector = "*" # CSS selector (default: all widgets)
tooltip_include_empty = false # Show widgets without tooltips (default: false)
Action Types
Press Keys
[[step]]
type = "press"
keys = ["tab", "ctrl+s", "enter"] # List syntax (preferred)
pause_between = 0.2 # Seconds between keys (default: 0.2)
# Legacy comma-separated syntax still works
key = "tab,ctrl+s,enter"
Supported modifiers: ctrl+, shift+, alt+, meta+
Click Button
[[step]]
type = "click"
label = "Submit" # Button text (spaces removed for ID)
Delay
[[step]]
type = "delay"
seconds = 1.5 # Seconds to wait
Capture Screenshot
[[step]]
type = "capture"
output = "my_state" # Optional: custom name
formats = ["svg", "txt"] # Optional: override global
capture_tooltips = true # Optional: override global
widget_selector = "Button" # Optional: custom selector
tooltip_include_empty = false # Optional: override global
If output is omitted, auto-generates capture_001, capture_002, etc.
Advanced Features
Selective Formats
Generate only what you need:
# Global default
formats = ["svg"] # Only SVG (faster)
[[step]]
type = "capture"
output = "visual_only"
# Uses global: svg only
[[step]]
type = "capture"
output = "complete"
formats = ["svg", "txt"] # Override: both formats
Valid formats: svg, txt
Tooltip Configuration
Fine-tune tooltip capture:
# Capture all widgets with tooltips
[[step]]
type = "capture"
output = "all_tooltips"
# Capture only buttons
[[step]]
type = "capture"
output = "button_tooltips"
widget_selector = "Button"
# Include widgets without tooltips
[[step]]
type = "capture"
output = "complete_audit"
tooltip_include_empty = true
Tooltip file format:
# Tooltips captured from: my_state
# Selector: *
# Timestamp: 2025-12-20 10:30:45
Button#run: Start the selected command
Button#cancel: Abort operation (Esc)
Input#search: Search for items
Label#status: (no tooltip)
Tooltip-Only Captures
Skip expensive rendering for fast metadata extraction:
formats = [] # No SVG or TXT
capture_tooltips = true
[[step]]
type = "capture"
output = "metadata_only"
# Creates only: metadata_only_tooltips.txt
Use cases:
- Fast UI audits
- Tooltip validation
- LLM analysis pipelines
- Documentation generation
CLI Usage
# Run capture sequence
textual-capture config.toml
# Show all actions as they execute
textual-capture config.toml --verbose
# Suppress all output except errors
textual-capture config.toml --quiet
# Validate config without running
textual-capture config.toml --dry-run
Dry-run output example:
Configuration: demo.toml
App: my_app.MyApp
Screen: 80x40
Output Directory: ./screenshots
Default Formats: svg, txt
Capture Tooltips: True
Tooltip Selector: *
Planned Steps (4 total):
1. press: keys=['tab', 'tab', 'enter']
2. delay: 0.5s
3. capture: output="my_state", formats=[svg, txt], tooltips=*
4. press: keys=['ctrl+q']
Validating module import...
✓ Successfully imported MyApp from my_app
✓ Configuration valid and ready to execute
🤖 LLM-Driven Workflows
Primary Use Case: AI assistants can generate configs, run captures, and analyze output.
How LLMs Use textual-capture
- Generate TOML config based on user request
- Run with
--dry-runto validate - Execute capture to get screenshots + tooltips
- Analyze text files (
.txtand_tooltips.txt) - Report findings to user
Example: Claude Code Integration
User: "Check if my settings dialog has proper tooltips"
Claude:
- Creates
settings_check.toml:
app_module = "your_app"
app_class = "YourApp"
formats = []
capture_tooltips = true
tooltip_include_empty = true
[[step]]
type = "press"
keys = ["ctrl+comma"] # Open settings
[[step]]
type = "capture"
output = "settings_tooltips"
- Runs:
textual-capture settings_check.toml - Reads:
settings_tooltips_tooltips.txt - Reports: "Found 3 buttons without tooltips: Button#apply, Button#reset, Button#advanced"
Pro tip: Copy LLM_INSTRUCTIONS.md into your project's CLAUDE.md file to give Claude Code full context.
Comparison with Other Tools
| Feature | textual-dev screenshot | pytest-textual-snapshot | textual-capture |
|---|---|---|---|
| Single capture | Yes | Yes | Yes |
| Multi-step sequences | No | No | ✅ Yes |
| Keyboard shortcuts | No | No | ✅ Yes |
| Button clicks | No | No | ✅ Yes |
| Delays/timing | No | No | ✅ Yes |
| Auto-sequencing | No | No | ✅ Yes |
| Tooltip capture | No | No | ✅ Yes |
| Dry-run validation | No | No | ✅ Yes |
| Organized output | No | No | ✅ Yes |
| LLM-friendly | No | No | ✅ Yes |
| Human-readable config | No | No | ✅ Yes |
Tips & Best Practices
For Documentation
- Use
formats = ["svg"]for faster generation - Use descriptive output names:
output = "main_menu" - Keep sequences focused on one feature/flow
For LLM Analysis
- Use
formats = ["txt"]+capture_tooltips = true - Use
tooltip_include_empty = truefor audits - Auto-sequence unnamed captures for exploration
For Testing
- Use
--dry-runduring development - Use
output_dirto keep project root clean - Validate configs in CI with dry-run
For Performance
- Use selective formats:
formats = ["svg"]or["txt"] - Use
formats = []for tooltip-only captures - Reduce
initial_delayif your app renders quickly
Examples
See the examples/ directory for:
llm_review.toml- LLM-driven UI analysis templatekeyboard_shortcuts.toml- Complex keyboard workflowstooltip_audit.toml- Accessibility checkingdocumentation.toml- Multi-capture documentation
Contributing
Contributions welcome! See CONTRIBUTING.md (coming soon).
Issues and feature requests: https://github.com/eyecantell/textual-capture/issues
License
MIT © 2025 Paul Neumann
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file textual_capture-0.3.0.tar.gz.
File metadata
- Download URL: textual_capture-0.3.0.tar.gz
- Upload date:
- Size: 23.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: pdm/2.26.2 CPython/3.12.12 Linux/5.15.167.4-microsoft-standard-WSL2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ef7050e60ef0d390ef0d53c0a6e4775b71ce10d922e9606ac293bf8b332f1ff
|
|
| MD5 |
99d29afb7f5ec3d7fa1d076369c343a2
|
|
| BLAKE2b-256 |
eda236d1580dd0e13b0445afdea80cba1b61d1268eababe321993090f832b8e5
|
File details
Details for the file textual_capture-0.3.0-py3-none-any.whl.
File metadata
- Download URL: textual_capture-0.3.0-py3-none-any.whl
- Upload date:
- Size: 12.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: pdm/2.26.2 CPython/3.12.12 Linux/5.15.167.4-microsoft-standard-WSL2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ce840280bb7aa29aebd4a624cd1f0422399c218356b56fb78157b5235d645cc
|
|
| MD5 |
2fcf0cbd711200961affa578d04dc557
|
|
| BLAKE2b-256 |
c7a5426936e2e3b75a3210994146a496e16bca4857ad29023eeb90dd3f0f8aaa
|