browser4-cli 0.1.25 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,833 +1,822 @@
1
- # Browser4
1
+ # browser4-cli
2
2
 
3
3
  Make websites accessible for AI agents. Automate tasks online with ease.
4
4
 
5
- ## Installation
5
+ ## What is browser4-cli?
6
6
 
7
- ### Global Installation (recommended)
7
+ `browser4-cli` is a command-line browser automation tool. It controls a real
8
+ Chrome browser — clicking, typing, scrolling, and extracting data — through a
9
+ local server that translates CLI commands into browser actions.
8
10
 
9
- Installs the native Rust binary:
11
+ **What you can do with it:**
10
12
 
11
- ```bash
12
- npm install -g browser4-cli
13
- ```
13
+ - Automate form filling, logins, and multistep web workflows
14
+ - Capture accessibility snapshots (ARIA tree) for interaction and HTML snapshots (HTML) for data analysis
15
+ - Extract structured data with AI, CSS selectors or X-SQL queries
16
+ - Swarm mode: Scrape at scale with parallel browser contexts
17
+ - Crawl websites recursively, following links to a configurable depth
18
+ - Run autonomous AI agent tasks from natural-language instructions
19
+ - Save screenshots, PDFs, and full HTML snapshots
14
20
 
15
- After installation, use `browser4-cli`. The shorter `browser4` command remains
16
- available as a compatibility alias.
21
+ **What makes it different:**
17
22
 
18
- ### Project Installation (local dependency)
23
+ - **HTML snapshots** - static HTML analysis without losing information
24
+ - **X-SQL** — a SQL-like query language for extracting structured data from
25
+ web pages in a single expression
26
+ - **Session persistence** — browser sessions survive across CLI invocations;
27
+ come back to the same tabs and state days later
28
+ - **Swarm scraping** — coordinate multiple browser contexts in parallel for
29
+ high-throughput data collection
19
30
 
20
- For projects that want to pin the version in `package.json`:
31
+ ## Installation
32
+
33
+ ### npm (recommended)
21
34
 
22
35
  ```bash
23
- npm install browser4-cli
36
+ npm install -g browser4-cli
37
+ browser4-cli install
24
38
  ```
25
39
 
26
- Then use via `package.json` scripts or by invoking `browser4-cli` directly.
27
-
28
- ### Standalone Installer Scripts (no npm needed)
29
-
30
- Bootstrap the native binary directly with a single command:
40
+ ### Standalone installers (no npm needed)
31
41
 
32
42
  **Windows (PowerShell):**
33
43
  ```powershell
34
- Invoke-WebRequest -Uri "https://browser4.oss-cn-beijing.aliyuncs.com/scripts/install-browser4-cli.ps1" -OutFile "$env:TEMP\install-browser4-cli.ps1"
35
- powershell -ExecutionPolicy Bypass -File "$env:TEMP\install-browser4-cli.ps1"
44
+ irm https://browser4.oss-cn-beijing.aliyuncs.com/scripts/install-browser4-cli.ps1 | iex
45
+ browser4-cli install
36
46
  ```
37
47
 
38
- **Linux / macOS (bash):**
48
+ **Linux / macOS:**
39
49
  ```bash
40
50
  curl -fsSL https://browser4.oss-cn-beijing.aliyuncs.com/scripts/install-browser4-cli.sh | bash
51
+ browser4-cli install
41
52
  ```
42
53
 
43
- Or run the scripts locally from a cloned repo:
44
- - `cli/scripts/install-browser4-cli.ps1` (Windows)
45
- - `cli/scripts/install-browser4-cli.sh` (Linux / macOS / Git Bash)
46
-
47
- See [Standalone CLI Installer Scripts](../docs/cli-standalone-install.md) for
48
- the full option reference, supported platforms, and examples.
49
-
50
- ### From Source
51
-
52
- **Build prerequisites:** Rust (stable, edition 2021), Node.js 24+, pnpm 10+, git.
54
+ ## Quick start
53
55
 
54
56
  ```bash
55
- git clone https://github.com/platonai/Browser4.git
56
- cd Browser4/cli/browser4-cli
57
- pnpm install
58
- pnpm build:native # Compiles the Rust binary (requires https://rustup.rs)
59
- pnpm link --global # Makes browser4-cli available globally
60
- ```
57
+ # Open a browser session
58
+ browser4-cli open --headed https://browser4.io
61
59
 
62
- Cross-compilation from Linux (for release builds) additionally requires:
63
- `cargo-zigbuild`, Zig 0.13.0, `gcc-aarch64-linux-gnu`, and `mingw-w64`.
64
- See `cli/docker/Dockerfile.build` for a Dockerized build environment.
60
+ # Navigate to a page — auto-opens a session if none is active
61
+ browser4-cli goto https://browser4.io
65
62
 
66
- ### Requirements
63
+ # Inspect the page — note the eN labels on interactive nodes
64
+ browser4-cli snapshot --boxes
67
65
 
68
- - **Chrome** Latest Chrome installed on your system. The CLI can auto-install Chrome on most platforms when missing.
69
- - **Java 17+** — Required to run the Browser4 backend (`Browser4.jar`). Eclipse Temurin recommended. JDK 21+ enables best jlink compression when the CLI auto-builds a runtime bundle from source.
70
- - **Rust** Only needed when building the CLI from source (see From Source above). The `stable` toolchain (edition 2021) is sufficient.
66
+ # Interact using refs from the snapshot
67
+ browser4-cli click e15
68
+ browser4-cli type e15 "Hello World"
69
+ browser4-cli press e15 Enter
71
70
 
72
- #### Additional requirements for auto-building a runtime bundle from source
71
+ # Extract data with CSS selectors
72
+ browser4-cli get text ".product-title"
73
+ browser4-cli get attr ".product-image" data-src
73
74
 
74
- When the CLI detects a Browser4 repository checkout, it attempts to build a
75
- self-contained runtime bundle (bundled JRE + dependency JARs) from source
76
- instead of downloading a pre-built release. This requires:
75
+ # HTML snapshot with X-SQL
76
+ browser4-cli htmlsnapshot capture
77
+ browser4-cli htmlsnapshot
78
+ browser4-cli htmlsnapshot get text "#main-content"
79
+ browser4-cli htmlsnapshot query --sql @query.sql
80
+ browser4-cli htmlsnapshot grep -i "error"
77
81
 
78
- | Tool | Version | Linux | macOS | Windows |
79
- |------|---------|-------|-------|---------|
80
- | **Maven** | 3.9+ | via `mvnw` wrapper | via `mvnw` wrapper | via `mvnw.cmd` wrapper |
81
- | **JDK tools** (`jdeps`, `jlink`) | bundled with JDK 16+ | included in JDK | included in JDK | included in JDK |
82
- | **PowerShell 7** (`pwsh`) | 7.0+ | **required** | **required** | built-in (`powershell.exe`) |
83
- | **tar** | any | **required** | **required** | built-in |
82
+ # AI-powered extraction and summarization (requires LLM key see LLM Configuration above)
83
+ browser4-cli extract "product name, price, and rating as JSON"
84
+ browser4-cli summarize "key points in 3 bullets"
84
85
 
85
- Set `BROWSER4_CLI_FORCE_REMOTE_BUNDLE=1` to skip the local build and always
86
- download a pre-built bundle useful in CI / corporate environments where
87
- Maven or jlink are unavailable.
86
+ # Autonomous agent task
87
+ browser4-cli agent run "Search amazon for mechanical keyboards, compare the top 3, write a summary"
88
88
 
89
- ## Usage
89
+ # Parallel scraping with swarm
90
+ browser4-cli swarm create --max-open-tabs 12 --display-mode HEADLESS
91
+ browser4-cli swarm submit --seed-file ./urls.txt --refresh --store-content
92
+ browser4-cli swarm result scrape-task-1
90
93
 
91
- ```
92
- browser4-cli <command> [args] [options]
93
- browser4-cli -s=<session> <command> [args] [options]
94
- ```
94
+ # Batch multiple commands
95
+ browser4-cli batch "goto https://browser4.io" "snapshot" "screenshot"
95
96
 
96
- ### Global options
97
+ # Take a screenshot
98
+ browser4-cli screenshot --full-page
97
99
 
98
- | Flag | Description |
99
- |--------------------|------------------------------------------------|
100
- | `-h`, `--help [command]` | Print help (optionally for a specific command) |
101
- | `-v`, `--version` | Print version |
102
- | `-s=<name>` | Named session label |
103
- | `--server=<url>` | Override Browser4 server URL |
104
- | `--proxy=<url>` | Manual HTTP proxy override for downloads |
105
- | `--json` | Emit machine-parseable JSON to stdout |
106
- | `-q`, `--quiet` | Suppress normal output, only show errors |
100
+ # Manage cookies and storage
101
+ browser4-cli cookie-list
102
+ browser4-cli state-save session.json
107
103
 
