Skip to main content

Winlenium is a CLI tool for automated testing of Windows programs via the MS UI Automation framework.

Project description

Winlenium

A command-line tool for automated testing of Windows applications using the Microsoft UI Automation framework. Winlenium exposes a set of shell commands (click, type, key, inspect, wait, and others) that locate UI elements by selector and perform actions on them. Designed for CI/CD pipelines, test scripts, and any workflow where you need to drive a Windows GUI without writing UIA code.

Winlenium is published on PyPI, so you can install it directly with uv or pip, or run it on demand with uvx.

Table of Contents

Installation

Requirements

  • Windows 10 or 11 with a desktop session (UI Automation requires an active desktop)
  • Python 3.12+
  • uv (recommended package manager)

Install Python and uv with winget:

winget install Python.Python.3.12
winget install astral-sh.uv

Verify both are available:

python --version
uv --version

Install with uv

# Install the CLI globally in uv's tool directory
uv tool install winlenium

# Verify installation
winlenium --version

Install with pip

pip install winlenium

Run without installing

# Run the published CLI directly from PyPI
uvx winlenium --version

After installation the winlenium command is available in your shell. If you want to work from source, run tests, or contribute changes, see DEVELOPMENT.md.

Quick Start

Launch Notepad, type some text, and save the file:

# 1. Start Notepad and wait for its window
winlenium run notepad.exe

# 2. Type text into the editor
winlenium type --text "Hello from Winlenium" --window-name "Untitled - Notepad"

# 3. Save the file with Ctrl+S
winlenium key --keys "Ctrl+S" --window-name "Untitled - Notepad"

# 4. Wait for the Save As dialog
winlenium wait --name "Save As" --timeout 5000

# 5. Type a filename and press Enter
winlenium type --text "demo.txt" --window-name "Save As"
winlenium key --keys "Enter" --window-name "Save As"

Commands

Process and Window Management

Command Description
run Launch an executable and wait for its main window
close Close a window (WindowPattern) or terminate a process
focus Bring a window to the foreground and set input focus
window Manage window state (minimize, maximize, restore)
list-windows List all top-level windows, optionally filtered by PID
list-processes List running processes that have visible windows

Element Interaction

Command Description
click Click a UI element (--button left|right|middle, --count 1|2)
type Send text input to an element or the focused control
key Send a key combination (e.g. Ctrl+S, Alt+F4)
move Mouse move, hover, or drag-and-drop
scroll Scroll within a scrollable element
toggle Toggle a checkbox or toggle button
select Select an item in a list, combo box, or tab control
expand Expand a tree node, menu, or dropdown
collapse Collapse a tree node, menu, or dropdown
set-value Set an element's value via ValuePattern

Inspection and Queries

Command Description
inspect Print the accessibility tree of a window or element
get-value Read an element's value (ValuePattern)
get-property Read a specific UIA property (e.g. IsEnabled)
wait Wait for an element to appear or disappear
screenshot Capture a screenshot of a window or element
clipboard Get or set clipboard content (get / set)
tray Interact with system tray icons (list, click, inspect)

Run winlenium <command> --help for the full list of options for any command.

Element Selectors

Most commands accept the following options to locate a UI element:

Option Description
--name Match element by its Name property
--automationid Match element by AutomationId
--controltype Match element by ControlType (e.g. Button, Edit)
--pid Scope the search to a process ID
--index Select the Nth match (0-based) when multiple elements match

Selectors can be combined to narrow the search:

winlenium click --name "OK" --controltype Button --window-name "My App"

At least one selector (--name, --automationid, --controltype, --pid, or --path) must be provided.

Path Selector

The --path option provides a powerful way to locate elements by their position in the UI tree using a slash-separated path of selectors:

# Direct child traversal (/ means direct child)
winlenium click --path "Pane/Button[@Name='OK']" --window-name "My App"

# Descendant search (// searches at any depth)
winlenium click --path "Pane//Button[@Name='OK']" --window-name "My App"

# Control type only
winlenium inspect --path "Window/Pane/Button" --window-name "My App"

# Index-based disambiguation (0-based)
winlenium click --path "Pane/Button[1]" --window-name "My App"

# AutomationId
winlenium click --path "Pane[@AutomationId='nav']/Button[@Name='Submit']" --window-name "My App"

Segment syntax: ControlType[@Attr='value'][index]

Component Example Description
Control type Button Matches elements of this control type
[@Name='…'] [@Name='OK'] Matches by Name property
[@AutomationId='…'] [@AutomationId='btn1'] Matches by AutomationId
[N] [2] Zero-based index for disambiguation

Path separators:

  • / — direct child (depth 1)
  • // — descendant at any depth

--path is mutually exclusive with --name, --automationid, --controltype, and --index. The --pid and --window-* options can still be used with --path.

Window Selectors

Commands that interact with elements inside a window accept window selector options to first locate the correct window:

