surf-cli 2.18.0 → 2.20.0

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.
@@ -7,11 +7,13 @@ description: Control Chrome browser via CLI for testing, automation, and debuggi
7
7
 
8
8
  Control Chrome browser via CLI or Unix socket.
9
9
 
10
+ Ordinary socket-backed CLI commands report top-level host tool-response errors on stderr with a supplied `[code]` on the first line and exit 1. `--json` additionally writes `{error:{code,message,details?}}` on stdout (missing code becomes `"error"`). `--soft-fail` instead keeps the original stderr warning, empty stdout and exit 0, even with `--json`. This does not cover local validation, transport/parser failures or compound-command errors: do not assume every failure produces JSON. Connection failures remain stderr-only and exit 1, including with `--soft-fail`.
11
+
10
12
  ## Native Host / Socket Notes
11
13
 
12
14
  For WSL2 with Windows Chrome, run `surf install <extension-id>` inside WSL2. Surf detects WSL2 and writes the Windows-side native messaging manifest plus a wrapper that launches the WSL host. Use `surf install <extension-id> --target linux` only for Linux browsers running inside WSLg.
13
15
 
14
- On macOS, Chrome reads the native messaging manifest at `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/surf.browser.host.json`. If native messaging fails, confirm that file exists, its `allowed_origins` extension ID matches `chrome://extensions`, then rerun `surf install <extension-id>`, restart Chrome, reload the extension, and inspect the extension service-worker console.
16
+ On macOS, Chrome reads the native messaging manifest at `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/surf.browser.host.json`. If native messaging fails, confirm that file exists, its `allowed_origins` extension ID matches `chrome://extensions`, then rerun `surf install <extension-id>`, restart Chrome, and reload the extension. Open Surf's service-worker console from `chrome://extensions`; in **Details > Extension options**, enable **Debug Mode**, reproduce the failure, then disable it when finished.
15
17
 
16
18
  If a command reports `Socket connect failed`, run `surf doctor` first, then check the `Attempted socket:` line. Default sockets are `/tmp/surf.sock` on macOS/Linux/WSL2 and `//./pipe/surf` on Windows. If `SURF_SOCKET` is set, the browser-launched host and the shell running `surf` must use the same value.
17
19
 
@@ -34,9 +36,18 @@ surf --remote 100.101.102.103:4321 \
34
36
  --remote-credential ~/.config/surf/agent-macbook.json \
35
37
  page.read
36
38
 
39
+ # TLS is client-side and requires a TLS-terminating reverse proxy in front of SURF_LISTEN
40
+ surf --remote surf.example.com:443 --remote-tls \
41
+ --remote-tls-ca ~/.config/surf/private-ca.pem \
42
+ --remote-credential ~/.config/surf/agent-macbook.json page.read
43
+
37
44
  surf remote revoke agent-macbook # Run on the browser host
38
45
  ```
39
46
 
47
+ Environment equivalents are `SURF_REMOTE_TLS=1`, `SURF_REMOTE_TLS_CA`, and
48
+ `SURF_REMOTE_TLS_SERVER_NAME`. A custom CA replaces system roots; Ed25519 credentials remain
49
+ mandatory after TLS validation.
50
+
40
51
  Remote paths are client-local by default. `local:./file` is explicit client-local syntax; only `remote:/absolute/path` accesses the browser host directly. Remote transfer supports one upload or ChatGPT/Gemini input and one screenshot, network-export, or Gemini image output. Limits are 256 MiB per file, 512 MiB and 32 files per connection, and 256 KiB decoded chunks. `record`, `aistudio.build`, smoke screenshot directories, directories, and multi-file inputs are not supported remotely. Successful action screenshots and failure `--auto-capture` diagnostics are transferred back to client-local paths.
41
52
 
42
53
  ## CLI Quick Reference
@@ -83,6 +94,83 @@ surf screenshot --full-page --output /tmp/shot.png
83
94
  surf animate-audit --selector ".thing" --duration 2000 --fps 10
84
95
  ```
85
96
 