108
- `--json` switches every command's stdout from human-readable text to a
109
- single-line JSON envelope (`{"status":"ok","command":"<name>","output":{...}}`).
110
- Omit `--json` for the default human-readable output.
104
+ # Close the session when done
105
+ browser4-cli close
106
+ ```
111
107
 
112
- `--proxy=<url>` sets a manual HTTP proxy used only for downloading the
113
- Browser4 runtime bundle. It does not affect browser traffic.
108
+ ## Global options
114
109
 
115
- `-q` / `--quiet` suppresses all normal stdout output. Errors and
116
- progress messages still go to stderr. Combine with `--json` for
117
- silent-on-success scripting: `browser4-cli --json -q open`.
110
+ | Flag | Description |
111
+ |---|---|
112
+ | `-h`, `--help [command]` | Print help (optionally for a command) |
113
+ | `-v`, `--version` | Print version |
114
+ | `-s <name>` | Named session (isolated state per name) |
115
+ | `--server <url>` | Override Browser4 server URL |
116
+ | `--proxy <url>` | HTTP proxy for runtime downloads only |
117
+ | `--json` | Emit machine-parseable JSON to stdout |
118
+ | `-q`, `--quiet` | Suppress normal output |
118
119
 
119
- Sessions are persisted independently per name. Omitting `-s` uses the
120
- default session (`~/.browser4/cli-state.json`). With `-s=<name>`, a
121
- separate state file is stored under `~/.browser4/sessions/<name>.json`.
122
- `open` without `-s` reuses the default session if one exists; with
123
- `-s=<name>` it switches to or creates the named session.
120
+ Sessions persist independently per name. Omit `-s` to use the default session
121
+ (`~/.browser4/cli-state.json`). With `-s <name>`, state is stored under
122
+ `~/.browser4/sessions/<name>.json`.
124
123
 
125
- ### Commands
124
+ `--json` makes the CLI emit only the JSON envelope on stdout — all human-readable
125
+ text, tips, hints, and side information are suppressed (equivalent to `--quiet`
126
+ but with structured output). Every successful command writes a single-line JSON
127
+ envelope: `{"status":"ok","command":"<name>","output":{...}}`. Errors also
128
+ produce a JSON envelope with `"status":"error"` and an `"error"` object.
126
129
 
127
- The tables below mirror the commands surfaced by the global `browser4-cli help` overview.
130
+ ## Command reference
128
131
 
129
- #### Core
132
+ ### Session management
130
133
 
131
134
  | Command | Description |
132
135
  |---|---|
133
- | `open [url]` | Open or switch to a browser session. Supports `--headed` (force visible window), `--headless` (force headless), `--profile=<path>`, `--profile-mode=<mode>` (temporary / sequential / default), and `--interact-level=<level>` (FASTEST / FAST / DEFAULT). |
134
- | `close` | Close the active session |
135
- | `goto <url>` | Navigate to a URL, auto-opening or refreshing the session if needed |
136
- | `click <ref> [button]` | Click an element. Supports `--modifiers` (modifier keys to press). |
137
- | `dblclick <ref> [button]` | Double-click an element. Supports `--modifiers` (modifier keys to press). |
138
- | `type <text> [ref]` | Type text into the focused element or an optional target element. Supports `--submit` (press Enter after typing). |
139
- | `fill <ref> <text>` | Fill text into an editable element. Supports `--submit` (press Enter after filling). |
140
- | `hover <ref>` | Hover over an element |
141
- | `select <ref> <val>` | Select an option in a dropdown |
142
- | `upload <ref> <file>` | Upload a file |
143
- | `check <ref>` | Check a checkbox or radio button |
144
- | `uncheck <ref>` | Uncheck a checkbox or radio button |
145
- | `drag <startRef> <endRef>` | Drag and drop between two elements |
146
- | `snapshot` | Capture accessibility snapshot. Supports `--filename=<path>` to save to file, `--boxes` for bounding boxes, `-i`/`--interactive` for interactive-only, `-u`/`--urls` for link URLs, `-c`/`--compact` for compact output, `-d`/`--depth <n>` for depth limiting, `-s`/`--selector <sel>` for CSS scoping, and `--raw` for raw output without page info. |
147
- | `eval <expression> [ref]` | Evaluate JavaScript on the page or a target element. Use `--file=<path>` to read the expression from a file. |
148
- | `get <mode> <selector> [name]` | Extract data from a page element. Modes: `text`, `html`, `box`, `styles`, `property`, `attr`. `name` is required for `property` and `attr`. |
149
- | `scroll <direction> <pixels>` | Scroll the page. Direction: `up`, `down`, `left`, or `right`. |
150
- | `wait [target]` | Wait for a condition. Positional: selector or milliseconds. Options: `--text=<text>`, `--url=<glob>`, `--load=<state>` (networkidle/domcontentloaded), `--fn=<JS expr>`. |
151
- | `dialog-accept [prompt]` | Accept a dialog |
152
- | `dialog-dismiss` | Dismiss a dialog |
153
- | `resize <w> <h>` | Resize the browser window |
154
- | `delete-data` | Delete session data |
155
-
156
- #### Navigation
136
+ | `open [url]` | Open or reuse a browser session. `--headed` / `--headless`, `--profile <path>`, `--profile-mode <mode>` (temporary / sequential / default), `--interact-level <level>` (FASTEST / FAST / DEFAULT). |
137
+ | `attach` | Attach to an existing browser via CDP endpoint or channel name. `--cdp <url\|channel>` (e.g. `http://localhost:9222` or `chrome`), `--endpoint <url>` for remote Browser4 servers. |
138
+ | `close` | Close the active session. |
139
+ | `list` | List sessions with status (Active / Stale / Unknown). `--all` to list across workspaces. |
140
+ | `close-all` | Close all sessions, keep the backend running. |
141
+ | `kill-all` | Forcefully stop the backend and all browser processes. |
142
+ | `stop` | Gracefully stop the Browser4 server. |
143
+ | `status` | Check whether the backend is reachable. `--server <url>` to check a specific server. |
144
+ | `doctor` | Run system diagnostics. `--server <url>`, `--file <log-name>`, `--lines <n>`. |
157
145
 
158
- | Command | Description |
159
- |---|---|
160
- | `go-back` | Go back to the previous page |
161
- | `go-forward` | Go forward to the next page |
162
- | `reload` | Reload the current page |
146
+ ```bash
147
+ browser4-cli open --headed https://example.com
148
+ browser4-cli open --profile-mode temporary https://example.com
149
+ browser4-cli attach --cdp chrome
150
+ browser4-cli list
151
+ browser4-cli status
152
+ ```
163
153
 
164
- #### Keyboard
154
+ ### Navigation
165
155
 
166
156
  | Command | Description |
167
157
  |---|---|
168
- | `press <key> [ref]` | Press a key on the focused element or an optional target element |
169
- | `keydown <key>` | Press and hold a key |
170
- | `keyup <key>` | Release a key |
171
-
172
- #### Mouse
158
+ | `goto <url>` | Navigate to a URL. Auto-opens a session if none is active. |
159
+ | `go-back` | Go back to the previous page. |
160
+ | `go-forward` | Go forward to the next page. |
161
+ | `reload` | Reload the current page. |
173
162
 
174
- | Command | Description |
175
- |---|---|
176
- | `mousemove <x> <y>` | Move mouse to coordinates |
177
- | `mousedown [button]` | Press mouse button |
178
- | `mouseup [button]` | Release mouse button |
179
- | `mousewheel <dx> <dy>` | Scroll the mouse wheel |
163
+ ```bash
164
+ browser4-cli goto https://example.com
165
+ browser4-cli -s mysession goto https://example.com
166
+ ```
180
167
 
181
- #### Screenshots
168
+ ### Page interaction
182
169
 
183
170
  | Command | Description |
184
171
  |---|---|
185
- | `screenshot [ref]` | Take a screenshot (optionally of a specific element). Supports `--filename=<path>` and `--full-page` (full scrollable page). |
186
- | `pdf` | Save the current page as a PDF. Supports `--filename=<path>`. |
172
+ | `click <ref> [button]` | Click an element. `--modifiers` for modifier keys. |
173
+ | `dblclick <ref> [button]` | Double-click an element. `--modifiers` for modifier keys. |
174
+ | `hover <ref>` | Hover over an element. |
175
+ | `drag <startRef> <endRef>` | Drag and drop between two elements. |
176
+ | `fill <ref> <text>` | Fill text into an editable element. `--submit` to press Enter after. `--verify` to confirm. |
177
+ | `type <text> [ref]` | Type text. `--submit`, `--verify`, `--focus` (click first to focus). |
178
+ | `select <ref> <val>` | Select an option in a dropdown. `--verify` to confirm. |
179
+ | `check <ref>` | Check a checkbox or radio. |
180
+ | `uncheck <ref>` | Uncheck a checkbox or radio. |
181
+
182
+ All interaction commands accept element references from `snapshot` (e.g. `e15`)
183
+ or CSS selectors (e.g. `#submit-btn`, `.menu-item`).
187
184
 
188
- #### Tabs
185
+ ```bash
186
+ browser4-cli click e15
187
+ browser4-cli fill e7 "John Doe" --submit
188
+ browser4-cli type "search term" e3
189
+ browser4-cli select e12 "option-value"
190
+ ```
191
+
192
+ ### Keyboard & mouse
189
193
 
190
194
  | Command | Description |
191
195
  |---|---|
192
- | `tab-list` | List all tabs with their zero-based index |
193
- | `tab-new [url]` | Create a new tab |
194
- | `tab-close [index]` | Close a tab by its zero-based index |
195
- | `tab-select <index>` | Select a tab by its zero-based index |
196
+ | `press <key> [ref]` | Press a key (`a`, `Enter`, `ArrowLeft`, `Escape`). Supports `--verify`. |
197
+ | `keydown <key>` | Press and hold a key. |
198
+ | `keyup <key>` | Release a key. |
199
+ | `mousemove <x> <y>` | Move mouse to coordinates. |
200
+ | `mousedown [button]` | Press mouse button (defaults to left). |
201
+ | `mouseup [button]` | Release mouse button. |
202
+ | `mousewheel <dx> <dy>` | Scroll the mouse wheel. |
203
+ | `scroll <direction> <pixels>` | Scroll the page (`up` / `down` / `left` / `right`). |
196
204
 
