Skip to main content

textual-capture

Sequenced screenshot capture for Textual TUI applications

PyPI - Version Python Version Tests Coverage License: MIT

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

  1. Generate TOML config based on user request
  2. Run with --dry-run to validate
  3. Execute capture to get screenshots + tooltips
  4. Analyze text files (.txt and _tooltips.txt)
  5. Report findings to user

Example: Claude Code Integration

User: "Check if my settings dialog has proper tooltips"

Claude:

  1. 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"
  1. Runs: textual-capture settings_check.toml
  2. Reads: settings_tooltips_tooltips.txt
  3. 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 = true for audits
  • Auto-sequence unnamed captures for exploration

For Testing

  • Use --dry-run during development
  • Use output_dir to 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_delay if your app renders quickly

Examples

See the examples/ directory for:

  • llm_review.toml - LLM-driven UI analysis template
  • keyboard_shortcuts.toml - Complex keyboard workflows
  • tooltip_audit.toml - Accessibility checking
  • documentation.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)

Source distribution for textual-capture 0.3.0
File Size Uploaded Provenance
textual_capture-0.3.0.tar.gz 23.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for textual-capture 0.3.0
File Interpreter ABI Platform
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page