lean-browser-use 0.0.0-stage → 0.1.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/CREDITS.md +18 -0
  3. package/LICENSE +21 -0
  4. package/README.md +159 -2
  5. package/agents/aun-browser-runner.md +48 -0
  6. package/bin/lean-browser-use.mjs +3 -0
  7. package/briefs/browser-read.md +63 -0
  8. package/briefs/helper-read.md +63 -0
  9. package/docs/PROVENANCE.md +32 -0
  10. package/docs/benchmark.md +91 -0
  11. package/docs/guards.md +54 -0
  12. package/docs/how-it-works.md +27 -0
  13. package/docs/install.md +78 -0
  14. package/docs/measure.md +53 -0
  15. package/docs/reader.md +39 -0
  16. package/docs/search.md +16 -0
  17. package/hooks/batch-nudge.mjs +14 -0
  18. package/hooks/batch-nudge.sh +8 -0
  19. package/hooks/common.mjs +71 -0
  20. package/hooks/hooks.settings.json +58 -0
  21. package/hooks/pick-guard.mjs +27 -0
  22. package/hooks/pick-guard.sh +8 -0
  23. package/hooks/retry-guard.mjs +69 -0
  24. package/hooks/retry-guard.sh +8 -0
  25. package/llms.txt +40 -0
  26. package/package.json +61 -4
  27. package/proof/benchmark.json +166 -0
  28. package/proof/results.json +241 -0
  29. package/reader/README.md +48 -0
  30. package/reader/crawl_helper.py +256 -0
  31. package/reader/reader +14 -0
  32. package/reader/reader_base.py +106 -0
  33. package/reader/reader_compile.py +106 -0
  34. package/reader/reader_crawl.py +67 -0
  35. package/reader/reader_extract.py +261 -0
  36. package/reader/reader_fetch.py +148 -0
  37. package/reader/reader_runtime.py +199 -0
  38. package/reader/reader_test_harness.py +173 -0
  39. package/reader/reader_test_support.py +214 -0
  40. package/reader/specs/claude-pricing.json +223 -0
  41. package/reader/specs/npm-package.json +67 -0
  42. package/reader/test_reader.py +345 -0
  43. package/reader/test_reader_1.py +309 -0
  44. package/reader/test_reader_2.py +348 -0
  45. package/reader/test_reader_3.py +254 -0
  46. package/reader/test_reader_contract.py +57 -0
  47. package/reader/testdata/claude-pricing.html +4 -0
  48. package/reader/testdata/compile_stub.py +24 -0
  49. package/reader/testdata/npm-react.html +4 -0
  50. package/reader/testdata/npm-schema.json +14 -0
  51. package/reader/testdata/npm-zod.html +4 -0
  52. package/reader/testdata/pricing-schema.json +24 -0
  53. package/searxng/README.md +29 -0
  54. package/searxng/compose.yml +21 -0
  55. package/searxng/core-config/settings.yml +26 -0
  56. package/searxng/deploy.sh +36 -0
  57. package/searxng/searx +73 -0
  58. package/searxng/test_searx.py +107 -0
  59. package/searxng/test_searx_offline.py +67 -0
  60. package/skills/lean-browser-use/SKILL.md +35 -0
  61. package/skills/lean-browser-use/references/cleanup.md +17 -0
  62. package/skills/lean-browser-use/references/cost-model.md +11 -0
  63. package/skills/lean-browser-use/references/draft-offline.md +9 -0
  64. package/skills/lean-browser-use/references/failure-modes.md +16 -0
  65. package/skills/lean-browser-use/references/logged-in-run.md +23 -0
  66. package/skills/lean-browser-use/references/packet-principle.md +15 -0
  67. package/skills/lean-browser-use/references/route-by-job.md +18 -0
  68. package/skills/lean-browser-use/references/runner-rules.md +27 -0
  69. package/skills/lean-browser-use/references/verify.md +9 -0
  70. package/src/cli.mjs +42 -0
  71. package/src/doctor.mjs +60 -0
  72. package/src/install.mjs +116 -0
  73. package/src/measure.mjs +64 -0
  74. package/src/paths.mjs +51 -0
  75. package/src/uninstall.mjs +68 -0
  76. package/src/util.mjs +35 -0