197
- Run `tab-list` first to find each tab's zero-based index. Pass that index to `tab-select` or `tab-close`.
205
+ ```bash
206
+ browser4-cli press Enter e7
207
+ browser4-cli mousemove 200 400
208
+ browser4-cli scroll down 300
209
+ ```
198
210
 
199
- #### Browser storage
211
+ ### Waiting & dialogs
200
212
 
201
213
  | Command | Description |
202
214
  |---|---|
203
- | `state-save <path>` | Save cookies and localStorage to a JSON file |
204
- | `state-load <path>` | Restore cookies and localStorage from a saved state file |
205
- | `cookie-list` | List all cookies (optionally filtered by `--domain` / `--path`) |
206
- | `cookie-get <name>` | Get a cookie by name |
207
- | `cookie-set <name> <value>` | Set a cookie. Supports `--path`, `--domain`, `--expires`, `--httpOnly`, `--secure`, `--sameSite` (Strict / Lax / None). |
208
- | `cookie-delete <name>` | Delete a cookie by name |
209
- | `cookie-clear` | Clear all cookies for the current page |
210
- | `localstorage-list` | List all localStorage entries |
211
- | `localstorage-get <key>` | Get a localStorage value by key |
212
- | `localstorage-set <key> <value>` | Set a localStorage key-value pair |
213
- | `localstorage-delete <key>` | Delete a localStorage key |
214
- | `localstorage-clear` | Clear all localStorage entries |
215
- | `sessionstorage-list` | List all sessionStorage entries |
216
- | `sessionstorage-get <key>` | Get a sessionStorage value by key |
217
- | `sessionstorage-set <key> <value>` | Set a sessionStorage key-value pair |
218
- | `sessionstorage-delete <key>` | Delete a sessionStorage key |
219
- | `sessionstorage-clear` | Clear all sessionStorage entries |
220
-
221
- #### Browser sessions
215
+ | `wait [target]` | Wait for a condition six modes available. |
216
+ | `dialog-accept [prompt]` | Accept a browser dialog (alert, confirm, prompt). |
217
+ | `dialog-dismiss` | Dismiss a browser dialog. |
222
218
 
223
- | Command | Description |
224
- |---|---|
225
- | `list` | List browser sessions. Supports `--all` (list sessions across all workspaces). |
226
- | `close-all` | Close all browser sessions without stopping `Browser4.jar` / the Browser4 backend |
227
- | `kill-all` | Forcefully stop `Browser4.jar` / the Browser4 backend and kill Browser4 browser processes |
219
+ `wait` supports six modes, selected by which option you provide:
220
+
221
+ | Mode | Syntax | Example |
222
+ |---|---|---|
223
+ | **selector** | `wait <ref\|selector>` | `browser4-cli wait e1` |
224
+ | **time** | `wait <milliseconds>` | `browser4-cli wait 2000` |
225
+ | **text** | `wait --text <text>` | `browser4-cli wait --text "Success"` |
226
+ | **url** | `wait --url <glob>` | `browser4-cli wait --url "**/dashboard"` |
227
+ | **load** | `wait --load <state>` | `browser4-cli wait --load networkidle` |
228
+ | **fn** | `wait --fn <JS expr>` | `browser4-cli wait --fn "window.ready === true"` |
228
229
 
229
- Use `close-all` for session cleanup when you want to keep the current Browser4 service running. Use `kill-all` only when you explicitly want to stop the backend and clean up tracked Browser4 processes.
230
+ All modes accept `--timeout <ms>` (default: 30000). Load states: `networkidle`,
231
+ `domcontentloaded`, `load`.
230
232
 
231
- #### Server management
233
+ ### Screenshots & PDF
232
234
 
233
235
  | Command | Description |
234
236
  |---|---|
235
- | `install` | Download the Browser4 runtime bundle. Supports `--tag=<version>` to pin a release and `--force` to reinstall even when already present. |
236
- | `upgrade` | Upgrade the Browser4 runtime bundle to the latest version or a specified `--tag` |
237
- | `uninstall` | Remove globally installed browser4-cli (npm) and its runtime data. Supports `-y` / `--yes` (skip confirmation) and `--dry-run` (preview). |
238
- | `stop` | Kill the Browser4 backend after closing all sessions |
239
- | `status` | Check whether the Browser4 backend is reachable and healthy |
240
-
241
- `install` and `upgrade` both manage the Browser4 runtime bundle — a self-contained
242
- distribution that includes all dependency jars, a minimal `jlink`-built JRE, and
243
- platform launcher scripts. Neither requires `cargo` or a Rust toolchain; the runtime
244
- is a Java application downloaded from GitHub Releases.
245
-
246
- Use `--tag=<version>` to pin a specific release (e.g. `--tag=v4.9.3`). Use `--force`
247
- to reinstall even when the same version is already present.
248
-
249
- When a local Browser4 checkout is detected with the `browser4-bundle` module present,
250
- `install` and `upgrade` auto-build the runtime bundle from source (via Maven) instead
251
- of downloading.
252
-
253
- `uninstall` attempts to remove browser4-cli from npm global packages
254
- and deletes the Browser4 runtime data and cache directories. It prompts
255
- for confirmation unless `-y` / `--yes` is passed. Use `--dry-run` to preview what
256
- would be removed without making changes. Does not require a running server.
257
-
258
- ```shell
259
- browser4-cli uninstall
260
- browser4-cli uninstall -y
261
- browser4-cli uninstall --dry-run
262
- ```
237
+ | `screenshot [ref]` | Take a screenshot. `--filename <path>`, `--full-page`. Optionally of a specific element. |
238
+ | `pdf` | Save page as PDF. `--filename <path>`. |
263
239
 
264
- ### Advanced commands
240
+ ```bash
241
+ browser4-cli screenshot --full-page --filename page.png
242
+ browser4-cli pdf --filename page.pdf
243
+ ```
265
244
 
266
- These commands are intentionally omitted from the global `browser4-cli help` overview.
267
- Query `browser4-cli help <command>` for the exact syntax when you need them.
245
+ ### Tabs
268
246
 
269
247
  | Command | Description |
270
248
  |---|---|
271
- | `batch [command...]` | Execute multiple commands in one invocation. Only DOM operations are supported (Core, Navigation, Keyboard, Mouse, Export, Tabs categories). Commands like `open`, `close`, `list`, `agent run`, etc. are not allowed in batch mode. |
272
- | `console [min-level]` | List console messages |
273
- | `extract <instruction>` | Extract structured data from the current page. Supports `--schema` (JSON Schema for typed output). |
274
- | `summarize [instruction]` | Summarize page content using AI |
275
- | `agent run <task>` | Run an autonomous agent task |
276
- | `agent status <id>` | Check the status of a running agent task |
277
- | `agent result <id>` | Get the result of a completed agent task |
278
- | `swarm create` | Create a swarm scrape session with parallel browser contexts |
279
- | `swarm submit [url]` | Submit URL(s) or raw X-SQL payloads as scrape jobs |
280
- | `swarm query <url>` | Run an X-SQL query against a loaded webpage |
281
- | `swarm status <id>` | Check the status of a scrape or query job |
282
- | `swarm result <id>` | Get the result of a completed job |
283
- | `crawl <url>` | Crawl a website from a seed URL, following links up to a configurable depth |
284
-
285
- ## Agent task workflow (`agent <subcommand>`)
286
-
287
- The `agent-*` commands wrap the backend command agent's asynchronous task API.
288
- They are useful when you want Browser4 to plan and execute a natural-language
289
- task in the background instead of issuing one low-level browser action at a
290
- time.
291
-
292
- Like other advanced commands, they are intentionally omitted from the global
293
- `browser4-cli help` overview. Query `browser4-cli help agent run` (or
294
- `agent status` / `agent result`) when you need the exact syntax.
295
-
296
- Use the spaced `agent <subcommand>` form:
297
-
298
- ```shell
299
- browser4-cli agent run "Open browser4.io and summarize the hero section"
300
- browser4-cli agent status agent-task-1
301
- browser4-cli agent result agent-task-1
249
+ | `tab-list` | List all tabs with their zero-based index. |
250
+ | `tab-new [url]` | Open a new tab. |
251
+ | `tab-close [index]` | Close a tab (current tab if no index). |
252
+ | `tab-select <index>` | Switch to a tab by index. |
253
+
254
+ ```bash
255
+ browser4-cli tab-list
256
+ browser4-cli tab-select 1
257
+ browser4-cli tab-new https://example.com
258
+ browser4-cli tab-close 1
302
259
  ```
303
260
 
304
- ### Command lifecycle
261
+ ### Element inspection
305
262
 
306
- | Step | Command | What it does |
263
+ | Command | Description |
264
+ |---|---|
265
+ | `snapshot` | Capture an accessibility snapshot. See [Snapshot](#snapshot) below. |
266
+ | `get <mode> <selector> [name]` | Extract data from a page element in one of six modes (see below). |
267
+ | `eval <expression> [ref]` | Evaluate JavaScript on the page or a target element. `--file <path>` to read from file. `--json` to wrap scalar results. |
268
+ | `generate-locator <ref>` | Generate a stable CSS selector path for an element. |
269
+ | `htmlsnapshot` | Short form of `htmlsnapshot capture`. Capture a static HTML snapshot. See [HTML Snapshot](#dom-snapshot) below. |
270
+ | `htmlsnapshot capture` | Capture a static HTML snapshot. See [HTML Snapshot](#dom-snapshot) below. |
271
+ | `extract <instruction>` | Extract structured data with AI. `--schema <file>` for typed output. `--filename <path>`, `--raw`. |
272
+ | `summarize [instruction]` | Summarize page content with AI. `--selector <css>`, `--filename <path>`, `--raw`. |
273
+
274
+ `get` modes:
275
+
276
+ | Mode | Returns | Example |
307
277
  |---|---|---|
308
- | 1 | `agent run <task>` | Submits an asynchronous natural-language task through `command_run` and prints the returned task ID |
309
- | 2 | `agent status <id>` | Fetches the latest task status payload through `command_status` |
310
- | 3 | `agent result <id>` | Fetches the completed task result payload through `command_result` |
311
-
312
- ### Notes
313
-
314
- - `agent run` is asynchronous: it returns immediately after the backend accepts
315
- the task and prints a follow-up `agent status` command with the generated task
316
- ID.
317
- - `agent status` prints the backend status payload as-is. In practice this is a
318
- JSON object that commonly includes fields such as `id`, `status`,
319
- `statusCode`, `processState`, `message`, `agentState`, `agentHistory`, and
320
- `commandResult`.
321
- - `agent result` prints the backend result payload as-is. Depending on the task,
322
- it may be plain text or structured JSON.
323
- - These commands are task-ID based and do not require an active CLI browser
324
- session slot. The global `-s=<name>` option is therefore usually not relevant
325
- for `agent-*` follow-up calls.
326
- - `agent` subcommands are not supported inside `batch` mode.
327
- - `agent run` performs a short post-submit status probe so obvious missing-LLM
328
- configuration failures can be surfaced immediately instead of leaving you with
329
- a task ID that will never succeed.
330
-
331
- ### Use cases
332
-
333
- #### 1. Submit an autonomous agent task
334
-
335
- ```shell
336
- browser4-cli agent run "Open browser4.io and summarize the hero section"
337
- ```
278
+ | `text` | Visible inner text | `browser4-cli get text ".price"` |
279
+ | `html` | Inner HTML | `browser4-cli get html e3` |
280
+ | `box` | Bounding box `{x,y,w,h}` | `browser4-cli get box "#header"` |
281
+ | `styles` | Computed CSS styles | `browser4-cli get styles e9` |
282
+ | `property` | DOM property value | `browser4-cli get property "input" value` |
283
+ | `attr` | HTML attribute value | `browser4-cli get attr "a.link" href` |
338
284
 
339
- Typical output:
340
-
341
- ```text
342
- Task submitted: agent-task-1
343
- Use 'browser4-cli agent status agent-task-1' to check progress.
285
+ ```bash
286
+ browser4-cli eval "document.title"
287
+ browser4-cli eval "el => el.textContent" e15
288
+ browser4-cli eval --file script.js
289
+ browser4-cli generate-locator e5
290
+ browser4-cli extract "product name, price, and rating"
291
+ browser4-cli summarize --selector "#reviews"
344
292
  ```
