pire-browser
Cross-platform Pi extension and Firefox bridge for local browser automation
Package details
Install pire-browser from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pire-browser- Package
pire-browser- Version
0.2.1- Published
- Jun 2, 2026
- Downloads
- not available
- Author
- ryenw
- License
- MIT
- Types
- extension, skill
- Size
- 209.8 KB
- Dependencies
- 0 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"pi/extensions/pire-browser.ts"
],
"skills": [
"skills"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pire-browser
Firefox automation for AI agents. pire-browser gives Pi and shell-based agents a local CLI for launching Firefox, inspecting pages, clicking and filling by stable refs, handling downloads/uploads, and reusing logged-in Firefox profiles.
It intentionally does not use BiDi or CDP. Firefox loads a WebExtension, the WebExtension talks to a native messaging host, and the CLI talks to that host through current-user IPC: Windows named pipes on Windows and Unix domain sockets on macOS/Linux.
Installation
Pi Package
Install the public Pi package:
pi install npm:pire-browser
Then start Pi and ask it to use the pire-browser tool:
pi
Use pire-browser to open https://example.com and snapshot the page.
Global CLI
Install the command directly:
npm install -g pire-browser
pire-browser setup
setup registers the Firefox Native Messaging host for the current OS user. Install also runs best-effort setup, but it is safe to run again.
Project Install
For projects that want to pin the version:
npm install pire-browser
npx pire-browser setup
If optional dependencies are disabled with --omit=optional, reinstall with optional dependencies enabled. The root package uses a small JS launcher plus one native optional package for your OS/architecture, such as @ryenw/pire-browser-win32-x64, @ryenw/pire-browser-darwin-arm64, or @ryenw/pire-browser-linux-x64.
From Source
Requires Node.js, npm, Rust, and Firefox.
git clone https://github.com/ryenwang/pire-browser
cd pire-browser
npm install
npm --prefix extension install
npm run build:extension
cargo build
cargo run -p pire-browser-cli -- setup
Build a platform package binary pair:
node scripts/build-platform.mjs win32-x64
Use the tuple for your platform: win32-x64, win32-ia32, win32-arm64, darwin-x64, darwin-arm64, linux-x64, or linux-arm64.
Requirements
- Firefox.
- Pi 0.75.4 or newer when installing as a Pi package.
- Supported public beta targets: Windows x64, Windows x86, Windows ARM64, macOS x64, macOS ARM64, Linux glibc x64, and Linux glibc ARM64.
- Alpine/musl Linux is not part of the beta.
On Linux, distro Firefox builds work best. Snap and Flatpak Firefox are detected, but sandboxed native messaging may require the WebExtensions portal or a non-sandboxed Mozilla Firefox build.
Custom Firefox Path
If Firefox is installed somewhere unusual:
pire-browser setup --firefox-path /path/to/firefox
PowerShell example:
$env:PIRE_BROWSER_FIREFOX_PATH = "D:\Apps\Mozilla Firefox\firefox.exe"
pire-browser setup --firefox-path $env:PIRE_BROWSER_FIREFOX_PATH
Quick Start
pire-browser open https://example.com
pire-browser snapshot -i
pire-browser click '@e1'
pire-browser fill '@e2' "hello@example.com"
pire-browser find role button --name "Submit" click
pire-browser wait --selector "#done"
pire-browser screenshot page.png
pire-browser close
PowerShell treats @ specially, so quote refs such as '@e1'.
Use semantic locators when you do not want to manage refs manually:
pire-browser find label "Email" fill "hello@example.com"
pire-browser find text "Continue" click
pire-browser find role button --name "Submit" click
Use --json when another tool or agent needs structured output.
Commands
Setup And Diagnostics
pire-browser status
pire-browser status --json
pire-browser doctor
pire-browser doctor --json
pire-browser setup
pire-browser setup --firefox-path /path/to/firefox
status and doctor are observational. Browser commands that need auto-launch can run lazy setup when native host registration is missing or mismatched.
Browser Lifecycle
pire-browser launch
pire-browser launch --url https://example.com
pire-browser open https://example.com
pire-browser goto https://example.com
pire-browser navigate https://example.com
pire-browser close
launch starts a managed Firefox profile. open, goto, and navigate open a URL, auto-launching the managed Default profile when no live session exists.
The default launch engine is web-ext, including public packages. The direct Firefox/XPI path is release-validation-only for now:
PIRE_BROWSER_EXTENSION_MODE=xpi pire-browser launch
Unsigned XPI testing is local-only and requires Firefox Developer Edition or Nightly plus:
PIRE_BROWSER_EXTENSION_MODE=xpi PIRE_BROWSER_ALLOW_UNSIGNED_XPI=1 pire-browser launch
Inspect And Act
pire-browser snapshot -i
pire-browser click '@e1'
pire-browser fill '@e2' "hello"
pire-browser type '@e2' "hello"
pire-browser press Enter
pire-browser wait --selector "#done"
pire-browser wait --text "Saved"
pire-browser screenshot out.png
Refs are short lived. Re-run snapshot -i after navigation, reloads, DOM changes, dialogs, downloads, uploads, or failed actions.
Semantic Find
pire-browser find role button --name "Submit"
pire-browser find role button --name "Submit" click
pire-browser find label "Email" fill "hello@example.com"
pire-browser find text "Sign in" click
pire-browser find placeholder "Search" fill "pire-browser"
Supported locator families include role, label, text, placeholder, alt, title, testid, first, last, and nth. Chained actions include click, fill, type, hover, focus, check, uncheck, and text.
Tabs
pire-browser tabs list
pire-browser tabs select t1
pire-browser tabs close t1
pire-browser open https://example.com --label docs
Tab ids are stable strings such as t1, t2, and t3.
Sessions
pire-browser session list
pire-browser session list --json
pire-browser session attach <session-id>
pire-browser session cleanup
pire-browser --session <session-id> snapshot -i
pire-browser --session-name work open https://example.com
pire-browser --session-name work snapshot -i
pire-browser --session-name work close
--session <id> is strict and never launches Firefox. --session-name <name> reuses or launches a managed Firefox profile with that name.
Profile names may contain letters, numbers, internal spaces, _, -, and .. Empty names, path traversal, slashes, and : are rejected.
Downloads
pire-browser snapshot -i
pire-browser download '@e4' ./downloads/report.txt
pire-browser click '@e4'
pire-browser wait --download ./downloads/report.txt --timeout 60000
Firefox downloads are staged under the OS app-data pire-browser/downloads directory for managed profiles, then moved to the requested destination. Destinations must not already exist. Action policy and confirmation use the download category.
Uploads
pire-browser upload '#file' ./fixtures/example.txt
pire-browser upload '#multi-file' ./one.txt ./two.json --json
Uploads assign small local files to page file inputs. Total raw file bytes are capped at 512 KiB. This does not control native OS file-picker dialogs.
Clipboard
pire-browser clipboard read
pire-browser clipboard write "hello"
pire-browser clipboard copy
pire-browser clipboard paste
Active-Origin State
pire-browser --session-name work open https://app.example.com/dashboard
pire-browser --session-name work state save ./.pire-state/app.example.com-review.json
pire-browser state inspect ./.pire-state/app.example.com-review.json
pire-browser state inspect --record ./.pire-state/app.example.com-review.json
pire-browser --session-name review state load --require-inspected ./.pire-state/app.example.com-review.json
State files are plaintext and contain active-origin cookies, localStorage, and sessionStorage. Do not commit or share them. The project gitignores .pire-state/.
state inspect is metadata-only. state inspect --record writes a 24-hour local receipt under the OS app-data directory. Set PIRE_BROWSER_REQUIRE_INSPECTED_STATE=1 to make normal state load require a fresh receipt; use --no-require-inspected only as an explicit one-command override.
This is active-origin state only. It does not export saved passwords, IndexedDB, browser cache, service workers, full profiles, auth vault entries, or cross-origin SSO state.
Skills
pire-browser skills list
pire-browser skills cat core
pire-browser skills cat core --json
Installed agents should use the bundled skill command for version-matched guidance instead of relying on stale cached instructions. The package also ships compact routing context under agent/, agent/workflows/, and agent/references/.
Updates
pire-browser update check --json
pire-browser update apply
pire-browser update configure --mode off|notify|patch
Update checks run in a detached background process so browser launches do not wait on registry network calls. Patch auto-update is allowed only for global npm installs or confirmed Pi-managed installs, and only when no managed Firefox session is active. Local project installs and minor/major updates notify only.
On Windows, close managed Firefox sessions before replacing binaries. Windows can keep running executables locked.
Authentication
The simplest login flow is to use a persistent managed Firefox profile:
pire-browser launch --url https://example.com/login
# Sign in manually in Firefox.
pire-browser status --json
Firefox stores cookies, sessions, and saved passwords inside its managed profile. pire-browser stores launcher metadata, session files, confirmations, receipts, and download staging under the OS app-data directory, but it does not inspect cookies, saved passwords, session tokens, or one-time codes for diagnostics.
The default profile locations are:
Windows: %LOCALAPPDATA%\pire-browser\firefox-profiles\Default
macOS: ~/Library/Application Support/pire-browser/firefox-profiles/Default
Linux: $XDG_DATA_HOME/pire-browser/firefox-profiles/Default
or ~/.local/share/pire-browser/firefox-profiles/Default
Use named profiles to isolate projects:
pire-browser --session-name github open https://github.com
pire-browser --session-name app open https://app.example.com
Deleting a managed profile folder clears that saved browser state.
Guardrails
Domain Allowlist
pire-browser --allowed-domains "app.example.com,*.example.com" open https://app.example.com/dashboard
AGENT_BROWSER_ALLOWED_DOMAINS="app.example.com,*.example.com" pire-browser snapshot -i
pire-browser --no-allowed-domains open https://example.net
The allowlist accepts host patterns such as example.com, *.example.com, localhost, and 127.0.0.1. This is a cooperative wrong-site guardrail, not a browser sandbox. It does not claim containment of redirects, subresources, WebSockets, EventSource, or races where a page navigates between check and action.
Action Policy
cat > policy-deny-eval.json <<'JSON'
{ "default": "allow", "deny": ["eval"] }
JSON
pire-browser --action-policy ./policy-deny-eval.json eval "document.title"
Policy files use optional default, allow, and deny fields. Categories include navigate, click, fill, eval, snapshot, scroll, wait, get, interact, state, network, download, and upload. deny wins over allow, and unknown keys fail closed.
Action Confirmation
pire-browser --confirm-actions eval eval "document.title" --json
pire-browser confirm c_8f3a1234
pire-browser deny c_8f3a1234
When confirmation is required, the command returns ConfirmationRequired with a short-lived id and the follow-up command to run. Agents should ask the user before running returned confirm <id> commands.
Confirmation records live under the OS app-data pire-browser/confirmations directory. They are plaintext, user-scoped, short-lived runtime metadata and may contain the original command arguments.
Security Model
pire-browser installs local native binaries, registers a Firefox Native Messaging host for the current OS user, and exposes a Pi extension. Pi extensions run with the current user's local permissions.
The Native Messaging host exposes only current-user IPC. On Windows, named pipes use a DACL restricted to the current Windows user plus required system/admin principals. On macOS/Linux, Unix domain sockets live in a short current-user runtime directory.
This protects against cross-user and remote access. It does not defend against malicious code already running as the same OS user.
Current Limits
- DOM-level automation only; no trusted OS input.
- File uploads, payment/auth flows, and browser-restricted pages can return
requires_user_activation. - Cross-origin frames are best-effort; inaccessible frames are opaque.
- Screenshots are visible-viewport only.
- Snap/Flatpak Firefox native messaging may require additional sandbox support or a non-sandboxed Firefox build.
Development
cargo build
npm --prefix extension install
npm --prefix extension run build
cargo run -p pire-browser-cli -- setup
npx --prefix extension web-ext run --source-dir extension --firefox "C:\Program Files\Mozilla Firefox\firefox.exe"
Common checks:
cargo test -q
npm test
npm run oracle:test
npm pack --dry-run --json
Run the local Windows smoke test:
.\scripts\smoke.ps1
Useful smoke variants:
npm run smoke:named-sessions
npm run smoke:state
npm run smoke:domain-policy
npm run smoke:downloads
npm run smoke:uploads
Package and packed-install checks:
node scripts/package-extension-xpi.mjs
node scripts/build-platform.mjs win32-x64
node scripts/package-platform.mjs win32-x64 --pack --pack-destination target/npm-artifact-smoke
node scripts/smoke-packed-package.mjs --no-browser --artifact-dir target/release-smoke-local
One-time npm trusted publishing setup:
npm run release:npm:trust
Run the printed npm trust github ... commands once for the root package and all seven @ryenw/* platform packages. Configure them for repository ryenwang/pire-browser, workflow npm-publish.yml, environment npm-production, and npm publish permission.
Before publishing, run the Platform Packages workflow in GitHub Actions. Its combined pire-browser-npm-artifacts artifact must contain the root npm tarball plus all seven optional native package tarballs, and the verifier must pass.
Then run the manual Release Smoke workflow with target=all and default web-ext mode. This is the packed-install publish gate for Windows x64, macOS ARM64, and Linux x64.
Publish through the manual Publish npm Package workflow from main. The workflow builds fresh root/platform tarballs, verifies them, publishes sidecar packages first through npm trusted publishing, then publishes the root package and creates the matching v<package.json version> GitHub release.
Signed-XPI smoke is separate. Run Release Smoke with run_signed_xpi=true only when AMO signing secrets are available and before claiming direct-XPI readiness. The public default remains web-ext.