Option Description
--window-name Match window by Name property
--window-automationid Match window by AutomationId
--window-controltype Match window by ControlType
--window-pid Match window by process ID
--window-index Select the Nth matching window (0-based)
--window-handle Match window by native handle (hex 0x1A2B or decimal)

Combine window and element selectors for precise targeting:

winlenium click --name "OK" --controltype Button --window-pid 1234 --window-index 0

Usage Examples

Discover running applications

# Find all processes with "notepad" in the name
winlenium list-processes --name notepad --format json

# List all windows belonging to a process
winlenium list-windows --pid 12345

Inspect the accessibility tree

# Show the first two levels of a window's element tree
winlenium inspect --window-name "Untitled - Notepad" --depth 2

# Inspect a specific element
winlenium inspect --name "Text Editor" --window-name "Untitled - Notepad"

Interact with UI controls

# Click a button
winlenium click --name "Submit" --controltype Button --window-name "My App"

# Toggle a checkbox
winlenium toggle --name "Enable feature" --window-name "Settings"

# Select a tab or list item
winlenium select --name "Advanced" --window-name "Settings"

# Expand a tree node
winlenium expand --name "Documents" --window-name "Explorer"

# Set a slider or text field value directly (no keystrokes)
winlenium set-value --name "Volume" --value "75" --window-name "Settings"

Read element state

# Check if a button is enabled
winlenium get-property --name "Submit" --property IsEnabled --window-name "My App"

# Read the current value of a text field
winlenium get-value --name "Username" --window-name "Login"

Mouse actions

# Hover over an element
winlenium move --name "Help" --hover --window-name "My App"

# Drag and drop
winlenium move --name "DragItem" --to-name "DropTarget" --window-name "My App"

# Scroll down three increments
winlenium scroll --name "ItemList" --direction down --amount 3 --window-name "My App"

Screenshots

# Capture a window screenshot to a file
winlenium screenshot --window-name "My App" --output screenshot.png

# Capture a specific element
winlenium screenshot --name "Chart" --window-name "Dashboard" --output chart.png

Window management

# Bring a window to the foreground
winlenium focus --window-name "Notepad"

# Minimize / maximize / restore
winlenium window minimize --window-name "Notepad"
winlenium window maximize --window-pid 12345
winlenium window restore --window-handle 0x1A2B3C

# Close a window gracefully
winlenium close --window-name "Save As"

# Force-terminate a process
winlenium close --pid 12345 --force

Clipboard

winlenium clipboard set --text "Copied text"
winlenium clipboard get

Tray icons

# List all tray icons
winlenium tray list --format json

# List only visible tray icons
winlenium tray list --area visible

# Click a tray icon by name substring
winlenium tray click --name "Volume"

# Right-click a tray icon to open its context menu
winlenium tray click --name "Volume" --button right

# Inspect a tray icon's accessibility tree
winlenium tray inspect --name "Volume" --format json

Context menus

# Right-click an element to open its context menu
winlenium click --name "TextArea" --window-name "Notepad" --button right

# Click a menu item in the popup (WinUI apps keep menus inside the window)
winlenium click --name "Undo" --controltype MenuItem --window-pid 12345

# Double-click an element
winlenium click --name "Word" --button left --count 2

Modal dialogs

# Trigger a dialog (e.g. Save As in Notepad)
winlenium key --keys "Ctrl+Shift+S" --window-name "Notepad"

# Wait for the dialog to appear inside the parent window
winlenium wait --name "Save as" --controltype Window \
  --window-handle 0x4303e4 --timeout 5000

# Discover the dialog handle via inspect (look for is_modal=true)
winlenium inspect --window-handle 0x4303e4 --format json --depth 1

# Interact with controls inside the dialog, scoped by its handle
winlenium type --name "File name:" --text "demo.txt" --window-handle 0x3b03e2
winlenium click --name "Save" --window-handle 0x3b03e2

# Wait for the dialog to disappear
winlenium wait --name "Save as" --controltype Window \
  --window-handle 0x4303e4 --until gone --timeout 5000

Wait for elements

# Wait for an element to appear (default)
winlenium wait --name "Success" --window-name "My App" --timeout 10000

# Wait for a dialog to disappear
winlenium wait --name "Loading" --until gone --timeout 15000

Output Formats

Commands that produce output accept --format text (default) or --format json:

# Human-readable text output
winlenium inspect --window-name "Notepad"

# Machine-readable JSON for scripting
winlenium inspect --window-name "Notepad" --format json

Exit Codes

Code Meaning
0 Success
1 Error (element not found, invalid selector, etc.)
2 Timeout (element did not appear within the limit)

Agentic Usage Examples

The original idea behind Winlenium was to let AI agents automate tedious manual testing on Windows. Instead of writing test scripts by hand, you describe a scenario in natural language and let the agent drive the GUI through the CLI.

The examples below use Codex as the agent, but any AI agent that can call a CLI will work the same way.

See the examples directory for full reports generated by these scenarios.

