FlaUI.Tool
0.1.14
dotnet tool install --global FlaUI.Tool --version 0.1.14
dotnet new tool-manifest
dotnet tool install --local FlaUI.Tool --version 0.1.14
#tool dotnet:?package=FlaUI.Tool&version=0.1.14
nuke :add-package FlaUI.Tool --version 0.1.14
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 - 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>] [--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) |
--timeout |
No | Maximum time in milliseconds to wait for the main window (default: 30000) |
session attach
Attach to an already running application.
flaui session attach [--pid <pid>] [--name <name>] [--title <title>] [--timeout <ms>]
| 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 |
--timeout |
No | Maximum time in milliseconds to wait for the main window (default: 10000) |
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>]
| 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 |
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.
elem expand
Expand a collapsible element (Expander, TreeViewItem, ComboBox, etc.) via the ExpandCollapse pattern.
flaui elem expand --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
elem collapse
Collapse an expandable element (Expander, TreeViewItem, ComboBox, etc.) via the ExpandCollapse pattern.
flaui elem collapse --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
elem get-range
Get an element's range value, minimum, maximum, and step sizes via the RangeValue pattern (Slider, SpinButton).
flaui elem get-range --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
Returns value, minimum, maximum, smallChange, and largeChange.
elem set-range
Set an element's value via the RangeValue pattern. Validates that the value is within the element's min/max bounds.
flaui elem set-range --id <id> --value <value> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--value |
Yes | Numeric value to set (must be within the element's min/max range) |
--window |
No | Window handle (hex) to target |
elem grid-info
Get row count, column count, and column headers from a Grid/Table element (DataGrid, Table).
flaui elem grid-info --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
Returns rowCount, columnCount, and columnHeaders (if the element supports the Table pattern).
elem get-cell
Get the value of a cell in a Grid element by row and column index.
flaui elem get-cell --id <id> --row <row> --column <column> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--row |
Yes | Row index (0-based) |
--column |
Yes | Column index (0-based) |
--window |
No | Window handle (hex) to target |
elem get-text
Get the full text content of an element via the Text pattern (RichTextBox, Document).
flaui elem get-text --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
Returns the full text content of the element's document range.
elem get-scroll
Get scroll position and scrollability of a container via the Scroll pattern.
flaui elem get-scroll --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
Returns horizontalPercent, verticalPercent, horizontalViewSize, verticalViewSize, horizontallyScrollable, and verticallyScrollable.
elem scroll
Scroll a container to a position via the Scroll pattern.
flaui elem scroll --id <id> [--horizontal <pct>] [--vertical <pct>] [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--horizontal |
No | Horizontal scroll percent (0-100), omit for no change |
--vertical |
No | Vertical scroll percent (0-100), omit for no change |
--window |
No | Window handle (hex) to target |
elem get-dock
Get an element's dock position via the Dock pattern.
flaui elem get-dock --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
elem set-dock
Set an element's dock position via the Dock pattern.
flaui elem set-dock --id <id> --position <pos> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--position |
Yes | Dock position: top, bottom, left, right, fill, none |
--window |
No | Window handle (hex) to target |
elem grid-item-info
Get row, column, and span info for a cell via the GridItem pattern.
flaui elem grid-item-info --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
Returns row, column, rowSpan, and columnSpan.
elem table-item-info
Get row and column header info for a cell via the TableItem pattern.
flaui elem table-item-info --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
Returns rowHeaders and columnHeaders arrays.
elem get-views
Get supported views and current view via the MultipleView pattern.
flaui elem get-views --id <id> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--window |
No | Window handle (hex) to target |
Returns currentViewId, currentViewName, supportedViewIds, and supportedViewNames.
elem set-view
Set the current view via the MultipleView pattern.
flaui elem set-view --id <id> --view <viewId> [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--view |
Yes | View ID to set (from get-views) |
--window |
No | Window handle (hex) to target |
elem transform
Move, resize, or rotate an element via the Transform pattern.
flaui elem transform --id <id> [--x <x>] [--y <y>] [--width <w>] [--height <h>] [--rotate <deg>] [--window <handle>]
| Option | Required | Description |
|---|---|---|
--id |
Yes | Element ID |
--x |
No | X coordinate to move to |
--y |
No | Y coordinate to move to |
--width |
No | Width to resize to |
--height |
No | Height to resize to |
--rotate |
No | Degrees to rotate |
--window |
No | Window handle (hex) to target |
At least one transform option must be specified. Returns canMove, canResize, and canRotate capabilities.
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 |
window get-state
Get window state (visual state, modal, topmost) via the Window pattern.
flaui window get-state --handle <handle>
| Option | Required | Description |
|---|---|---|
--handle |
Yes | Window handle as hex string (from window list) |
Returns visualState (Normal, Minimized, Maximized), canMaximize, canMinimize, isModal, and isTopmost.
window minimize
Minimize a window via the Window pattern.
flaui window minimize --handle <handle>
| Option | Required | Description |
|---|---|---|
--handle |
Yes | Window handle as hex string (from window list) |
Returns the new window state after minimizing.
window maximize
Maximize a window via the Window pattern.
flaui window maximize --handle <handle>
| Option | Required | Description |
|---|---|---|
--handle |
Yes | Window handle as hex string (from window list) |
Returns the new window state after maximizing.
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
}
report
Create a GitHub issue on the FlaUI.Cli repository via the gh CLI.
flaui report --title <title> --description <description>
| Option | Required | Description |
|---|---|---|
--title |
Yes | Issue title |
--description |
Yes | Issue body / description |
Requires GitHub CLI installed and authenticated (gh auth login).
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 scroll-into-view, elem menu, 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 |
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 |
GitHub CLI not installed (returned by report command) |
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 with elem expand, then search for child elements. Use elem collapse when done.
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 |