chrome-cdp-skill: driving your live Chrome session from an agent CLI
Give your AI agent access to your live Chrome session — works out of the box, connects to tabs you already have open
At a glance
- What is it?
- chrome-cdp-skill is an MIT-licensed Node.js CLI that attaches an AI agent to the Chrome you already have open, using one persistent daemon per tab. It trades isolation for your real logged-in state, and the trade-off is the whole point.
- Who is it for?
- Adopt chrome-cdp-skill if your agent needs pages that only exist behind your logins, or if a Puppeteer-style tool keeps timing out while enumerating a large tab set. Skip it if you need a disposable, reproducible browser profile, since this design deliberately has none.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 79 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: agents that need your logged-in browser, not a clean one
Most browser automation starts by launching a fresh browser. That browser has no cookies, no sessions, no open tabs, and no history of what you were doing five minutes ago. The README states the motivation directly: this project connects to the Chrome you are already running so an agent can read pages you are logged into (it names Gmail, GitHub and internal tools), interact with tabs you are actively working in, and see the actual state of a page mid-workflow rather than a clean reload. That last point is the one that matters most in practice. If a form is half filled, a modal is open, or a single-page app has accumulated state across several clicks, a fresh browser cannot reproduce it, and a scripted replay of the clicks is a different thing from observing the page as it stands. The intended user is someone whose agent work depends on authenticated, stateful pages, and who is willing to give that agent access to a real browser profile. The project is a JavaScript CLI, MIT-licensed, with no homepage listed in the repository metadata.
One daemon per tab, and why the Allow modal appears once
The mechanism is a direct WebSocket connection to Chrome's remote debugging endpoint. There is no Puppeteer and no intermediary process in the path. On the first command that touches a given tab, the CLI spawns a lightweight background daemon that holds that session open. Chrome's Allow debugging modal appears once per tab, and every later command reuses the existing daemon silently. Daemons exit on their own after 20 minutes of inactivity, so an idle tab does not hold a connection forever. The README contrasts this with chrome-devtools-mcp, which it says reconnects on every command, causing the Allow modal to reappear repeatedly and target enumeration to time out when many tabs are open. The project claims the persistent-daemon design handles 100+ tabs reliably. I cannot verify that number from the material, but the architectural reason is legible: enumeration is paid once per tab rather than once per command. The cost is a process per tab that you do not directly manage. The stop command exists for that reason.
Getting it running: one toggle, one install line, Node.js 22+
The runtime dependency is Node.js 22 or newer, and the README states no npm install is needed. As a pi skill the install is a single command: pi install git:github.com/pasky/chrome-cdp-skill@v1.0.1. For other agents (Amp, Claude Code, Cursor and similar), you clone or copy the skills/chrome-cdp/ directory into wherever your agent loads skills or context from. The browser side is one toggle: navigate to chrome://inspect/#remote-debugging and switch it on. The CLI auto-detects Chrome, Chromium, Brave, Edge and Vivaldi on macOS, Linux and Windows. If your browser writes DevToolsActivePort somewhere non-standard, set the CDP_PORT_FILE environment variable to the full path. Note the version skew in the material: the install example pins v1.0.1 while the releases list shows v1.1.0 as the most recent tag, so the pinned example in the README is not the newest release. Commands are subcommands of scripts/cdp.mjs, and the target argument is a unique prefix of the targetId printed by list.
The command surface, and the two that behave differently
The verbs are list, shot, snap, html, eval, nav, net, click, clickxy, type, loadall, evalraw, open and stop. Most map to a single page operation: shot writes a screenshot to a runtime directory, snap returns the accessibility tree in what the README calls a compact, semantic form, html returns full markup or a subtree scoped by CSS selector, eval runs an expression in page context, nav navigates and waits for load, net returns network resource timing, click targets a CSS selector while clickxy targets CSS pixel coordinates, and loadall repeatedly clicks a load-more selector until it is gone. Two deserve separate mention. The type command types at the focused element and the README states it works in cross-origin iframes, which is a case where selector-based clicking often cannot reach. The evalraw command is a passthrough for arbitrary CDP methods with a JSON argument, which is the escape hatch when no subcommand covers what you need. The open command carries an explicit warning in the usage list: it triggers the Allow prompt. That is a small but honest piece of documentation, because it tells you the modal is not fully retired by the daemon model, only reduced.
Where this is the wrong tool
The design gives an agent your real browser profile, and that is a security boundary, not a convenience feature. Anything the agent can reach through a tab, it can read, and the eval and evalraw commands execute arbitrary JavaScript in page context. There is no sandbox described in the material, because the entire premise is that there is no separate browser to sandbox into. The second limitation is reproducibility. A fresh browser is a known starting state; your live session is not, and two runs of the same agent task will not see the same DOM, the same cookies, or the same open tabs. If your workflow needs a clean profile per run, this project is pointed the wrong way. Third, the daemon lifecycle is a resource you are trusting to a 20-minute idle timer. If a daemon is wedged, the visible recovery path is stop, optionally scoped to a target. Fourth, the Chrome toggle at chrome://inspect/#remote-debugging is a browser-level setting, and the README treats it as a prerequisite rather than something the tool manages, so it is on you to know whether it is on. Finally, the whole model assumes the Allow modal behaves as described. The README's claim that it fires once per tab is the load-bearing assumption, and it is a claim about Chrome's behaviour, not about this code.
The alternative: chrome-devtools-mcp and the reconnect trade-off
The README names chrome-devtools-mcp as the comparison point, and the difference is architectural rather than cosmetic. chrome-devtools-mcp reconnects on every command. chrome-cdp-skill holds a persistent daemon per tab. Those two choices produce opposite failure profiles. With per-command reconnection, the Allow modal can reappear repeatedly, and target enumeration times out when many tabs are open, according to the README. With a persistent daemon, the modal fires once and enumeration is amortised, but you now have long-lived background processes attached to your browser and a stop command to remember. Neither is strictly better. If your agent runs short, isolated tasks against a handful of tabs and you would rather not have daemons lingering, the reconnect model is simpler to reason about. If your agent works against a large tab set and the modal is interrupting every step, the daemon model addresses exactly that. The choice is about which failure you would rather debug.
Upgrades, the pinned version, and what MIT does not settle
The material shows two releases: v1.0.2 in March 2026 and v1.1.0 in June 2026, with the last push to the repository on the same day as v1.1.0. That is a small release history, so there is little to infer about upgrade cadence. What is concrete is the version skew: the README's install command pins v1.0.1 while the newest tag is v1.1.0. If you copy that line verbatim you will install an older release than the one the repository advertises. For non-pi agents the upgrade path is whatever your copy of skills/chrome-cdp/ does, which means upgrades are manual unless you re-copy the directory. There is no npm install step to update, and no dependency tree to audit, which keeps maintenance low. The licence is MIT, which permits commercial and private use; that is a statement about the licence text, not legal advice, and you should read the LICENSE file yourself if the distinction matters to your organisation. The larger operational cost is not code maintenance at all. It is the standing decision to expose a live, authenticated browser to an agent process, and no upgrade will change that.
Editorial conclusion
Adopt chrome-cdp-skill if your agent needs pages that only exist behind your logins, or if a Puppeteer-style tool keeps timing out while enumerating a large tab set. Skip it if you need a disposable, reproducible browser profile, since this design deliberately has none. Before relying on it, verify the Node.js 22+ requirement against your runtime, confirm the DevToolsActivePort file location or set CDP_PORT_FILE, and test the Allow debugging modal against your Chrome build, because the README's claim that it fires once per tab is the load-bearing assumption behind the whole daemon design.
Community notes