345
293
 
346
- #### 2. Poll task progress
294
+ ### Browser storage
347
295
 
348
- ```shell
349
- browser4-cli agent status agent-task-1
350
- ```
351
-
352
- Example status payload:
296
+ | Command | Description |
297
+ |---|---|
298
+ | `state-save [path]` | Save cookies & localStorage to a JSON file. |
299
+ | `state-load <path>` | Restore cookies & localStorage from a saved state. |
300
+ | `cookie-list` | List cookies. `--domain`, `--path` filters. |
301
+ | `cookie-get <name>` | Get a cookie by name. |
302
+ | `cookie-set <name> <value>` | Set a cookie. `--domain`, `--path`, `--expires`, `--httpOnly`, `--secure`, `--sameSite` (Strict / Lax / None). |
303
+ | `cookie-delete <name>` | Delete a cookie. `--domain`, `--path` overrides. |
304
+ | `cookie-clear` | Clear all cookies. |
305
+ | `localstorage-list` | List localStorage entries. |
306
+ | `localstorage-get <key>` | Get a localStorage value. |
307
+ | `localstorage-set <key> <value>` | Set a localStorage value. |
308
+ | `localstorage-delete <key>` | Delete a localStorage key. |
309
+ | `localstorage-clear` | Clear all localStorage. |
310
+ | `sessionstorage-list` | List sessionStorage entries. |
311
+ | `sessionstorage-get <key>` | Get a sessionStorage value. |
312
+ | `sessionstorage-set <key> <value>` | Set a sessionStorage value. |
313
+ | `sessionstorage-delete <key>` | Delete a sessionStorage key. |
314
+ | `sessionstorage-clear` | Clear all sessionStorage. |
353
315
 
354
- ```json
355
- {"id":"agent-task-1","status":"RUNNING"}
316
+ ```bash
317
+ browser4-cli state-save auth.json
318
+ browser4-cli state-load auth.json
319
+ browser4-cli cookie-set token abc123 --httpOnly --secure --sameSite Lax
320
+ browser4-cli cookie-list --domain example.com
356
321
  ```
357
322
 
358
- On a real Browser4 backend the payload can be richer and may include lifecycle
359
- details such as `processState`, agent history snapshots, or an embedded partial
360
- `commandResult`.
323
+ ### Batch & loop
361
324
 
362
- #### 3. Read the final result
325
+ | Command | Description |
326
+ |---|---|
327
+ | `batch [command...]` | Execute multiple commands in one invocation. `--bail` to stop on first failure. `--json` to read commands from stdin JSON. |
328
+ | `loop <task>` | Execute a task repeatedly on an interval. Supports plain text tasks, X-SQL, shell commands (`--shell`), and CLI subcommands (after `--`). |
363
329
 
364
- ```shell
365
- browser4-cli agent result agent-task-1
366
- ```
330
+ `batch` only supports DOM operations (navigation, keyboard, mouse, core
331
+ interactions, screenshots, tabs). Session lifecycle commands (`open`, `close`)
332
+ must run separately.
367
333
 
368
- If the backend returns a structured `CommandResult`, expect fields such as
369
- `summary`, `pageSummary`, `fields`, `links`, or `xsqlResultSet`.
334
+ ```bash
335
+ # Batch form fill
336
+ browser4-cli batch "fill e1 'John'" "fill e2 'john@example.com'" "click e3"
370
337
 
371
- ## Swarm scrape workflow (`swarm <subcommand>`)
338
+ # Stop on first failure
339
+ browser4-cli batch --bail "goto https://example.com" "click e1" "screenshot"
372
340
 
373
- The `swarm` subcommands support a swarm scrape workflow where one CLI session
374
- coordinates multiple browser contexts in the Browser4 backend.
341
+ # Pipe commands as JSON
342
+ echo '[
343
+ ["goto", "https://example.com"],
344
+ ["fill", "#name", "Bob"],
345
+ ["click", "#submit"]
346
+ ]' | browser4-cli batch --json
375
347
 
376
- ### Command overview
348
+ # Loop: run every 5 minutes, 10 iterations
349
+ browser4-cli loop "load https://example.com and extract the page title" -i 300 -n 10
377
350
 
378
- | Command | Purpose | Backend endpoint |
379
- |---|---|---|
380
- | `swarm create` | Create a swarm scrape session | `POST /api/swarm` |
381
- | `swarm submit <url>` | Scrape URLs or submit raw X-SQL | `POST /api/swarm/submit` |
382
- | `swarm query <url>` | Run X-SQL queries against loaded pages | `POST /api/swarm/query` |
383
- | `swarm status <id>` | Poll job status | `GET /api/swarm/{id}/status` |
384
- | `swarm result <id>` | Fetch completed job result | `GET /api/swarm/{id}/result` |
385
- | `crawl <url>` | Start a website crawl | `POST /api/crawl` |
386
- | (poll) | Track crawl progress | `GET /api/crawl/{id}/result` |
387
-
388
- ### URL scraping with `swarm submit`
389
-
390
- ```shell
391
- # create a session
392
- browser4-cli swarm create \
393
- --profile-mode=TEMPORARY \
394
- --max-open-tabs=12 \
395
- --max-browser-contexts=3 \
396
- --display-mode=HEADLESS
397
-
398
- # submit URLs as scrape jobs
399
- browser4-cli swarm submit https://example.com/direct \
400
- --seed-file=./swarm-seeds.txt \
401
- --deadline=2026-03-30T00:00:00Z \
402
- --expires=1d \
403
- --refresh --store-content
404
-
405
- # poll and fetch the result
406
- browser4-cli swarm status scrape-task-4
407
- browser4-cli swarm result scrape-task-4
351
+ # Loop a shell command
352
+ browser4-cli loop --shell "curl -s https://api.example.com/health" -i 60 -n 10
408
353
  ```
409
354
 
410
- ### X-SQL queries with `swarm query`
411
-
412
- Run structured X-SQL queries against loaded webpages to extract data.
355
+ ### Server management
413
356
 
