Actionbook CLI (Rust)
A high-performance CLI for browser automation with zero installation. Built in Rust for speed and reliability.
Design Principles
| Principle | Description | Implementation |
|---|---|---|
| Zero Installation | Use existing system browser, no downloads | Auto-detect Chrome/Brave/Edge/Arc |
| CDP-First | Direct Chrome DevTools Protocol control | WebSocket via chromiumoxide |
| Config Flexibility | Override at any level | CLI > env > config file > auto-discovery |
| Multi-Profile | Isolated browser sessions | Profile-based user data dirs |
| Multi-Session | Multiple tabs per profile | -S flag, per-session tab routing |
| Persistent Daemon | Reuse WS connection across commands | Per-profile daemon on Unix (default) |
| Session Persistence | Maintain state across commands | Disk-based session storage |
| Stealth Mode | Anti-detection browser automation | Fingerprint spoofing, navigator override |
| API Key Auth | Authenticated API access | --api-key / ACTIONBOOK_API_KEY |
Why These Principles?
┌─────────────────────────────────────────────────────────────┐
│ Traditional Approach │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Download │ -> │ Install │ -> │ Run │ (Slow, Heavy) │
│ │ Chromium │ │ Driver │ │ Tests │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Actionbook Approach │
│ ┌─────────────────────────────────────┐ │
│ │ Use Existing Browser via CDP │ (Fast, Light) │
│ │ Chrome/Brave/Edge already installed │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Comparison
| Feature | actionbook-rs | actionbook (TS) | agent-browser |
|---|---|---|---|
| Language | Rust | TypeScript | TypeScript |
| Binary Size | 7.8 MB | ~150 MB (Node.js) | ~200 MB |
| Startup Time | ~5ms | ~500ms | ~800ms |
| CDP Control | Native (chromiumoxide) | Proxy to agent-browser | Puppeteer |
| Browser Download | No | No | Optional |
| Actionbook API | Built-in | Built-in | - |
| Multi-Profile | Yes | Yes | Yes |
| Session Persistence | Disk-based | Disk-based | Memory |
| Persistent WS Daemon | Yes (per-profile, Unix) | - | Yes (per-session) |
| Auto-Discovery | Yes (DevToolsActivePort + port scan) | - | - |
| Stealth Mode | Yes (built-in) | - | - |
| API Key Auth | Yes | - | - |
| Headless Mode | Yes | Yes | Yes |
| Cookie Management | Yes | Yes | Yes |
| PDF Export | Yes | Yes | Yes |
| Screenshot | Yes | Yes | Yes |
| Scroll | Yes (5 directions) | Yes | Yes |
| Batch Execution | Yes (JSON) | - | - |
| Fingerprint Rotation | Yes (dynamic) | - | - |
| Animation Disabling | Yes (CSS + media) | - | - |
| A11y Snapshot | Yes (token truncation) | - | Yes |
| Human-Like Input | Yes (bezier + typing) | - | - |
| Dependencies | 0 runtime | Node.js 20+ | Node.js 20+ |
When to Use Which?
| Use Case | Recommended |
|---|---|
| CI/CD pipelines | actionbook-rs (fast startup, no runtime) |
| AI Agent automation | actionbook (TS) + MCP |
| Quick scripting | actionbook-rs (single binary) |
| Complex browser logic | agent-browser (full Puppeteer API) |
| Production deployment | actionbook-rs (minimal footprint) |
Features
- Zero Installation - Uses your existing browser (Chrome, Brave, Edge, Arc)
- CDP-First - Direct Chrome DevTools Protocol control via WebSocket
- Actionbook Integration - Search and retrieve pre-recorded website selectors
- Multi-Profile - Isolated browser sessions with persistent state
- Stealth Mode - Anti-detection with OS/GPU fingerprint spoofing, navigator override, WebGL emulation
- API Key Auth - Authenticated API access via
--api-keyflag orACTIONBOOK_API_KEYenv var - Accessibility Snapshot - CDP-based a11y tree with refs, token truncation, and diff mode
- Flexible Configuration - CLI args > env vars > config file > auto-discovery
- Human-Like Input - Bezier curve mouse movement, realistic typing with typos and hesitation
- Readability Extraction - Clean text extraction stripping nav/ads/chrome
- Resource Blocking - Block images/media/CSS for faster page loads
- Animation Disabling - CSS injection to disable all animations and transitions
- Batch Execution - Run sequences of actions from JSON with error control
- Fingerprint Rotation - Dynamically change UA, screen, hardware fingerprint
- Chrome Session Integrity - Clean stale lock files, prevent "didn't shut down correctly" bar
- Scroll - 5 directions (down, up, top, bottom, to element) with smooth option
- Console Log Capture - Intercept and display page console.log/warn/error messages
- Network Idle Wait - Wait for all network requests to complete (SPA-friendly)
- Dialog Auto-Handling - Auto-dismiss JavaScript alert/confirm/prompt dialogs
- Element Info - Get element bounding box, attributes, computed styles, and suggested selectors
- Local Storage Management - Get, set, remove, clear, and list localStorage/sessionStorage
- Device Emulation - Emulate mobile/tablet devices with preset viewports (iPhone, Pixel, iPad)
- Wait for JS Condition - Poll a JavaScript expression until it returns truthy
- Persistent Daemon - Per-profile daemon holds a persistent WS connection (Unix, default on). Eliminates per-command connect overhead. Opt-out with
--no-daemon - Auto-Discovery - Detect running Chrome via
DevToolsActivePortfiles and port scanning (9222-9229), with Chrome-specific target type validation - Electron App Automation - Automate desktop apps (VS Code, Slack, Discord, Figma) via
actionbook appcommand - Keyboard Hotkeys - Send keyboard combinations (Ctrl+C, Cmd+A, multi-modifier shortcuts)
- Shadow DOM Support - Interact with elements inside Shadow DOM using
::shadow-rootselector syntax - IFrame Context Switching - Switch between main frame and iframes for embedded content
- Scroll with Wait - Scroll and wait for
scrollendevent, essential for lazy-loaded content - Multi-Session - Run multiple independent sessions per profile (
-S), each bound to its own tab
Architecture
┌───────────────────────────────────────────────────────────────────────┐
│ Actionbook CLI │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│ │ search │ │ get │ │ sources │ │ browser │ │ daemon │ │
│ │ command │ │ command │ │ command │ │ commands │ │ status │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └───┬────┘ │
│ │ │ │ │ │ │
│ └─────────────┴─────────────┴──────────────┤ │ │
│ │ │ │ │
│ ┌──────────────────────┴───────────────────┐ │ │ │
│ │ Core Modules │ │ │ │
│ │ ┌───────────┐ ┌───────────┐ │ │ │ │
│ │ │ API Client│ │ Config │ │ │ │ │
│ │ │ (reqwest) │ │ (figment) │ │ │ │ │
│ │ └─────┬─────┘ └─────┬─────┘ │ │ │ │
│ └────────┼───────────────┼─────────────────┘ │ │ │
│ │ │ │ │ │
└───────────┼───────────────┼──────────────────────┼─────────────┼──────┘
│ │ │ │
▼ ▼ ▼ ▼
┌────────────────┐ ┌──────────────┐ ┌──────────────────────────┐
│ Actionbook │ │ ~/.actionbook│ │ Per-Profile Daemon │
│ API Server │ │ /config.toml│ │ (persistent WS, Unix) │
└────────────────┘ │ /sessions/ │ │ │
│ /daemons/ │ │ CLI ──UDS──→ Daemon │
└──────────────┘ │ ↕ WS │
│ Chrome Browser │
└──────────────────────────┘
Daemon Architecture (Unix, default)
CLI
│
┌────────────┼────────────┐
-P profile1 -P profile2 -P profile3
│ │ │
Daemon 1 Daemon 2 Daemon 3 ← auto-started on active commands
profile1.sock profile2.sock profile3.sock
│ │ │
Persistent WS Persistent WS Persistent WS
│ │ │
Browser/CDP1 Browser/CDP2 Browser/CDP3
Each profile = independent daemon process = independent persistent WS = independent CDP connection.
Use --no-daemon to fall back to per-command direct connections.
Multi-Session Architecture
1 Profile → 1 Daemon → 1 Chrome Process → N Sessions (each bound to its own tab)
CLI
│
┌────────────┼────────────┐
-S arxiv -S twitter -S amazon (all using -P work)
│ │ │
└────────────┼────────────┘
│
Daemon (work)
work.sock
│
Persistent WS
│
Chrome (CDP)
┌─────────┼─────────┐
Tab 1 Tab 2 Tab 3
(arxiv) (twitter) (amazon)
Each session tracks its own active_page_id. Sessions share the same Chrome process, cookies, and login state. Use -S <name> to create and route to sessions.
Module Structure
src/
├── main.rs # Entry point, tracing setup
├── cli.rs # CLI argument definitions (clap)
├── error.rs # Error types (thiserror)
├── api/
│ ├── mod.rs # API module exports
│ ├── client.rs # Actionbook API client
│ └── types.rs # API request/response types
├── browser/
│ ├── mod.rs # Browser module exports
│ ├── auto_connect.rs # Auto-discover running Chrome (DevToolsActivePort + port scan)
│ ├── discovery.rs # Auto-detect installed browsers
│ ├── launcher.rs # Launch browser with CDP + session integrity (G3)
│ ├── session.rs # Session state, animations (G2), fingerprint (G5)
│ ├── router.rs # BrowserDriver multi-backend dispatch
│ ├── snapshot.rs # CDP Accessibility Tree (F1), diff (F6), truncation (G1)
│ ├── readability.rs # Readability text extraction (F4)
│ ├── human_input.rs # Human-like mouse/typing (F5)
│ ├── content.rs # Content extraction utilities
│ ├── stealth.rs # Stealth mode (anti-detection profiles)
│ ├── stealth_enhanced.rs # Enhanced stealth (Camoufox techniques)
│ ├── fingerprint_generator.rs # Statistical fingerprint generation
│ ├── human_behavior.rs # Human behavior simulation
│ ├── extension_bridge.rs # Chrome Extension WebSocket bridge
│ ├── extension_installer.rs # Extension download/install
│ └── native_messaging.rs # Chrome Native Messaging host
├── daemon/ # Per-profile daemon (persistent WS, Unix only)
│ ├── mod.rs # Module exports
│ ├── server.rs # UDS listener + WS connection loop + target attach
│ ├── client.rs # CLI → daemon UDS client (try_send, ensure_daemon)
│ ├── protocol.rs # DaemonRequest/DaemonResponse JSON-line protocol
│ └── lifecycle.rs # spawn/stop daemon, socket/PID path helpers
├── config/
│ ├── mod.rs # Configuration loading
│ └── profile.rs # Profile management
└── commands/
├── mod.rs # Command module exports
├── search.rs # Search actions command
├── get.rs # Get action by ID command
├── sources.rs # List/search sources command
├── browser.rs # Browser automation commands
├── daemon.rs # Daemon serve/status/stop commands
├── app.rs # Electron app automation commands
├── batch.rs # Batch action execution (G4)
├── act.rs # Action execution command
├── execute.rs # Execute action on element
├── record.rs # Record browser actions
├── replay.rs # Replay recorded actions
├── validate.rs # Validate selectors
├── config.rs # Config management commands
├── profile.rs # Profile management commands
└── setup/ # Interactive setup wizard
Prerequisites
| Requirement | Description |
|---|---|
| Chromium-based Browser | One of: Google Chrome, Brave, Microsoft Edge, Arc, or Chromium |
What You DON'T Need
| Traditional Tools | actionbook-rs |
|---|---|
| Node.js runtime | Not needed |
| Download Chromium | Not needed (uses system browser) |
| WebDriver/Selenium | Not needed (direct CDP) |
| Python | Not needed |
Verify Prerequisites
# Check if a supported browser is detected
actionbook browser status
Installation
From Source
git clone https://github.com/actionbook/actionbook.git
cd actionbook/packages/actionbook-rs
cargo build --release
# Binary at: ./target/release/actionbook
Binary Size
The release binary is ~7.8 MB (with LTO and strip enabled).
Quick Start
1. Search for Website Actions
# Search for Etsy-related actions
actionbook search "etsy"
# Search with domain filter
actionbook search "valentine" --domain etsy.com
# Paginated results
actionbook search "login" --page 1 --page-size 5
2. Get Action Details
# Get full action details by area ID
# Area ID format: site:path:area (e.g., "airbnb.com:/:default")
actionbook get "etsy.com:/:search_form"
3. Browser Automation
# Check browser status
actionbook browser status
# Open a URL in browser
actionbook browser open "https://www.etsy.com"
# Navigate to a page
actionbook browser goto "https://www.etsy.com/market/valentines_day_gifts"
# Take a screenshot
actionbook browser screenshot /tmp/screenshot.png
# Click an element
actionbook browser click "button.search-btn"
# Type text into an input
actionbook browser type "input[name=search]" "valentine gifts"
# Execute JavaScript
actionbook browser eval "document.title"
4. Configuration
# Show current configuration
actionbook config show
# Get config file path
actionbook config path
# Set a config value
actionbook config set api_url "https://api.actionbook.dev"
5. Profile Management
# List profiles
actionbook profile list
# Create a new profile
actionbook profile create work
# Use a profile
actionbook --profile work browser open "https://example.com"
Configuration
Config File Location
- macOS:
~/.actionbook/config.toml - Linux:
~/.actionbook/config.toml - Windows:
%USERPROFILE%\.actionbook\config.toml
Example Config
[api]
base_url = "https://api.actionbook.dev"
api_key = "sk-your-api-key" # Optional, for authenticated access
[browser]
headless = false
default_profile = "actionbook"
[profiles.actionbook]
cdp_port = 9222
headless = false
[profiles.headless]
cdp_port = 9223
headless = true
By default, each profile uses an isolated browser data directory:
<data_dir>/actionbook/profiles/<profile>.
Environment Variables
All config values can be overridden via environment variables:
# API
ACTIONBOOK_API_KEY=sk-your-api-key
# Browser
ACTIONBOOK_HEADLESS=true
ACTIONBOOK_BROWSER_PATH=/usr/bin/google-chrome
# Stealth
ACTIONBOOK_STEALTH=true
ACTIONBOOK_STEALTH_OS=macos-arm
ACTIONBOOK_STEALTH_GPU=apple-m4-max
Configuration Priority
CLI args > Environment variables > Config file > Auto-discovery
Global Flags
| Flag | Env Var | Description |
|---|---|---|
--json |
Output in JSON format | |
--verbose |
Enable verbose logging | |
--headless |
ACTIONBOOK_HEADLESS |
Run browser in headless mode |
--profile <NAME> |
ACTIONBOOK_PROFILE |
Use specific profile |
--browser-path <PATH> |
ACTIONBOOK_BROWSER_PATH |
Custom browser executable path |
--cdp <PORT|URL> |
ACTIONBOOK_CDP |
Connect to CDP port or WebSocket URL (verified before persisting) |
--no-daemon |
ACTIONBOOK_NO_DAEMON |
Disable per-profile daemon (Unix only, daemon is on by default) |
--auto-connect |
ACTIONBOOK_AUTO_CONNECT |
Auto-discover running Chrome via DevToolsActivePort + port scan |
--api-key <KEY> |
ACTIONBOOK_API_KEY |
API key for authenticated access |
--stealth |
ACTIONBOOK_STEALTH |
Enable stealth mode (anti-detection) |
--stealth-os <OS> |
ACTIONBOOK_STEALTH_OS |
Stealth OS: windows, macos-arm, macos-intel, linux |
--stealth-gpu <GPU> |
ACTIONBOOK_STEALTH_GPU |
Stealth GPU: rtx4080, apple-m4-max, intel-uhd630, etc. |
--block-images |
ACTIONBOOK_BLOCK_IMAGES |
Block image downloads for faster page loads |
--block-media |
ACTIONBOOK_BLOCK_MEDIA |
Block images, fonts, CSS, and media |
--no-animations |
ACTIONBOOK_NO_ANIMATIONS |
Disable CSS animations, transitions, and smooth scrolling |
--auto-dismiss-dialogs |
ACTIONBOOK_AUTO_DISMISS_DIALOGS |
Auto-dismiss JS alert/confirm/prompt dialogs |
-S, --session <NAME> |
ACTIONBOOK_SESSION |
Use a named session (each session binds to its own tab) |
Commands Reference
search - Search Actions
actionbook search <QUERY> [OPTIONS]
Options:
-d, --domain <DOMAIN> Filter by domain (e.g., "airbnb.com")
-u, --url <URL> Filter by specific URL
-p, --page <N> Page number [default: 1]
-s, --page-size <N> Results per page (1-100) [default: 10]
Output: Plain text with area_id list for next step.
get - Get Action by Area ID
actionbook get <AREA_ID>
# Area ID format: site:path:area
# Examples:
actionbook get "airbnb.com:/:default"
actionbook get "etsy.com:/search:search_results"
Output: Plain text with element selectors and methods.
sources - Manage Sources
actionbook sources list [--limit <N>]
actionbook sources search <QUERY> [--limit <N>]
browser - Browser Automation
actionbook browser status # Show connection status
actionbook browser open <URL> # Open URL in new browser
actionbook browser goto <URL> # Navigate current page
actionbook browser click <SELECTOR> # Click element
actionbook browser type <SELECTOR> <TEXT> # Type text
actionbook browser fill <SELECTOR> <TEXT> # Fill input field
actionbook browser wait <SELECTOR> # Wait for element
actionbook browser screenshot [PATH] # Take screenshot
actionbook browser pdf <PATH> # Save as PDF
actionbook browser eval <CODE> # Execute JavaScript
actionbook browser snapshot # Accessibility tree snapshot
actionbook browser snapshot --max-tokens 500 # Truncated snapshot for LLM context
actionbook browser inspect <X> <Y> # Inspect element at coordinates
actionbook browser viewport # Show viewport size
actionbook browser scroll down [PIXELS] # Scroll down (default: viewport height)
actionbook browser scroll down [PIXELS] --wait # Scroll and wait for scrollend event
actionbook browser scroll up [PIXELS] # Scroll up
actionbook browser scroll bottom # Scroll to page bottom
actionbook browser scroll top # Scroll to page top
actionbook browser scroll to <SELECTOR> # Scroll to element
actionbook browser hotkey <KEYS> # Send keyboard combination (e.g., "Control+C", "Meta+A")
actionbook browser switch-frame <TARGET> # Switch to iframe ("default"/"parent" or selector)
actionbook browser batch --file actions.json # Execute batch of actions
actionbook browser fingerprint rotate # Rotate browser fingerprint
actionbook browser console # Capture console log messages
actionbook browser console --duration 5000 # Listen for 5 seconds
actionbook browser console --level error # Errors only
actionbook browser wait-idle # Wait for network idle
actionbook browser wait-idle --timeout 10000 --idle-time 1000
actionbook browser info <SELECTOR> # Get element info (bbox, attrs, styles)
actionbook browser storage list # List all localStorage keys
actionbook browser storage get <KEY> # Get localStorage value
actionbook browser storage set <KEY> <VALUE> # Set localStorage value
actionbook browser storage clear # Clear localStorage
actionbook browser storage list --session # Use sessionStorage
actionbook browser emulate iphone-14 # Emulate iPhone 14
actionbook browser emulate pixel-7 # Emulate Pixel 7
actionbook browser emulate ipad # Emulate iPad
actionbook browser emulate 1280x720 # Custom resolution
actionbook browser wait-fn "document.querySelector('#done')" # Wait for condition
actionbook browser wait-fn "window.loaded === true" --timeout 10000
actionbook browser connect <PORT> # Connect via local CDP port
actionbook browser connect <WSS_URL> # Connect via remote WebSocket URL
actionbook browser close # Close browser
actionbook browser restart # Restart browser
actionbook browser cookies list # List cookies
actionbook browser cookies get <NAME> # Get cookie
actionbook browser cookies set <NAME> <VALUE> # Set cookie
actionbook browser cookies delete <NAME> # Delete cookie
actionbook browser cookies clear # Clear all cookies
actionbook browser no longer auto-attaches to local CDP ports (9222/9223/9224).
Use actionbook browser connect <PORT|WS_URL> explicitly when you want to reuse an existing browser.
For remote WebSocket endpoints that require authentication headers (e.g. SigV4-signed URLs), optionally pass -H/--header flags:
actionbook browser connect "wss://example.com/automation" \
-H "authorization:AWS4-HMAC-SHA256 ..." \
-H "x-amz-date:20260312T080000Z"
Headers are persisted in the session state and used for all subsequent WebSocket connections (page enumeration, CDP commands, liveness probes).
config - Configuration
actionbook config show # Show all config
actionbook config path # Show config file path
actionbook config get <KEY> # Get config value
actionbook config set <KEY> <VALUE> # Set config value
profile - Profile Management
actionbook profile list # List all profiles
actionbook profile create <NAME> # Create new profile
actionbook profile delete <NAME> # Delete profile
daemon - Daemon Management (Unix only)
actionbook daemon status # Check if daemon is running for current profile
actionbook daemon stop # Stop the daemon for current profile
The daemon is automatically started when needed by browser commands. These commands are for manual inspection and control.
How It Works:
- Each profile gets its own daemon process holding a persistent WebSocket connection
- CLI commands communicate with the daemon via Unix Domain Sockets (
~/.actionbook/daemons/{profile}.sock) - Daemon auto-starts on active browser commands (snapshot, click, type, etc.)
- Read-only commands (status, pages, tab list) bypass the daemon
- Use
--no-daemonorACTIONBOOK_NO_DAEMON=1to fall back to per-command direct connections - The
-S/--sessionflag is ignored by daemon commands (daemon is profile-scoped)
browser session - Session Management
Manage multiple named sessions within a single profile. Each session binds to its own browser tab.
actionbook browser session list # List all sessions for current profile
actionbook browser session list --json # JSON output
actionbook browser session active # Show current session name
actionbook browser session active --json # JSON with exists/profile info
actionbook browser session destroy <NAME> # Detach session from daemon routing table
Multi-Session Usage:
# Open different sites in separate sessions (same profile, same Chrome process)
actionbook -S arxiv -P work browser open "https://arxiv.org"
actionbook -S twitter -P work browser open "https://x.com"
actionbook -S amazon -P work browser open "https://amazon.com"
# Each session operates on its own tab independently
actionbook -S arxiv -P work browser snapshot # arXiv page
actionbook -S twitter -P work browser snapshot # X/Twitter page
actionbook -S amazon -P work browser snapshot # Amazon page
# All browser commands support -S
actionbook -S arxiv -P work browser click "#search-input"
actionbook -S arxiv -P work browser type "machine learning"
actionbook -S arxiv -P work browser screenshot
Session Naming Rules:
- Allowed: alphanumeric characters, dashes (
-), underscores (_) - Not allowed: spaces, slashes, dots, colons, or any other special characters
- Invalid names are rejected immediately (not silently rewritten)
Session File Storage:
~/.actionbook/sessions/
├── work@default.json # default session
├── work@arxiv.json # arxiv session
├── work@twitter.json # twitter session
└── work@amazon.json # amazon session
Session Fork Mechanism:
When -S specifies a non-existent session, it forks from the first alive session in the same profile (inheriting CDP connection info but creating a new tab).
Key Behaviors:
- Without
-S, defaults to thedefaultsession (backward compatible) - Sessions share cookies and login state (same Chrome process)
- Snapshot cache is per-session (
~/.actionbook/snapshots/{profile}@{session}.json) - Legacy session files (
{profile}.json) are auto-migrated to{profile}@default.json - Multiple terminals/agents can operate different sessions concurrently
Multi-Profile vs Multi-Session:
Multi-Profile (-P) |
Multi-Session (-S) |
|
|---|---|---|
| Chrome processes | N (independent) | 1 (shared) |
| Cookies/login | Independent | Shared |
| Resource usage | High (~200MB per process) | Low (~50MB per tab) |
| Use case | Different login identities | Same identity, parallel operations |
app - Electron App Automation
Automate desktop applications built with Electron (VS Code, Slack, Discord, Figma, Notion, Spotify, etc.) using Chrome DevTools Protocol.
App-Specific Commands:
actionbook app launch <NAME> # Auto-discover and launch Electron app
actionbook app attach <PORT> # Attach to running app on CDP port
actionbook app list # List all discoverable Electron apps
actionbook app status # Show current app connection status
actionbook app close # Close the connected app
actionbook app restart # Restart the app (preserves session)
All Browser Commands Available:
Every browser command works with app prefix (35+ commands):
# Navigation
actionbook app goto <URL>
# Interaction
actionbook app click <SELECTOR>
actionbook app type <TEXT> [SELECTOR]
actionbook app fill <TEXT> [SELECTOR]
actionbook app hotkey "Control+C"
# Analysis
actionbook app snapshot [--format compact]
actionbook app screenshot output.png
actionbook app eval "document.title"
# Tab management
actionbook app tab list
actionbook app tab new
actionbook app tab switch <PAGE_ID>
Example Workflows:
# Automate VS Code
actionbook app launch "Visual Studio Code"
actionbook app hotkey "Cmd+Shift+P" # Open command palette
actionbook app type "Git: Commit"
actionbook app hotkey "Enter"
# Automate Slack
actionbook app launch Slack
actionbook app click "#channel-name"
actionbook app type "Hello team!" "div[role='textbox']"
actionbook app hotkey "Enter"
# Automate Figma
actionbook app attach 9222 # If Figma already running with --remote-debugging-port=9222
actionbook app click "button:has-text('Export')"
actionbook app screenshot design.png
Supported Apps:
| App | macOS | Linux | Windows |
|---|---|---|---|
| Visual Studio Code | ✅ | ✅ | ✅ |
| Slack | ✅ | ✅ | ✅ |
| Discord | ✅ | ✅ | ✅ |
| Figma | ✅ | ✅ | ✅ |
| Notion | ✅ | ✅ | ✅ |
| Spotify | ✅ | ✅ | ✅ |
| Any Electron App | ✅ | ✅ | ✅ |
How It Works:
- Auto-Discovery: Scans common install locations for Electron apps
- CDP Launch: Starts app with
--remote-debugging-port=9222 - Session Tracking: Stores app path for restart preservation
- Full Feature Parity: All browser automation features work (Shadow DOM, iframes, hotkeys, etc.)
Port Inference:
# If app already running with CDP enabled
actionbook app attach 9222 # Validates CDP endpoint and matches against known apps
Stealth Mode
Stealth mode applies anti-detection measures to avoid bot detection:
# Enable stealth with default profile (macOS ARM + Apple M4 Max)
actionbook --stealth browser open "https://example.com"
# Custom OS/GPU fingerprint
actionbook --stealth --stealth-os windows --stealth-gpu rtx4080 browser open "https://example.com"
# Via environment variables
export ACTIONBOOK_STEALTH=true
export ACTIONBOOK_STEALTH_OS=macos-arm
export ACTIONBOOK_STEALTH_GPU=apple-m4-max
actionbook browser open "https://example.com"
What Stealth Mode Does
| Feature | Description |
|---|---|
| Navigator Override | Spoofs navigator.webdriver, platform, hardwareConcurrency, deviceMemory |
| WebGL Emulation | Overrides WebGL renderer/vendor to match selected GPU |
| Plugin Spoofing | Injects fake Chrome plugins (PDF, Native Client) |
| Webdriver Masking | navigator.webdriver override via CDP script injection (no unsupported Chrome flags) |
| Persistent Injection | Uses Page.addScriptToEvaluateOnNewDocument for cross-navigation persistence |
Available Profiles
OS: windows, macos-intel, macos-arm, linux
GPU: rtx4080, rtx3080, gtx1660, rx6800, uhd630, iris-xe, m1-pro, m2-max, m4-max
Scroll
Scroll the page in any direction, with optional smooth animation and wait for completion:
actionbook browser scroll down # Down one viewport height
actionbook browser scroll down 500 # Down 500 pixels
actionbook browser scroll down 500 --wait # Scroll and wait for scrollend event
actionbook browser scroll up 300 --smooth # Up 300px with smooth animation
actionbook browser scroll up 500 --smooth --wait # Smooth scroll + wait
actionbook browser scroll bottom # Scroll to page bottom
actionbook browser scroll top # Scroll to page top
actionbook browser scroll to "#footer" # Scroll to element
actionbook browser scroll to ".form" --align start # Align to top of viewport
| Direction | Argument | Description |
|---|---|---|
down |
[PIXELS] |
Scroll down (default: viewport height) |
up |
[PIXELS] |
Scroll up (default: viewport height) |
bottom |
— | Scroll to absolute bottom |
top |
— | Scroll to absolute top |
to |
<SELECTOR> |
Scroll to CSS selector (--align start|center|end|nearest) |
Scroll with Wait (--wait flag)
The --wait flag makes the scroll command wait for the browser's scrollend event, ensuring:
- Lazy-loaded images/content appear after scroll
- DOM is stable before the next action
- No "element not found" errors on dynamic content
# Essential for infinite scroll and lazy-loaded content
actionbook browser scroll down 1000 --wait
actionbook browser scroll bottom --wait
# Smooth scroll + wait = complete animation before continuing
actionbook browser scroll down 800 --smooth --wait
Accessibility Snapshot
CDP-based accessibility tree extraction for AI agents:
actionbook browser snapshot # Full tree, compact format
actionbook browser snapshot --format text # Indented text format
actionbook browser snapshot --format json # JSON format
actionbook browser snapshot --filter interactive # Only buttons/links/inputs
actionbook browser snapshot --depth 3 # Limit tree depth
actionbook browser snapshot --selector "#main" # Scope to element
actionbook browser snapshot --diff # Show changes since last snapshot
actionbook browser snapshot --max-tokens 500 # Truncate for LLM context
Snapshot Formats
Compact (default, ~60-70% fewer tokens):
e0:navigation "Main Menu"
e1:link "Home"
e2:searchbox "Search" [focused]
e3:button "Submit"
Text (indented tree):
e0 navigation "Main Menu"
e1 link "Home"
e2 searchbox "Search" [focused]
e3 button "Submit"
Interactive Filter (--filter interactive)
Filters the accessibility tree to only show actionable elements — the nodes an AI agent can actually interact with. This dramatically reduces noise from decorative/structural nodes.
16 supported ARIA roles:
| Category | Roles |
|---|---|
| Form inputs | textbox, searchbox, combobox, spinbutton, slider |
| Buttons | button |
| Links | link |
| Selection | checkbox, radio, switch, menuitem, option |
| Containers | tab, treeitem |
| Media | video, audio |
# Interactive-only snapshot
actionbook browser snapshot --filter interactive
# Combine with token budget (recommended for LLM agents)
actionbook browser snapshot --filter interactive --max-tokens 500
# Interactive + JSON output
actionbook browser snapshot --filter interactive --format json
Typical reduction: A full page may have 200+ a11y nodes; --filter interactive typically returns 20-40 actionable elements. Combined with --max-tokens, this gives agents a focused, budget-friendly view of what they can do on the page.
Token Truncation (--max-tokens)
When --max-tokens N is set, nodes are included until the token budget is exceeded. A (truncated to ~N tokens) notice is appended. In JSON mode, truncated output includes "truncated": true.
Batch Execution
Execute a sequence of browser actions from JSON:
# From file
actionbook browser batch --file actions.json
# From stdin
echo '{"actions":[{"kind":"goto","url":"https://example.com"},{"kind":"snapshot"}],"stopOnError":true}' | actionbook browser batch
# Custom delay between steps
actionbook browser batch --file actions.json --delay 100
JSON Format
{
"actions": [
{"kind": "goto", "url": "https://example.com"},
{"kind": "click", "selector": "#login"},
{"kind": "type", "selector": "#email", "text": "user@test.com"},
{"kind": "click", "selector": "#submit"},
{"kind": "wait", "selector": ".dashboard", "timeout": 5000},
{"kind": "snapshot"}
],
"stopOnError": true
}
Supported kinds: goto, click, type, fill, select, snapshot, text, screenshot, scroll, wait.
Output
{
"results": [
{"index": 0, "kind": "goto", "success": true},
{"index": 1, "kind": "click", "success": true},
{"index": 2, "kind": "type", "success": false, "error": "Element not found: #email"}
],
"total": 3,
"successful": 2,
"failed": 1
}
Fingerprint Rotation
Dynamically change browser fingerprint on a running session:
# Random fingerprint
actionbook browser fingerprint rotate
# Specific OS
actionbook browser fingerprint rotate --os windows
actionbook browser fingerprint rotate --os mac
actionbook browser fingerprint rotate --os linux
# Custom screen resolution
actionbook browser fingerprint rotate --os windows --screen 1920x1080
Rotates: User-Agent, platform, screen dimensions, hardware concurrency, device memory.
Animation Disabling
Disable all CSS animations and transitions for stable snapshots and screenshots:
# Via global flag
actionbook --no-animations browser open "https://animate.style"
# Via environment variable
ACTIONBOOK_NO_ANIMATIONS=true actionbook browser goto "https://example.com"
Injects CSS animation: none !important; transition: none !important; and sets prefers-reduced-motion: reduce via CDP Emulation.
Console Log Capture
# Snapshot current console messages
actionbook browser console
# Listen for 5 seconds, errors only
actionbook browser console --duration 5000 --level error
# All levels: all, log, info, warn, error, debug
actionbook browser console --level warn
Installs a JS interceptor that captures console.log/warn/error/info/debug messages. Up to 200 messages are buffered. The interceptor persists across navigations via Page.addScriptToEvaluateOnNewDocument.
Network Idle Wait
# Wait until no pending requests for 500ms (default)
actionbook browser wait-idle
# Custom timeout and idle threshold
actionbook browser wait-idle --timeout 10000 --idle-time 1000
Monitors fetch() and XMLHttpRequest to track pending network requests. Returns when no requests have been in-flight for the specified idle time. Essential for SPAs that load data asynchronously after initial page load.
Dialog Auto-Handling
# Enable globally — auto-dismiss all JS dialogs
actionbook --auto-dismiss-dialogs browser open "https://example.com"
# Or via environment variable
export ACTIONBOOK_AUTO_DISMISS_DIALOGS=true
Overrides window.alert, window.confirm (returns true), and window.prompt (returns default value). Logged dismissed dialogs are accessible via the console capture feature. Prevents JavaScript dialogs from blocking agent execution.
Element Info
# Get detailed info about an element
actionbook browser info "#search-button"
# Output includes:
# Element: <button>
# id: search-button
# text: "Search"
# bbox: (120, 340) 200x40
# visible: yes | interactive: yes
# selectors:
# #search-button
# button.btn.btn-primary
Returns element's tag name, bounding box, attributes, computed styles (display, visibility, color, cursor, etc.), visibility status, interactivity detection, and suggested CSS selectors.
Local Storage Management
# localStorage operations
actionbook browser storage list # List all keys
actionbook browser storage get "token" # Get a value
actionbook browser storage set "key" "val" # Set a value
actionbook browser storage remove "key" # Remove a key
actionbook browser storage clear # Clear all
# sessionStorage — add --session flag
actionbook browser storage list --session
actionbook browser storage get "tab_id" --session
Device Emulation
# Preset devices
actionbook browser emulate iphone-14 # 390x844 @3x, mobile UA
actionbook browser emulate iphone-se # 375x667 @2x, mobile UA
actionbook browser emulate pixel-7 # 412x915 @2.625x, mobile UA
actionbook browser emulate ipad # 820x1180 @2x, mobile UA
actionbook browser emulate desktop-hd # 1920x1080 @1x
actionbook browser emulate desktop-4k # 3840x2160 @2x
# Custom resolution (WxH)
actionbook browser emulate 1280x720
actionbook browser emulate 375x812
Sets viewport dimensions, device scale factor, user agent, and touch emulation via CDP Emulation.setDeviceMetricsOverride.
Wait for JS Condition
# Wait for element to appear
actionbook browser wait-fn "document.querySelector('#loaded')"
# Wait for custom flag
actionbook browser wait-fn "window.appReady === true"
# With custom timeout and polling interval
actionbook browser wait-fn "document.title.includes('Done')" --timeout 10000 --interval 200
Polls the JavaScript expression at the specified interval until it returns a truthy value (non-null, non-false, non-empty, non-zero). Returns the expression's value on success or times out with an error.
Keyboard Hotkeys
Send keyboard combinations for shortcuts, copy/paste, and other key-based interactions:
# Single modifier + key
actionbook browser hotkey "Control+C" # Copy (Ctrl+C)
actionbook browser hotkey "Meta+V" # Paste on macOS (Cmd+V)
actionbook browser hotkey "Control+A" # Select all
# Multiple modifiers
actionbook browser hotkey "Control+Shift+P" # Command palette (many editors)
actionbook browser hotkey "Meta+Shift+N" # New private window
# Navigation
actionbook browser hotkey "Control+Tab" # Next tab
actionbook browser hotkey "Control+W" # Close tab
actionbook browser hotkey "Meta+R" # Refresh (macOS)
Modifier Keys:
Control: Ctrl key (all platforms)Meta: Cmd key (macOS) / Windows key (Windows)Shift: Shift keyAlt: Alt/Option key
Common Patterns:
# Copy-paste workflow
actionbook browser hotkey "Control+A" # Select all
actionbook browser hotkey "Control+C" # Copy
actionbook browser click "textarea#destination"
actionbook browser hotkey "Control+V" # Paste
# VS Code command palette
actionbook browser hotkey "Control+Shift+P"
actionbook browser type "input" "Format Document"
# Browser shortcuts
actionbook browser hotkey "Control+T" # New tab
actionbook browser hotkey "Control+L" # Focus address bar
actionbook browser hotkey "Control+Plus" # Zoom in
Shadow DOM Support
Interact with elements inside Shadow DOM using the ::shadow-root selector syntax. Essential for modern web components (Custom Elements) and frameworks like Lit, Polymer, Stencil.
# Basic shadow DOM selector
actionbook browser click "custom-button::shadow-root > button"
# Type into shadow input
actionbook browser type "my-input::shadow-root > input" "Hello world"
# Nested shadow DOM
actionbook browser click "outer::shadow-root > inner::shadow-root > button"
# Combined with other selectors
actionbook browser click "app-root::shadow-root > nav > button.primary"
When to Use:
- Web components with encapsulated styles
- Modern UI libraries (Lit, Stencil, Shoelace)
- Enterprise apps with isolated components
Example - Shoelace UI components:
actionbook browser open "https://shoelace.style"
# Click button inside shadow DOM
actionbook browser click "sl-button::shadow-root > button"
# Type in shadow input
actionbook browser type "sl-input::shadow-root > input" "search term"
# Toggle shadow checkbox
actionbook browser click "sl-checkbox::shadow-root > input"
IFrame Context Switching
Switch between main frame and iframes when pages embed external content (payment forms, embedded apps, widgets):
# Switch to iframe
actionbook browser switch-frame "iframe#payment"
# Interact inside iframe (all commands work)
actionbook browser type "input#card-number" "4111111111111111"
actionbook browser click "button.submit"
# Switch back to parent frame
actionbook browser switch-frame "parent"
# Switch to main frame (top level)
actionbook browser switch-frame "default"
Frame Targets:
<selector>: CSS selector for iframe element (e.g.,iframe#checkout,iframe.widget)parent: Switch to parent frame (one level up)default: Switch to main/top frame (reset to root)
Complete Flow - Stripe Payment:
# Open checkout page
actionbook browser open "https://example.com/checkout"
# Wait for page load
actionbook browser wait-idle
# Switch to Stripe iframe
actionbook browser switch-frame "iframe[name='stripe_frame']"
# Fill payment details (now inside iframe)
actionbook browser type "input[name='cardnumber']" "4242424242424242"
actionbook browser type "input[name='exp-date']" "12/25"
actionbook browser type "input[name='cvc']" "123"
actionbook browser click "button[type='submit']"
# Switch back to main frame
actionbook browser switch-frame "default"
# Verify confirmation (now in main frame)
actionbook browser wait ".confirmation"
actionbook browser screenshot confirmation.png
Nested IFrames:
# Level 0: Main frame
actionbook browser open "https://example.com"
# Level 1: Outer iframe
actionbook browser switch-frame "iframe#outer"
# Level 2: Inner iframe (inside outer)
actionbook browser switch-frame "iframe#inner"
# Interact at level 2
actionbook browser click "button"
# Back to level 1
actionbook browser switch-frame "parent"
# Back to level 0
actionbook browser switch-frame "default"
Supported Browsers
The CLI auto-detects and supports:
| Browser | macOS | Linux | Windows |
|---|---|---|---|
| Google Chrome | ✓ | ✓ | ✓ |
| Brave | ✓ | ✓ | ✓ |
| Microsoft Edge | ✓ | ✓ | ✓ |
| Arc | ✓ | - | - |
| Chromium | ✓ | ✓ | ✓ |
Development
Build
cargo build # Debug build
cargo build --release # Release build (optimized)
Test
cargo test # Run all tests
cargo test --test cli_test # CLI tests only
cargo test --test integration_test # Integration tests only
Test Coverage
- 610+ tests total (unit + integration + e2e)
- Generate CLI unit-test coverage locally with
make coverage - CI uploads
ut-coverage-reportwithlcov.infoandcoverage-summary.txt, and adds the line coverage percentage to the workflow summary
License
MIT License - see LICENSE for details.
Related
- Actionbook MCP - MCP Server for AI agents
- Actionbook SDK - JavaScript SDK
- Actionbook API - REST API