FlaUI.Tool
0.1.9
See the version list below for details.
dotnet tool install --global FlaUI.Tool --version 0.1.9
dotnet new tool-manifest
dotnet tool install --local FlaUI.Tool --version 0.1.9
#tool dotnet:?package=FlaUI.Tool&version=0.1.9
nuke :add-package FlaUI.Tool --version 0.1.9
flaui
Let your AI agent navigate your app, verify its own changes, and write the tests.
AI coding agents write your code. But when that code has a UI, the agent can't see what it built, can't check if the button works, and can't write a test for it. flaui closes that gap.
A stateless CLI built on FlaUI and Windows UI Automation (UIA3). Every command returns structured JSON. Every element selector is quality-rated. The agent drives it the same way it drives git or dotnet — from the terminal.
The workflow:
1. Agent writes code that changes a WPF form
2. Agent launches the app: flaui session new --app "MyApp.exe"
3. Agent navigates to the form: flaui elem find --name "Customer Details"
4. Agent verifies its changes work: flaui elem find --aid "EmailField"
flaui elem type --id a1b2 --text "test@co.com"
flaui elem find --name "Save"
flaui elem click --id c3d4
5. Agent uses menus and keyboard: flaui elem menu --path "File > Save As"
flaui elem keys --keys "ctrl+s"
6. Agent reads the result: flaui elem get-value --id a1b2
7. Agent captures visual proof: flaui screenshot --output form-state.png
8. Agent exports the steps as test: flaui record export --out customer-form-test.json
Why flaui
- Agents can verify their own UI changes — the agent builds a feature, launches the app, and checks that buttons, fields, and workflows actually work
- Agents generate tests from real interactions — every click, type, and navigation is recorded and exported as structured test steps; the agent turns them into test cases
- Selector quality keeps tests reliable — every element is rated
Stable,Acceptable, orFragile; the agent knows which selectors will survive the next refactor - Selector policies fail fast — set a quality floor per session; fragile selectors return exit code
2instead of silently producing a flaky test - Stateless and JSON-native — no persistent process, no shared memory; agents parse JSON natively, so there's zero glue code between the agent and the tool
Installation
Requires .NET 10 SDK or later. Windows only.
dotnet tool install --global FlaUI.Tool
Quick Start
# Agent launches the app it just modified
flaui session new --app "C:\Path\To\MyApp.exe"
# Agent explores the UI to understand the layout
flaui elem tree --depth 3
# Agent finds the field it added in the last commit
flaui elem find --aid "UsernameTextBox"
# Agent types into it to verify it works
flaui elem type --id a1b2c3d4 --text "testuser@example.com"
# Agent clicks submit to test the full flow
flaui elem find --name "Submit"
flaui elem click --id e5f6g7h8
# Agent reads back the result to confirm
flaui elem get-value --id a1b2c3d4
# Done — agent closes the app
flaui session end --close-app
Commands
All commands accept a global --session <path> option to specify the session file. If omitted, the most recent session file in the current directory is used.
session new
Launch an application and create a new session.
flaui session new --app <path> [--args <args>] [--wait-title <text>] [--wait-timeout <ms>]
| Option | Required | Description |
|---|---|---|
--app |
Yes | Path to the application executable. Forward slashes are accepted and normalized automatically |
--args |
No | Arguments to pass to the application |
--wait-title |
No | Wait until a window with a title containing this text appears before completing session creation |
--wait-timeout |
No | Maximum time in milliseconds to wait for --wait-title (default: 30000) |
session attach
Attach to an already running application.
flaui session attach [--pid <pid>] [--name <name>] [--title <title>]
| Option | Required | Description |
|---|---|---|
--pid |
One of three | Process ID to attach to |
--name |
One of three | Process name to attach to |
--title |
One of three | Window title to attach to |
session status
Check if the session's process is still running and the window is valid.
flaui session status
Returns process alive state, window validity, element count, recording status, and the live main window title and handle. When the process and window are alive, the command reattaches to read the current window title (which may have changed since session creation).
session end
End the session and optionally close the application.
flaui session end [--close-app] [--force]
| Option | Required | Description |
|---|---|---|
--close-app |
No | Close the application when ending session |
--force |
No | Force-kill the application process (use with --close-app for unresponsive apps) |
elem find
Find an element by one or more properties. Returns an element ID for use in subsequent commands.
flaui elem find [--aid <id>] [--name <name>] [--type <type>] [--class <class>] [--timeout <ms>] [--window <handle>] [--policy <policy>]
| Option | Required | Description |
|---|---|---|
--aid |
No | AutomationId to find |
--name |
No | Element name to find |
--type |
No | ControlType to find |
--class |
No | ClassName to find |
--timeout |
No | Search timeout in milliseconds (default: 10000) |
--window |
No | Window handle (hex) to search in instead of the main window |
--policy |
No | Override session selector policy for this command (stable, acceptable, fragile) |
Response includes selectorQuality and selectorStrategy so the agent knows how reliable the selector is.
elem tree
Dump the element tree as JSON.
flaui elem tree [--root <id>] [--depth <n>]
| Option | Required | Description |
|---|---|---|
--root |
No | Element ID to use as tree root (default: main window) |
--depth |
No | Maximum tree depth (default: 3) |
elem props
Get all properties of an element.
flaui elem props --id <id>
Returns AutomationId, Name, ControlType, ClassName, Bounds, IsEnabled, IsOffscreen, RuntimeId, HelpText, and AcceleratorKey.
elem click
Click an element.
flaui elem click --id <id> [--double] [--right]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--double |
No | Double click |
--right |
No | Right click |
elem clear
Clear the text content of an element. Uses the Value pattern if supported, otherwise selects all text and deletes it via keyboard.
flaui elem clear --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
elem type
Type text into an element. When used on a ComboBox, automatically redirects to select logic — expanding the dropdown and selecting the matching item by name.
flaui elem type --id <id> --text <text>
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--text |
Yes | Text to type (or item name to select for ComboBoxes) |
elem set-value
Set an element's value via the Value pattern.
flaui elem set-value --id <id> --value <value>
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--value |
Yes | Value to set |
elem select
Select an item in a combo box or list.
flaui elem select --id <id> --item <item>
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--item |
Yes | Item to select |
elem get-value
Get an element's current value.
flaui elem get-value --id <id> [--save <name>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--save |
No | Save the value to a session variable for later use |
elem get-state
Get an element's toggle/check state, enabled status, and visibility.
flaui elem get-state --id <id>
elem keys
Send keyboard input (key combinations or single keys).
flaui elem keys --keys <keys> [--id <id>] [--window <handle>]
| Option | Required | Description |
|---|---|---|
--keys |
Yes | Key combination (e.g. ctrl+shift+s, tab, alt+f4) |
--id |
No | Element ID to focus before sending keys |
--window |
No | Window handle (hex) to target |
Supported keys: ctrl, alt, shift, tab, escape/esc, enter/return, space, delete/del, backspace, up/down/left/right, home, end, pageup, pagedown, f1-f24, a-z, 0-9.
elem menu
Navigate and click a menu item by path.
flaui elem menu --path <path> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--path |
Yes | Menu path with > separators (e.g. "File > Save As") |
--window |
No | Window handle (hex) to target |
elem scroll-into-view
Scroll an element into view using the UIA ScrollItem pattern.
flaui elem scroll-into-view --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
Returns scrolled: true if the element supported the ScrollItem pattern and was scrolled, or scrolled: false if the pattern is not supported. This is also called automatically by elem click, elem type, and other interaction commands.
window list
List all top-level windows for the attached application.
flaui window list
Returns an array of windows with handle (hex), title, isModal, className, and bounds.
window focus
Bring a window to the foreground.
flaui window focus --handle <handle>
| Option | Required | Description |
|---|---|---|
--handle |
Yes | Window handle as hex string (from window list) |
window close
Close a window by handle or title.
flaui window close [--handle <handle>] [--title <title>] [--force]
| Option | Required | Description |
|---|---|---|
--handle |
One of two | Window handle as hex string |
--title |
One of two | Window title (partial, case-insensitive) |
--force |
No | Force-kill the window's process if graceful close fails |
wait
Wait for an element condition or a window title to appear.
flaui wait --aid <id> --timeout <ms> [--value <value>] [--state <state>]
flaui wait --title <text> --timeout <ms>
| Option | Required | Description |
|---|---|---|
--aid |
One of two | AutomationId of the element to wait for |
--title |
One of two | Wait until a window title contains this text (case-insensitive, partial match) |
--timeout |
Yes | Timeout in milliseconds |
--value |
No | Wait until element has this value (use with --aid) |
--state |
No | Wait for state: hidden, visible, enabled (use with --aid) |
When using --title, the response includes windowHandle and windowTitle fields, and the session's main window is updated to match.
record start
Begin recording interactions. All subsequent elem commands are recorded as steps.
flaui record start
record stop
Stop recording.
flaui record stop
record drop
Drop the last recorded step.
flaui record drop
record keep
Mark the last recorded step as kept.
flaui record keep
record list
List all recorded steps with their sequence numbers, commands, and targets.
flaui record list
record export
Export recorded steps to a JSON file.
flaui record export --out <path>
| Option | Required | Description |
|---|---|---|
--out |
Yes | Output file path |
audit
Audit selector quality across all elements or recorded steps.
flaui audit [--window <id>] [--recording] [--out <path>]
| Option | Required | Description |
|---|---|---|
--window |
No | Element ID to scope the audit to |
--recording |
No | Audit recorded steps instead of live elements |
--out |
No | Write audit report to file |
Returns total elements, AutomationId coverage, selector quality distribution, and a list of issues (interactive controls with weak selectors).
screenshot
Capture a screenshot of a window or element and save it to a file.
flaui screenshot --output <path> [--id <id>] [--window <handle>]
| Option | Required | Description |
|---|---|---|
--output |
Yes | Output file path. Format inferred from extension (.png, .bmp, .jpg) |
--id |
No | Element ID — captures that element's bounding rectangle |
--window |
No | Window handle (hex) — captures that window instead of the main window |
If neither --id nor --window is given, captures the main window from the session.
Response:
{
"success": true,
"message": "Screenshot saved.",
"outputPath": "C:/absolute/path/to/screenshot.png",
"width": 1024,
"height": 768
}
batch
Execute multiple commands in a single session (one process attach, shared element state).
flaui batch --file <path> [--continue-on-error]
flaui batch --steps '<json>' [--continue-on-error]
| Option | Required | Description |
|---|---|---|
--file |
One of two | Path to a JSON file with batch steps |
--steps |
One of two | Inline JSON string with batch steps |
--continue-on-error |
No | Continue executing remaining steps after a failure |
Input format:
{
"steps": [
{"cmd": "elem find", "args": {"aid": "SubmitButton"}},
{"cmd": "elem click", "args": {"id": "$prev.elementId"}},
{"cmd": "elem keys", "args": {"keys": "ctrl+s"}},
{"cmd": "elem menu", "args": {"path": "File > Save As"}}
]
}
Use $prev.field to reference the previous step's result, or $steps[N].field to reference step N's result.
Supported commands: elem find, elem click, elem clear, elem type, elem select, elem set-value, elem get-value, elem get-state, elem keys, elem menu, elem scroll-into-view, window list, window focus, window close, screenshot.
Selector Quality System
Every time flaui resolves an element, it evaluates the selector and assigns a quality rating:
| Rating | What It Means | Agent Action |
|---|---|---|
| Stable | Unique AutomationId — the gold standard |
Use with confidence |
| Acceptable | Resolved by Name + ControlType composite |
Use, but note the risk |
| Fragile | Resolved by position, index, or volatile property | Flag for review or find a better selector |
| Unresolvable | Element not found | Retry, adjust approach, or report failure |
Selector Policy
flaui session new --app "MyApp.exe" --selector-policy stable
With policy set to stable, any elem find that resolves below that threshold returns exit code 2 (policy violation). The agent knows immediately that the selector isn't reliable enough for production tests.
Test Generation from Real Interactions
The agent doesn't write tests from imagination. It writes code, runs the app, interacts with it, and turns those real interactions into tests.
# Agent finished implementing a login feature — now it verifies and records
flaui session new --app "MyApp.exe"
flaui record start
# Agent navigates the UI it just built
flaui elem find --name "Username"
flaui elem type --id <id> --text "admin"
flaui elem find --name "Password"
flaui elem type --id <id> --text "secret"
flaui elem find --name "Login"
flaui elem click --id <id>
# Agent checks the result
flaui elem find --aid "WelcomeLabel"
flaui elem get-value --id <id>
# Agent exports the verified steps as a test definition
flaui record stop
flaui record export --out login-test.json
# Agent audits selector quality to ensure test stability
flaui audit --recording
Every recorded step includes element selectors, quality ratings, timestamps, and parameters. The agent uses this structured JSON to generate test cases in whatever framework the project uses — NUnit, xUnit, MSTest, or a custom harness.
Exit Codes
| Code | Meaning |
|---|---|
0 |
Success |
1 |
General error |
2 |
Selector policy violation — element found but selector quality below policy threshold |
3 |
Element unresolvable — element not found within timeout |
Agents use exit codes for control flow. A non-zero exit tells the agent exactly what went wrong without parsing error messages.
Known Limitations & Workarounds
1. Elements inside collapsed WPF Expanders are not found
elem find returns "not found" for elements inside collapsed Expanders. This is correct UIA behavior — collapsed containers don't expose their children to the automation tree.
Workaround: First expand the Expander (find it, then elem click to expand), then search for child elements.
2. elem tree returns no children for WPF ComboBox
WPF ComboBoxes use virtualized item panels. Items only appear in the UIA tree when the dropdown is open and items are scrolled into view.
Workaround: Use elem select --id <id> --item "ItemName" to select items by name — this command expands the dropdown internally. To list items, open the dropdown first with elem click, then run elem tree.
Architecture
┌─────────────────────────────┐
│ AI Coding Agent │
│ (Claude Code, Cursor, etc) │
└─────────┬───────────────────┘
│ shell commands + JSON
▼
┌─────────────────────────────┐
│ flaui CLI │
│ stateless, per-command │
└─────────┬───────────────────┘
│ UI Automation (UIA3)
▼
┌─────────────────────────────┐
│ Windows Desktop App │
│ (WPF, WinForms, Win32) │
└─────────────────────────────┘
No SDK integration. No library imports. The agent calls flaui the same way it calls git or dotnet — as a CLI tool.
Building from Source
git clone https://github.com/kodroi/FlaUI.Cli.git
cd FlaUI.Cli
dotnet build src/FlaUI.Cli/FlaUI.Cli.csproj
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.14 | 190 | 3/13/2026 |
| 0.1.13 | 115 | 3/12/2026 |
| 0.1.12 | 113 | 3/11/2026 |
| 0.1.11 | 123 | 3/11/2026 |
| 0.1.10 | 112 | 3/11/2026 |
| 0.1.9 | 115 | 3/11/2026 |
| 0.1.8 | 127 | 3/11/2026 |
| 0.1.7 | 121 | 3/11/2026 |
| 0.1.6 | 107 | 3/11/2026 |
| 0.1.5 | 110 | 3/11/2026 |
| 0.1.4 | 118 | 3/11/2026 |
| 0.1.3 | 116 | 3/11/2026 |
| 0.1.2 | 121 | 3/11/2026 |
| 0.1.1 | 120 | 3/11/2026 |
| 0.1.0 | 119 | 3/11/2026 |