browserctl-cli
Self-contained global CLI to drive a standalone Chrome/Edge via browserctl commands. Designed for non-Electron use: CI pipelines, local automation scripts, or any context where you want the full browserctl command set without the Electron shell.
The command set is identical to the Electron-embedded browserctl; the difference is the daemon runs as a plain Node.js process rather than inside Electron.
Requirements: Node.js ≥ 20, Google Chrome or Microsoft Edge installed.
Install
npm install -g browserctl-cli
pnpm add -g browserctl-cli
Then:
browserctl open https://www.baidu.com
browserctl snapshot --interactive
browserctl quit
Global install registers the browserctl command (auto-starts a background daemon on first use).
Usage
Quick start:
browserctl open https://www.baidu.com
browserctl snapshot --interactive
browserctl fill @e1 "search query"
browserctl click @e2
browserctl screenshot --annotate --out shot.png
browserctl quit
Full command reference (same as desktop browserctl, minus Electron-only open-artifact / close):
browserctl health
browserctl open <url>
browserctl snapshot [--max-nodes 200] [--compact|-c] [--depth N|-d N] [--scope <sel>|-s <sel>] [--tree | --interactive]
browserctl wait (--selector <css> [--state visible|hidden] | --text <text> | --url <glob> | --load load|domcontentloaded|networkidle | --fn <js> | --fn-file <path> | --fn-stdin | --ms <n>) [--timeout 10000]
browserctl eval (<js> | --file <path> | --stdin) [--timeout 10000]
browserctl tab
browserctl tab new [--label <name>] [url]
browserctl tab <tN|label>
browserctl tab close [tN|label]
browserctl click <@eN|selector> [--confirm "确认文案"]
browserctl fill <@eN|selector> (<text> | --text-file <path> | --text-stdin)
browserctl hover|dblclick|focus|check|uncheck <@eN|selector>
browserctl type [@eN|selector] (<text> | --text-file <path> | --text-stdin)
browserctl drag <@eN|selector> <@eN|selector>
browserctl upload <@eN|selector> <file...>
browserctl press <key> [@eN|selector] [--ctrl|--shift|--alt|--meta]
browserctl scroll [@eN|selector] [--to top|bottom] [--by <px>]
browserctl select <@eN|selector> (<value> | --label <文本>)
browserctl get url|title|value|text|html|count|box|styles|attr <@eN|selector> [attrName]
browserctl is visible|enabled|checked <@eN|selector>
browserctl find role|text|…
browserctl back|forward|reload
browserctl scrollintoview|scroll-into-view <@eN|selector>
browserctl dialog status|accept [text]|dismiss
browserctl extract-text
browserctl screenshot [--full] [--annotate] [--out <path>]
browserctl batch [--bail] [--json] "<cmd>" …
Detailed syntax, find flag mode, dialog semantics, and batch examples:
command reference.
Browser extension recorder flows should be exported as browserctl-flow.json
and validated before they are turned into skills:
browserctl validate-flow browserctl-flow.json --pretty
browserctl run-flow browserctl-flow.json --var RECORDED_USERNAME=demo --var RECORDED_PASSWORD=secret
browserctl generate-skill browserctl-flow.json --out-dir ./skills
browserctl batch --json remains the low-level command-array executor. Use
run-flow for full browserctl-flow.json files because it resolves
credentials, inputs, and runtime capture bindings first.
fill focuses and clears the target, inserts text, then dispatches
input / change / blur. type appends without clearing; without a
target it types into the current focused element.
Tabs follow agent-browser's switch-then-operate style. Use stable tN IDs or
labels, never numeric indexes; run a fresh snapshot after switching. There is
no public --tab option. Structured batch --json items may capture
data.tabId and reuse it as a complete ${KEY} argv token; see the command
reference for the schema and errors.
Daemon lifecycle
The daemon process manages the browser session in the background.
Auto-start — the first browser command automatically starts the daemon (default: Chrome, headed, persistent profile at ~/.browserctl/profile-chrome). No explicit step needed.
Chrome window closed — if you close the browser window, the daemon exits automatically; the next browserctl command starts a fresh daemon and Chrome (login state is kept in the persistent profile). You do not need browserctl quit in this case.
Explicit start with non-default config — runs in the foreground; press Ctrl+C to stop:
browserctl serve --browser edge --headless
Stop — shuts down the daemon and closes the browser:
browserctl quit
Login state (OA / SSO)
Use the persistent profile to avoid repeated logins:
- Run any command (e.g.
browserctl open https://your-oa/) — Chrome opens with the persistent profile.
- Log in manually in the browser window that appears.
- Close the window or leave it open — the profile is preserved across restarts.
Subsequent daemon starts reuse the same profile, so login state is retained automatically.
Environment variables
BROWSER_RUNTIME_BRIDGE_URL | http://127.0.0.1:34555 | Daemon bridge URL (auto-set by CLI) |
BROWSER_RUNTIME_TIMEOUT_MS | 60000 | Per-request socket timeout |
BROWSERCTL_STATE_DIR | ~/.browserctl | Daemon PID/state directory |
Windows note: process cleanup
browserctl quit writes a stop signal and cleans the state file, but process.kill may not reliably terminate the daemon process on Windows. If the daemon lingers after quit:
Chrome is closed indirectly by the daemon's shutdown handler; if Chrome also lingers, close it manually.