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
Metadata
Release files for textual-capture 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| textual_capture-0.3.0.tar.gz | 23.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| textual_capture-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.6 kB
Release files / textual_capture-0.3.0.tar.gz
| Download URL | textual_capture-0.3.0.tar.gz |
|---|---|
| Size | 23.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5ef7050e60ef0d390ef0d53c0a6e4775b71ce10d922e9606ac293bf8b332f1ff
|
|
BLAKE2b-256 checksum How to use checksums |
eda236d1580dd0e13b0445afdea80cba1b61d1268eababe321993090f832b8e5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
pdm/2.26.2 CPython/3.12.12 Linux/5.15.167.4-microsoft-standard-WSL2
|
Release files / textual_capture-0.3.0-py3-none-any.whl
| Download URL | textual_capture-0.3.0-py3-none-any.whl |
|---|---|
| Size | 12.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8ce840280bb7aa29aebd4a624cd1f0422399c218356b56fb78157b5235d645cc
|
|
BLAKE2b-256 checksum How to use checksums |
c7a5426936e2e3b75a3210994146a496e16bca4857ad29023eeb90dd3f0f8aaa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
pdm/2.26.2 CPython/3.12.12 Linux/5.15.167.4-microsoft-standard-WSL2
|
Security for textual-capture 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.