# chrome-devtools

`chrome-devtools` is a profile-aware command-line wrapper for running Chrome DevTools MCP operations with isolated Chrome user data directories.

The tool is designed to be called as a regular CLI from agent skills. It is not registered in Hermes as an MCP server.

## Agent Skill Installation

This repository is also a single-skill repository. Install the skill with the Vercel Labs `skills` CLI:

```sh
npx skills add https://github.com/conao3/rust-chrome-devtools
```

Install it for Codex explicitly:

```sh
npx skills add https://github.com/conao3/rust-chrome-devtools -a codex
```

Install it globally:

```sh
npx skills add https://github.com/conao3/rust-chrome-devtools -g
```

For local development, install from a checkout:

```sh
npx skills add ./rust-chrome-devtools
```

## Design

- Profiles are explicit: every operation that targets a browser profile requires `--profile <name>`.
- Profiles own their Chrome user data directory and DevTools port.
- Profiles are read from `~/.config/chrome-devtools/config.toml`.
- If the config file is missing on startup, the CLI creates a `default` profile using `~/.config/chrome-devtools/profiles/default`.
- `user_data_dir` is optional; when omitted, it defaults to `~/.config/chrome-devtools/profiles/<profile-name>`.
- Prefer `user_data_dir` values under `~/.config/chrome-devtools/profiles/<profile-name>` so Chrome profile data stays with the tool config.
- The CLI may execute `chrome-devtools-mcp` internally for a selected profile.
- MCP JSON-RPC input and output are routed through one long-lived per-profile daemon by default.
- Hermes-side Chrome DevTools MCP registration is not required for this workflow.
- Snapshot `uid` values are MCP-process-local. Keep `take_snapshot -> click/fill` on the same profile daemon, or in one direct MCP process when bypassing the daemon.
- The daemon owns one `chrome-devtools-mcp` process per profile, so multiple CLI invocations do not create competing MCP processes for the same Chrome profile.
- `mcp direct-call` and `mcp direct-list` remain available as a fallback and take a per-profile lock under `~/.cache/chrome-devtools/locks`.

## Configuration

```toml
[[profiles]]
name = "default"
port = 9222
```

## Commands

```sh
chrome-devtools mcp list --profile default
chrome-devtools mcp call --profile default
chrome-devtools mcp help
chrome-devtools daemon start --profile default
chrome-devtools daemon status --profile default
chrome-devtools daemon stop --profile default
chrome-devtools profile list
chrome-devtools profile status --profile default
chrome-devtools profile stop --profile default
```

`mcp list` starts the profile daemon when needed, queries `tools/list` through that daemon, and prints the raw MCP JSON response.

`mcp call` starts the profile daemon when needed, forwards stdin JSON-RPC lines to the daemon-owned `chrome-devtools-mcp` process, waits for the matching JSON-RPC responses, and prints them to stdout. Each CLI invocation is serialized by the daemon, but the MCP process stays alive across invocations.

Important: `take_snapshot` result `uid` values are local to the running MCP process. The daemon keeps that MCP process alive for the selected profile, so a later `click`/`fill` can use snapshot state from an earlier daemon-routed invocation as long as the daemon has not restarted.

`daemon start` starts one background broker for the profile. Daemon metadata lives under `~/.cache/chrome-devtools/daemons`. `daemon stop` asks the broker to stop and cleans up its socket/pid files.

`mcp direct-call` and `mcp direct-list` bypass the daemon and run `chrome-devtools-mcp` directly. Use them only for fallback/manual debugging; they cannot preserve snapshot state across independent process invocations.

See [`docs/session-daemon-design.md`](docs/session-daemon-design.md) for the per-profile daemon/broker design and future session ownership direction.

`mcp help` prints MCP-specific usage, examples, and notes about stdio JSON-RPC forwarding.

## Development

This repository intentionally provides Rust through the Nix flake development shell. Do not assume `cargo` is installed globally.

```sh
nix develop -c cargo check
nix develop -c cargo fmt
nix develop -c cargo clippy
```