414
- ```shell
415
- # Inline query:
416
- browser4-cli swarm query "https://www.amazon.com/dp/B08PP5MSVB" --sql "
417
- SELECT
418
- dom_base_uri(dom) AS url,
419
- dom_first_text(dom, '#productTitle') AS title,
420
- dom_first_slim_html(dom, 'img:expr(width > 400)') AS img
421
- FROM load_and_select(@url, 'body');
422
- "
423
-
424
- # From a file:
425
- browser4-cli swarm query "https://www.amazon.com/dp/B08PP5MSVB" --sql @query.sql
357
+ | Command | Description |
358
+ |---|---|
359
+ | `install` | Download the Browser4 runtime bundle. `--tag <version>`, `--force`. |
360
+ | `upgrade` | Upgrade the runtime. `--tag <version>`, `--force`. |
361
+ | `uninstall` | Remove browser4-cli and its runtime data. `-y` / `--yes` to skip confirmation, `--dry-run` to preview. |
426
362
 
427
- # With seed file and load options:
428
- browser4-cli swarm query --sql @query.sql --seed-file=./urls.txt --refresh
363
+ ```bash
364
+ browser4-cli install
365
+ browser4-cli install --tag v4.11.0
366
+ browser4-cli upgrade --force
367
+ browser4-cli uninstall --dry-run
368
+ browser4-cli uninstall -y
429
369
  ```
430
370
 
431
- ### Notes
432
-
433
- - `swarm create` accepts backend capability hints: `--profile-mode`, `--max-open-tabs`,
434
- `--max-browser-contexts`, `--display-mode`.
435
- - `swarm submit` and `swarm query` both accept a positional URL, `--seed-file`, or both.
436
- Seed files use one URL per line; `#` comments and blank lines are ignored.
437
- - Both commands support load-option flags: `--deadline`, `--expires`, `--refresh`,
438
- `--parse`, `--store-content`.
439
- - `swarm query --sql` is **required**; `swarm submit --sql` also works as a convenience.
440
- Use `@url` in the X-SQL template; it is replaced with the target URL server-side.
441
- - Prefix the `--sql` value with `@` to read from a file (e.g. `--sql @query.sql`).
442
- - All commands return a task ID; use `swarm status` / `swarm result` to track progress.
371
+ ### Other
443
372
 
444
- ## Crawl (`crawl`)
445
-
446
- Recursive website crawling from a seed URL.
447
-
448
- ### Command overview
373
+ | Command | Description |
374
+ |---|---|
375
+ | `resize <w> <h>` | Resize the browser window. |
376
+ | `delete-data` | Delete session data (cookies, storage, cache). |
377
+ | `console [min-level]` | List console messages. `--clear` to clear. |
378
+ | `upload <ref> <file>` | Upload files to a file input. |
449
379
 
450
- | Command | Purpose | Backend endpoint |
451
- |---|---|---|
452
- | `crawl <url>` | Crawl a website from a seed URL | `POST /api/crawl` |
453
- | (poll) | Track crawl progress | `GET /api/crawl/{id}/result` |
380
+ ---
454
381
 
455
- ### Basic crawling
382
+ ## Commands with subcommands
456
383
 
457
- ```shell
458
- # depth=1: extract all links from homepage, load each linked page
459
- browser4-cli crawl "https://example.com" --out-link-selector "a[href]"
384
+ ### Snapshot
460
385
 
461
- # depth=2: follow links two levels deep, filter by pattern
462
- browser4-cli crawl "https://shop.example.com" \
463
- --depth 2 \
464
- --out-link-selector "a.product-link" \
465
- --out-link-pattern "/product/" \
466
- --top-links 10
386
+ `snapshot` captures an accessibility tree of the current page. Every interactive
387
+ element is labeled with a ref (`e15`, `e42`) that you can pass directly to
388
+ `click`, `type`, `fill`, and other interaction commands.
467
389
 
468
- # with LoadOptions passthrough
469
- browser4-cli crawl "https://example.com" -ol "a[href]" -a "-refresh -nMaxRetry 5"
390
+ ```
391
+ browser4-cli snapshot [options]
392
+ browser4-cli snapshot grep [OPTIONS] <pattern>
470
393
  ```
471
394
 
472
- ### Key flags
473
-
474
- | Flag | Default | Description |
475
- |---|---|---|
476
- | `-d`, `--depth` | `1` | Maximum crawl depth |
477
- | `-ol`, `--out-link-selector` | — | CSS selector to extract links from each page |
478
- | `-olp`, `--out-link-pattern` | `.+` | Regex pattern to filter extracted links |
479
- | `-tl`, `--top-links` | `20` | Maximum links to extract per page |
480
- | `-a`, `--args` | — | Additional LoadOptions passthrough |
481
- | `--refresh` | — | Force a fresh fetch, ignoring cache |
482
- | `--parse` | — | Parse each page immediately after fetching |
483
- | `--expires` | — | Cache expiration duration |
484
- | `--store-content` | — | Persist page content to storage |
485
- | `--page-load-timeout` | — | Maximum time to wait for page load |
486
- | `--readonly` | — | Non-destructive mode |
395
+ #### snapshot
487
396
 
488
- ### Notes
397
+ Capture the accessibility snapshot.
489
398
 
490
- - All LoadOptions flags available via `--args` passthrough (e.g. `-a "-nMaxRetry 5 -lazyFlush"`).
491
- - Depth=1 reuses `PulsarSession.submitForOutPages`; depth>1 uses BFS continuous crawl with visited-URL dedup.
492
- - CLI timeout: 600s default, configurable via `BROWSER4_CLI_CRAWL_TIMEOUT_SECS`.
493
- - Duplicate URLs are skipped (normalized: lowercase, no trailing slash, no query string).
399
+ | Option | Description |
400
+ |---|---|
401
+ | `--filename <path>` | Save snapshot to file instead of stdout |
402
+ | `--boxes` | Include bounding boxes `[box=x,y,w,h]` per element |
403
+ | `-i`, `--interactive` | Show only interactive elements |
404
+ | `-u`, `--urls` | Include href URLs for link elements |
405
+ | `-c`, `--compact` | Remove empty structural nodes (default) |
406
+ | `--no-compact` | Include all structural nodes |
407
+ | `-d`, `--depth <n>` | Limit tree depth |
408
+ | `-l`, `--limit <n>` | Cap total rendered nodes |
409
+ | `-s`, `--selector <css>` | Scope snapshot to a CSS selector |
410
+ | `--raw`, `--stdout` | Print directly to stdout (for piping) |
411
+ | `-vp`, `--viewport <spec>` | Capture specific viewports (e.g. `0,2,4` or `1-3`) |
494
412
 
495
- ## DOM Snapshot commands (`domsnapshot <subcommand>`)
413
+ ```bash
414
+ # Full snapshot with bounding boxes
415
+ browser4-cli snapshot --boxes
496
416
 
497
- The `domsnapshot` commands capture and query a **static DOM snapshot** of the
498
- current page. Unlike the real-time accessibility `snapshot`, a DOM snapshot is
499
- a full HTML capture that can be queried repeatedly with CSS selectors and X-SQL
500
- without re-fetching the page.
417
+ # Interactive elements only, depth-limited
418
+ browser4-cli snapshot -i -c -d 5
501
419
 
502
- Use the spaced `domsnapshot <subcommand>` form:
420
+ # Scope to a specific section, pipe to grep
421
+ browser4-cli snapshot -s "#main-content" --raw | grep "button"
503
422
 
504
- ```shell
505
- browser4-cli domsnapshot
506
- browser4-cli domsnapshot get text "#productTitle"
507
- browser4-cli domsnapshot query --sql "SELECT dom_first_text(dom, '#title') AS title FROM dom(dom)"
508
- browser4-cli domsnapshot export --file=page.html
423
+ # Capture specific viewports
424
+ browser4-cli snapshot --viewport 0,2,4
509
425
  ```
510
426
 
511
- ### Command overview
512
-
513
- | Command | Description |
514
- |---|---|
515
- | `domsnapshot` | Capture a static DOM snapshot of the current page |
516
- | `domsnapshot get <field> [selector] [name]` | Extract elements from the static DOM snapshot |
517
- | `domsnapshot query [url] --sql=<query>` | Run X-SQL against the DOM snapshot via the scrape API |
518
- | `domsnapshot export [--file=<path>]` | Save full snapshot HTML content to a local file |
519
- | `domsnapshot grep [OPTIONS] <pattern>` | Search snapshot HTML with regex and grep-style output |
427
+ #### snapshot grep
520
428
 
521
- ### `domsnapshot grep` flags
522
-
523
- Line numbers are shown by default (unlike GNU grep). Use `--no-line-number` to suppress them.
429
+ Search the accessibility-tree YAML with regex patterns and grep-style output.
430
+ Line numbers are shown by default.
524
431
 
525
432
  | Flag | Description |
526
433
  |---|---|
527
434
  | `-i` | Case-insensitive matching |
528
435
  | `-A N`, `-B N`, `-C N` | Context lines after / before / around each match |
529
- | `-v` | Invert match (select non-matching lines) |
436
+ | `-v` | Invert match (non-matching lines) |
530
437
  | `-c` | Print only count of matching lines |
531
- | `-l` | Print only whether matches exist (prints "domsnapshot" if matches found; use with `\| grep -q domsnapshot` for CI pass/fail) |
438
+ | `-l` | Print only whether matches exist |
532
439
  | `-F` | Treat pattern as a literal string |
533
440
  | `-w` | Match whole words only |
534
- | `--no-line-number` | Suppress line numbers in output |
535
- | `--selector <CSS>` | Scope search to a CSS selector |
441
+ | `--no-line-number` | Suppress line numbers |
442
+ | `--selector <css>` | Scope search to a CSS selector |
443
+ | `--page N`, `--page-size N`, `--all` | Output pagination (2000 lines per page default) |
444
+
445
+ ```bash
446
+ browser4-cli snapshot grep -i error
447
+ browser4-cli snapshot grep -C 2 "timeout"
448
+ browser4-cli snapshot grep -F -w "Error" --selector main
449
+ ```
536
450
 
