CLI Reference
tauri-pilot is a command-line client that communicates with the tauri-plugin-pilot server running inside your Tauri application over a Unix socket.
Global Options
Section titled “Global Options”These options can be used with any command.
| Option | Description |
|---|---|
--socket <path> | Explicit path to the Unix socket. Auto-detected if omitted. Env: TAURI_PILOT_SOCKET |
--window <label> | Target a specific window by label. Env: TAURI_PILOT_WINDOW. Default: main, falls back to first available |
--json | Output JSON instead of human-readable text |
Socket Auto-Detection
Section titled “Socket Auto-Detection”When --socket is not specified, the CLI resolves the socket in this priority order:
--socket <path>— explicit flag (highest priority)$TAURI_PILOT_SOCKET— environment variable- Glob
/tmp/tauri-pilot-*.sock→ most recently modified file (by mtime)
Window Targeting
Section titled “Window Targeting”The --window <label> option (or TAURI_PILOT_WINDOW env var) selects which window all commands operate on:
tauri-pilot --window settings snapshot # snapshot the settings windowtauri-pilot click @e3 --window main # click in the main windowTAURI_PILOT_WINDOW=settings tauri-pilot snapshotIf --window is not specified, the CLI targets the main window and falls back to the first available window. If the specified window label does not exist, the command exits with an error.
Target Syntax
Section titled “Target Syntax”Many commands accept a <target> argument that identifies a DOM element. Three formats are supported:
| Format | Example | Description |
|---|---|---|
| Element ref | @e1 | Reference from the last snapshot call |
| CSS selector | #submit-btn or .class | Standard CSS selector |
| Coordinates | 100,200 | Raw x,y screen coordinates |
Note: Element refs (
@e1,@e2, …) are reset on everysnapshotcall. Always take a fresh snapshot before using refs.
Commands
Section titled “Commands”Health check. Verifies the plugin server is reachable and responding.
tauri-pilot pingExample:
$ tauri-pilot ping✓ okwindows
Section titled “windows”List all open windows with their label, URL, and title.
tauri-pilot windowsExample:
$ tauri-pilot windowsmain http://localhost:1420/dashboard PR Dashboardsettings http://localhost:1420/settings Settingsabout http://localhost:1420/about AboutJSON-RPC example:
// Request{"jsonrpc":"2.0","id":1,"method":"windows.list","params":{}}
// Response{"jsonrpc":"2.0","id":1,"result":{"windows":[ {"label":"main","url":"http://localhost:1420/dashboard","title":"PR Dashboard"}, {"label":"settings","url":"http://localhost:1420/settings","title":"Settings"}, {"label":"about","url":"http://localhost:1420/about","title":"About"}]}}snapshot
Section titled “snapshot”Capture the current accessibility tree of the WebView and assign stable element refs (e1, e2, …).
tauri-pilot snapshot [OPTIONS]Options:
| Option | Description |
|---|---|
-i, --interactive | Only include interactive elements (buttons, inputs, links, etc.) |
-s, --selector <sel> | Scope the snapshot to the subtree matching this CSS selector |
-d, --depth <n> | Maximum tree depth to traverse |
--save <file> | Save the snapshot to a JSON file for later comparison with diff --ref |
Example:
$ tauri-pilot snapshot --interactivee1 heading "PR Dashboard"e2 textbox "Search PRs" value=""e3 button "Refresh"JSON-RPC example:
// Request{"jsonrpc":"2.0","id":1,"method":"snapshot","params":{"interactive":true}}
// Response{"jsonrpc":"2.0","id":1,"result":{"elements":[ {"ref":"e1","role":"heading","name":"PR Dashboard","depth":0}, {"ref":"e2","role":"textbox","name":"Search PRs","depth":1,"value":""}, {"ref":"e3","role":"button","name":"Refresh","depth":1}]}}Compare the current page state with a previous snapshot and show only the differences. Massive token savings for AI agents that currently re-read the entire tree after each interaction.
tauri-pilot diff [OPTIONS]Options:
| Option | Description |
|---|---|
--ref <file> | Diff against a saved snapshot file instead of the last in-memory snapshot |
-i, --interactive | Only include interactive elements in the new snapshot |
-s, --selector <sel> | Scope the new snapshot to a CSS selector |
-d, --depth <n> | Maximum tree depth to traverse |
Output format:
+ button "Submit" [ref=e8] # added- button "Loading..." [ref=e3] # removed~ textbox "Search PRs" [ref=e2] value: "" → "workspace" # changedExample:
# Take a snapshot, interact, then diff$ tauri-pilot snapshot -i$ tauri-pilot fill @e2 "workspace"$ tauri-pilot click @e3$ tauri-pilot diff -i~ textbox "Search PRs" [ref=e2] value: "" → "workspace"
# Save and diff against a file$ tauri-pilot snapshot -i --save before.snap$ tauri-pilot fill @e2 "workspace"$ tauri-pilot diff -i --ref before.snap
# No changes$ tauri-pilot diff -iNo changes detected.How matching works:
Elements are matched between snapshots by (role, name, depth) — not by ref ID, since refs reset on every snapshot. For duplicate elements sharing the same identity, position order is used as a tiebreaker.
JSON-RPC example:
// Request (diff vs last snapshot){"jsonrpc":"2.0","id":1,"method":"diff","params":{"interactive":true}}
// Request (diff vs saved reference){"jsonrpc":"2.0","id":1,"method":"diff","params":{"interactive":true,"reference":{"elements":[...]}}}
// Response{"jsonrpc":"2.0","id":1,"result":{ "added": [{"ref":"e8","role":"button","name":"Submit","depth":1}], "removed": [{"ref":"e3","role":"button","name":"Loading...","depth":1}], "changed": [{"old":{"ref":"e2","role":"textbox","name":"Search PRs","value":"","depth":1}, "new":{"ref":"e2","role":"textbox","name":"Search PRs","value":"workspace","depth":1}, "changes":["value"]}]}}assert
Section titled “assert”One-step verification of element state, text, or URL. Returns exit code 0 with ok on success, exit code 1 with a clear error message on failure. Designed to reduce AI agent round-trips and token usage.
tauri-pilot assert <subcommand> [args...]Subcommands:
| Subcommand | Arguments | Description |
|---|---|---|
text | <target> <expected> | Assert exact text content match |
visible | <target> | Assert element is visible |
hidden | <target> | Assert element is hidden |
value | <target> <expected> | Assert input/textarea/select value |
count | <selector> <expected> | Assert number of elements matching CSS selector |
checked | <target> | Assert checkbox/radio is checked |
contains | <target> <expected> | Assert text contains substring |
url | <expected> | Assert current URL contains substring |
Examples:
# Take a snapshot first (refs reset each time)$ tauri-pilot snapshot -i
# Exact text match$ tauri-pilot assert text @e1 "Dashboard"✓ ok
# Element visibility$ tauri-pilot assert visible @e3✓ ok
# Check input value$ tauri-pilot assert value @e2 "workspace"FAIL: expected value "workspace", got ""
# Count elements by CSS selector$ tauri-pilot assert count ".list-item" 5✓ ok
# Checkbox state$ tauri-pilot assert checked @e4FAIL: element is not checked
# Partial text match$ tauri-pilot assert contains @e1 "Dash"✓ ok
# URL check$ tauri-pilot assert url "/dashboard"✓ okNote: Element refs (
@e1,@e2, …) require a priorsnapshotcall. Always take a fresh snapshot before using refs in assertions.
Exit codes:
| Code | Meaning |
|---|---|
0 | Assertion passed |
1 | Assertion failed — error message on stderr |
Simulate a realistic click on an element (dispatches focus → mousedown → mouseup → click events).
tauri-pilot click <target>Example:
tauri-pilot click @e3tauri-pilot click "#submit-btn"tauri-pilot click 100,200Clear an input field and type a new value. Uses the native setter to trigger synthetic React events.
tauri-pilot fill <target> <value>Example:
tauri-pilot fill @e2 "my-feature-branch"tauri-pilot fill "#search" "open issues"Type text into a focused element without clearing existing content first.
tauri-pilot type <target> <text>Example:
tauri-pilot type @e2 " additional text"Send a keyboard event to the focused element.
tauri-pilot press <key>Common keys: Enter, Tab, Escape, ArrowDown, ArrowUp, Backspace, Space.
Example:
tauri-pilot press Entertauri-pilot press Tabtauri-pilot press Escapeselect
Section titled “select”Select an option in a <select> dropdown by value.
tauri-pilot select <target> <value>Example:
tauri-pilot select "#status-filter" "open"tauri-pilot select @e5 "closed"Toggle a checkbox (check if unchecked, uncheck if checked).
tauri-pilot check <target>Example:
tauri-pilot check "#remember-me"tauri-pilot check @e7scroll
Section titled “scroll”Scroll the page or a specific element.
tauri-pilot scroll <direction> [amount] [OPTIONS]Arguments:
| Argument | Description |
|---|---|
<direction> | up, down, left, or right |
[amount] | Scroll distance in pixels (default: 300) |
Options:
| Option | Description |
|---|---|
--ref <ref> | Element to scroll (defaults to the page) |
Example:
tauri-pilot scroll down 500tauri-pilot scroll up --ref @e4Drag an element to another element or by a pixel offset. Dispatches the full HTML5 drag event sequence: mousedown → dragstart → dragleave → dragenter → dragover → drop → dragend.
tauri-pilot drag <source> [target] [OPTIONS]Arguments:
| Argument | Description |
|---|---|
<source> | Element to drag (ref, selector, or coordinates) |
[target] | Element to drop onto (mutually exclusive with --offset) |
Options:
| Option | Description |
|---|---|
--offset <X,Y> | Drag by pixel offset instead of to an element (mutually exclusive with [target]) |
Examples:
# Drag a card to a column (kanban board)tauri-pilot drag "#card-1" "#col-done"
# Drag by ref (after snapshot)tauri-pilot drag @e5 @e8
# Drag a slider thumb by pixel offsettauri-pilot drag "#slider-thumb" --offset "150,0"
# Drag to coordinatestauri-pilot drag @e5 "400,200"JSON-RPC example:
// Element-to-element drag{"jsonrpc":"2.0","id":1,"method":"drag","params":{"source":{"ref":"e5"},"target":{"ref":"e8"}}}
// Offset drag{"jsonrpc":"2.0","id":1,"method":"drag","params":{"source":{"selector":"#thumb"},"offset":{"x":150,"y":0}}}Simulate a file drop on an element. Reads files from disk, base64-encodes them, and creates DataTransfer + File objects in the WebView. Useful for testing file upload zones, import features, and drag-from-OS scenarios.
tauri-pilot drop <target> --file <path> [--file <path>...]Arguments:
| Argument | Description |
|---|---|
<target> | Element to drop files onto (ref, selector, or coordinates) |
Options:
| Option | Description |
|---|---|
--file <path> | File to drop (required, can be repeated for multiple files) |
Limits: 50 MB per file, 100 MB total payload.
Examples:
# Drop a single filetauri-pilot drop "#file-zone" --file ./photo.png
# Drop multiple filestauri-pilot drop @e3 --file ./doc.pdf --file ./data.csvJSON-RPC example:
{"jsonrpc":"2.0","id":1,"method":"drop","params":{ "selector":"#file-zone", "files":[{"name":"photo.png","type":"image/png","data":"iVBORw0KGgo..."}]}}Watch for DOM mutations using MutationObserver. Blocks until changes are detected (or timeout), then returns a summary of what changed. Useful for waiting on async UI updates without polling snapshots.
tauri-pilot watch [OPTIONS]Options:
| Option | Description |
|---|---|
--selector <sel> | Scope observation to a subtree matching this CSS selector |
--timeout <ms> | Maximum wait time in milliseconds (default: 10000) |
--stable <ms> | Wait until DOM is stable (no new mutations) for N ms (default: 300) |
Examples:
# Wait for any DOM changetauri-pilot watch
# Watch a specific subtreetauri-pilot watch --selector "#results-list"
# Short timeouttauri-pilot watch --timeout 3000
# Wait for DOM to settle after animationstauri-pilot watch --stable 500JSON-RPC example:
{"jsonrpc":"2.0","id":1,"method":"watch","params":{"selector":"#results","timeout":5000,"stable":300}}Get the text content of an element.
tauri-pilot text <target>Example:
$ tauri-pilot text @e1PR DashboardGet the innerHTML of an element, or the full document HTML if no target is given.
tauri-pilot html [target]Example:
tauri-pilot html @e1tauri-pilot html "#main-content"tauri-pilot htmlGet the current value of an input, textarea, or select element.
tauri-pilot value <target>Example:
$ tauri-pilot value "#search"my-feature-branchGet all HTML attributes of an element as key-value pairs.
tauri-pilot attrs <target>Example:
$ tauri-pilot attrs @e3id = submit-btnclass = btn btn-primarydisabled = falsetype = buttonExecute arbitrary JavaScript in the WebView context and return the result.
tauri-pilot eval <script>Example:
$ tauri-pilot eval "document.title"PR Dashboard
$ tauri-pilot eval "window.location.pathname"/dashboardCall a Tauri IPC command (registered with tauri::Builder) and return the response.
tauri-pilot ipc <command> [OPTIONS]Options:
| Option | Description |
|---|---|
--args <json> | JSON object of arguments to pass to the command |
Example:
tauri-pilot ipc get_prstauri-pilot ipc create_pr --args '{"title":"Fix bug","branch":"fix/issue-42"}'screenshot
Section titled “screenshot”Capture the current WebView as a PNG using the injected html-to-image bridge.
tauri-pilot screenshot [path] [OPTIONS]Arguments:
| Argument | Description |
|---|---|
[path] | Output file path. Prints base64 to stdout if omitted |
Options:
| Option | Description |
|---|---|
--selector <sel> | Capture only the element matching this CSS selector |
Example:
tauri-pilot screenshot ./dashboard.pngtauri-pilot screenshot --selector "#main-panel" ./panel.pngtauri-pilot screenshot # prints base64 PNG to stdoutnavigate
Section titled “navigate”Change the WebView URL.
tauri-pilot navigate <url>Example:
tauri-pilot navigate "http://localhost:1420/settings"tauri-pilot navigate "/"Get the current page URL.
tauri-pilot urlExample:
$ tauri-pilot urlhttp://localhost:1420/dashboardGet the current page title.
tauri-pilot titleExample:
$ tauri-pilot titlePR DashboardGet the current page state: URL, title, viewport dimensions, and scroll position.
tauri-pilot stateExample:
$ tauri-pilot stateurl http://localhost:1420/dashboardtitle PR Dashboardviewport 1280x800scroll 0,0Wait for an element to appear (or disappear) in the DOM.
tauri-pilot wait [target] [OPTIONS]Options:
| Option | Description |
|---|---|
--selector <sel> | CSS selector to wait for (alternative to positional [target]) |
--gone | Wait for the element to disappear instead of appear |
--timeout <ms> | Maximum wait time in milliseconds (default: 10000) |
Example:
tauri-pilot wait "@e3"tauri-pilot wait --selector "#loading-spinner" --gonetauri-pilot wait --selector ".toast-success" --timeout 5000Display or stream captured console logs (console.log, console.warn, console.error, console.info).
The JS bridge monkey-patches the browser console methods and stores entries in a 500-entry ring buffer with timestamp, level, serialized arguments, and source location.
tauri-pilot logs [OPTIONS]Options:
| Option | Description |
|---|---|
--level <level> | Filter by log level: log, info, warn, error |
--last <n> | Show only the last N entries |
-f, --follow | Continuously poll for new logs (500ms interval) |
--clear | Flush the ring buffer |
Examples:
# Show all captured logs$ tauri-pilot logs[14:32:01.123] log App initialized[14:32:01.456] warn Deprecated API call[14:32:02.789] ✗ error Failed to fetch: NetworkError
# Filter by level$ tauri-pilot logs --level error[14:32:02.789] ✗ error Failed to fetch: NetworkError
# Last 5 entries$ tauri-pilot logs --last 5
# Stream logs in real-time$ tauri-pilot logs --follow
# Stream errors as NDJSON (one JSON object per line, compatible with jq)$ tauri-pilot logs --follow --level error --json
# Clear the buffer$ tauri-pilot logs --clear✓ clearedJSON output format:
[ { "id": 1, "timestamp": 1712073600000, "level": "error", "args": ["Failed to fetch:", "NetworkError: 500"], "source": "app.js:42" }]JSON-RPC examples:
// Get logs filtered by level{"jsonrpc":"2.0","id":1,"method":"console.getLogs","params":{"level":"error","last":10}}
// Clear buffer{"jsonrpc":"2.0","id":2,"method":"console.clear"}network
Section titled “network”Display or stream captured network requests (fetch and XMLHttpRequest).
The JS bridge monkey-patches fetch and XMLHttpRequest and stores entries in a 200-entry ring buffer with timestamp, method, URL, status code, duration, and error details.
tauri-pilot network [OPTIONS]Options:
| Option | Description |
|---|---|
--filter <pattern> | Filter by URL substring match |
--failed | Show only failed requests (4xx/5xx and network errors) |
--last <n> | Show only the last N entries |
-f, --follow | Continuously poll for new requests (500ms interval) |
--clear | Flush the ring buffer |
Examples:
# Show all captured requests$ tauri-pilot network[14:32:01.123] GET https://api.github.com/repos 200 125ms[14:32:02.456] POST https://api.github.com/graphql 200 340ms[14:32:03.789] GET https://api.github.com/rate_limit 403 12ms
# Filter by URL$ tauri-pilot network --filter graphql
# Show only failures$ tauri-pilot network --failed
# Stream requests in real-time$ tauri-pilot network --follow
# Stream as NDJSON (compatible with jq)$ tauri-pilot network --follow --json
# Clear the buffer$ tauri-pilot network --clear✓ clearedJSON-RPC examples:
// Get requests filtered by URL{"jsonrpc":"2.0","id":1,"method":"network.getRequests","params":{"filter":"graphql","last":10}}
// Clear buffer{"jsonrpc":"2.0","id":2,"method":"network.clear"}storage
Section titled “storage”Read and write browser storage (localStorage or sessionStorage) from the CLI. Useful for AI agents inspecting persisted state, auth tokens, or modifying app configuration during testing.
tauri-pilot storage <subcommand> [OPTIONS]Subcommands:
| Subcommand | Arguments | Description |
|---|---|---|
get | <key> | Read a single key |
set | <key> <value> | Write a key-value pair |
list | Dump all key-value pairs | |
clear | Clear all storage |
Options:
| Option | Description |
|---|---|
--session | Use sessionStorage instead of localStorage |
Examples:
# Read a key from localStorage$ tauri-pilot storage get "auth_token"eyJhbGciOiJIUzI1NiJ9...
# Write a key$ tauri-pilot storage set "theme" "dark"✓ ok
# List all localStorage entries$ tauri-pilot storage listauth_token = eyJhbGciOiJIUzI1NiJ9...theme = darklocale = en
# Clear localStorage$ tauri-pilot storage clear✓ cleared
# Use sessionStorage instead$ tauri-pilot storage --session list$ tauri-pilot storage --session get "csrf_token"
# JSON output$ tauri-pilot storage list --json[{"key":"auth_token","value":"eyJ..."},{"key":"theme","value":"dark"}]JSON-RPC examples:
// Get a key{"jsonrpc":"2.0","id":1,"method":"storage.get","params":{"key":"auth_token","session":false}}
// Set a key{"jsonrpc":"2.0","id":2,"method":"storage.set","params":{"key":"theme","value":"dark","session":false}}
// List all{"jsonrpc":"2.0","id":3,"method":"storage.list","params":{"session":false}}
// Clear{"jsonrpc":"2.0","id":4,"method":"storage.clear","params":{"session":false}}Dump all form fields on the page in a single command. Useful for AI agents inspecting form state, pre-filled values, or verifying form structure without calling value on each input individually.
tauri-pilot forms [OPTIONS]Options:
| Option | Description |
|---|---|
--selector <css> | Target a specific form by CSS selector |
Notes:
- Password fields display
[redacted]in human-readable output (raw values are available in--jsonmode) - Output is limited to 100 forms and 500 fields per form; a truncation warning appears if exceeded
- The
--selectormust match a<form>element; other elements are rejected with an error
Examples:
# Dump all forms on the page$ tauri-pilot forms
# Target a specific form$ tauri-pilot forms --selector "#login-form"
# JSON output$ tauri-pilot forms --jsonJSON-RPC:
// Dump all forms{"jsonrpc":"2.0","id":1,"method":"forms.dump"}
// Dump specific form{"jsonrpc":"2.0","id":2,"method":"forms.dump","params":{"selector":"#login-form"}}record
Section titled “record”Record user interactions for later replay.
record start
Section titled “record start”Start recording interactions. All subsequent actions (click, fill, type, etc.) will be captured.
tauri-pilot record startrecord stop
Section titled “record stop”Stop recording and save captured interactions to a JSON file.
tauri-pilot record stop --output test.json| Option | Description |
|---|---|
--output, -o | Output file path (JSON format, required) |
record status
Section titled “record status”Check if recording is currently active.
tauri-pilot record statusreplay
Section titled “replay”Replay a previously recorded session.
tauri-pilot replay test.jsonExport as a shell script instead of replaying:
tauri-pilot replay test.json --export sh| Option | Description |
|---|---|
--export | Export format instead of replaying (supported: sh) |
Output format
Section titled “Output format”Recordings are stored as JSON arrays:
[ {"action": "click", "ref": "e3", "timestamp": 0}, {"action": "fill", "ref": "e2", "value": "test", "timestamp": 1200}]JSON-RPC examples
Section titled “JSON-RPC examples”// Start recording{"jsonrpc":"2.0","id":1,"method":"record.start","params":{}}
// Stop recording{"jsonrpc":"2.0","id":2,"method":"record.stop","params":{}}
// Check recording status{"jsonrpc":"2.0","id":3,"method":"record.status","params":{}}
// Add an explicit entry (e.g., assertion from CLI){"jsonrpc":"2.0","id":4,"method":"record.add","params":{"action":"click","ref":"e3","timestamp":0}}JSON-RPC Protocol
Section titled “JSON-RPC Protocol”The CLI communicates with the plugin over a Unix socket using a hand-rolled JSON-RPC 2.0 protocol with newline-delimited framing (\n).
You can interact directly with the socket using socat or nc for debugging:
echo '{"jsonrpc":"2.0","id":1,"method":"ping","params":{}}' | socat - UNIX-CONNECT:/tmp/tauri-pilot-com.myapp.sockRequest structure:
{"jsonrpc":"2.0","id":1,"method":"<method>","params":{...}}Success response:
{"jsonrpc":"2.0","id":1,"result":{...}}Error response:
{"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"Method not found"}}