@phnx-labs/browser-cli
v0.1.17
Published
Drive real browsers over CDP, WebDriver BiDi and native Arc
Readme
browser-cli
browser drives real browsers from the command line — the same Chrome, Brave,
Edge, Chromium, Comet, Firefox or Arc you use by hand, with their profiles and
cookies. It manages the browser process, tabs and network capture through a
local IPC service, so a sequence of commands (start, navigate, screenshot,
done) acts on one persistent session instead of a fresh headless launch each
time. It talks to Chromium-family browsers over the Chrome DevTools Protocol,
Firefox over WebDriver BiDi, and Arc over Apple Events, and it can drive a
browser on another machine over SSH.
Install
npm install -g @phnx-labs/browser-cli
browser --versionnpm installs a small Node launcher plus one compiled binary for your platform (macOS arm64/x64, Linux arm64/x64, or Windows x64). No TypeScript sources or source maps ship in the package.
First run
browser profiles create work --browser chromium
browser start --profile work
browser navigate https://example.com --profile work
browser screenshot -o shot.png
browser done --profile workstart launches (or attaches to) the browser for a profile and opens a task —
a named browsing context with its own tabs and capture ledger. Page verbs like
navigate and screenshot attach to that task: they resolve the caller's live
task, or take --task <id> to pick one explicitly. done closes the task's
tabs; browser stop stops the whole service.
Run browser --help for the full verb list and browser <verb> --help for its
options.
Command reference
scripts/generate-cli-docs.sh # refresh docs/
scripts/generate-cli-docs.sh --check # fail on stale docs
scripts/generate-cli-docs.sh --out-dir .agents/scratch/cli-docs # previewRun after bun install --frozen-lockfile. The script works from any directory;
--out-dir is relative to your current directory. Open command-reference.html
from the output folder to browse the tree and search commands.
CI uploads a browser-cli-docs artifact on pull requests and pushes to main
or release/**. It contains the HTML reference plus Markdown and JSON indexes.
Tests and releases check the committed files; commit regenerated docs/ with
command changes. Release checks also run with --skip-tests / --skip-build.
Browse the generated command reference or the command index for arguments, options, examples and notes.
Profiles and endpoints
A profile names a browser, where it runs, and how to reach it. Profiles are
machine-local and stored under ~/.agents/devices/<machine>/agents.yaml.
browser profiles create work --browser chrome # local Chrome, auto-assigned CDP port
browser profiles create hl --browser chromium --headless # headless Chromium
browser profiles list
browser profiles logins # signed-in services and accounts per profile
browser profiles logins --json # [{"profile","service","account"} | {"profile","service":null,"account":null,"unread"}]logins reads each profile's cookie store where its browser keeps it: Arc's
User Data/<profile dir>, Comet's own user-data dir, a pinned userDataDir,
or the runtime dir browser launched into. A store it cannot read here (a
profile declared on another device, a browser reached over ssh://, Firefox,
a profile never launched on this machine) is listed as (not read: <reason>),
and in --json as one {"profile", "service": null, "account": null,
"unread"} row, so a profile with no rows had its store read and has no live
session.
Each profile resolves to an endpoint:
cdp://127.0.0.1:9222— a Chromium-family browser over the DevTools Protocol.bidi=firefox-bidi://127.0.0.1:9674— Firefox over WebDriver BiDi.ssh://user@box?port=9222— a browser on a remote host reached over SSH.
Remote browsers
Bind a task to a browser on another machine with --device on start:
browser start --device box --profile work
browser navigate https://example.com
browser screenshot -o shot.png--device <alias> resolves against ~/.ssh/config, and against an inherited
context descriptor when the CLI runs under agents-cli. browser-cli itself does
not read a fleet registry. Use --device local to force the task onto this
machine. The device is bound once at start; page verbs run against the task's
bound device, so --device is only valid there.
Agent skill
The package ships the browser skill in the standard Agent Skills layout, so agents learn the CLI from the version that is installed:
skills/browser/
SKILL.md # workflow, defaults, where to look for flags
references/arc.md # Arc limits and sharing the user's window
references/sites/<site>.md # per-site guides (higgsfield, linkedin, perplexity, slack)
scripts/slack/*.js # page scripts the Slack guide runs with evaluate --filenpx skills add phnx-labs/browser-cli # install into your agents
browser skills path # the installed copy (link agents here)
browser skills get arc # read one document
browser help --json # every command, argument and optionThe skill lists no flags. Agents read browser <command> --help or
browser help --json, which always match the installed binary.
browser start --url prints the site guide for that host.
Using it through agents-cli
Agents CLI ships agents browser as a thin consumer of this binary. It forwards
every verb unchanged and adds the concerns it owns: fleet device discovery
(--device becomes an SSH target), agent-session identity, remote-control
consent, and cross-machine session history. The seam between the two — the
inherited context descriptor, the event stream, and the shared on-disk paths —
is documented in docs/integration.md. The command
reference is docs/browser.md.
Platform support
| Platform | Architectures | | --- | --- | | macOS | arm64, x64 | | Linux | arm64, x64 | | Windows | x64 |
Chromium CDP, Firefox BiDi and SSH endpoints work on all three. Native Arc control is macOS-only. Safari is not supported.
Troubleshooting
- Headless on Linux. A headless Chromium or Brave needs the usual shared
libraries (fonts,
libnss3,libatk,libgbm, and friends). Install your distribution's chromium package to pull them in; a missing library shows up as the browser process exiting immediately afterstart. - Port already in use. Each profile binds a debugging port. If
startreports a squatted port, another browser or a stale process holds it — stop it, or create the profile with a different--endpoint. - Comet and Arc. Comet is driven as a Chromium-family browser over CDP and works best as an attach-only profile against a browser you already launched. Arc is always attach-only and reuses an open tab or Space rather than creating one; it is macOS-only.
- Service state.
browser statusshows whether the IPC service is running and lists active tasks.browser stopshuts the service down.
Development
bash scripts/install.sh # install dependencies
bash scripts/test.sh # typecheck + tests
bash scripts/build.sh # compile this platform's binary into dist/scripts/build.sh bundles and minifies src/, obfuscates the bundle, then
compiles a bytecode binary per target. scripts/verify-compiled.mjs asserts the
shipped artifact behaves correctly and that source string literals do not survive
in plaintext. Run dist/<platform>-<arch>/browser directly during development.
Release with the repository's own script:
bash scripts/release.sh # print the release plan (dry run)
secrets exec npmjs.com -- bash scripts/release.sh --confirmRelease requires a clean linked worktree at the reviewed origin/main commit. It
builds every platform, verifies packed file lists and immutable package
integrity, publishes the launcher and per-platform packages, and checks a
registry install.
Minification, obfuscation and bytecode compilation raise the bar for casual inspection; they are not a guarantee against reverse engineering. Keep credentials out of the binary.
License
Functional Source License 1.1 with an Apache 2.0 future grant (FSL-1.1-Apache-2.0).
Browse history
browser sessions opens a searchable task and capture picker in a terminal.
Use arrows to move, Enter to browse or open a capture, and Escape to go back.
--no-interactive keeps the printed listing; --json keeps the existing
profile/capture schema. Add --tasks for durable task rows, including tasks
without captures, or --search <text> to filter those rows.
The same core filters as sessions apply to the picker, the printed listing
and --json: --since <when> / --until <when> take 2h, 7d, 4w, 1mo,
1y or an ISO date and keep rows by last activity (capture time in the
profile listing), and an invalid value exits 2. --limit <n> caps the printed
listing (default 50); --json is unbounded unless --limit is given. The
count footer (Showing 50 of 120 tasks. --limit 120 or --json to see all, …)
goes to stderr, so piped stdout carries rows only. The picker header names the
active filters.
browser sessions --since 7d
browser sessions --tasks --since 1mo --until 7d --json
browser sessions --no-interactive --limit 20Browser owns 365-day task summaries in .history/browser/history.db under
its configured Agents home. Neither Agents nor Sessions needs to be installed.
On first task listing it adopts legacy browser summaries read-only;
browser sessions migrate [--from /path/to/sessions.db] --json repeats the
import safely. Captures stay in place and are never deleted by summary retention.