537
- ```shell
538
- # Basic search
539
- browser4-cli domsnapshot grep -i error
451
+ ---
540
452
 
541
- # With context and literal match
542
- browser4-cli domsnapshot grep -F -C 2 "404 Not Found"
453
+ ### HTML Snapshot
543
454
 
544
- # Count matches
545
- browser4-cli domsnapshot grep -c "div"
455
+ `htmlsnapshot` captures a **static HTML snapshot** of the current page — a full
456
+ HTML capture stored in the backend that can be queried repeatedly without
457
+ re-fetching. Unlike the accessibility `snapshot`, this works against the raw DOM.
546
458
 
547
- # Search within a specific element
548
- browser4-cli domsnapshot grep --selector main "Submit"
459
+ ```
460
+ browser4-cli htmlsnapshot capture
461
+ browser4-cli htmlsnapshot
462
+ browser4-cli htmlsnapshot get <field> [selector] [name]
463
+ browser4-cli htmlsnapshot get all <field> [selector] [name]
464
+ browser4-cli htmlsnapshot query [url] --sql <query>
465
+ browser4-cli htmlsnapshot export [--file <path>]
466
+ browser4-cli htmlsnapshot summary
467
+ browser4-cli htmlsnapshot grep [OPTIONS] <pattern>
468
+ browser4-cli htmlsnapshot inspect [selector] [--max N] [--depth D]
549
469
  ```
550
470
 
551
- ### `domsnapshot get` fields
471
+ #### htmlsnapshot / htmlsnapshot capture
552
472
 
553
- | Field | Description |
554
- |---|---|
555
- | `text` | Extract text content from the matched element |
556
- | `html` | Extract inner HTML from the matched element |
557
- | `attr` | Extract an attribute value (requires `name`, e.g. `attr "#link" "href"`) |
473
+ Capture the DOM and display metadata (URL, title, timestamps, image/link counts,
474
+ interactive elements with tag, class, id, aria, and bounding boxes).
475
+ `htmlsnapshot` is a short form of `htmlsnapshot capture`.
558
476
 
559
- `selector` defaults to `:root` when omitted. `name` (attribute name) is
560
- required for the `attr` field.
477
+ ```bash
478
+ browser4-cli htmlsnapshot capture
479
+ browser4-cli htmlsnapshot
480
+ ```
561
481
 
562
- ### `domsnapshot query` with X-SQL
482
+ #### htmlsnapshot get
563
483
 
564
- ```shell
565
- # Inline X-SQL:
566
- browser4-cli domsnapshot query "https://example.com" --sql "
567
- SELECT
568
- dom_base_uri(dom) AS url,
569
- dom_first_text(dom, 'h1') AS title
570
- FROM dom(dom);
571
- "
484
+ Extract elements from the stored snapshot by CSS selector.
572
485
 
573
- # From a file:
574
- browser4-cli domsnapshot query --sql @query.sql
575
- ```
486
+ | Field | Returns | Example |
487
+ |---|---|---|
488
+ | `text` | Inner text of the first match | `htmlsnapshot get text "#title"` |
489
+ | `html` | Inner HTML of the first match | `htmlsnapshot get html "body"` |
490
+ | `attr` | Attribute value (requires `name`) | `htmlsnapshot get attr "a" href` |
576
491
 
577
- - `--sql` is **required**. Prefix with `@` to read from a file (e.g. `--sql @query.sql`).
578
- - `url` is optional and defaults to the current session's page URL.
579
- - These commands do not require an active swarm session.
492
+ Selector defaults to `:root`. `get html` output is paginated (2000 lines per page);
493
+ `get text` is not paginated by default. Use `--page N`, `--page-size N`, or `--all`.
580
494
 
581
- ### Notes
495
+ ```bash
496
+ browser4-cli htmlsnapshot get text "#productTitle"
497
+ browser4-cli htmlsnapshot get html "#main-content"
498
+ browser4-cli htmlsnapshot get attr "a.product-link" href
499
+ browser4-cli htmlsnapshot get html "body" --page 2
500
+ browser4-cli htmlsnapshot get html --all
501
+ ```
582
502
 
583
- - `domsnapshot` commands are not supported inside `batch` mode.
584
- - Use `domsnapshot get` for quick element extraction; use `domsnapshot query`
585
- with X-SQL for structured multi-element extraction.
586
- - The DOM snapshot is cached in the backend until the next `domsnapshot`
587
- capture or session navigation.
503
+ #### htmlsnapshot get all
588
504
 
589
- ## Element References
505
+ Like `get`, but extracts ALL matching elements (querySelectorAll semantics).
506
+ Supports `--offset N` and `--limit N` for element-level pagination, plus
507
+ `--page N`, `--page-size N`, `--all` for output pagination. `get all html` is
508
+ paginated at 2000 lines by default; `get all text` is not paginated by default.
590
509
 
591
- The `snapshot` command returns an accessibility tree where every interactive
592
- node is labeled with a short identifier such as `e15`. Pass this identifier
593
- directly to commands like `click`, `type`, or `press`. You can also use plain
594
- CSS selectors (e.g. `.my-button`, `#search-input`).
510
+ > **Note:** Each `get all` call scans the whole document independently. For
511
+ > **correlated multi-field extraction** (title + price + URL per item), use
512
+ > `htmlsnapshot query` with X-SQL's `DOM_LOAD_AND_SELECT` it scopes each row
513
+ > to a parent container so fields stay aligned. See the
514
+ > [list-page scraping pattern](skill/references/x-sql-dom-load-select.md).
595
515
 
596
- ## State Persistence
516
+ ```bash
517
+ browser4-cli htmlsnapshot get all text "h2 a"
518
+ browser4-cli htmlsnapshot get all text ".result" --offset 10 --limit 5
519
+ browser4-cli htmlsnapshot get all text "p" --page-size 500
520
+ ```
597
521
 
598
- `browser4-cli` persists CLI state between invocations under `~/.browser4` by
599
- default. Override the root directory with the `BROWSER4_CLI_STATE_DIR`
600
- environment variable.
522
+ #### htmlsnapshot query
601
523
 
602
- - Default session state: `~/.browser4/cli-state.json`
603
- - Named session state (`-s=<name>`): `~/.browser4/sessions/<name>.json`
524
+ Run an X-SQL query against the stored HTML snapshot. `--sql` is required. Use
525
+ `@url` as a placeholder for the target page URL (unquoted — the server handles
526
+ escaping).
604
527
 
605
- Each state file stores the current Browser4 server URL plus session-scoped
606
- fields such as:
528
+ **Recommended:** Write queries to a `.sql` file to avoid shell escaping issues.
529
+ Prefix the `--sql` value with `@` to read from a file. Use `--sql-stdin` for
530
+ piped/scripted workflows, or `--sql-base64` for transport-safe encoded queries.
607
531
 
608
- - `sessionId` — active Browser4 session ID
609
- - `baseUrl` Browser4 backend URL used by the CLI
610
- - `activeSelector` last selector tracked for keyboard restore flows
611
- - `lastMousePosition` — last pointer coordinates tracked for mouse restore flows
532
+ ```bash
533
+ # From a file (recommended no shell escaping)
534
+ cat > query.sql << 'SQLEOF'
535
+ SELECT
536
+ dom_base_uri(dom) AS url,
537
+ dom_first_text(dom, 'h1') AS title
538
+ FROM load_and_select(@url, ':root')
539
+ SQLEOF
540
+ browser4-cli htmlsnapshot query --sql @query.sql
541
+
542
+ # From stdin
543
+ cat query.sql | browser4-cli htmlsnapshot query --sql-stdin
544
+
545
+ # From base64 (transport-safe, no quoting issues)
546
+ browser4-cli htmlsnapshot query --sql "$(base64 -w0 query.sql)" --sql-base64
547
+
548
+ # Inline (simple queries only — quoted selectors require escaping on Windows)
549
+ browser4-cli htmlsnapshot query --sql "
550
+ SELECT dom_base_uri(dom) AS url, dom_first_text(dom, 'h1') AS title
551
+ FROM load_and_select(@url, ':root')
552
+ "
553
+ ```
612
554
 
613
- ### Session state transitions
555
+ #### htmlsnapshot export
614
556
 
615
- | Command | Behavior |
616
- |---|---|
617
- | `open` | Creates a new session, or reuses an existing active one. Stale sessions are automatically refreshed. |
618
- | `open -s=<name>` | Same as `open` but scoped to a named session slot. |
619
- | `goto <url>` | Reuses the current session if active; otherwise opens a fresh one before navigating. |
620
- | `close` | Closes the current session (no-op if none active). |
621
- | `close-all` / `kill-all` / `stop` | Clears all persisted session state. |
557
+ Save the full snapshot HTML to a local file.
622
558
 
623
- The `list` command shows each session's status: **Active** (backend confirms),
624
- **Stale** (backend has stopped it), or **Unknown** (backend unreachable).
559
+ ```bash
560
+ browser4-cli htmlsnapshot export --file snapshot.html
561
+ ```
625
562
 
626
- ## Runtime Temp Files
563
+ #### htmlsnapshot summary
627
564
 
628
- `browser4-cli` keeps ephemeral runtime artifacts under the system temp directory:
565
+ Generate a compressed Web Page Summary Index (WPSI) page type, structure, key
566
+ content nodes, repeated lists, tables, and stats — typically <1% of the original
567
+ HTML size.
629
568
 