97
+ ## Optional semantic decisions
98
+
99
+ `semantic.act` is a bounded, goal-driven website controller. It repeatedly
100
+ observes the page, lets Jev select the next action from Surf's allowed menu,
101
+ validates and executes that action, and checks the overall goal:
102
+
103
+ ```text
104
+ goal -> observe -> choose -> validate + act -> verify
105
+ ^ |
106
+ +-------- incomplete ----------+
107
+ ```
108
+
109
+ It returns when the goal is complete, a decision is uncertain, or a configured
110
+ budget is exhausted. Use `semantic.find` for one control, `semantic.filter` for
111
+ relevant page regions, and
112
+ `semantic.verify` for one outcome. Use Jev when the page or happy path is
113
+ unfamiliar; once the path is stable, prefer deterministic Surf commands for
114
+ repeated runs. The agent owns the goal and final confirmation, while Surf retains
115
+ execution authority. Only `semantic.*` sends bounded, value-free page text to
116
+ TypeSafe.
117
+
118
+ ```bash
119
+ surf semantic.find "the settings control"
120
+ surf semantic.verify "Settings were saved" --json
121
+ surf semantic.filter "settings"
122
+ surf semantic.act "Open settings" --max-steps 5
123
+ surf semantic.act "Fill email" --input email="$EMAIL" --allow-write --allow-ref e3
124
+ surf semantic.act 'Add the selected item to the cart' --allow-write --threshold write=0.85
125
+ printf '%s\n' "$TYPESAFE_KEY" | surf semantic auth set
126
+ surf semantic auth status
127
+ surf semantic auth clear
128
+ ```
129
+
130
+ For reusable bounded recipes, put only linear `semantic.step` operations in a
131
+ workflow with `"semantic":{"version":1}`. Check it offline with
132
+ `surf workflow.validate flow.json` or `surf do --file flow.json --dry-run`, then
133
+ run with `--allow-semantic`; declared fill/check/click operations also require
134
+ `--allow-write`. Supply private fill slots as a bounded JSON object on stdin:
135
+
136
+ ```bash
137
+ printf '%s' '{"quantity":"2"}' | SURF_SESSION=shopping surf do --file flow.json \
138
+ --inputs-stdin --allow-semantic --allow-write --json
139
+ ```
140
+
141
+ The closed operations are `find`, same-origin direct `open`, `ensureChecked`,
142
+ `fill`, one-shot `click` with an explicit expectation, and `assert`. Search is
143
+ bounded overlapping coverage, not global ranking. Unknown write outcomes stop
144
+ without replay; a later new run can still repeat an external effect. Input
145
+ values never enter provider state, workflow variables, events, or checkpoints.
146
+
147
+ Required argument shapes:
148
+
149
+ ```text
150
+ find target (+ optional search), usually save with "as"
151
+ open target
152
+ ensureChecked target + checked
153
+ fill target + input
154
+ click target + expect
155
+ assert mode + claim (semantic) or predicate (local)
156
+ ```
157
+
158
+ The complete valid six-operation example in the README uses these shapes; start
159
+ from it instead of inventing fields.
160
+
161
+ Every click/fill requires `--allow-write`; repeat `--allow-ref` to narrow it.
162
+ Broad writes use threshold `0.95`; exactly one allowed ref with one applicable
163
+ write uses `0.65`. The applied threshold is included in decision/trace output.
164
+ Repeatable `--threshold name=value` overrides applicable confidence thresholds
165
+ for one run only; defaults remain safer, and overrides never grant write authority.
166
+ `TYPESAFE_API_KEY` is the ephemeral/CI override.
167
+ The shared credential schema is `{"version":1,"apiKey":"..."}` at
168
+ `${XDG_CONFIG_HOME:-~/.config}/typesafe/credentials.json` (Unix/macOS) or
169
+ `%APPDATA%\TypeSafe\credentials.json` (Windows), independent of Surf state and
170
+ the project. POSIX directories/files use `0700`/`0600`; Windows relies on the
171
+ current user's profile ACL. `TYPESAFE_API_KEY` wins. Status reveals only source
172
+ and fingerprint; clear affects all clients using the shared file.
173
+
86
174
  ## AI Assistants (No API Keys)
87
175
 
88
176
  Query AI models using your browser's logged-in session. Must be logged into the respective service in Chrome.
@@ -321,6 +409,7 @@ surf page.text # Plain text content only
321
409
  surf page.html --strip-scripts # Rendered HTML without scripts
322
410
  surf page.save --selector "#artifact" --strip-scripts --output page.html # Save one static element
323
411
  surf page.state # Modals, loading state, scroll info
412
+ surf frame.diagnose # Why a selector misses: DOM iframes (incl. open shadow roots) vs extension frames vs CDP tree, with warnings; out-of-process frames need frame.switch, not frame.js
324
413
  ```
325
414
 
326
415
  ### Export Rendered HTML
@@ -398,8 +487,14 @@ surf wait.network # Wait for network idle
398
487
  surf wait.url "/success" # Wait for URL pattern
399
488
  surf wait.dom --stable 100 # Wait for DOM stability
400
489
  surf wait.load # Wait for page load complete
490
+ surf wait.ready --selector ".results" # Ready, or fail fast: login / challenge / not-found / error
491
+ surf wait.ready --url-prefix "https://app.example.com/" --empty-text "No results" # empty vs blocked
492
+ surf wait.ready --accept login --json # Return the negative state instead of failing
493
+ surf page.readiness --json # Classify the current page once (state + evidence)
401
494
  ```
402
495
 
496
+ Typed readiness states replace "the selector never appeared": exit codes carry `page_login`, `page_challenge`, `page_not_found`, `page_error` or `page_timeout`. Detection uses visible UI (a rendered password field, a login route, the page's wording, a URL outside `--url-prefix`), not site selectors.
497
+
403
498
  ## Dialog Handling
404
499
 
405
500
  ```bash