Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.9.1] - 2026-07-21
Window targeting by platform id: the window-consuming commands can now skip the title-regex path entirely. Additive and backwards-compatible — no flag changed meaning and all output additions are optional-only.
Added
-w, --window-id <id>onscreenshot,info,snapshot, andcapture(#9, reported by @papercupai) — target a window by its platform id (fromlist-windows) instead of a--titleregex. SkipsfindWindow()entirely, so there is no shell-quoting risk (ids have no spaces) and windows a title regex can't uniquely or reliably match (e.g. unmapped/headless windows underxdotool search) become addressable. The id passes through unvalidated at the CLI layer — its format is adapter-specific (X11/macOS/Sway numeric, Hyprland hex0x…); adapters that shell-interpolate ids keep their existingvalidateWindowId()guards.screenshot --window-idfull-window capture needs no bridge at all. Unrelated to--window-label(Tauri webview label, a bridge concept).- Shared
resolveWindowId()export fromsrc/commands/shared.ts(windowId > title > bridgedocument.titleprecedence), replacing three duplicated per-command resolution helpers.CaptureToDirOptionsgains an optionalwindowIdfield, andscreenshot --jsonoutput now includes the resolvedwindowId(both additive).
Changed
info --titleis no longer a required option — one of--titleor--window-idsuffices.--titlehelp text on window-targeting commands now notes that titles containing spaces must be shell-quoted (an unquoted title splits at the shell and can substring-match the wrong window).
[0.9.0] - 2026-07-15
Fork-uplift release: bug fixes and features generalized from the contextful_debugger fork. Everything is additive and backwards-compatible; schema additions are optional-only, and the bridge protocol change is opt-in by request shape.
Added
logs --follow(+--interval <ms>) — tail live bridge logs until interrupted. Against a v0.8 bridge this uses non-draining cursor long-polls (seeded at cursor 0 to replay the buffered backlog) so multiple log consumers can coexist; evicted entries surface as adropped-count warning. Against a pre-0.8 bridge it emits a one-timenote:and degrades to drain polling every--intervalms.sidecar replay --tap-format/--dir in|out— unwrap{dir,ts,line}tap wrapper rows (the common shape for bidirectional IPC tap recordings) before replaying, optionally filtered by direction. Malformed wrapper rows fail with a line-numbered error.captureToDir()library API —capture's pipeline is now an exported function (src/commands/capture.ts) returning theCaptureManifest, so other tooling can snapshot evidence programmatically. CLI behavior unchanged.BridgeClient.fetchLogs()cursor overload — passing{cursor, waitMs, limit, timeoutMs}returns{entries, cursor?, dropped?}via the non-draining v0.8/logscursor mode. A pre-0.8 bridge answers without acursorfield, so callers feature-detect by response shape with no extra round-trips (this is howlogs --followdecides to degrade to drain polling). The legacyfetchLogs(timeout?)drain call is unchanged; log-entry/response schemas gain optionalid,cursor, anddroppedfields.scripts/check-bridge-parity.mjs(npmcheck:bridge-parity, part ofnpm run lint) — lint gate that regex-parsesBRIDGE_VERSION+ the endpoint list fromdev_bridge.rsandENDPOINT_MIN_VERSIONfromclient.ts, failing on missing/extra entries or a min-version aboveBRIDGE_VERSION(semver compare, so legacy entries survive protocol bumps).
Changed
- Stronger artifact redaction —
bundlenow redacts via the sharedsrc/util/redactText.tsengine: Bearer/JWT/query-param/env-var secrets, AWS keys, emails, IPs, phone numbers, and home paths (including base64-encoded ones);.json/.ndjsonartifacts are re-serialized so they stay parseable after masking. The redact phase reports{redactions, warnings, failures}, fails on write-back failures, and flags unredacted images as warnings. AscanResidualSecrets()helper (known token prefixes + Shannon-entropy gate with a configurable artifact-name allowlist) is available for downstream gates. Clock times and ISO timestamps (which share the IPv6 colon-group shape) and bare~prose (~10s) survive redaction unchanged. probereports instead of throwing when no bridge exists — with nothing discoverable and no explicit--port/--token/--pid, probe now emits a complete result (JSON and human forms) withtarget.alive=falseand an actionablenote, so agents can branch on structured output.
Changed — Rust dev bridge (re-copy recommended, drop-in)
BRIDGE_VERSIONbumped from"0.7.0"to"0.8.0".- Cursor-mode
/logs: a request carrying{cursor, waitMs ≤ 25000, limit 1..1000}returns{entries, cursor, dropped}without draining the ring buffer; requests withwaitMs > 0long-poll on a worker thread (the accept loop is serial).LogEntrygains a monotonicid. Bare{token}requests keep the legacy drain semantics unchanged, so pre-0.8 CLIs are unaffected. - Integrators can re-copy
examples/tauri-bridge/src/dev_bridge.rsas a drop-in — nomain.rssignature changes this time. Without the re-copy,logs --followdegrades gracefully to drain polling.
Fixed
- Integer CLI flags now parse reliably. Every
.option(..., parseInt, <default>)coercion passed the option default toparseIntas its radix, so explicitly-passed values were ignored (--interval 1000→NaN→ silent fallback to the default) or misparsed (dom --depth 12, default 3, parsed in base 3 as 5). All 24 numeric flag coercions now share a base-10parseIntArg()helper incommands/shared.ts. - Bridge discovery now prefers the newest live bridge. Token files are sorted by mtime (newest first, filename tie-break) instead of readdir order, so running several bridge-enabled apps no longer attaches the CLI to a stale instance.
sidecar tapno longer drops or reorders envelopes under bursty output. Async chunk handling is serialized through a promise chain andclosewaits for it to drain before flushing the trailing line.
[0.8.0] - 2026-06-19
Real-world observability hardening. Everything in this release is additive and backwards-compatible: no command was removed or renamed, no flag changed meaning, no default output changed, and all schema additions are optional-only. The existing test suite passes unchanged; new behavior is opt-in or only affects paths that previously errored.
Added
logs— merge a Tauri app's scattered logs into one timestamp-ordered stream. Discovers and normalizes the on-disktauri-plugin-logLogDir files (auto-resolved fromtauri.conf.json, an--identifier, or--log-dir/--log-file) and the live bridge/logsring buffer, then emits NDJSON (--prettyfor humans). Timezone-less timestamps are normalized to UTC so ordering is host-independent. Filters:--level,--source,--filter;--correlateinfersrun_id/requestId-style correlation ids. Works with no bridge.bundle— collect a shareable incident bundle (mergedlogs+ deepprocess-tree+app-paths+forensics, plus an optional UIcapture) into one directory and a.tar.gz. Secrets (token/api_key/password/…) are redacted from text artifacts on write. Best-effort: each phase degrades cleanly.process-tree --deep— walk the real OS process descendant tree (sidecar children, MCP servers, ML workers — including grandchildren the bridge never registered) viaps. Needs no bridge with an explicit--pid. New optional JSON fields:ppid,children,source,descendants.ipc-monitor --slow <ms>/--stats— flag IPC calls that completed but took ≥ N ms, and print a per-command latency summary (count, max, avg, errors) on exit.--strictflag (shared) — for the v0.7-endpoint commands, fail with the actionable upgrade error instead of degrading.
Changed
- Graceful degradation against older/vendored bridges.
health,capabilities audit, andwebview attachnow feature-detect viaGET /versionand emit a clearnote:instead of throwing when the bridge predates v0.7 (default behavior;--strictrestores the hard error).process-treewithout--deepdegrades to the OS walk when the bridge lacks/processand the app PID is resolvable, otherwise it still surfaces the actionable upgrade error. This fixes a latent regression where these commands hard-failed against any bridge older than v0.7.0. BridgeClientgained a non-throwinghasEndpoint()capability check (shares the/versioncache withrequireEndpoint).- Agent skills (
tauri-agent-tools,tauri-debug-quickstart,tauri-bridge-setup) updated to document the new commands and the degrade-by-default behavior; the now-inaccurate "emits an error against older bridges" guidance was corrected.
Fixed
- macOS window listing on recent macOS. JXA's
ObjC.deepUnwraponCGWindowListCopyWindowInfobegan returning a non-array, so.mapthrew"list.map is not a function"and broke every macOS window command (screenshot,info,list-windows,snapshot,capture). The adapter now reads theCFArrayelement-by-element viaCFArrayGetCount/CFArrayGetValueAtIndex/castRefToObject, keeping the macOS adapter dependency-free on the built-inosascript(no PyObjC / pip). Thanks to @ethan-krich (#8).
[0.7.1] - 2026-05-18
Fixed
- Bridge auto-discovery now scans both
os.tmpdir()and/tmp, fixing macOS where the Rust dev bridge writes token files to/tmpbut Node'sos.tmpdir()resolves to/var/folders/.../T/. Closes #5. - Dev bridge eval callbacks now use Tauri 2's
window.__TAURI_INTERNALS__.invokepath first, so apps no longer needapp.withGlobalTauri: truefor bridge-backed commands (dom,click,eval,page-state,screenshot --selector, etc.). Closes #7. - Documented the missing
libc = "0.2"Cargo dependency inrust-bridge/README.mdanddocs/getting-started/bridge-setup.md. The bridge's/processand/healthendpoints depend onlibc::kill()for sidecar liveness probing on Unix. Closes #6.
[0.7.0] - 2026-05-13
Added — Agent UX (Tier 3)
diagnose— best-effort super-command. Composesforensics(Tier 1) with live bridge data (Tier 2) into one bundle. Always runs the forensics half; layers/process,/capabilities,/devtools,/healthon top when a bridge is reachable. Output:<out-dir>/{summary.md, summary.json, bridge.json, forensics/...}. Use--no-bridgeto skip the bridge phase entirely.- New agent skill:
tauri-debug-quickstart— first-30-seconds triage skill with symptom → command table, decision flowchart, and "when this skill is wrong" caveats. - MkDocs troubleshooting page —
docs/troubleshooting/decision-tree.mdwith a mermaid flowchart mirroring the skill's symptom-table for human readers.
Added — Bridge-extending diagnostics (Tier 2)
Four CLI commands that talk to new dev-bridge endpoints. Each calls GET /version first to feature-detect; against a pre-v0.7 bridge they emit "requires bridge v0.7.0+ — re-copy examples/tauri-bridge/src/dev_bridge.rs" instead of an opaque 404.
process-tree— Tauri PID + registered sidecars rendered as a tree withalive/DEADannotations.capabilities audit— Devtron-style live audit of declared Tauri capabilities, surfacing wildcard"*", over-broadfs:allow-all/shell:allow-*/http:allow-all, and window labels referenced but not registered.webview attach— print the webview inspector URL (webview2/webkitgtk) or platform hint (wkwebview— Safari activation).--print-urlfor scripting,--opento launch the default browser.health— uptime + webview readiness + per-sidecar liveness. Exits non-zero when the app is unhealthy so this can drive CI gates.
Added — Bridge-free diagnostics (Tier 1)
The toolkit can now diagnose Tauri apps without needing a live debug bridge — covering release builds, dead processes, and sidecar protocols.
app-paths— resolve a Tauri 2 app's OS data/log/cache/config directories fromtauri.conf.json(or a bare--identifier). Encodes Tauri 2'sPathResolversemantics for all three platforms;--existsflag annotates which paths are present on disk.config inspect— emit a structured snapshot oftauri.conf.jsonplus a Devtron-style capability matrix. Cross-checks capability permissions againstCargo.toml's plugin declarations and flags wildcard / over-broad scopes (*,fs:allow-all,shell:allow-spawn, …).os-logs— tail the host OS's log stream filtered to a Tauri bundle id. macOS useslog streamwith asubsystem == "<id>"predicate; Linux usesjournalctl --user -t <productName>. Output is one normalized NDJSON envelope per line. Windows is stubbed for v0.7.sidecar tap/sidecar replay— wrap-and-run a sidecar binary, frame its stdout as NDJSON, validate each envelope against an optional JSON Schema (--schema <path>, powered by Ajv), and record the raw stream to a file with--record.sidecar replayreads the recording back to stdout or pipes it into a fresh process via--to-exec, optionally rate-limited with--rate <lps>.forensics— one-shot bundle for post-crash analysis. Resolves the project, lists files inappDataDir/appLogDir, tails the most-recent log for panic markers, pulls macOSDiagnosticReportsfiltered byproductName, captures a brief live OS-log tail, and writessummary.md+summary.json+ supporting artifacts. Zero bridge calls — works on a dead app.
Changed — Rust dev bridge (BREAKING for integrators)
BRIDGE_VERSIONbumped from"0.6.0"to"0.7.0".- Four new endpoints:
/process,/capabilities,/devtools,/health(all POST + token auth). start_bridgenow returns(u16, Arc<LogBuffer>, Arc<SidecarRegistry>)instead of(u16, Arc<LogBuffer>). Integrators destructure the third element to register sidecars.spawn_sidecar_monitorednow takes an optionalOption<&Arc<SidecarRegistry>>so spawned sidecars appear inprocess-tree/health. PassNoneto opt out.- New
register_sidecar()for users who spawn children manually. - Added
libc = "0.2"Cargo dep (Unix only) for the cheapkill(pid, 0)liveness probe.
Integrators must re-copy examples/tauri-bridge/src/dev_bridge.rs and adjust main.rs to destructure the new return shape. The CLI's new commands fail loudly with a "re-copy" error against older bridges, so partial upgrades are obvious.
Internal
- New deps:
ajv^8,ajv-formats^3 (NDJSON envelope schema validation). - Command count: 25 → 36. Test count: 623 → 710.
[0.6.0] - 2026-04-04
Added
- Interaction commands —
click,type,scroll,focus,navigate,selectfor agent-driven UI interaction (debug builds only) invokecommand — call Tauri IPC commands from the CLI with JSON payload supportstore-inspectcommand — inspect reactive store state (Pinia, Vue devtools, custom__DEBUG_STORES__hook)capturecommand — collect screenshot + DOM + page state + storage into a single debug evidence bundlecheckcommand — structured assertions against DOM state with pass/fail resultsprobecommand — target discovery and bridge health checkeval --fileoption — load JavaScript from a file instead of inline string--pidand--window-labelbridge options for multi-app and multi-window targetingBridgeClientmulti-window eval via optionalwindowLabelparameter- Zod schemas for interaction command results (
schemas/interact.ts) - Shared interaction utilities:
escapeSelector(),buildFindElementScript()
Changed
- Rust bridge example: added
/versionand/describeendpoints, multi-window eval support - Command count increased from 14 to 25
[0.5.1] - 2026-03-24
Added
src/util/magick.ts— ImageMagick version detection module with caching; auto-detects v6 (standaloneconvert) vs v7 (unifiedmagickbinary) at runtime (#4)
Fixed
- ImageMagick v7 compatibility — all ImageMagick invocations (
convert,import,identify,compare) now route through the version-awaremagickCommand()resolver, usingmagick <subcommand>on v7 and standalone commands on v6 resizeImage()backslash escape bug —-resizeargument was800x\>(literal backslash) instead of800x>, causing "invalid argument" errors on ImageMagick v7- Tool availability checks (
detect.ts) now recognizemagickbinary as valid ImageMagick installation, falling back toconvertfor v6
[0.5.0] - 2026-03-23
Added
- Hyprland Wayland compositor support via
HyprlandAdapterusinghyprctlfor window management andgrimfor screenshots (#3 by @gabrielpgagne) HYPRLAND_INSTANCE_SIGNATUREenvironment variable detection for automatic adapter selectioncheckHyprlandTools()for verifying Hyprland-specific tool availabilityHyprClientSchemaZod schema for validatedhyprctl clients -joutput
Changed
DisplayServertype now distinguisheswayland-sway,wayland-hyprland, and genericwaylanddetectDisplayServer()checksSWAYSOCKandHYPRLAND_INSTANCE_SIGNATUREfor compositor-specific adapterscheckWaylandTools()renamed tocheckSwayTools()for clarity
[0.4.0] - 2026-03-19
Added
rust-logscommand — monitor Rust backendtracing/logoutput and sidecar process stdout/stderr in real-time via the bridge's/logsendpointRustLogEntrytype for structured Rust log entries with timestamp, level, target, message, and source fieldsBridgeClient.fetchLogs()method for polling the/logsendpoint with 404 detection for old bridges- Severity-based level filtering (
--level warnshows warn and error, matching RustRUST_LOGconvention) --target <regex>filtering by Rust module path--source <source>filtering by origin (rust,sidecar,all, orsidecar:<name>)- Rust bridge:
LogBufferring buffer (max 1000 entries),BridgeLogLayertracing layer,spawn_sidecar_monitored()helper,POST /logsendpoint,create_log_layer()public API
Changed
start_bridge()now returns(u16, Arc<LogBuffer>)instead ofu16- Bridge example requires
tracingandtracing-subscribercrate dependencies
[0.3.0] - 2026-03-17
Added
diffcommand — compare two screenshots with pixel-level difference metrics, threshold gating, and diff image outputmutationscommand — watch DOM mutations on a CSS selector with polling, attribute tracking, and auto-cleanupsnapshotcommand — capture screenshot + DOM tree + page state + storage in a single invocationdom --text <pattern>option — find elements by text content (case-insensitive), respects--first,--count, and selector scoping
Fixed
- CSS selector escaping in mutation observer now escapes backslashes before single quotes (consistent with bridge client)
dom --textnow scopes search to the provided selector instead of always searchingdocument.bodydom --text --firstflag is now respected (was previously ignored)diff --thresholdnow throws a clear error whenidentifyfails instead of silently reporting 0%
Changed
buildSerializerScriptexported fromdom.tsfor reuse bysnapshotcommandformatEntryandMutationEntryexported frommutations.tssnapshotdeduplicates window discovery via sharedresolveWindowIdhelper
[0.2.1] - 2026-03-17
Fixed
- CLI
--versionflag now reads frompackage.jsoninstead of being hardcoded
[0.2.0] - 2026-03-17
Fixed
- Dev bridge now returns actual JS eval results instead of echoing back the expression string
- Uses Tauri command callback pattern (
__TAURI__.core.invoke) for reliable round-trip evaluation - All bridge-dependent commands (dom, eval, screenshot --selector, storage, console-monitor, ipc-monitor, page-state) now work correctly
Changed
- Bridge setup requires
uuidcrate andinvoke_handlerregistration inmain.rs - Updated integration guide and agent skill with new setup steps
[0.1.0] - 2025-03-17
Added
- Initial CLI with 11 commands:
screenshot,dom,eval,wait,info,list-windows,ipc-monitor,console-monitor,storage,page-state - Rust dev bridge with token-authenticated localhost HTTP server
- Platform support: Linux X11, Linux Wayland/Sway, macOS CoreGraphics
- Agent Skills (
.agents/skills/) andAGENTS.mdfor agent-driven discovery - DOM-targeted pixel capture using bridge + ImageMagick crop
- Auto-discovery of bridge via
/tmptoken files - All commands read-only with
--jsonstructured output