Releases: aeroxy/chrome-devtools-cli
chrome-devtools-cli v0.2.1
1. High-Level Summary (TL;DR)
- Impact: High - This is a major structural refactoring of how commands are executed, how results are bubbled up, and how the tool provides observability.
- Key Changes:
- Structured Results: Commands now return a typed
CommandResultcontaining metadata likenavigated_toanderror_codeinstead of plain strings. - Centralized Execution: Introduced
executor.rsto handle target resolution, session attachment, and unified command dispatching. - Telemetry Logging: Added an asynchronous background worker to record CLI command metrics (success/fail, duration) to local files.
- Direct File Output: Added
--output(-o) flags to commands (screenshot,snapshot,evaluate,navigate) for saving output directly to disk viatokio::fs. - Stable Error Codes: Introduced
ErrorCodefor machine-parseable error identification.
- Structured Results: Commands now return a typed
2. Visual Overview (Code & Logic Map)
This diagram illustrates the new execution pipeline, highlighting the centralized execution loop and the flow of the new structured CommandResult.
3. Detailed Change Analysis
🎯 Core Execution Pipeline
- What Changed: Replaced disparate target-resolution and CDP session-attachment logic across commands with a unified entry point in
src/commands/executor.rs.- Source:
executor.rs,commands/mod.rs - The
execute_command()function automatically clears staleCdpClientevents to prevent memory leaks in daemon mode, attaches to targets, runsinner_execute(), and safely detaches upon completion.
- Source:
- What Changed: Added
CdpClientTraitinsrc/cdp.rsto abstract CDP operations. This is a foundational step for dependency injection and mocking CDP connections in future testing.
📦 Structured Returns & Error Handling
- What Changed: Instead of commands returning
Result<String>, they now returnResult<CommandResult>. This struct encapsulates the text output, target ID, and navigation changes.- Source:
result.rs,protocol.rs
- Source:
- What Changed: Added a standardized
ErrorCodeenum and typedCliErrorto replace genericanyhowerrors in key paths. This enables downstream consumers (like an MCP server) to programmatically handle errors (e.g.,ErrorCode::ChromeConnection = 2).- Source:
error.rs
- Source:
💾 File Output & Command Flags
- What Changed: Enhanced commands to support writing their outputs directly to disk instead of exclusively printing to stdout.
tokio::fs::writeis utilized for async I/O. Added a-tflag toevaluateto track URL changes triggered by script execution.
| Command | New Flags | Description |
|---|---|---|
screenshot |
--output, -o |
Saves the Base64/binary image directly to the specified path. |
snapshot |
--output, -o |
Saves the JSON/text accessibility tree directly to the specified path. |
evaluate |
--output, -o, -t |
Saves result to file. Tracks navigations with -t (--track-navigation). |
navigate |
--output, -o |
Writes the success/result message to a file. |
📊 Telemetry & Daemon Reliability
- What Changed: Created a best-effort, non-blocking telemetry system utilizing an MPSC channel. A background worker thread opens log files in
~/.chrome-devtools-cli/logsand flushes command usage statistics (duration, success/failure).- Source:
telemetry.rs
- Source:
- What Changed: Exposed Daemon timeouts as environment variables to allow fine-tuning for slower environments (e.g., CI/CD).
Daemon Configuration:
| Environment Variable | Default Value | Description |
|---|---|---|
DAEMON_WAIT_TIMEOUT_SECS |
5 |
Maximum seconds to wait for a daemon to spawn. |
DAEMON_IDLE_TIMEOUT_SECS |
300 |
Maximum idle seconds before the daemon terminates itself. |
Dependencies Added:
| Package | Old Version | New Version | Purpose |
|---|---|---|---|
chrono |
None | 0.4.44 |
Used in telemetry.rs for timestamping log entries. |
4. Impact & Risk Assessment
⚠️ Breaking Changes (Protocol): TheDaemonResponseJSON structure has been modified. Two new fields (navigated_toanderror_code) have been added. Any external script strictly parsing the IPC socket responses might need updates, although the changes are additive.- 🐛 Testing Suggestions:
- File I/O Verification: Test the
--outputflag onscreenshotandsnapshotwith both valid and invalid (permission denied) file paths to ensure the async write handles errors gracefully. - Telemetry Logs: Run a few commands and inspect
~/.chrome-devtools-cli/logsto verify that the MPSC worker successfully writes log lines and doesn't block execution. - Navigation Tracking: Use
evaluate -t "window.location.href = 'https://example.com'"and verify that thenavigated_tofield in the response accurately captures the URL change.
- File I/O Verification: Test the
chrome-devtools-cli v0.2.0
1. High-Level Summary (TL;DR)
- Impact: Medium - Introduces cross-platform support for the background daemon and improves connection stability.
- Key Changes:
- ✨ Added Windows support by replacing Unix domain sockets with local TCP loops for Windows environments.
- 🛡️ Improved daemon startup resiliency by implementing an exponential backoff with jitter strategy in
wait_for_daemon(). - ♻️ Refactored the daemon loop in
src/daemon.rsby extracting request handling intohandle_connection(). - 🛠️ Enhanced fallback execution in
src/main.rsby routing failures cleanly throughrun_direct_fallback().
2. Visual Overview (Code & Logic Map)
3. Detailed Change Analysis
🖥️ Cross-Platform IPC Architecture
- What Changed: The application historically relied on
UnixStreamfor CLI-to-daemon communication. This PR introduces conditional compilation (#[cfg(windows)]and#[cfg(unix)]) to use aTcpStreambound to127.0.0.1:0on Windows, while preservingUnixStreamfor Linux/macOS. Additionally, the daemon process on Windows is now spawned with theCREATE_NO_WINDOWflag (0x08000000). - Source Files:
src/client.rs,src/daemon.rs,src/protocol.rs.
| Platform | Protocol | Connection Artifact | Process Flag |
|---|---|---|---|
| Unix | UnixStream / UnixListener |
/tmp/chrome-devtools-daemon.sock |
Default |
| Windows | TcpStream / TcpListener |
/tmp/chrome-devtools-daemon.addr |
0x08000000 (No Window) |
⏳ Resilient Daemon Connections
- What Changed: Updated the polling logic inside
wait_for_daemon(). Instead of a static 100ms delay, the client now utilizes an exponential backoff (starting at 50ms, doubling up to 500ms) paired with sub-millisecond jitter derived fromSystemTime::now(). - Source File:
src/client.rs.
♻️ Daemon Loop Refactoring
- What Changed: Extracted the massive inline loop body of
run_daemon()into a new state-driven function calledhandle_connection(). Arun_accept_loop_body!macro was created to orchestrate connection acceptance. A newConnectionOutcomeenum controls whether the loop shouldContinueor exit viaFatal. - Source File:
src/daemon.rs.
⚙️ CLI Execution & Fallback Routing
- What Changed: Added
run_direct_fallback()to cleanly handle scenarios where the daemon fails to boot (e.g. timeout or permission issues). Error handling for CLI help and version output (ErrorKind::DisplayHelp/ErrorKind::DisplayVersion) was streamlined to exit immediately without noisy error rendering. - Source File:
src/main.rs.
4. Impact & Risk Assessment
- Breaking Changes: None. This is a purely architectural and platform-support improvement.
- Testing Suggestions:
- Windows Environment: Validate that the daemon successfully spawns invisibly and communicates via TCP over localhost.
- Fallback Logic: Intentionally block the daemon port/socket creation and verify that the CLI correctly warns the user and completes the command using
run_direct_fallback(). - Concurrency: Trigger multiple CLI commands concurrently in a fresh environment to ensure the exponential backoff jitter prevents thundering herd issues on daemon spawn.
chrome-devtools-cli v0.1.3
New commands
list-3p-tools— lists custom developer tools exposed by the page viawindow.__dtmcp.toolGroupexecute-3p-tool <name> <params>— executes a named tool viawindow.__dtmcp.executeTool(name, params)with a JSON params string
Improvements
- Automatic dialog handling —
evaluateno longer hangs or fails when a script triggersalert,confirm, orprompt. Pass--dialog-action accept,--dialog-action dismiss, or a custom string (used as the prompt input) to handle dialogs automatically.
- Native
<option>clicking —clicknow detects<option>elements and selects them by updating the parent<select>value and dispatching nativeinput/changeevents, instead of attempting a synthetic mouse click that browsers ignore. - Environment variable support —
--ws-endpoint,--user-data-dir, and--channelcan now be set viaCHROME_WS_ENDPOINT,CHROME_USER_DATA_DIR, andCHROME_CHANNELenvironment variables.
chrome-devtools-cli v0.1.2
This release focuses on significantly improving reliability, interaction robustness, and the Developer/AI Agent Experience (Agent UX).
What's new
- Agent UX & Help Improvements: Automatically dumps the full help menu to stderr on invalid commands, preventing AI agents from wasting tokens on "guess-and-check" loops.
- In-band Agent Hints: The
evaluatecommand now detects common DOM traversal scripts (querySelector, etc.) and JavaScript exceptions, providing dynamic hints to use the token-efficientsnapshot,click, andfillcommands instead. - Rock-solid Daemon: The background daemon now binds its Unix socket instantly and connects to Chrome lazily. This eliminates timeouts caused by macOS "Allow Incoming Network Connections" dialogs. The daemon also automatically shuts down and recovers if Chrome crashes or the WebSocket closes.
- Advanced Form Filling: The
fillcommand natively handles<select>dropdowns (by value or text) and toggles<input type="checkbox">and<input type="radio">using"true"/"false"strings. - Global Dialog Prevention: Proactively detects open JavaScript dialogs (alerts, confirms). Commands like
clickorfillwill now fail immediately with a helpful error rather than hanging indefinitely, andevaluatesuggests using--dialog-action.
chrome-devtools-cli v0.1.1
This release introduces new interaction capabilities and improves asynchronous event handling.
What's new
- Coordinate clicking: New
click-at <x> <y>command for precise interaction when element selectors aren't sufficient. - Auto-dialog handling: New
--dialog-action <accept|dismiss|text>flag for theevaluatecommand to automatically handle JavaScript alerts, confirms, and prompts. - Enhanced typing: Added
--submit-key <key>flag totype-textto press keys likeEnterorTabimmediately after typing. - Asynchronous events: Refactored the internal CDP client to support listening for protocol events (like dialogs) during command execution.
Core benefits
- Native performance: Lightweight native binary with zero runtime dependencies.
- Agent-first architecture: Deterministic
[target:word-pair]page pinning and accessibility treesnapshotcommand for low-token-cost context. - Persistent connection: Background daemon maintains a single WebSocket connection to Chrome.
chrome-devtools-cli v0.1.0
Control Chrome from the terminal.
How it works
The CLI auto-connects to an existing Chrome browser by reading DevToolsActivePort from Chrome's user data directory — no manual WebSocket URL needed. On first run it spawns a background daemon that holds a persistent connection, so Chrome only prompts for DevTools access once. Subsequent commands reuse that connection with near-zero latency.
Page targeting
Every command prints a [target:red-snake]-style name — a deterministic word-pair derived from the page's internal ID. Pass --target red-snake to subsequent commands to stay on the same tab regardless of how Chrome reorders its pages.
Commands
Navigation: navigate, navigate --back/--forward/--reload, new-page, close-page, select-page, list-pages
Inspection: screenshot, screenshot --full-page, evaluate, snapshot
Interaction: click, fill, type-text, press-key, hover
Viewport: resize, wait-for
Prerequisites
Enable remote debugging in Chrome: open chrome://inspect/#remote-debugging and turn on the remote debugging server.
Installation
Homebrew (macOS)
brew tap aeroxy/chrome-devtools-cli
brew install chrome-devtoolsCargo
cargo install chrome-devtools-cliBuild from source
cargo build --release