Skip to main content
Glama
README.md
# claude-chrome

Claude-in-Chrome on steroids: MV3 extension + local hub daemon + MCP server.
Full plan in [PLAN.md](PLAN.md).

## Build

```bash
npm install
npm run build
```

## Install the extension

1. Open `chrome://extensions`, enable Developer mode.
2. "Load unpacked" → select the `extension/` folder.
3. The toolbar badge shows `●` (green) when connected to the hub.

## Register the MCP server

Claude Code (CLI):

```bash
claude mcp add claude-chrome -- node /Users/edem/Personal/claude-chrome/daemon/dist/index.js
```

Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "claude-chrome": {
      "command": "node",
      "args": ["/Users/edem/Personal/claude-chrome/daemon/dist/index.js"]
    }
  }
}
```

The MCP server auto-spawns the hub (`ws://127.0.0.1:48333`) if it isn't running.
Start it manually with `npm run hub` to watch logs.

## Tools

| Tool | What |
| --- | --- |
| `browser_navigate` | Open URL in the active (or new) tab, wait for load |
| `browser_outline` | Semantic page outline with `r<N>` refs (shadow DOM + same-origin iframes) |
| `browser_click` / `browser_type` | Act on `ref` / `css` / text match; trusted CDP input. Refuses hidden/covered/disabled targets (pass `force`) — surfaces bad page state instead of clicking into the void |
| `browser_check` | Visual/layout/animation audit: still-moving elements, horizontal overflow, broken images, covered/off-screen/tiny targets, unsettled animations |
| `browser_select` | Pick `<select>` option by value or label (fires input+change) |
| `browser_hover` / `browser_scroll` / `browser_key` / `browser_wait` | Mouse-over, wheel scroll, key combos ("ctrl+a", "Escape"), settle wait |
| `browser_text` | Plain page text (main content when detectable) |
| `browser_screenshot` | JPEG of the visible viewport |
| `browser_js` | Evaluate JS in the page (awaits promises) |
| `browser_network` / `browser_console` | Per-tab ring buffers; `failed_only` / `errors_only` filters |
| `browser_tabs` / `browser_tab_new` / `browser_tab_close` / `browser_tab_focus` | Tab management |
| `browser_resize` | Resize the window |
| `do` | Plain-text intent → matching saved flow → deterministic replay + smoke report |
| `flow_save` | Snapshot the last N journaled actions as a named flow |
| `flow_run` / `flow_list` | Replay / enumerate saved flows |
| `journal` | Inspect recent replayable actions before saving |
| `secrets_list` | Names of credentials available for login flows |

Flows persist in `~/.claude-chrome/flows.json`.

## Login flows (secrets)

Login pages don't break the run. Put credentials in `~/.claude-chrome/secrets.json`
(chmod 600) — you own this file; the values never pass through the chat, the journal,
saved flows, or logs:

```json
{ "crm_user": "you@example.com", "crm_password": "…" }
```

Then a login step is `browser_type secret="crm_password"`. The hub swaps the name for
the value only on the wire to the browser; `flow_save` records the **name**, so a saved
login flow re-resolves the current value on every replay. `secrets_list` shows the names.