English | 简体中文
CSI — Ctrl+Shift+I,每个程序员都按过的 DevTools 快捷键;也是 Crime Scene Investigation——AI 勘查浏览器案发现场。
Browser automation for AI agents. Let AI (Claude Code and other agents) control your real Chrome browser — navigate, click, type, read pages, take screenshots, save PDFs — using your actual login sessions. No automation-flagged browser, no separate profile: the agent drives the Chrome you already use. Under the hood it's a local Go daemon plus a Chrome extension (MV3) talking over the Chrome DevTools Protocol (CDP) — a lightweight alternative to MCP-based browser control or Playwright/Selenium when you need your real login sessions instead of a fresh headless profile.
AI client (Claude Code skill)
│ HTTP POST /command (JSON)
▼
┌─────────────────────────────┐
│ daemon (Go) │ 127.0.0.1:10088
│ HTTP server + WS server │ loopback only, no auth (v1)
└─────────────────────────────┘
▲ WebSocket /ws (extension is the WS client, auto-reconnects)
│
┌─────────────────────────────┐
│ Chrome extension (MV3 SW) │ runs in your real Chrome
│ executes tools via CDP │ debugger API on your tabs
└─────────────────────────────┘
- The daemon is an HTTP server for AI clients and a WebSocket server for the extension. The extension connects out to the daemon; only one extension connection is kept at a time.
- Every command carries a
sessionname; each session's tabs are collected into a Chrome tab group (agent:<session>) so you can see at a glance what the agent is doing. - Screenshots and PDFs are written to disk by the daemon and returned as file paths.
The full wire contract is in docs/protocol.md.
Prerequisites: Chrome. The extension comes from the Chrome Web Store or a prebuilt zip on GitHub Releases. The daemon is always a prebuilt binary from Releases — no Go/Node, and you do not need to build from source.
1. Install the extension from the Chrome Web Store.
2. Install the daemon (and Claude Code skills). --no-extension skips the unpacked zip — the store already has the extension:
# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/ximing/csi/master/scripts/install.sh | bash -s -- --no-extension# Windows (PowerShell 5.1+)
$env:CSI_NO_EXTENSION='1'; irm https://raw.githubusercontent.com/ximing/csi/master/scripts/install.ps1 | iex3. Open the extension popup and confirm it shows "connected".
4. Check everything is wired up (the installer already started the daemon; csi start is idempotent — safe to run anytime):
curl -s http://127.0.0.1:10088/status
# → {"running":true,"extension_connected":true,...}Use this when you cannot use the Chrome Web Store. The installer downloads the prebuilt daemon, csi-extension.zip, and skills.
1. Install — daemon → ~/.csi/bin, extension → ~/.csi/extension, Claude Code skills → ~/.claude/skills/csi + ~/.claude/skills/csi-e2e; the daemon is started at the end:
# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/ximing/csi/master/scripts/install.sh | bash# Windows (PowerShell 5.1+)
irm https://raw.githubusercontent.com/ximing/csi/master/scripts/install.ps1 | iex2. Load the extension in Chrome (manual step): chrome://extensions → Developer mode → Load unpacked → select ~/.csi/extension. Open the extension popup and confirm it shows "connected".
3. Check status — same curl as in Option A.
Both installers accept the same flags: --no-extension / -NoExtension (skip the unpacked zip; also CSI_NO_EXTENSION=1), --no-start / -NoStart (don't start the daemon), --no-autostart / -NoAutostart (don't register login autostart; also CSI_NO_AUTOSTART=1; re-running the installer turns autostart back on even after csi autostart off), --no-skill / -NoSkill (skip skills entirely), --agents codex,cursor / -Agents codex,cursor (pick skill targets — see Coding Agent Skills), -y / -Yes (don't prompt before overwriting an existing skill install). Pin a specific release with CSI_VERSION=v0.1.0.
If you live in Homebrew, the daemon is available from our tap — prebuilt binary, managed by brew services with KeepAlive (restarts on crash, starts at login):
brew tap ximing/csi
brew install csi
brew services start csiNotes:
- The formula installs only the daemon. Get the extension from the Chrome Web Store (Option A, steps 1 & 3), and the skills via your agent's plugin command (see Coding Agent Skills).
- Stop / restart with
brew services stop|restart csi— a plaincsi stopwon't stick: KeepAlive brings the daemon right back. - Already running a curl-installed daemon? Stop it first (
csi stop, or~/.csi/bin/csi stop) so the two don't fight over port10088.
| curl installer (Options A/B) | Homebrew (Option C) | |
|---|---|---|
| Installs | daemon + skills (+ extension zip) | daemon only |
| Binary | ~/.csi/bin/csi |
Homebrew prefix |
| Start / stop | csi start / csi stop |
`brew services start |
| Login persistence | csi autostart (no KeepAlive) |
brew services KeepAlive |
Drive the browser:
curl -s -X POST http://127.0.0.1:10088/command \
-H 'Content-Type: application/json' \
-d '{"action":"navigate","args":{"url":"https://example.com","newTab":true,"group_title":"Demo"},"session":"demo"}'
curl -s -X POST http://127.0.0.1:10088/command \
-H 'Content-Type: application/json' \
-d '{"action":"snapshot","args":{},"session":"demo"}'
curl -s -X POST http://127.0.0.1:10088/command \
-H 'Content-Type: application/json' \
-d '{"action":"screenshot","args":{},"session":"demo"}'The installer also copies two Claude Code skills to ~/.claude/skills/: csi (browser control — used automatically whenever you ask Claude Code to interact with websites) and csi-e2e (e2e test suites — see below).
Pick the channel that matches how you installed:
- Re-run the installer — it is idempotent, so the install commands from Quick start double as a full upgrade (daemon + skills + extension zip). The daemon is restarted automatically at the end.
csi update— updates just the daemon binary in place: downloads the new release, verifies the checksum, swaps the binary, and restarts the daemon if it is running.csi update --checkonly reports versions (current/latest/update_available) without changing anything;--with-skillsalso refreshes the skill packs under~/.claude/skills/,--with-extensionrefreshes the sideloaded extension under~/.csi/extension. Homebrew installs are refused (self-update would overwrite brew-managed files) — usebrew upgrade csiinstead.brew upgrade csi— for Homebrew (Option C) users.
The installer also registers a daily update task alongside login autostart: once a day it probes for a new release and self-updates the daemon. csi autostart off removes both the login entry and the daily task; csi autostart on brings both back. To see what it would find, run csi update --check yourself.
The extension and the skills move on their own tracks:
- Chrome Web Store extension — Chrome updates it automatically; nothing to do.
- Sideloaded extension — re-run the installer or
csi update --with-extension, then hit reload onchrome://extensions. - Skills —
csi update --with-skills, re-run the installer, or re-install via your agent's plugin command.
csi uninstall # asks for confirmation; -y skips the promptThis stops the daemon, removes login autostart and the daily update task, and deletes ~/.csi (binary, config, logs). Two things it deliberately leaves to you:
- Skill directories — remove
~/.claude/skills/csiand~/.claude/skills/csi-e2e(plus the copies under any other agents' skill dirs you installed to). - Chrome extension — remove it at
chrome://extensions. For a sideloaded install the unpacked entry is enough;~/.csi/extensionis already gone.
Homebrew installs keep the binary in the brew prefix, so finish with brew services stop csi && brew uninstall csi.
csi mcp runs a stdio MCP server exposing all 21 browser tools. It is a thin proxy: each tool call is forwarded to the local daemon's POST /command (same CSI_PORT, default 10088), so the daemon must be running (csi start).
Mount it in Claude Code:
claude mcp add csi -- ~/.csi/bin/csi mcpEach tool also takes an optional top-level session argument (default "default") that maps to the daemon's session field. screenshot/save_as_pdf return a file path — view it with the Read tool.
The installer also drops a second skill, csi-e2e, into ~/.claude/skills/. It turns natural-language browser scenarios into replayable e2e regression suites — driven by the same daemon, no test framework, no dependencies beyond Node ≥ 18:
- Describe — the model writes
e2e/cases/<name>.mdin your project: a header declaring the URL under test and how to start the app, then numbered steps each with a machine-checkable 【预期】. - Verify — it executes the case live in your real Chrome via the daemon, iterating until every expectation holds.
- Solidify — what passed gets translated into
e2e/suites/<name>.mjs(plain Node scripts talking to the daemon over HTTP). - Replay —
node e2e/run.mjs [suite...], no model involved.
Ask Claude Code to "write an e2e test for X" in any web project and the skill kicks in. See skills/csi-e2e/SKILL.md for the full workflow.
CSI ships Agent Skills in skills/ that teach coding agents to drive your real Chrome browser:
| Skill | Purpose |
|---|---|
csi |
Drive the user's real Chrome via the local daemon — navigate, click, type, screenshot, save PDF, with real login sessions. |
csi-e2e |
Turn natural-language browser scenarios into replayable e2e regression suites (describe → verify → solidify → replay). |
The skills are plain SKILL.md documents (plus references/ and templates) with no runtime dependency, so the same files work across coding tools. Installation differs by tool — if you use more than one, install separately for each.
/plugin marketplace add ximing/csi
/plugin install csi@csiOr manually: cp -r skills/csi skills/csi-e2e ~/.claude/skills/
This repository doubles as a Codex plugin marketplace (see .agents/plugins/marketplace.json), so no official listing is needed:
codex plugin marketplace add ximing/csi
codex plugin add csi@csiThe plugin manifest lives at .cursor-plugin/plugin.json. In Cursor Agent chat run /add-plugin csi, or search for csi in the plugin marketplace. Manually, copy the skill directories into .cursor/skills/ of your project.
Install from xAI's official plugin marketplace (listing in review at xai-org/plugin-marketplace#266):
grok plugin install csi@xai-official --trust/plugins install https://github.com/ximing/csi
Then start a fresh session (/new) so the plugin loads.
Add the plugin to opencode.json (global or project-level); it registers skills/ through OpenCode's plugin system:
{
"plugin": ["csi@git+https://github.com/ximing/csi.git"]
}pi install git:github.com/ximing/csiThe package manifest in package.json declares the skills/ directory for Pi's native skill discovery.
Note: the shell/PowerShell installers in Quick start can also drop the skills into other tools' directories directly — run them with
--agents codex,cursor,agents,opencode(orall; PowerShell:-Agents ...). Default isclaudeonly. Targets:~/.codex/skills/(Codex),~/.cursor/skills/(Cursor),~/.agents/skills/(the cross-tool standard dir, read by Cursor and OpenCode),~/.config/opencode/skills/(OpenCode). Kimi, Grok Build, and Pi use their own plugin install commands above — the installer doesn't cover them. The daemon is still required either way; the Chrome extension comes from the Chrome Web Store or the Release zip. Skills only teach the agent how to talk to the daemon.
21 tools: navigate, find_tab, snapshot (default compact YAML accessibility tree with @e refs), click, fill (inputs + contenteditable), evaluate, network, mouse_click (trusted coordinate-level clicks), wait, scroll, hover, key_type, send_keys, cdp (raw passthrough), screenshot, save_as_pdf, upload, list_tabs, close_tab, close_session, list_frames. See docs/protocol.md §4 for the exact contract.
csi/
├── docs/protocol.md # the single source of truth for the wire protocol
├── daemon/ # Go daemon (HTTP + WS server, session state)
│ └── cmd/csi/
├── extension/ # Chrome MV3 extension (TypeScript, service worker)
│ └── dist/ # build output — load this in chrome://extensions
├── skills/csi/ # coding-agent skill: browser control (SKILL.md + references/)
├── skills/csi-e2e/ # coding-agent skill: describe→verify→solidify→replay e2e suites
├── .claude-plugin/ # plugin manifests: Claude Code, Codex, Cursor, Kimi, OpenCode, Pi
│ └── ... # (.claude-plugin/ .codex-plugin/ .agents/ .cursor-plugin/ .kimi-plugin/ .opencode/)
├── scripts/ # installers: install.sh (macOS/Linux), install.ps1 (Windows)
└── .github/workflows/ # release.yml — tag v* → cross-build daemon + extension → GitHub Release
This section is for contributors. To use CSI, install the extension from the Chrome Web Store or a GitHub Release zip — do not build from source unless you are changing the code.
# daemon
cd daemon
go test ./...
go build -o ~/.csi/bin/csi ./cmd/csi
# extension
cd extension
npm install
npm run build # outputs extension/dist — reload in chrome://extensions
# release (pushes a tag → workflow cross-builds everything and drafts a Release)
git tag v0.1.0 && git push origin v0.1.0Protocol changes: edit docs/protocol.md first, then update both sides. The protocol file is the contract; implementations must follow it.
Port: default 10088, override with the CSI_PORT environment variable (set the same port in the extension popup). Click the extension icon → Settings to open the options page: view daemon status, change the port / log retention days / tool timeout, and adjust the auto-reconnect interval.
- The daemon binds
127.0.0.1only; there is no authentication in v1 — loopback is the isolation boundary (this machine vs the network, not a process sandbox). Anything that canPOST /commandcan drive your browser./wsadditionally rejects browser pages whoseOriginis notchrome-extension://…; empty Origin (curl, tests) is still allowed. That is not authentication — a local process can still connect. A hijacked slot receivestool_calls; it cannot drive the real extension. evaluateandcdpare arbitrary code execution channels in the page. That is a designed capability, not a bug — treat skill prompts accordingly.screenshot/save_as_pdfwrite the caller-suppliedpathas-is (parents created, existing files overwritten). There is no path sandbox: a local process that canPOST /commandis already in the loopback trust domain and can write those files itself. Prefer an absolutepath— relative ones resolve against the daemon's cwd, which is not the client's. See docs/protocol.md §7.uploadpasses caller-suppliedfilespaths as-is to ChromeDOM.setFileInputFiles. There is no Downloads (or other) path sandbox: the product is attaching user-specified local files — including project files — to a page file input. A random webpage cannotPOST /command; if an agent is tricked into uploading secrets, that is an agent/user trust issue. See docs/protocol.md §7.
PolyForm Noncommercial 1.0.0 — any noncommercial purpose is permitted (personal use, research, education, charities, government...); commercial use is not licensed. If you need a commercial license, open an issue.
- 0.4 Agent reliability — done: compact YAML snapshots, a real
waittool,scroll/hover, full-page screenshots, and a version handshake so a stale store extension says "please update" instead ofunknown tool. Spec: docs/superpowers/specs/2026-03-30-agent-reliability-design.md. - 0.5 Autostart — done:
csi autostart on|offplus installer default-on, so a reboot does not leave the daemon dead. - 0.6 Hard pages — iframe targeting (refs carry
frameId) is done. Still open: JS dialogs, downloads (CWS permission needed). - DirectCDPBackend: connect to obscura — a Rust headless browser with a built-in CDP server. The daemon would talk directly to its CDP WebSocket, no Chrome extension needed, for fully headless automation alongside the current real-Chrome mode.