- name
- tauri-connector
- version
- 0.16.0
- description
- Deep inspection, interaction, debugging, and code review for Tauri v2 desktop apps. Use this skill whenever: working with a Tauri app's UI (clicking, filling forms, reading DOM, screenshots, dragging elements); debugging console logs, IPC calls, or Tauri events; reviewing component trees, accessibility, or visual regressions; testing user flows or validating IPC contracts; setting up tauri-connector in a new project. Also triggers on: DOM snapshots, element refs, webview interaction, drag-and-drop, IPC debugging, Tauri app testing, visual regression, admin/ front/ or tool/ desktop apps, @eN ref syntax, or any mention of tauri-connector CLI or MCP tools. This is Claude's bridge to any running Tauri v2 desktop app -- if a Tauri app is involved, use this skill.
- allowed-tools
- ["Bash","Read","Glob","Grep"]
# Tauri Connector -- Debug & Code Review Suite
Inspect, interact with, debug, and review Tauri v2 desktop apps. The MCP server is embedded in the Tauri plugin -- it starts automatically when the app launches. No separate server process needed. (A standalone `tauri-connector-mcp` stdio binary also exists for clients that can't reach the embedded HTTP server; most sessions never need it.)
## Architecture
The plugin injects a JavaScript bridge into each Tauri webview. Commands flow through three paths:
| Path | When to use |
|---|---|
| **MCP tools** (preferred) | Claude has MCP access via `.mcp.json` -- tools appear as `webview_*`, `ipc_*`, etc. |
| **CLI** (`tauri-connector`) | Shell commands with `@eN` ref addressing from snapshots |
| **Bun scripts** (fallback) | Neither MCP nor CLI binary available -- scripts at `scripts/` relative to this skill |
Pick the first path available, in that order: MCP tools need no shell round-trip; the CLI needs the binary (`which tauri-connector`); Bun scripts need only `bun` plus this skill's `scripts/` dir. All three drive the same WebSocket protocol, so refs and capabilities behave identically.
Verify the intended application using its live PID record and actual ports; port 9555 is only a default. Match the PID, executable, app identifier and window before acting.
Port layout:
| Range | Purpose |
|---|---|
| 9300--9400 | Internal bridge (plugin <-> webview JS) |
| 9555--9655 | External WebSocket (CLI + bun scripts) |
| 9556--9656 | Embedded MCP HTTP server: `/mcp` Streamable HTTP, `/sse` legacy HTTP+SSE |
## Known multi-step intent: workflow first
For a known short sequence, query `workflow_capabilities`, then submit a strict sequential v1 spec with `workflow_run`. The application performs target resolution, input, condition checks and prior-step bindings. Use `workflow_get` to inspect the returned `runId` after a timeout or disconnect. Read an individual retained evidence reference with `evidenceId` and follow `evidencePage.nextOffset` as the next byte `offset` when the report is truncated. Reuse the same `runKey` and spec when the submission response is lost; never restart an uncertain write with a new key.
The host must configure a workflow token of at least 32 bytes. CLI/standalone MCP read `TAURI_CONNECTOR_WORKFLOW_TOKEN`; embedded MCP takes `authToken` outside the spec. Do not place tokens or other credentials in workflow inputs. Run fixture examples only against isolated test data.
```bash
tauri-connector workflow capabilities
tauri-connector workflow run fixture.json --wait-ms 30000
tauri-connector workflow get <runId> --include evidence
tauri-connector workflow resume <runId> --expected-revision 7 --checkpoint-id <checkpointId> --intent reconcile
```
For a complete local form spec with an explicit final goal, use the [isolated-form example](references/upgrade-and-smoke.md#example-workflow). Prepare its dedicated test controls first; use real business controls only when that action is the user's intended test.
Each locator must resolve to exactly one actionable element (`target_not_found` / `ambiguous_target` / `not_actionable` otherwise) -- narrow it with `name`, a nested `scope` locator, or `entity: {attribute, value}`. `runKey` identifies a logical workflow submission: resubmitting the identical spec returns the existing run, while a changed spec under the same key returns `run_key_conflict`. Check `authentication.configured` in `workflow_capabilities` when a call returns `unauthorized`.
The Bun fallback uses the same app-owned service: `bun run $SCRIPTS/workflow.ts run @arguments.json`, where the file contains `{"spec": {...}}`. Use `get`, `cancel`, `resume` or `capabilities` with their JSON arguments. It reads `TAURI_CONNECTOR_WORKFLOW_TOKEN`, checks application support, and preserves incomplete/failure exit codes.
`continue` is limited to an undispatched paused step within the same application instance and original deadline. `reconcile` only rechecks an available postcondition; it does not replay actions or erase the original failure. Cancellation prevents future dispatch and does not roll back prior effects. CLI codes are `0` completed, `1` failed/cancelled, `2` pending/paused/unknown; a `completed` run still exits `1` when `goalStatus`/`originalTestVerdict` is `failed` and `2` when `inconclusive`. Over MCP only the exit-1 case sets `isError`, so read `status` and `allowedNextActions` from the body. `goalStatus: not_requested` does not mean the business goal was verified. `query` steps refuse password/secret-looking fields (`capability_unavailable`). See `references/mcp-tools.md` and `references/cli-commands.md` for exact arguments and examples.
Workflow v1 supports role/label/testId/CSS locators; it rejects legacy `@ref` fallback, arbitrary JS, unknown IPC, parallel scheduling and transition-event assertions. DOM conditions establish observed UI state, not business persistence. For an unknown UI issue, continue with the inspection loop below.
## Core Loop: Debug Snapshot -> Act And Verify
Start with the high-level tools when debugging an unknown UI issue:
```bash
# MCP
debug_snapshot(includeDom: true, includeLogs: true, includeRuntime: true, includeScreenshot: true)
webview_act_and_verify(action: "click", selector: "@e5", waitForText: "Success", includeLogs: true, includeIpc: true, includeRuntime: true)
# CLI
tauri-connector debug snapshot --dom --logs --runtime --screenshot
tauri-connector act click @e5 --wait-text Success --logs --ipc --runtime
```
Fallback to the manual Snapshot -> Act -> Verify loop when you need finer control:
1. **Snapshot** the DOM to see what's on screen and get ref IDs
2. **Act** on elements using those refs (click, fill, drag, type, etc.)
3. **Verify** the result (re-snapshot, check logs, wait for element, screenshot)
Refs like `@e5`, `@e12` are stable handles assigned to interactive elements during a snapshot. The engine uses a multi-strategy fallback (CSS selector -> ARIA role+name -> tag+text content) to re-resolve them even after DOM changes. **Always re-snapshot after DOM-changing actions** -- old refs may point to stale or removed elements.
```bash
# MCP
webview_dom_snapshot(mode: "ai") # 1. Snapshot
webview_interact(action: "click", selector: "@e5") # 2. Act
webview_wait_for(text: "Success", timeout: 5000) # 3. Verify
# CLI
tauri-connector snapshot -i # 1. Snapshot (interactive refs)
tauri-connector click @e5 # 2. Act
tauri-connector wait --text "Success" # 3. Verify
```
---
## Debugging
### Console Errors
```bash
# Recent errors
read_logs(level: "error", lines: 100)
tauri-connector logs -l error -n 100
# Multi-level with regex
read_logs(level: "error,warn", pattern: "timeout|failed")
tauri-connector logs -l error,warn -p "timeout|failed"
# Historical logs (survive app restarts, stored as JSONL)
read_log_file(source: "console", level: "error", lines: 200, since: 1711900000000)
```
### IPC Debugging
Monitor all `invoke()` calls to find failing commands, unexpected args, or slow responses:
```bash
# 1. Start monitoring
ipc_monitor(action: "start")
tauri-connector ipc monitor
# 2. Trigger the action in the app
# 3. Check captured calls (each entry has: command, args, duration_ms, error)
ipc_get_captured(pattern: "user_\\d+", limit: 20)
tauri-connector ipc captured -p "user_\d+" -l 20
# 4. Test a specific command directly
ipc_execute_command(command: "greet", args: {"name": "test"})
tauri-connector ipc exec greet -a '{"name":"test"}'
# 5. Stop monitoring
ipc_monitor(action: "stop")
tauri-connector ipc unmonitor
```
### Protected inspection and active element selection
For bounded IPC return previews, use authenticated `ipc_capture` sessions and `ipc_query`; keep the returned session ID and follow readiness, gaps and pending status. Legacy IPC logs do not expose these protected results. An invoke observation does not establish backend persistence or a causal relationship to a workflow step.
For an ambiguous target, start `webview_select_element` (CLI `picker start` or `select-element`). The user hovers and confirms an actual element; use `get` / `cancel` with the returned handle across connections. Request-key retries preserve one picker and its deadline. Selection, screenshot and cleanup have independent status. Polling never repeats capture. The picker cannot edit an existing workflow spec or original verdict, and cannot release unknown-write quarantine. Review [the picker contract](references/mcp-tools.md#webview_select_element) before using candidates or requesting an image.
New inspection tools require `inspectionProtocolVersion:1` and the host's existing workflow token in the envelope, outside the spec. Verify application instance and page context; a health response or new screenshot never permits replaying a possibly dispatched write.
### Event Debugging
Monitor Tauri app-level events (not DOM events):
```bash
# Listen for specific events
ipc_listen(action: "start", events: ["user:login", "app:error", "state:update"])
tauri-connector events listen user:login,app:error,state:update
# Trigger actions, then check captured events
event_get_captured(pattern: "error", limit: 50)
tauri-connector events captured -p "error" -l 50
# Stop listening
ipc_listen(action: "stop")
tauri-connector events stop
```
### Visual Debugging
```bash
# Legacy window screenshot (xcap, with explicit DOM fallback provenance)
webview_screenshot(format: "png", maxWidth: 1280, save: true, nameHint: "debug")
tauri-connector screenshot --name-hint debug -m 1280
# Annotated vision map: labels [N] map to @eN refs from the latest ai snapshot
webview_dom_snapshot(mode: "ai")
webview_screenshot(format: "png", annotate: true, save: true, nameHint: "map")
tauri-connector snapshot -i && tauri-connector screenshot --annotate --name-hint map
# DOM snapshot shows full element tree with refs
webview_dom_snapshot(mode: "ai")
tauri-connector snapshot -i
# Search the snapshot for patterns
webview_search_snapshot(pattern: "error|warning", context: 3)
```
### Runtime State Inspection
```bash
# App metadata: name, version, debug/release, OS, arch, window list
ipc_get_backend_state()
tauri-connector state
# Execute arbitrary JS for runtime inspection
webview_execute_js(script: "(() => { return window.__APP_STATE__ })()")
tauri-connector eval "JSON.stringify(window.__APP_STATE__)"
# Check element computed styles
webview_get_styles(selector: ".error-banner", properties: ["display", "color", "visibility"])
tauri-connector get styles ".error-banner"
# Get specific element properties
tauri-connector get text @e7 # Text content
tauri-connector get value @e3 # Input value
tauri-connector get attr @e5 href # Attribute
tauri-connector get box @e5 # Bounding box
tauri-connector get count ".item" # Count matching elements
```
### Full Debug Recipe
When investigating a bug, use `debug_snapshot` first to collect app/bridge state, DOM, logs, runtime captures, and optional screenshot in one call. For a failing interaction, use `webview_act_and_verify` to mark, act, wait, and collect log/IPC/runtime diffs. If the verdict is inconclusive, fall back to the manual loop:
1. `debug_snapshot(includeDom: true, includeLogs: true, includeRuntime: true)`
2. `webview_act_and_verify(action: "...", selector: "@eN", waitForText: "...", includeLogs: true, includeIpc: true, includeRuntime: true)`
3. Manual fallback: `webview_dom_snapshot` -> `ipc_monitor(start)` -> action -> `read_logs` / `runtime_get_captured` / `ipc_get_captured` -> `webview_screenshot` -> `ipc_monitor(stop)`
For more recipes: read [references/debug-playbook.md](references/debug-playbook.md).
---
## Code Review
### Visual Regression Check
Capture before/after screenshots as artifacts, then diff them:
```bash
# MCP
webview_screenshot(format: "png", save: true, nameHint: "before-fix")
# ...apply the code change, rebuild/hot-reload...
webview_screenshot(format: "png", save: true, nameHint: "after-fix")
artifact_compare(before: "<beforeArtifactId>", after: "<afterArtifactId>")
# CLI
tauri-connector screenshot --name-hint before-fix
tauri-connector screenshot --name-hint after-fix
tauri-connector artifacts compare <beforeId> <afterId>
```
`artifact_compare` is a fast byte-level diff (`metric: "byte-diff"`), not a perceptual one: `percentDifferent` is the 0--1 fraction of differing bytes and `passed` means `percentDifferent <= threshold` (default 0). Byte-identical proves nothing changed; any nonzero diff only means *something* changed -- read both screenshots and judge visually before declaring a regression.
### Accessibility Audit
Use accessibility mode to review ARIA roles, names, and semantic structure:
```bash
webview_dom_snapshot(mode: "accessibility")
tauri-connector snapshot -i --mode accessibility
```
Check for: missing labels on interactive elements, incorrect ARIA roles, broken focus order, form fields without associated labels, missing alt text.
### Component Tree Review
React apps get component names extracted from fiber internals:
```bash
webview_dom_snapshot(mode: "ai", reactEnrich: true, followPortals: true)
tauri-connector snapshot -i
```
The snapshot shows React component names, stitches portals to their triggers, and annotates virtual scroll containers:
```
- combobox "Status" [ref=e5, component=InternalSelect, expanded=true]:
- listbox "Status options" [portal]:
- option "Active" [selected]
- option "Inactive"
- list [virtual-scroll, visible=8]:
- option "Item 1" [ref=e10]
```
### IPC Contract Validation
Verify that UI actions trigger correct IPC commands with expected arguments:
1. `ipc_monitor(action: "start")`
2. Walk through the user flow step by step
3. `ipc_get_captured()` -- verify each command name, args shape, and response
4. Check for: unexpected commands, missing required args, error responses, excessive duplicate calls
### DOM Structure Review
Scope snapshots to specific components for focused review:
```bash
webview_dom_snapshot(selector: ".ant-form", mode: "ai")
tauri-connector snapshot -i -s ".ant-form"
# Search DOM for patterns (data-testid coverage, class conventions, etc.)
webview_search_snapshot(pattern: "data-testid", context: 2)
```
### Event Flow Verification
Verify correct event sequences after user actions:
1. `ipc_listen(action: "start", events: ["state:update", "ui:refresh", "data:saved"])`
2. Perform the action being reviewed
3. `event_get_captured()` -- verify events fired in correct order with expected payloads
For more workflows: read [references/code-review-playbook.md](references/code-review-playbook.md).
---
## Interaction Reference
### Click, Fill, Type
```bash
# MCP
webview_interact(action: "click", selector: "@e5")
webview_interact(action: "click", selector: "button.submit", strategy: "css")
webview_interact(action: "double-click", selector: "@e3")
webview_interact(action: "focus", selector: "#email")
webview_keyboard(action: "type", text: "user@example.com")
webview_keyboard(action: "press", key: "Enter")
webview_keyboard(action: "press", key: "a", modifiers: ["ctrl"])
# CLI
tauri-connector click @e5
tauri-connector dblclick @e3
tauri-connector focus @e3
tauri-connector fill @e3 "user@example.com" # Clear + set value + fire input/change
View on GitHub