fastbrowser_cli 1.0.35 → 1.0.37

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.
@@ -0,0 +1,10 @@
1
+ #!/bin/env bash
2
+
3
+ # restart the server
4
+ NODE_OPTIONS='' NPM_CONFIG_LOGLEVEL=silent npm run dev:cli -- server restart
5
+
6
+ # navigate to whatsapp web
7
+ NODE_OPTIONS='' NPM_CONFIG_LOGLEVEL=silent npm run dev:cli -- navigate_page --url https://web.whatsapp.com/
8
+
9
+ # List all conversations in the chat list
10
+ NODE_OPTIONS='' NPM_CONFIG_LOGLEVEL=silent npm run dev:cli -- query_selectors -s 'grid[name="Chat list"] > row' -a
package/listitem ADDED
@@ -0,0 +1,3 @@
1
+ Expected ] at column 22:
2
+ list[name=Conversation List]
3
+ ^
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastbrowser_cli",
3
- "version": "1.0.35",
3
+ "version": "1.0.37",
4
4
  "description": "A CLI tool for FastBrowser, providing commands to interact with the FastBrowser MCP (Model Context Protocol) server and perform various browser automation tasks.",
5
5
  "main": "dist/fastbrowser_cli/fastbrowser_cli.js",
6
6
  "bin": {
@@ -30,7 +30,7 @@
30
30
  "typescript": "^6.0.3",
31
31
  "zod": "^4.3.6",
32
32
  "zod-from-json-schema": "^0.5.2",
33
- "a11y_parse": "^1.0.5"
33
+ "a11y_parse": "^1.0.7"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/express": "^4.17.21",
@@ -45,6 +45,31 @@ npx fastbrowser_cli close_page --page-id 1
45
45
 
46
46
  # Navigate the current page to a URL
47
47
  npx fastbrowser_cli navigate_page --url https://example.com
48
+
49
+ # Restart the daemon - run this if pages opened by the bridge were closed manually
50
+ # and the MCP connection has broken
51
+ npx fastbrowser_cli server restart
52
+ ```
53
+
54
+
55
+ ## Configuration
56
+
57
+ Global flags accepted by every command:
58
+
59
+ | Flag / env | Purpose | Default |
60
+ |---|---|---|
61
+ | `--server <url>` / `FASTBROWSER_SERVER` | URL of the `fastbrowser_httpd` daemon | `http://localhost:8787` |
62
+ | `--autostart` / `--no-autostart` | Auto-start the daemon if it is not already running | `--autostart` |
63
+ | `--mcp-target <target>` / `FASTBROWSER_MCP_TARGET` | Browser backend: `playwright` or `chrome_devtools` | `playwright` |
64
+
65
+ The daemon binds to one backend at startup. If it is already running with a different backend, the CLI refuses the request and prints the exact restart command to switch.
66
+
67
+ ```bash
68
+ # Use chrome-devtools-mcp for one command
69
+ npx fastbrowser_cli --mcp-target chrome_devtools list_pages
70
+
71
+ # Switch the running daemon to a different backend
72
+ npx fastbrowser_cli --mcp-target chrome_devtools server restart
48
73
  ```
49
74
 
50
75
 
@@ -59,7 +84,7 @@ Matches nodes by their accessibility role.
59
84
  ```
60
85
  button
61
86
  link
62
- comboxbox
87
+ combobox
63
88
  searchbox
64
89
  heading
65
90
  WebArea
@@ -93,6 +118,7 @@ Attribute selectors match values inside `node.attributes`. The special virtual a
93
118
  | `[attr^="prefix"]` | starts with |
94
119
  | `[attr$="suffix"]` | ends with |
95
120
  | `[attr*="sub"]` | contains substring |
121
+ | `[attr~="word"]` | contains `word` as a whole space-separated word |
96
122
 
97
123
  ```
98
124
  link[href]
@@ -100,6 +126,7 @@ button[disabled="true"]
100
126
  link[href^="https"]
101
127
  link[href$=".com"]
102
128
  link[href*="example"]
129
+ button[name~="Submit"]
103
130
  heading[name="Welcome"]
104
131
  link[name="Click \"here\""]
105
132
  ```
@@ -110,15 +137,56 @@ link[name="Click \"here\""]
110
137
  |--------|-----------|
111
138
  | `A B` | B is a descendant of A (any depth) |
112
139
  | `A > B` | B is a direct child of A |
140
+ | `A + B` | B is the immediately following sibling of A |
141
+ | `A ~ B` | B is any following sibling of A |
113
142
  | `A, B` | union — matches A or B |
114
143
 
115
144
  ```
116
145
  WebArea link
117
146
  main > button
147
+ label + textbox
148
+ link ~ link
118
149
  heading, button
119
150
  RootWebArea > link[href^="https"]
120
151
  ```
121
152
 
153
+ ### Positional pseudo-classes
154
+
155
+ Narrow a match by position within the parent's children array. Indexing is 1-based; the root node never matches a positional pseudo-class.
156
+
157
+ | Syntax | Semantics |
158
+ |--------|-----------|
159
+ | `:first-child` | node is the first child of its parent |
160
+ | `:last-child` | node is the last child of its parent |
161
+ | `:nth-child(n)` | node is the nth child (1-based) |
162
+
163
+ ```
164
+ link:first-child
165
+ button:last-child
166
+ menuitem:nth-child(2)
167
+ ```
168
+
169
+ ### Functional pseudo-classes
170
+
171
+ Take a comma-separated selector list inside parentheses. The argument list itself supports the full selector language and may be nested.
172
+
173
+ | Syntax | Semantics |
174
+ |--------|-----------|
175
+ | `:is(s1, s2, …)` | node matches any selector in the list |
176
+ | `:where(s1, s2, …)` | alias of `:is()` (no specificity in this engine) |
177
+ | `:not(s1, s2, …)` | node matches none of the selectors |
178
+ | `:has(s1, s2, …)` | node has a descendant matching any selector |
179
+
180
+ `:has()` walks descendants of the candidate node (excluding the node itself). Relative leading combinators (e.g. `:has(> link)`) are not supported.
181
+
182
+ ```
183
+ :is(heading, button)
184
+ link:not(:first-child)
185
+ *:has(button)
186
+ *:not(:has(link))
187
+ main > *:not(button)
188
+ ```
189
+
122
190
  ### Examples
123
191
 
124
192
  Sample accessibility tree:
@@ -136,38 +204,47 @@ uid=1 WebArea "Main Page"
136
204
 
137
205
  Example queries on it:
138
206
  - `link` matches all the links (uid=4, uid=7, uid=8)
139
- - 'navigation > link' matches only the links that are direct children of navigation (uid=7, uid=8)
207
+ - `navigation > link` matches only the links that are direct children of navigation (uid=7, uid=8)
140
208
  - `link[href^="https"]` matches links with an external href (uid=4)
141
209
  - `button[name="Submit"]` matches the submit button by name (uid=5)
142
210
  - `*[disabled="true"]` matches any disabled element (uid=5)
143
211
  - `heading, button` matches both headings and buttons in one query (uid=3, uid=5)
144
212
  - `#7` matches a node by its UID (uid=7)
213
+ - `link:first-child` matches uid=4 and uid=7 (first child of `main` and `navigation`)
214
+ - `link + button` matches uid=5 (button immediately after a link)
215
+ - `:is(heading, button)` is equivalent to `heading, button` (uid=3, uid=5)
216
+ - `link:not([href^="https"])` matches the relative-href links (uid=7, uid=8)
217
+ - `*:has(button)` matches ancestors of a button (uid=1, uid=2)
145
218
 
146
219
  ## Inspection
147
220
 
148
221
  - `query_selectors` is the most efficient way to get specific elements or data from the page. Use it instead of `take_snapshot` whenever possible.
149
222
  - By default, `query_selectors` returns the first match per selector (cheaper, less output). Pass `-a, --all` when you need every match — pair it with `--limit` to cap results per selector.
223
+ - Use `--wa, --with-ancestors` to include each match's ancestor chain in the result, and `--wc, --with-children` to include the descendant subtree of each match.
150
224
 
151
225
  ```bash
152
226
  # Query the accessibility tree returning the FIRST match per selector (--selector is repeatable)
153
227
  npx fastbrowser_cli query_selectors --selector "button" --selector "link"
154
228
 
155
- # Exclude ancestor nodes from the result
156
- npx fastbrowser_cli query_selectors --selector 'heading[level="1"]' --no-with-ancestors
229
+ # Include ancestor nodes in the result
230
+ npx fastbrowser_cli query_selectors --selector 'heading[level="1"]' --with-ancestors
231
+
232
+ # Include the descendant subtree of each match
233
+ npx fastbrowser_cli query_selectors --selector 'main' --with-children
157
234
 
158
- # Per-selector control over withAncestors via JSON
235
+ # Per-selector control over withAncestors / withChildren via JSON
159
236
  npx fastbrowser_cli query_selectors \
160
- --selectors-json '[{"selector":"button","withAncestors":true},{"selector":"link","withAncestors":false}]'
237
+ --selectors-json '[{"selector":"button","withAncestors":true},{"selector":"link","withChildren":true}]'
161
238
 
162
239
  # Pass --all to return every match per selector; --limit caps results per selector (0 = unlimited)
163
240
  npx fastbrowser_cli query_selectors --all --selector "button" --selector "link" --limit 5
164
241
 
165
- # Exclude ancestor nodes from the result
166
- npx fastbrowser_cli query_selectors --all --selector 'heading[level="1"]' --no-with-ancestors
242
+ # Include ancestor nodes in the result
243
+ npx fastbrowser_cli query_selectors --all --selector 'heading[level="1"]' --with-ancestors
167
244
 
168
- # Per-selector control over limit / withAncestors via JSON (with --all)
245
+ # Per-selector control over limit / withAncestors / withChildren via JSON (with --all)
169
246
  npx fastbrowser_cli query_selectors --all \
170
- --selectors-json '[{"selector":"button","limit":3,"withAncestors":true},{"selector":"link","limit":0,"withAncestors":false}]'
247
+ --selectors-json '[{"selector":"button","limit":3,"withAncestors":true},{"selector":"link","limit":0,"withChildren":true}]'
171
248
 
172
249
  # Take an accessibility-tree full page snapshot of the current page - very expensive, prefer targeted queries when possible
173
250
  npx fastbrowser_cli take_snapshot
@@ -239,9 +316,11 @@ press_keys --keys "Tab, Enter"
239
316
  | `fill_form` | Fill a form field by accessibility selector | `--selector` / `-s`, `--value` |
240
317
  | `press_keys` | Press a comma-separated key sequence | `--keys` |
241
318
  | `batch` | Run multiple commands from a file, piped stdin, or `--script` inline | one of: `<file>`, `--script`, or piped stdin |
319
+ | `install [skill-folder]` | Install bundled skills into `<skill-folder>/skills/` (default: `.`) | — |
242
320
  | `server start` | Start the HTTP server daemon | — |
243
321
  | `server status` | Report server running/stopped | — |
244
322
  | `server stop` | Stop the HTTP server | — |
323
+ | `server restart` | Restart the HTTP server (re-establishes the MCP connection) | — |
245
324
 
246
325
  ## Output & Errors
247
326
 
@@ -1,19 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Restart the server to clear any previous state
4
- NODE_OPTIONS='' NPM_CONFIG_LOGLEVEL=silent npm run dev:cli -- server restart
5
-
6
- # Goto linkedin messaging page using the CLI commands below:
7
- NODE_OPTIONS='' NPM_CONFIG_LOGLEVEL=silent npm run dev:cli -- navigate_page --url https://www.linkedin.com/messaging/
8
-
9
- # list all the threads conversations in the left sidebar
10
- NODE_OPTIONS='' NPM_CONFIG_LOGLEVEL=silent npm run dev:cli -- query_selectors -s 'list[name="Conversation List"] > listitem heading' -a
11
-
12
- # Select the conversation with Eric Defiez
13
- NODE_OPTIONS='' NPM_CONFIG_LOGLEVEL=silent npm run dev:cli -- click -s 'list[name="Conversation List"] > listitem heading[name^="Eric Defiez"]'
14
-
15
- # Fill the message content
16
- NODE_OPTIONS='' NPM_CONFIG_LOGLEVEL=silent npm run dev:cli -- fill_form -s 'textbox[name^="Write"]' -v "Hello"
17
-
18
- # Click the "Send" button to send the message
19
- NODE_OPTIONS='' NPM_CONFIG_LOGLEVEL=silent npm run dev:cli -- click -s 'button[name^="Send"]'