630
- - Windows: `%TEMP%\browser4\browser4-cli`
631
- - Linux/macOS: `${TMPDIR:-/tmp}/browser4/browser4-cli`
569
+ ```bash
570
+ browser4-cli htmlsnapshot summary
571
+ ```
632
572
 
633
- This temp subtree contains items such as:
573
+ #### htmlsnapshot grep
634
574
 
635
- - startup logs for auto-started Browser4 servers
636
- - staged Maven wrapper launchers
637
- - Rust test scratch directories used by `browser4-cli` tests
575
+ Search the HTML snapshot HTML with regex patterns. Same grep flags as
576
+ `snapshot grep`: `-i`, `-A N`, `-B N`, `-C N`, `-v`, `-c`, `-l`, `-F`, `-w`,
577
+ `--no-line-number`, `--selector <css>`, `--page N`, `--page-size N`, `--all`.
638
578
 
639
- Persistent CLI state remains under `~/.browser4` by default. The Browser4 runtime
640
- bundle (JRE, JARs, launchers) is stored separately in a platform-conventional
641
- data directory so that clearing CLI session state does not require re-downloading
642
- the ~200 MB runtime:
579
+ ```bash
580
+ browser4-cli htmlsnapshot grep -i error
581
+ browser4-cli htmlsnapshot grep -F -C 2 "404 Not Found"
582
+ browser4-cli htmlsnapshot grep --selector main "Submit"
583
+ browser4-cli htmlsnapshot grep --all "TODOs"
584
+ ```
643
585
 
644
- - Linux: `~/.local/share/browser4/runtime/<version>/`
645
- - macOS: `~/Library/Application Support/browser4/runtime/<version>/`
646
- - Windows: `%APPDATA%/browser4/runtime/<version>/`
586
+ #### htmlsnapshot inspect
647
587
 
648
- The `current.tag` file in the `runtime/` directory records the active version.
649
- Override the runtime data root with the `BROWSER4_RUNTIME_DIR` environment variable.
650
- Downloaded archives are cached under the platform cache directory
651
- (`~/.cache/browser4/downloads/` on Linux, `~/Library/Caches/browser4/downloads/`
652
- on macOS, `%LOCALAPPDATA%/browser4/downloads/` on Windows).
588
+ Analyze DOM structure and discover CSS selectors for recurring patterns (product
589
+ cards, prices, titles). Run without arguments to auto-discover the page's most
590
+ prominent repeating content. When the selector matches multiple similar elements,
591
+ it compares their child structures and ranks selectors by recurrence.
653
592
 
654
- ## Snapshots
593
+ ```bash
594
+ browser4-cli htmlsnapshot inspect # auto-discover repeating patterns
595
+ browser4-cli htmlsnapshot inspect ".product_pod" # inspect a specific container
596
+ browser4-cli htmlsnapshot inspect ".s-result-item" --depth 6 --max 20
597
+ ```
655
598
 
656
- After each command that modifies browser state, the CLI automatically:
599
+ ---
657
600
 
658
- 1. Retrieves the current page URL and title
659
- 2. Captures an accessibility snapshot
660
- 3. Saves the snapshot to `.browser4-cli/snapshot/page-<timestamp>.yml`
661
- 4. Prints the snapshot path in Markdown link format
601
+ ### Agent
662
602
 
663
- ## Examples
603
+ The `agent` subcommands submit natural-language tasks that the Browser4 backend
604
+ executes autonomously — it plans, browses, and returns a result.
664
605
 
665
- ```shell
666
- # Open a new browser window (defaults to headed)
667
- browser4-cli open
606
+ ```
607
+ browser4-cli agent run <task>
608
+ browser4-cli agent status <id>
609
+ browser4-cli agent result <id>
610
+ ```
668
611
 
669
- # Open in headed or headless mode
670
- browser4-cli open --headed https://browser4.io
671
- browser4-cli open --headless https://browser4.io
612
+ #### agent run
672
613
 
673
- # Open with a persistent profile
674
- browser4-cli open --profile=~/.browser4/profiles/work
614
+ Submit an asynchronous natural-language task. Returns immediately with a task ID.
675
615
 
676
- # Open with a temporary (single-use) profile
677
- browser4-cli open --profile-mode=temporary https://browser4.io
616
+ ```bash
617
+ browser4-cli agent run "Open browser4.io and summarize the hero section"
618
+ # → Task submitted: agent-task-1
619
+ # → Use 'browser4-cli agent status agent-task-1' to check progress.
620
+ ```
678
621
 
679
- # Open with interact-level control (FASTEST / FAST / DEFAULT)
680
- browser4-cli open --interact-level=FAST https://browser4.io
622
+ #### agent status
681
623
 
682
- # Navigate to a page — auto-opens a session if none is active
683
- browser4-cli goto https://browser4.io
624
+ Poll the status of a running task.
684
625
 
685
- # Inspect the page — note the eN labels on interactive nodes
686
- browser4-cli snapshot
626
+ ```bash
627
+ browser4-cli agent status agent-task-1
628
+ ```
687
629
 
688
- # Include element bounding boxes in the snapshot
689
- browser4-cli snapshot --boxes
630
+ #### agent result
690
631
 
691
- # Show only interactive elements with compact output, depth-limited
692
- browser4-cli snapshot -i -c -d 5
632
+ Fetch the completed task result.
693
633
 
694
- # Scope snapshot to a specific CSS selector
695
- browser4-cli snapshot -s "#main-content"
634
+ ```bash
635
+ browser4-cli agent result agent-task-1
636
+ ```
696
637
 
697
- # Raw output no page info, just the snapshot content (useful for piping)
698
- browser4-cli snapshot --raw | grep "button"
638
+ Agent commands are task-ID based and do not require an active browser session.
639
+ They are not supported inside `batch` mode.
699
640
 
700
- # Capture a static DOM snapshot and extract data
701
- browser4-cli domsnapshot
702
- browser4-cli domsnapshot get text "#productTitle"
703
- browser4-cli domsnapshot get attr "#productTitle" "href"
704
- browser4-cli domsnapshot export --file=page.html
641
+ ---
705
642
 
706
- # Interact using refs from the snapshot
707
- browser4-cli click e15
708
- browser4-cli type "Hello World" e15
709
- browser4-cli press Enter e15
710
- browser4-cli eval "document.title"
711
- browser4-cli eval "element => element.textContent" e15
712
- browser4-cli keydown Shift
713
- browser4-cli mousemove 150 300
714
- browser4-cli mousewheel 0 100
715
- browser4-cli keyup Shift
643
+ ### Swarm
716
644
 
717
- # Take a screenshot and save it to disk
718
- browser4-cli screenshot
645
+ Swarm mode coordinates multiple browser contexts in parallel for high-throughput
646
+ scraping and data extraction.
719
647
 
720
- # Take a full-page screenshot
721
- browser4-cli screenshot --full-page
648
+ ```
649
+ browser4-cli swarm create [options]
650
+ browser4-cli swarm submit [url] [options]
651
+ browser4-cli swarm query <url> --sql <query>
652
+ browser4-cli swarm status <id>
653
+ browser4-cli swarm result <id>
654
+ ```
722
655
 
723
- # Save the current page as a PDF
724
- browser4-cli pdf --filename=page.pdf
656
+ #### swarm create
725
657
 
726
- # Inspect tab indices before switching tabs
727
- browser4-cli tab-list
728
- browser4-cli tab-select 1
729
- browser4-cli tab-close 1
658
+ Create a swarm scrape session.
730
659
 
731
- # Use a custom server URL
732
- browser4-cli open --server http://localhost:9090
660
+ | Option | Default | Description |
661
+ |---|---|---|
662
+ | `--profile-mode` | `SEQUENTIAL` | Profile mode: `SEQUENTIAL` or `TEMPORARY` |
663
+ | `--max-open-tabs` | `8` | Max open tabs per browser context |
664
+ | `--max-browser-contexts` | `2` | Number of isolated browser environments |
665
+ | `--display-mode` | — | Display mode: `GUI`, `HEADLESS`, `SUPERVISED` |
733
666
 
734
- # Advanced: execute multiple commands in one process (batch mode)
735
- # Batch mode only supports DOM operations. You must run `open` separately first.
736
- browser4-cli open
737
- browser4-cli batch "goto https://browser4.io" "snapshot"
667
+ ```bash
668
+ browser4-cli swarm create \
669
+ --profile-mode TEMPORARY \
670
+ --max-open-tabs 12 \
671
+ --max-browser-contexts 3 \
672
+ --display-mode HEADLESS
673
+ ```
738
674
 
739
- # Advanced: stop on the first batch failure
740
- browser4-cli batch --bail "goto https://browser4.io" "click e1" "screenshot"
675
+ #### swarm submit
741
676
 
742
- # Advanced: batch mode for form filling (recommended use case)
743
- browser4-cli batch "fill e1 'John Doe'" "fill e2 'john@example.com'" "click e3"
677
+ Submit URLs as scrape jobs. Accepts a direct URL, a `--seed-file` (one URL per
678
+ line; `#` comments and blank lines ignored), or both.
744
679
 
