Metadata-Version: 2.4
Name: winlenium
Version: 0.3.0
Summary: Winlenium is a CLI tool for automated testing of Windows programs via the MS UI Automation framework.
Author: Andrey Meshkov
License-Expression: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Testing
Classifier: Typing :: Typed
Requires-Dist: uiautomation
Requires-Dist: click
Requires-Dist: pillow
Requires-Dist: pyperclip
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/ameshkov/winlenium
Project-URL: Repository, https://github.com/ameshkov/winlenium
Project-URL: Issues, https://github.com/ameshkov/winlenium/issues
Description-Content-Type: text/markdown

# 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](https://pypi.org/project/winlenium/), so you
can install it directly with `uv` or `pip`, or run it on demand with `uvx`.

## Table of Contents

- [Installation](#installation)
    - [Requirements](#requirements)
    - [Install with uv](#install-with-uv)
    - [Install with pip](#install-with-pip)
    - [Run without installing](#run-without-installing)
- [Quick Start](#quick-start)
- [Commands](#commands)
    - [Process and Window Management](#process-and-window-management)
    - [Element Interaction](#element-interaction)
    - [Inspection and Queries](#inspection-and-queries)
- [Element Selectors](#element-selectors)
    - [Path Selector](#path-selector)
- [Window Selectors](#window-selectors)
- [Usage Examples](#usage-examples)
    - [Discover running applications](#discover-running-applications)
    - [Inspect the accessibility tree](#inspect-the-accessibility-tree)
    - [Interact with UI controls](#interact-with-ui-controls)
    - [Read element state](#read-element-state)
    - [Mouse actions](#mouse-actions)
    - [Screenshots](#screenshots)
    - [Window management](#window-management)
    - [Clipboard](#clipboard)
    - [Tray icons](#tray-icons)
    - [Context menus](#context-menus)
    - [Modal dialogs](#modal-dialogs)
    - [Wait for elements](#wait-for-elements)
- [Output Formats](#output-formats)
- [Exit Codes](#exit-codes)
- [Agentic Usage Examples](#agentic-usage-examples)
    - [Application Walkthrough](#application-walkthrough)
    - [Accessibility Audit](#accessibility-audit)
    - [Test Case Automation](#test-case-automation)
- [Documentation](#documentation)

## Installation

### Requirements

- Windows 10 or 11 with a desktop session (UI Automation requires an active
  desktop)
- Python 3.12+
- [uv](https://docs.astral.sh/uv/) (recommended package manager)

Install Python and uv with [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/):

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

Verify both are available:

```bash
python --version
uv --version
```

### Install with uv

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

# Verify installation
winlenium --version
```

### Install with pip

```bash
pip install winlenium
```

### Run without installing

```bash
# 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](DEVELOPMENT.md).

## Quick Start

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

```bash
# 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:

```bash
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:

```bash
# 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:

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

## Usage Examples

### Discover running applications

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

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

### Tray icons

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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`:

```bash
# 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](https://openai.com/codex/) as the agent,
but any AI agent that can call a CLI will work the same way.

See the [examples](examples/README.md) 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:

```text
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:

```bash
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:

```text
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:

```bash
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:

```text
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:

```bash
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

- [Development guide](DEVELOPMENT.md) — setup, testing, and contribution
  workflow
- [Changelog](CHANGELOG.md)
- [LLM agent rules](AGENTS.md)
- [Agentic workflows examples](./examples/README.md)