@@ -0,0 +1,166 @@
1
+ {
2
+ "version": 1,
3
+ "measured": "2026-10-25",
4
+ "conditions": {
5
+ "task": "Open https://news.ycombinator.com, read the titles and comment counts of the top 5 stories, then open https://example.com and read its h1. Both arms found that example.com has no h1 and reported the page title.",
6
+ "arms": {
7
+ "plain": "Browser work in the main session.",
8
+ "runner": "Same task through the lean-browser-use skill and fresh runner, with the package installed project-scoped in a scratch project."
9
+ },
10
+ "models": "Main session claude-sonnet-5-5 in both arms; runner subagent claude-haiku-5-5.",
11
+ "tools": "In-app Browser pane tools (mcp__Claude_Browser__*); lean-browser-use measure 0.1.0 over each arm transcripts.",
12
+ "method": "One paired run. Per-step values are median input-context tokens; task values sum input-context tokens across browser steps, including main-session browser steps in the runner arm. Whole-run context totals cover every call in each arm. Counts include fresh input, cache creation and cache read tokens; output is separate.",
13
+ "one_paired_run": true
14
+ },
15
+ "arms": {
16
+ "plain": {
17
+ "step_tokens": 188487,
18
+ "task_tokens": 1506374,
19
+ "browser_steps": {
20
+ "main": 8
21
+ },
22
+ "whole_run": {
23
+ "calls": 14,
24
+ "fresh_input": 28,
25
+ "cache_creation": 129118,
26
+ "cache_read": 2528144,
27
+ "context_total": 2657290,
28
+ "output": 2188
29
+ }
30
+ },
31
+ "runner": {
32
+ "step_tokens": 59725,
33
+ "task_tokens": 725151,
34
+ "browser_steps": {
35
+ "main": 1,
36
+ "runner": 9
37
+ },
38
+ "whole_run": {
39
+ "calls": 23,
40
+ "fresh_input": 46,
41
+ "cache_creation": 195388,
42
+ "cache_read": 2651358,
43
+ "context_total": 2846792,
44
+ "output": 5905,
45
+ "model_split": {
46
+ "main_claude_sonnet_5_5": {
47
+ "calls": 11,
48
+ "context_total": 2134331,
49
+ "output": 2968
50
+ },
51
+ "runner_claude_haiku_5_5": {
52
+ "calls": 12,
53
+ "context_total": 712461,
54
+ "output": 2937
55
+ }
56
+ }
57
+ }
58
+ }
59
+ },
60
+ "derived": {
61
+ "whole_run_ratio": 0.93,
62
+ "delta_percent": 7.13,
63
+ "break_even_browser_steps": 15.54,
64
+ "estimate": true
65
+ },
66
+ "small_task": {
67
+ "measured": "2026-10-25",
68
+ "task": "Open https://example.com, read the page title and the first sentence of the body, close the tab. Claude in Chrome tools in both tests, same Chrome profile, scratch folders under the same user config.",
69
+ "test_a_native": {
70
+ "calls": 6,
71
+ "context_total": 1133195,
72
+ "output": 734,
73
+ "browser_steps": {
74
+ "main": 4,
75
+ "median": 189084,
76
+ "total": 757290
77
+ },
78
+ "model": "claude-sonnet-5-5"
79
+ },
80
+ "test_b_package": {
81
+ "calls": 10,
82
+ "context_total": 1241361,
83
+ "output": 2846,
84
+ "main": {
85
+ "calls": 5,
86
+ "context_total": 956151,
87
+ "model": "claude-sonnet-5-5"
88
+ },
89
+ "runner": {
90
+ "calls": 5,
91
+ "context_total": 285210,
92
+ "model": "claude-haiku-5-5"
93
+ },
94
+ "browser_steps": {
95
+ "main": 1,
96
+ "runner": 4,
97
+ "runner_median": 58057,
98
+ "runner_total": 226289,
99
+ "main_step": 190532
100
+ }
101
+ },
102
+ "derived": {
103
+ "per_step_ratio": 3.26,
104
+ "whole_run_ratio": 0.91,
105
+ "whole_run_delta_percent": 9.55
106
+ }
107
+ },
108
+ "cost_usd": {
109
+ "pricing_source": "https://platform.claude.com/docs/en/about-claude/pricing",
110
+ "pricing_read": "2026-10-25",
111
+ "price_unit": "usd_per_million_tokens",
112
+ "prices": {
113
+ "claude-sonnet-5-5": {
114
+ "input": 2,
115
+ "cache_write_5m": 2.5,
116
+ "cache_read": 0.1,
117
+ "output": 10
118
+ },
119
+ "claude-haiku-5-5": {
120
+ "input": 0.1,
121
+ "cache_write_5m": 0.125,
122
+ "cache_read": 0.01,
123
+ "output": 0.5,
124
+ "max_prompt_tokens": 100000
125
+ }
126
+ },
127
+ "cache_write_assumed": "5m",
128
+ "method": "List API prices applied per model call, then summed by arm. Recorded arm totals and model splits are quoted to four decimal places; split rounding may differ from the arm total.",
129
+ "run1": {
130
+ "plain": {
131
+ "total": 0.5975,
132
+ "model_split": {
133
+ "claude-sonnet-5-5": 0.5975
134
+ }
135
+ },
136
+ "runner": {
137
+ "total": 0.5787,
138
+ "model_split": {
139
+ "claude-sonnet-5-5": 0.5629,
140
+ "claude-haiku-5-5": 0.0157
141
+ }
142
+ }
143
+ },
144
+ "run2": {
145
+ "plain": {
146
+ "total": 0.5779,
147
+ "model_split": {
148
+ "claude-sonnet-5-5": 0.5779
149
+ }
150
+ },
151
+ "runner": {
152
+ "total": 0.4319,
153
+ "model_split": {
154
+ "claude-sonnet-5-5": 0.4215,
155
+ "claude-haiku-5-5": 0.0104
156
+ }
157
+ }
158
+ },
159
+ "derived": {
160
+ "run1_percent": -3.15,
161
+ "run2_percent": -25.26,
162
+ "pooled_percent": -14.02,
163
+ "best_percent": 25.26
164
+ }
165
+ }
166
+ }
@@ -0,0 +1,241 @@
1
+ {
2
+ "version": 1,
3
+ "rows": [
4
+ {
5
+ "id": "runtime_dependencies",
6
+ "claim": "Runtime dependencies",
7
+ "value": 0,
8
+ "unit": "dependencies",
9
+ "measured": "2026-10-25",
10
+ "expires": "2027-01-25",
11
+ "how": "node scripts/proof.mjs"
12
+ },
13
+ {
14
+ "id": "tests_passing",
15
+ "claim": "Passing Node tests, including Python suite checks",
16
+ "value": 258,
17
+ "unit": "tests",
18
+ "measured": "2026-10-25",
19
+ "expires": "2027-01-25",
20
+ "how": "node --test test/"
21
+ },
22
+ {
23
+ "id": "tests_failing",
24
+ "claim": "Failing Node tests at measurement time",
25
+ "value": 0,
26
+ "unit": "tests",
27
+ "measured": "2026-10-25",
28
+ "expires": "2027-01-25",
29
+ "how": "node --test test/"
30
+ },
31
+ {
32
+ "id": "guard_rules",
33
+ "claim": "Blocking guard rules verified by the suite",
34
+ "value": 7,
35
+ "unit": "rules",
36
+ "measured": "2026-10-25",
37
+ "expires": "2027-01-25",
38
+ "how": "node --test test/"
39
+ },
40
+ {
41
+ "id": "guard_ms_median",
42
+ "claim": "Median wall time per guard via its shim over 50 calls",
43
+ "value": {
44
+ "pick-guard": 40.624,
45
+ "retry-guard": 42.568,
46
+ "batch-nudge": 45.23
47
+ },
48
+ "unit": "ms",
49
+ "measured": "2026-10-25",
50
+ "expires": "2027-01-25",
51
+ "how": "node scripts/proof.mjs"
52
+ },
53
+ {
54
+ "id": "install_ms",
55
+ "claim": "Install wall time into a new temporary config directory",
56
+ "value": 58.872,
57
+ "unit": "ms",
58
+ "measured": "2026-10-25",
59
+ "expires": "2027-01-25",
60
+ "how": "node scripts/proof.mjs"
61
+ },
62
+ {
63
+ "id": "tarball_bytes",
64
+ "claim": "Packed tarball size reported before this proof refresh",
65
+ "value": 83399,
66
+ "unit": "bytes",
67
+ "measured": "2026-10-25",
68
+ "expires": "2027-01-25",
69
+ "how": "npm pack --dry-run --json"
70
+ },
71
+ {
72
+ "id": "tarball_files",
73
+ "claim": "Files in the packed tarball",
74
+ "value": 76,
75
+ "unit": "files",
76
+ "measured": "2026-10-25",
77
+ "expires": "2027-01-25",
78
+ "how": "npm pack --dry-run --json"
79
+ },
80
+ {
81
+ "id": "paired_step_tokens_plain",
82
+ "claim": "Plain session median input-context tokens per browser step",
83
+ "value": 188487,
84
+ "unit": "tokens",
85
+ "measured": "2026-10-25",
86
+ "how": "see docs/benchmark.md"
87
+ },
88
+ {
89
+ "id": "paired_step_tokens_runner",
90
+ "claim": "Runner median input-context tokens per browser step",
91
+ "value": 59725,
92
+ "unit": "tokens",
93
+ "measured": "2026-10-25",
94
+ "how": "see docs/benchmark.md"
95
+ },
96
+ {
97
+ "id": "paired_step_ratio",
98
+ "claim": "Plain-to-runner median browser-step token ratio",
99
+ "value": 3.16,
100
+ "unit": "ratio",
101
+ "measured": "2026-10-25",
102
+ "how": "see docs/benchmark.md"
103
+ },
104
+ {
105
+ "id": "paired_task_tokens_plain",
106
+ "claim": "Plain arm total browser-step tokens",
107
+ "value": 1506374,
108
+ "unit": "tokens",
109
+ "measured": "2026-10-25",
110
+ "how": "see docs/benchmark.md"
111
+ },
112
+ {
113
+ "id": "paired_task_tokens_runner_arm",
114
+ "claim": "Runner arm total browser-step tokens",
115
+ "value": 725151,
116
+ "unit": "tokens",
117
+ "measured": "2026-10-25",
118
+ "how": "see docs/benchmark.md"
119
+ },
120
+ {
121
+ "id": "paired_task_ratio",
122
+ "claim": "Plain-to-runner arm total browser-step tokens ratio",
123
+ "value": 2.08,
124
+ "unit": "ratio",
125
+ "measured": "2026-10-25",
126
+ "how": "see docs/benchmark.md"
127
+ },
128
+ {
129
+ "id": "paired_run_tokens_plain",
130
+ "claim": "Plain arm whole-run input-context tokens",
131
+ "value": 2657290,
132
+ "unit": "tokens",
133
+ "measured": "2026-10-25",
134
+ "how": "see docs/benchmark.md"
135
+ },
136
+ {
137
+ "id": "paired_run_tokens_runner_arm",
138
+ "claim": "Runner arm whole-run input-context tokens",
139
+ "value": 2846792,
140
+ "unit": "tokens",
141
+ "measured": "2026-10-25",
142
+ "how": "see docs/benchmark.md"
143
+ },
144
+ {
145
+ "id": "paired_run_ratio",
146
+ "claim": "Plain-to-runner whole-run input-context token ratio",
147
+ "value": 0.93,
148
+ "unit": "ratio",
149
+ "measured": "2026-10-25",
150
+ "how": "see docs/benchmark.md"
151
+ },
152
+ {
153
+ "id": "paired_break_even_steps",
154
+ "claim": "Estimated break-even browser steps (an estimate from two data points; no run longer than 9 browser steps was measured)",
155
+ "value": 15.54,
156
+ "unit": "steps",
157
+ "measured": "2026-10-25",
158
+ "how": "see docs/benchmark.md"
159
+ },
160
+ {
161
+ "id": "paired_small_run_tokens_plain",
162
+ "claim": "Small task (one page, 4 browser steps), native Claude in Chrome: whole-run input-context tokens",
163
+ "value": 1133195,
164
+ "unit": "tokens",
165
+ "measured": "2026-10-25",
166
+ "how": "see docs/benchmark.md"
167
+ },
168
+ {
169
+ "id": "paired_small_run_tokens_runner_arm",
170
+ "claim": "Small task (one page), with the package, main session plus runner: whole-run input-context tokens",
171
+ "value": 1241361,
172
+ "unit": "tokens",
173
+ "measured": "2026-10-25",
174
+ "how": "see docs/benchmark.md"
175
+ },
176
+ {
177
+ "id": "paired_small_run_ratio",
178
+ "claim": "Small task: plain-to-package whole-run input-context token ratio",
179
+ "value": 0.91,
180
+ "unit": "ratio",
181
+ "measured": "2026-10-25",
182
+ "how": "see docs/benchmark.md"
183
+ },
184
+ {
185
+ "id": "paired_small_step_ratio",
186
+ "claim": "Small task: plain median browser step to runner median browser step token ratio",
187
+ "value": 3.26,
188
+ "unit": "ratio",
189
+ "measured": "2026-10-25",
190
+ "how": "see docs/benchmark.md"
191
+ },
192
+ {
193
+ "id": "paired_cost_usd_plain",
194
+ "claim": "Run 1 plain arm dollar cost at list API prices",
195
+ "value": 0.5975,
196
+ "unit": "usd",
197
+ "measured": "2026-10-25",
198
+ "how": "see docs/benchmark.md"
199
+ },
200
+ {
201
+ "id": "paired_cost_usd_runner_arm",
202
+ "claim": "Run 1 runner arm dollar cost at list API prices",
203
+ "value": 0.5787,
204
+ "unit": "usd",
205
+ "measured": "2026-10-25",
206
+ "how": "see docs/benchmark.md"
207
+ },
208
+ {
209
+ "id": "paired_small_cost_usd_plain",
210
+ "claim": "Run 2 plain arm dollar cost at list API prices",
211
+ "value": 0.5779,
212
+ "unit": "usd",
213
+ "measured": "2026-10-25",
214
+ "how": "see docs/benchmark.md"
215
+ },
216
+ {
217
+ "id": "paired_small_cost_usd_runner_arm",
218
+ "claim": "Run 2 runner arm dollar cost at list API prices",
219
+ "value": 0.4319,
220
+ "unit": "usd",
221
+ "measured": "2026-10-25",
222
+ "how": "see docs/benchmark.md"
223
+ },
224
+ {
225
+ "id": "paired_cost_best_saving_percent",
226
+ "claim": "Best dollar saving in two measured runs on one setup",
227
+ "value": 25.26,
228
+ "unit": "percent",
229
+ "measured": "2026-10-25",
230
+ "how": "see docs/benchmark.md"
231
+ },
232
+ {
233
+ "id": "paired_cost_pooled_saving_percent",
234
+ "claim": "Pooled dollar saving across two measured runs on one setup",
235
+ "value": 14.02,
236
+ "unit": "percent",
237
+ "measured": "2026-10-25",
238
+ "how": "see docs/benchmark.md"
239
+ }
240
+ ]
241
+ }
@@ -0,0 +1,48 @@
1
+ # Compile-once page reader
2
+
3
+ The reader turns a public page into an extraction spec. Later reads run the spec as code. Embedded JSON extraction uses the Python standard library. CSS extraction and browser fetching use Crawl4AI, which you install yourself:
4
+
5
+ ```sh
6
+ python3 -m pip install crawl4ai
7
+ ```
8
+
9
+ Use Python 3. The installer copies these files only when you pass `--with-reader`.
10
+
11
+ ## Compile, run, list
12
+
13
+ Choose a command that reads a prompt from stdin and prints extraction JSON on stdout. For example:
14
+
15
+ ```sh
16
+ export READER_COMPILE_CMD='claude -p'
17
+ reader/reader compile package --url 'https://www.npmjs.com/package/{name}' --param name=react --want 'name, version, license'
18
+ reader/reader run npm-package --param name=react
19
+ reader/reader ls
20
+ ```
21
+
22
+ `READER_COMPILE_CMD` is split with `shlex` and executed directly. Shell expansion and shell pipelines are not used. A command may be another agent CLI, a script calling an API, or a local model. Compile and self-heal require this variable; a valid compiled spec runs without it. Add `--example` with a JSON object to anchor the compile to an observed row. Page text is untrusted data.
23
+
24
+ A failed extraction gets one self-heal. `--no-heal` reports the extraction failure directly. Fetches accept public HTTP and HTTPS destinations, check redirects and browser requests, and refuse private addresses. Use the browser runner for pages that need your login.
25
+
26
+ ## Files and state
27
+
28
+ Bundled specs are in `specs/`. `READER_SPECS_DIR` selects a different spec directory. Successful reads and healed overrides live under `~/.cache/lean-browser-use/reader`, or `READER_STATE_DIR`. Runs preserve the bundled spec files. `READER_CRAWL4AI_PYTHON` selects the Python executable with Crawl4AI installed.
29
+
30
+ To add a spec, compile a known public URL with the fields you need and an observed example. Verify the JSON result against the page. Keep a public fixture and an offline regression check beside the spec. The bundled pricing fixture is a captured test page, not current pricing guidance.
31
+
32
+ ## Exit codes
33
+
34
+ | Code | Meaning |
35
+ |---|---|
36
+ | 0 | Completed |
37
+ | 2 | Usage, unset compile command, or refused target |
38
+ | 10 | Fetch failed |
39
+ | 11 | Compile failed |
40
+ | 12 | Extraction failed after the allowed heal |
41
+
42
+ ## Offline checks
43
+
44
+ ```sh
45
+ python3 -m unittest discover -s reader -p 'test_*.py'
46
+ ```
47
+
48
+ The suite uses the standard library. Crawl4AI and local socket integration checks skip with a reason when their capability is unavailable. Mocked subprocess contracts and embedded JSON extraction still run.