In every scenario the first step is the same: the agent learns the available commands by running uvx winlenium --help and uvx winlenium <command> --help, and then carries out the task.

Application Walkthrough

Ask the agent to navigate through an application and produce a Markdown document that describes every screen, lists available options, and includes screenshots.

Example prompt:

Learn what Winlenium can do by running `uvx winlenium --help` and
`uvx winlenium <command> --help`. Then launch [Your App], navigate through
every screen and dialog, and build a Markdown document that:

- Lists each screen with a description of available options and controls.
- Includes a full-window screenshot of every screen.
- Includes close-up screenshots of individual noteworthy elements.

Save the document as walkthrough.md and screenshots in a screenshots/ folder.

Do not automate the process, just go manually and use winlenium to interact with the app.

Run it with Codex:

codex exec --yolo "Learn what Winlenium can do by running 'uvx winlenium --help' and 'uvx winlenium <command> --help'. Then launch [Your App], navigate through every screen and dialog, and build a Markdown document that lists each screen with a description of available options and controls, includes a full-window screenshot of every screen, and close-up screenshots of noteworthy elements. Save the document as walkthrough.md and screenshots in a screenshots/ folder. Do not automate the process, just go manually and use winlenium to interact with the app."

Accessibility Audit

Ask the agent to navigate through an application, evaluate it from a screen reader user's perspective, and compile a detailed accessibility report.

Example prompt:

Learn what Winlenium can do by running `uvx winlenium --help` and
`uvx winlenium <command> --help`. Then launch [Your App] and perform an
accessibility audit. Navigate through every screen and dialog and for each
screen inspect the UI Automation tree and check how usable it is for a person
relying on a screen reader. Compile a report where every issue includes:

1. The screen where the issue occurs.
2. The exact Winlenium command to inspect the problematic element.
3. A screenshot of the screen and, if possible, of the problematic element
   itself.

Save the report as accessibility-audit.md and screenshots in a screenshots/
folder.

Do not automate the process, just go manually and use winlenium to interact
with the app.

Run it with Codex:

codex exec --yolo "Learn what Winlenium can do by running 'uvx winlenium --help' and 'uvx winlenium <command> --help'. Then launch [Your App] and perform an accessibility audit. Navigate through every screen and dialog and for each screen inspect the UI Automation tree and check how usable it is for a screen reader user. Compile a report where every issue includes the screen, the exact Winlenium command to inspect the problematic element, and screenshots. Save the report as accessibility-audit.md and screenshots in a screenshots/ folder. Do not automate the process, just go manually and use winlenium to interact with the app."

Test Case Automation

Ask the agent to execute a manual test case against your application: launch it, perform the described steps, verify expected outcomes, and produce a pass/fail report with screenshots.

Example prompt:

Learn what Winlenium can do by running `uvx winlenium --help` and
`uvx winlenium <command> --help`. Then execute the following test case
against [Your App]:

1. Launch the application.
2. Open Settings and enable the "Dark mode" toggle.
3. Verify the title bar background color changed.
4. Disable the toggle and verify it reverts.

For each step, take a screenshot. Produce a Markdown report with
pass/fail status for every step, the Winlenium commands used, and
the screenshots.

Save the report as test-report.md and screenshots in a screenshots/ folder.

Run it with Codex:

codex exec --yolo "Learn what Winlenium can do by running 'uvx winlenium --help' and 'uvx winlenium <command> --help'. Then execute the following test case against [Your App]: 1. Launch the application. 2. Open Settings and enable the Dark mode toggle. 3. Verify the title bar background color changed. 4. Disable the toggle and verify it reverts. For each step, take a screenshot. Produce a Markdown report with pass/fail status for every step, the Winlenium commands used, and the screenshots. Save the report as test-report.md and screenshots in a screenshots/ folder."

Documentation

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

winlenium-0.3.0.tar.gz (28.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

winlenium-0.3.0-py3-none-any.whl (46.1 kB view details)

Uploaded Python 3

File details

Details for the file winlenium-0.3.0.tar.gz.

File metadata

  • Download URL: winlenium-0.3.0.tar.gz
  • Upload date:
  • Size: 28.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for winlenium-0.3.0.tar.gz
Algorithm Hash digest
SHA256 77da8e71e8c59d14a99bee7f2f5aa99be678e068ad67f404ae3ca1fc9bc1b482
MD5 6cef8cbb8301799a7ebadb834c10809f
BLAKE2b-256 d33747044b2df8a283cce60eeef8ba991bde50288541901ad891b20e727291b0

See more details on using hashes here.

File details

Details for the file winlenium-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: winlenium-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 46.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for winlenium-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a68b553e5884126a9e08f427fc9d2801fd0d4928665dee7b2362b127eeeb498d
MD5 7af4c4d8606bed1a1678f47b7380ff9c
BLAKE2b-256 471423b2c47300ff7d1dbf24529008c704c351cf7c9e1e815e410f5c981cdfc6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page