name: lvt description: > Inspect running Windows application UIs using the lvt (Live Visual Tree) CLI tool. Use this skill when you need to understand a Windows app's visual tree structure, capture annotated screenshots, detect UI frameworks, or find specific UI elements for verification or interaction planning.
Inspect Windows application UI with lvt
When to use
Use lvt whenever you need to understand the visual content or structure of a running Windows application. Common scenarios:
- UI verification — confirm that a UI change was applied correctly (e.g. a button label changed, a dialog appeared)
- Finding UI elements — locate a specific control, menu item, or text field in an app's visual tree
- Screenshot capture — take an annotated screenshot of an app with element IDs overlaid
- Framework detection — determine which UI frameworks an app uses (Win32, ComCtl, XAML, WinUI 3)
- Automated UI interaction planning — get element IDs and bounds to plan mouse clicks or keyboard input
Prerequisites
Before using lvt, ensure lvt.exe and lvt_tap.dll are available. If they are not already on PATH or in the current directory, download and extract them automatically:
# Download the latest release zip and extract to ~/.lvt
$lvtDir = "$env:USERPROFILE\.lvt"
if (-not (Test-Path "$lvtDir\lvt.exe")) {
New-Item -ItemType Directory -Path $lvtDir -Force | Out-Null
$release = Invoke-RestMethod "https://api.github.com/repos/asklar/lvt/releases/latest"
$asset = $release.assets | Where-Object { $_.name -like "lvt-*-x64.zip" } | Select-Object -First 1
$zip = "$env:TEMP\lvt.zip"
Invoke-WebRequest -Uri $asset.browser_download_url -OutFile $zip
Expand-Archive -Path $zip -DestinationPath $lvtDir -Force
Remove-Item $zip
}
# Run lvt from the install directory
& "$lvtDir\lvt.exe" --help
Once downloaded, lvt.exe persists in ~/.lvt/ and does not need to be downloaded again.
Usage
Target an application
You must specify exactly one target. Pick the most convenient option:
# By process name (most common — omit .exe extension if you like)
lvt --name notepad
# By window title substring
lvt --title "Untitled - Notepad"
# By PID
lvt --pid 1234
# By HWND (hex)
lvt --hwnd 0x1A0B3C
Get the visual tree
# JSON output (default) — best for programmatic parsing
lvt --name notepad
# XML output — more compact, easier to read
lvt --name notepad --format xml
# Write to a file instead of stdout
lvt --name notepad --output tree.json
Capture a screenshot
# Screenshot only (no tree output)
lvt --name notepad --screenshot out.png
# Screenshot + tree output together
lvt --name notepad --screenshot out.png --dump
Screenshots are annotated with element IDs (e0, e1, …) overlaid on each element, making it easy to correlate visual positions with tree nodes.
Scope to a subtree
When the full tree is too large, scope to a specific element:
# Only show element e5 and its descendants, up to 3 levels deep
lvt --name myapp --element e5 --depth 3
Detect frameworks only
lvt --name notepad --frameworks
Interpreting the output
Element IDs
Every element gets a stable ID like e0, e1, e2, etc., assigned in depth-first order. These IDs are consistent within a single invocation — use them to:
- Reference specific elements in follow-up commands (
--element e5) - Correlate screenshot annotations with tree nodes
- Identify click targets by combining element ID with its
bounds
Key element properties
| Property | Description |
|---|---|
id |
Stable element ID (e.g. e0) |
type |
Element type name (e.g. Window, Button, TextBlock) |
framework |
Which framework owns this element (win32, comctl, xaml, winui3) |
className |
Win32 window class name (Win32/ComCtl elements) |
text |
Visible text content or window title |
bounds |
Screen-relative bounding rectangle {x, y, width, height} |
children |
Nested child elements |
JSON example
{
"target": { "hwnd": "0x001A0B3C", "pid": 12345, "processName": "Notepad.exe" },
"frameworks": ["win32", "winui3"],
"root": {
"id": "e0",
"type": "Window",
"framework": "win32",
"className": "Notepad",
"text": "Untitled - Notepad",
"bounds": { "x": 100, "y": 100, "width": 800, "height": 600 },
"children": [ ... ]
}
}
XML example
<LiveVisualTree hwnd="0x001A0B3C" pid="12345" process="Notepad.exe" frameworks="win32,winui3">
<Window id="e0" framework="win32" className="Notepad" text="Untitled - Notepad" bounds="100,100,800,600">
<ContentPresenter id="e1" framework="winui3" bounds="108,140,784,552" />
</Window>
</LiveVisualTree>
Recommended workflow
- Start the target app if it isn't already running
- Run
lvt --name <app> --format xmlto get a quick overview of the UI tree - Take a screenshot with
lvt --name <app> --screenshot ui.pngto see the visual layout with element IDs - Drill into a subtree with
--element <id> --depth <n>if the tree is large - Use element IDs and bounds to plan any UI interactions (clicks, keyboard input)
Tips
- Use
--format xmlfor human-readable output and--format jsonfor programmatic parsing - If the tree is very large, use
--depthto limit traversal depth first, then drill deeper with--element - Element IDs change between invocations if the UI structure changes — always re-query before acting on stale IDs
- The tool requires no special permissions beyond being able to read the target process (same user session)
- For XAML/WinUI 3 apps, lvt injects a helper DLL into the target — this is safe and non-destructive but means
lvt_tap.dllmust be next tolvt.exe