|
| 1 | +# Running reins locally |
| 2 | + |
| 3 | +reins lets an MCP client (Claude Code, Codex) drive your real, logged-in |
| 4 | +Chromium browser. It has two halves: |
| 5 | + |
| 6 | +- **`reins-mcp`** — a stdio MCP server that hosts a localhost WebSocket and |
| 7 | + exposes browser tools (currently `list_tabs`). |
| 8 | +- **the extension** — an MV3 extension that connects to that WebSocket and |
| 9 | + executes commands in your browser. |
| 10 | + |
| 11 | +> Status: the `list_tabs` loop is implemented. Driving tools (`click`, `type`, |
| 12 | +> `navigate`, `screenshot`, …) land in M2. |
| 13 | +
|
| 14 | +## 1. Prerequisites & build |
| 15 | + |
| 16 | +```bash |
| 17 | +mise install # Node 24.18.0 + pnpm 11.9.0 |
| 18 | +pnpm install |
| 19 | +pnpm build # builds all three packages |
| 20 | +``` |
| 21 | + |
| 22 | +This produces: |
| 23 | +- `packages/mcp/dist/server.js` — the MCP server |
| 24 | +- `packages/mcp/dist/cli.js` — the `reins` CLI |
| 25 | +- `packages/extension/dist/` — the loadable unpacked extension |
| 26 | + |
| 27 | +## 2. Register the MCP server with your agent |
| 28 | + |
| 29 | +**Claude Code:** |
| 30 | + |
| 31 | +```bash |
| 32 | +claude mcp add reins -- node "$(pwd)/packages/mcp/dist/server.js" |
| 33 | +``` |
| 34 | + |
| 35 | +**Codex** (`~/.codex/config.toml`): |
| 36 | + |
| 37 | +```toml |
| 38 | +[mcp_servers.reins] |
| 39 | +command = "node" |
| 40 | +args = ["/absolute/path/to/reins/packages/mcp/dist/server.js"] |
| 41 | +``` |
| 42 | + |
| 43 | +On first start the server creates `~/.reins/{token,port}` (token is 32 random |
| 44 | +bytes, file mode 0600) and binds `ws://127.0.0.1:8765`. |
| 45 | + |
| 46 | +## 3. Load the extension |
| 47 | + |
| 48 | +1. Open `chrome://extensions` (or `dia://extensions` etc.). |
| 49 | +2. Enable **Developer mode**. |
| 50 | +3. **Load unpacked** → select `packages/extension/dist`. |
| 51 | + |
| 52 | +## 4. Pair the browser |
| 53 | + |
| 54 | +Print the pairing details: |
| 55 | + |
| 56 | +```bash |
| 57 | +node packages/mcp/dist/cli.js pair |
| 58 | +# WebSocket URL : ws://127.0.0.1:8765 |
| 59 | +# Token : <token> |
| 60 | +``` |
| 61 | + |
| 62 | +Click the reins toolbar icon, paste the **URL** and **token**, and hit |
| 63 | +**Connect**. The status pill turns green ("Connected") once the extension |
| 64 | +authenticates. |
| 65 | + |
| 66 | +(`reins doctor` checks the config; `reins status` shows the configured port.) |
| 67 | + |
| 68 | +## 5. Try it |
| 69 | + |
| 70 | +Ask your agent to call the `list_tabs` tool — it returns the live tabs of your |
| 71 | +paired browser (`tabId`, `title`, `url`, `active`). |
| 72 | + |
| 73 | +## Security notes |
| 74 | + |
| 75 | +- The server binds `127.0.0.1` only; the extension must present the pairing |
| 76 | + token and a `chrome-extension://` origin. |
| 77 | +- A bad token closes the connection (no infinite retry) and surfaces an |
| 78 | + "Auth failed" status in the popup. |
| 79 | +- The extension uses `chrome.debugger` in later milestones, which shows the |
| 80 | + native "being debugged" banner. The popup's **Disconnect** is the kill switch. |
| 81 | + |
| 82 | +## Troubleshooting |
| 83 | + |
| 84 | +- **Port already in use:** another `reins-mcp` is running (the default port is |
| 85 | + fixed at 8765). Stop the other client or override with `REINS_PORT`. |
| 86 | +- **Popup says "Auth failed":** re-run `reins pair` and paste the current token |
| 87 | + (the token rotates only if `~/.reins/token` is deleted/regenerated). |
0 commit comments