745
- # Advanced: pipe batch commands as JSON via stdin
746
- echo '[
747
- ["goto", "https://example.com/form-filling"],
748
- ["click", "#reset-btn"],
749
- ["fill", "#first-name", "Bob"],
750
- ["fill", "#last-name", "Smith"],
751
- ["fill", "#email", "bob@example.com"],
752
- ["select", "#country", "uk"],
753
- ["check", "#agree-terms"],
754
- ["click", "#submit-btn"]
755
- ]' | browser4-cli batch --json
680
+ | Option | Description |
681
+ |---|---|
682
+ | `--seed-file <path>` | File of URLs to submit |
683
+ | `--sql <query>` | X-SQL query (inline or `@file.sql`). Sends to query API instead of submit. |
684
+ | `--deadline <ISO 8601>` | Task completion deadline |
685
+ | `--expires <duration>` | Cache expiration (e.g. `1d`, `1h`) |
686
+ | `--refresh` | Force fresh fetch, ignore cache |
687
+ | `--parse` | Parse page immediately after fetching |
688
+ | `--store-content` | Persist page content to storage |
756
689
 
757
- # Close the session when done
758
- browser4-cli close
690
+ ```bash
691
+ # Submit URLs from a file
692
+ browser4-cli swarm submit --seed-file ./urls.txt \
693
+ --deadline 2026-03-30T00:00:00Z \
694
+ --expires 1d --refresh --store-content
759
695
 
760
- # Close all sessions but keep the current Browser4 backend running
761
- browser4-cli close-all
696
+ # Submit with inline X-SQL
697
+ browser4-cli swarm submit "https://www.amazon.com/dp/B08PP5MSVB" --sql "
698
+ SELECT
699
+ dom_base_uri(dom) AS url,
700
+ dom_first_text(dom, '#productTitle') AS title
701
+ FROM load_and_select(@url, 'body')
702
+ "
762
703
 
763
- # Explicitly stop the Browser4 backend and clean up tracked Browser4 processes
764
- browser4-cli kill-all
704
+ # Submit with X-SQL from a file
705
+ browser4-cli swarm submit "https://www.amazon.com/dp/B08PP5MSVB" --sql @query.sql
765
706
  ```
766
707
 
767
- ## Architecture
708
+ #### swarm query
768
709
 
769
- The Rust CLI is structured as follows:
710
+ Run an X-SQL query against loaded webpages. `--sql` is required. Supports a
711
+ direct URL, `--seed-file`, or both — runs the same query against each. Also
712
+ accepts `--deadline`, `--expires`, `--refresh`.
770
713
 
771
- | Module | Purpose |
772
- |---|---|
773
- | `main.rs` | Entry point, command dispatch, session management |
774
- | `args.rs` | CLI argument parsing (global flags, positional args, options) |
775
- | `commands.rs` | Command definitions mapping to MCP tool names and parameters |
776
- | `http.rs` | HTTP client for calling `/mcp/call-tool` |
777
- | `state.rs` | Persistent state management for the default state file and named session files under `~/.browser4/` |
778
- | `daemon.rs` | Local server auto-start (prefer Maven from repo root, fall back to jar) and health checking |
779
- | `managed_processes.rs` | Registry for browser4 server processes |
780
- | `snapshot.rs` | Snapshot and screenshot file helpers |
781
- | `help.rs` | Help text generation |
714
+ ```bash
715
+ # Inline X-SQL
716
+ browser4-cli swarm query "https://www.amazon.com/dp/B08PP5MSVB" --sql "
717
+ SELECT dom_first_text(dom, '#productTitle') AS title
718
+ FROM load_and_select(@url, 'body')
719
+ "
782
720
 
783
- ## Testing
721
+ # From a file, with seed URLs
722
+ browser4-cli swarm query --sql @query.sql --seed-file ./urls.txt --refresh
723
+ ```
784
724
 
785
- ```bash
786
- ## Run all tests (unit + end-to-end):
787
- cargo test
725
+ #### swarm status / swarm result
788
726
 
789
- ## Run only the end-to-end tests and print their output:
790
- cargo test --test e2e -- --nocapture
727
+ Poll and fetch results same pattern as `agent status` / `agent result`.
791
728
 
792
- ## Run a specific end-to-end test scenario:
793
- cargo test --test e2e -- --nocapture --scenario=test_e2e_batch_form_submission
729
+ ```bash
730
+ browser4-cli swarm status scrape-task-4
731
+ browser4-cli swarm result scrape-task-4
794
732
  ```
795
733
 
796
- ## Publishing the CLI package
797
-
798
- For maintainers, the CLI package now uses an npm version guard before publish.
734
+ ---
799
735
 
800
- The GitHub release workflow publishes the npm package via npm trusted publishing
801
- (GitHub Actions OIDC) instead of `NODE_AUTH_TOKEN`. This avoids CI failures caused
802
- by npm one-time-password challenges (`EOTP`).
736
+ ### Crawl
803
737
 
804
- - Local release entrypoint: `npm run release`
805
- - Direct guarded publish entrypoint: `npm run publish:if-needed`
806
- - GitHub release workflow: re-checks npm immediately before the publish step
738
+ Recursive website crawling from a seed URL. Reuses the swarm infrastructure.
807
739
 
808
- If the local version in `cli/package.json` already matches the version currently
809
- published on npm, the publish step is skipped automatically.
740
+ ```
741
+ browser4-cli crawl <url> [options]
742
+ ```
810
743
 
811
- Examples:
744
+ | Flag | Default | Description |
745
+ |---|---|---|
746
+ | `-d`, `--depth` | `1` | Maximum crawl depth |
747
+ | `-ol`, `--out-link-selector` | — | CSS selector to extract links from each page |
748
+ | `-olp`, `--out-link-pattern` | `.+` | Regex filter for extracted links |
749
+ | `-tl`, `--top-links` | `20` | Max links extracted per page |
750
+ | `-a`, `--args` | — | Additional LoadOptions passthrough (e.g. `-a "-nMaxRetry 5"`) |
751
+ | `--refresh` | — | Force fresh fetch |
752
+ | `--parse` | — | Parse pages immediately after fetching |
753
+ | `--store-content` | — | Persist page content |
754
+ | `--expires` | — | Cache expiration (e.g. `1d`, `1h`, `30m`) |
755
+ | `-p`, `--priority` | — | Queue priority (lower = higher) |
756
+ | `--ignore-url-query` | — | Strip query params during URL normalization |
757
+ | `--no-norm` | — | Disable URL normalization |
758
+ | `--readonly` | — | Non-destructive mode |
759
+ | `--page-load-timeout` | — | Max wait for each page load |
760
+ | `-bg`, `--background` | — | Submit crawl and return immediately; use `crawl list` to track |
812
761
 
813
762
  ```bash
814
- # Check whether npm publish is needed
815
- node scripts/check-npm-publish-needed.js --json
763
+ # Depth 1: extract all links from homepage, load each linked page
764
+ browser4-cli crawl "https://example.com" --out-link-selector "a[href]"
765
+
766
+ # Depth 2: follow product links, filter by pattern
767
+ browser4-cli crawl "https://shop.example.com" \
768
+ --depth 2 \
769
+ --out-link-selector "a.product-link" \
770
+ --out-link-pattern "/product/" \
771
+ --top-links 10
816
772
 
817
- # Publish only when the local version differs from npm
818
- npm run publish:if-needed
773
+ # Deep crawl with refresh and content storage
774
+ browser4-cli crawl "https://example.com" --depth 3 --refresh --store-content
819
775
 
820
- # Standard maintainer release command (also guarded)
821
- npm run release
776
+ # Background crawl submit and return immediately
777
+ browser4-cli crawl "https://example.com" -ol "a[href]" --background
778
+ browser4-cli crawl list
822
779
  ```
823
780
 
824
- For local testing, you can override the detected remote version:
781
+ ---
782
+
783
+ ## Element references
784
+
785
+ The `snapshot` command returns an accessibility tree where every interactive
786
+ element is labeled with a ref like `e15`. Pass this ref to any interaction
787
+ command:
825
788
 
826
789
  ```bash
827
- BROWSER4_CLI_NPM_REMOTE_VERSION=0.1.7 node scripts/check-npm-publish-needed.js --json
828
- BROWSER4_CLI_NPM_REMOTE_VERSION=0.1.7 node scripts/publish-if-needed.js --dry-run
790
+ browser4-cli snapshot # see e15 is the search input
791
+ browser4-cli click e15 # click it
792
+ browser4-cli type "query" e15 # type into it
829
793
  ```
830
794
 
795
+ You can also use CSS selectors (e.g. `#search`, `.btn-primary`,
796
+ `input[name=email]`) anywhere a ref is accepted.
797
+
798
+ ## State persistence
799
+
800
+ CLI state is stored under `~/.browser4` (override with `BROWSER4_CLI_STATE_DIR`):
801
+
802
+ - Default session: `~/.browser4/cli-state.json`
803
+ - Named sessions (`-s <name>`): `~/.browser4/sessions/<name>.json`
804
+
805
+ Each state file stores the session ID, server URL, and cursor position — so your
806
+ next `open` or `goto` picks up right where you left off.
807
+
808
+ The Browser4 runtime bundle (~200 MB) is stored separately in a
809
+ platform-conventional data directory so clearing CLI session state does not
810
+ require re-downloading:
811
+
812
+ | Platform | Path |
813
+ |---|---|
814
+ | Linux | `~/.local/share/browser4/runtime/<version>/` |
815
+ | macOS | `~/Library/Application Support/browser4/runtime/<version>/` |
816
+ | Windows | `%APPDATA%/browser4/runtime/<version>/` |
817
+
818
+ Override the runtime data root with `BROWSER4_RUNTIME_DIR`.
819
+
831
820
  ## License
832
821
 
833
822
  Apache-2.0