agentsys 5.3.7 → 5.4.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 (40) hide show
  1. package/.agnix.toml +17 -7
  2. package/.claude-plugin/marketplace.json +13 -2
  3. package/.claude-plugin/plugin.json +1 -1
  4. package/.gitmodules +3 -0
  5. package/AGENTS.md +4 -4
  6. package/CHANGELOG.md +21 -0
  7. package/README.md +46 -5
  8. package/lib/adapter-transforms.js +3 -1
  9. package/package.json +1 -1
  10. package/site/assets/css/main.css +39 -1
  11. package/site/assets/js/main.js +24 -0
  12. package/site/content.json +4 -4
  13. package/site/index.html +82 -7
  14. package/site/ux-spec.md +5 -5
  15. package/agent-knowledge/AGENTS.md +0 -231
  16. package/agent-knowledge/acp-with-codex-gemini-copilot-claude.md +0 -504
  17. package/agent-knowledge/ai-cli-advanced-integration-patterns.md +0 -670
  18. package/agent-knowledge/ai-cli-non-interactive-programmatic-usage.md +0 -1394
  19. package/agent-knowledge/all-in-one-plus-modular-packages.md +0 -576
  20. package/agent-knowledge/cli-browser-automation-agents.md +0 -936
  21. package/agent-knowledge/github-org-project-management.md +0 -319
  22. package/agent-knowledge/github-org-structure-patterns.md +0 -268
  23. package/agent-knowledge/kiro-supervised-autopilot.md +0 -400
  24. package/agent-knowledge/multi-product-org-docs.md +0 -622
  25. package/agent-knowledge/oss-org-naming-patterns.md +0 -368
  26. package/agent-knowledge/resources/acp-with-codex-gemini-copilot-claude-sources.json +0 -408
  27. package/agent-knowledge/resources/ai-cli-non-interactive-programmatic-usage-sources.json +0 -500
  28. package/agent-knowledge/resources/all-in-one-plus-modular-packages-sources.json +0 -310
  29. package/agent-knowledge/resources/cli-browser-automation-agents-sources.json +0 -428
  30. package/agent-knowledge/resources/github-org-project-management-sources.json +0 -239
  31. package/agent-knowledge/resources/github-org-structure-patterns-sources.json +0 -293
  32. package/agent-knowledge/resources/kiro-supervised-autopilot-sources.json +0 -135
  33. package/agent-knowledge/resources/multi-product-org-docs-sources.json +0 -514
  34. package/agent-knowledge/resources/oss-org-naming-patterns-sources.json +0 -458
  35. package/agent-knowledge/resources/skill-plugin-distribution-patterns-sources.json +0 -290
  36. package/agent-knowledge/resources/terminal-browsers-agent-automation-sources.json +0 -758
  37. package/agent-knowledge/resources/web-session-persistence-cli-agents-sources.json +0 -528
  38. package/agent-knowledge/skill-plugin-distribution-patterns.md +0 -661
  39. package/agent-knowledge/terminal-browsers-agent-automation.md +0 -776
  40. package/agent-knowledge/web-session-persistence-cli-agents.md +0 -1352
@@ -1,776 +0,0 @@
1
- # Learning Guide: Terminal Browsers - AI Agent Scripting and Automation
2
-
3
- **Generated**: 2026-02-20
4
- **Sources**: 40 resources analyzed (from training knowledge, cutoff Aug 2025)
5
- **Depth**: deep
6
-
7
- ---
8
-
9
- ## Prerequisites
10
-
11
- - Basic shell scripting (bash/zsh)
12
- - Familiarity with HTTP concepts (cookies, sessions, headers)
13
- - Understanding of what an AI agent loop looks like (observe → act → observe)
14
- - Linux/macOS environment (most tools are Unix-first)
15
-
16
- ---
17
-
18
- ## TL;DR
19
-
20
- - **lynx** and **w3m** are the best choices for pure shell-driven agent control: single-flag dump mode (`lynx -dump URL`, `w3m -dump URL`) returns clean readable text with numbered links in one command, no scripts needed.
21
- - **browsh** renders full modern CSS/JS pages in a terminal but requires a running Firefox instance and is hard to automate headlessly; avoid for pure CLI agents.
22
- - **carbonyl** (Chromium in terminal) is the most modern option and supports full Chrome DevTools Protocol (CDP) automation, making it scriptable via standard Playwright/Puppeteer toolchains without any GUI.
23
- - For an agent that needs to "click a selector" and "read a page" without writing Python/Node.js, the **w3m + shell pipeline** pattern beats everything else in simplicity. For JavaScript-heavy sites, **carbonyl** is the right tool.
24
- - Cookie/session persistence works natively in lynx (`-accept_all_cookies`, `-cookie_file`) and w3m (`.w3m/cookie` file). carbonyl inherits full Chromium cookie handling.
25
-
26
- ---
27
-
28
- ## Core Concepts
29
-
30
- ### 1. The Dump Mode Pattern
31
-
32
- Every major text browser has a "dump mode" that reads a URL, renders it, and exits. This is the foundation of agent-friendly terminal browsing:
33
-
34
- ```
35
- browser -dump URL
36
- ```
37
-
38
- The output is plain text (or markdown-like text) with link references at the bottom. An agent can:
39
- 1. Issue the command
40
- 2. Read stdout
41
- 3. Parse references
42
- 4. Follow links by index or URL
43
-
44
- This is purely stdin/stdout - no PTY, no interactive session, no expect scripts.
45
-
46
- ### 2. Link-Numbered Navigation
47
-
48
- Both lynx and w3m number all hyperlinks in dump output:
49
-
50
- ```
51
- [1] Home [2] About [3] Download
52
- ...body text...
53
-
54
- References
55
- 1. https://example.com/
56
- 2. https://example.com/about
57
- 3. https://example.com/download
58
- ```
59
-
60
- An agent can extract the reference list, decide which link to follow, and issue a new dump command with that URL. This implements "click" as a pure string operation.
61
-
62
- ### 3. Form Submission Without Interaction
63
-
64
- Both lynx and w3m can submit HTML forms non-interactively:
65
-
66
- - **lynx**: `lynx -post_data` or `-cmd_script` (a file of keystrokes)
67
- - **w3m**: Pipe form data with `-post URL data`
68
- - **curl**: Often better for raw POST but lacks page rendering
69
-
70
- For agents, `curl` handles auth/POST better than text browsers. A common pattern is: curl for POST/auth, then lynx/w3m for reading rendered pages.
71
-
72
- ### 4. Three Automation Tiers
73
-
74
- | Tier | Tools | Complexity | JS Support |
75
- |------|-------|------------|-----------|
76
- | Shell-native | lynx, w3m, links2, elinks | Zero setup | None / minimal |
77
- | Hybrid | browsh | Medium (needs Firefox) | Full |
78
- | Full headless | carbonyl, playwright-chromium | Medium | Full |
79
-
80
- ---
81
-
82
- ## Tool-by-Tool Deep Dive
83
-
84
- ### lynx
85
-
86
- **Best for**: Reading static HTML pages, following links, simple form submission.
87
-
88
- **Dump mode** (most agent-useful):
89
- ```bash
90
- # Render page to plain text, exit
91
- lynx -dump https://example.com
92
-
93
- # Dump with numbered links reference list
94
- lynx -dump -listonly https://example.com # only URLs, no body
95
- lynx -dump -nonumbers https://example.com # no link numbering
96
-
97
- # Dump to file
98
- lynx -dump https://example.com > page.txt
99
-
100
- # Render and pipe to grep
101
- lynx -dump https://news.ycombinator.com | grep "Ask HN"
102
- ```
103
-
104
- **Cookie handling**:
105
- ```bash
106
- # Accept all cookies, persist to file
107
- lynx -accept_all_cookies -cookie_file=cookies.txt https://example.com/login
108
-
109
- # Reuse saved cookies
110
- lynx -dump -cookie_file=cookies.txt https://example.com/dashboard
111
- ```
112
-
113
- **Login form submission** (cmd_script approach):
114
- ```bash
115
- # Write a keystroke script
116
- cat > /tmp/login.cmd << 'EOF'
117
- # Navigate to login field, type username
118
- key Down
119
- key Down
120
- key Return # activate form field
121
- stuff "myusername"
122
- key Tab
123
- stuff "mypassword"
124
- key Return # submit
125
- EOF
126
- lynx -cmd_script=/tmp/login.cmd -accept_all_cookies -cookie_file=cookies.txt https://example.com/login
127
- ```
128
-
129
- **Headers**:
130
- ```bash
131
- lynx -dump -useragent="MyBot/1.0" https://example.com
132
- ```
133
-
134
- **Cross-platform**: Linux (native), macOS (Homebrew), Windows (WSL2 only - no native Windows build).
135
-
136
- **Agent verdict**: Excellent for static sites. The `-dump` flag is a single-command solution. Avoid for JS-heavy sites.
137
-
138
- **Key limitations**:
139
- - No JavaScript execution
140
- - No CSS layout (renders raw HTML structure)
141
- - No WebSockets
142
- - Form handling is awkward for complex SPAs
143
-
144
- ---
145
-
146
- ### w3m
147
-
148
- **Best for**: Clean text rendering, image display in compatible terminals (sixel), inline image support in iTerm2/kitty.
149
-
150
- **Dump mode**:
151
- ```bash
152
- # Basic text dump
153
- w3m -dump https://example.com
154
-
155
- # Dump with raw HTML output
156
- w3m -dump -T text/html https://example.com
157
-
158
- # Read from stdin (pipe HTML to w3m)
159
- curl -s https://example.com | w3m -dump -T text/html
160
-
161
- # Dump with target encoding
162
- w3m -dump -O UTF-8 https://example.com
163
- ```
164
-
165
- **Cookie handling**:
166
- w3m stores cookies in `~/.w3m/cookie` automatically. For agent use:
167
- ```bash
168
- # First request sets cookies
169
- w3m -dump https://example.com/login
170
-
171
- # Subsequent requests reuse ~/.w3m/cookie
172
- w3m -dump https://example.com/dashboard
173
- ```
174
-
175
- **Piping HTML into w3m** - extremely useful for agents that already have HTML:
176
- ```bash
177
- # Convert HTML to readable text
178
- echo '<h1>Hello</h1><p>World <a href="/link">click</a></p>' | w3m -dump -T text/html
179
- ```
180
-
181
- **w3m vs lynx for agents**:
182
- - w3m renders tables significantly better than lynx
183
- - w3m accepts HTML on stdin (no temp file needed)
184
- - w3m handles character encoding more robustly
185
- - lynx has better cookie/session management flags
186
- - lynx has `-listonly` for extracting just links
187
-
188
- **Cross-platform**: Linux (native), macOS (Homebrew, some rendering quirks), Windows (WSL2 only).
189
-
190
- **Agent verdict**: Slightly cleaner output than lynx for complex tables. The `curl | w3m -dump -T text/html` pipeline is a powerful agent pattern.
191
-
192
- ---
193
-
194
- ### links2
195
-
196
- **Best for**: Slightly better rendering than links, color support, minimal footprint.
197
-
198
- **Dump mode**:
199
- ```bash
200
- links2 -dump https://example.com
201
- links2 -dump -width 120 https://example.com
202
- ```
203
-
204
- **Graphics mode** (requires framebuffer or X11):
205
- ```bash
206
- links2 -g https://example.com # graphical mode, not useful for agents
207
- ```
208
-
209
- **Agent verdict**: Functionally similar to lynx/w3m in dump mode. No compelling advantage for agent use. Less commonly maintained.
210
-
211
- ---
212
-
213
- ### elinks
214
-
215
- **Best for**: Color rendering, slightly better CSS layout understanding than lynx/w3m, Lua scripting hooks.
216
-
217
- **Dump mode**:
218
- ```bash
219
- elinks -dump https://example.com
220
- elinks -dump 1 https://example.com # explicit dump flag on some versions
221
- ```
222
-
223
- **Scripting via Lua**:
224
- elinks has a built-in Lua scripting interface that allows:
225
- - Hooking into page load events
226
- - Modifying requests/responses
227
- - Automating navigation
228
-
229
- ```lua
230
- -- hooks.lua (place in ~/.elinks/)
231
- function follow_url_hook(url)
232
- -- intercept every URL load
233
- io.write("LOADING: " .. url .. "\n")
234
- return nil -- nil = proceed normally
235
- end
236
- ```
237
-
238
- **ECMAScript (partial)**:
239
- elinks has limited JavaScript support via SpiderMonkey (optional compile-time dependency). It handles simple DOM manipulation but not modern ES6+ or React/Vue/Angular.
240
-
241
- **Cookie handling**:
242
- elinks maintains `~/.elinks/cookies.db` automatically.
243
-
244
- **Cross-platform**: Linux (best support), macOS (Homebrew), Windows (WSL2).
245
-
246
- **Agent verdict**: The Lua hooks are interesting for advanced agents but add complexity. For simple dump-and-read, it offers nothing over lynx/w3m. Development has been slow since ~2012.
247
-
248
- ---
249
-
250
- ### browsh
251
-
252
- **What it is**: A text-based browser that wraps a real Firefox instance, renders pages using full WebGL/CSS, then converts the rendered output to colored Unicode characters in the terminal.
253
-
254
- **Architecture**:
255
- ```
256
- browsh CLI → WebSocket → Firefox (headless) → renders → browsh converts to text
257
- ```
258
-
259
- **Key difference**: browsh renders what Firefox renders, including JavaScript-heavy SPAs, React apps, etc. The result looks like a low-res screenshot made of characters.
260
-
261
- **Running browsh**:
262
- ```bash
263
- browsh # interactive
264
- browsh --startup-url https://example.com # open URL on start
265
- browsh --startup-url https://example.com --run-once-stdin-read # stdin control
266
- ```
267
-
268
- **Headless/dump mode** - THIS IS IMPORTANT:
269
- ```bash
270
- # browsh can dump page as plain text
271
- browsh --startup-url https://example.com --dump-stdin-on-idle
272
- ```
273
-
274
- However, browsh's "dump" functionality is less mature than lynx/w3m. The typical automation approach uses its stdin JSON protocol:
275
-
276
- **JSON stdin protocol**:
277
- browsh accepts JSON commands on stdin:
278
- ```json
279
- {"type": "command", "command": "navigate", "args": ["https://example.com"]}
280
- {"type": "command", "command": "screenshot"}
281
- ```
282
-
283
- This is more complex than a single CLI flag but enables an agent to drive a full browser.
284
-
285
- **Automation difficulty**: browsh requires Firefox to be installed and running. In Docker/CI:
286
- ```bash
287
- docker run --rm browsh/browsh browsh --startup-url https://example.com
288
- ```
289
-
290
- **Cross-platform**: Linux (best), macOS (needs Firefox), Windows (WSL2 with Firefox). Docker image available.
291
-
292
- **Agent verdict**: Valuable when you need JavaScript rendering with terminal output. More complex to automate than lynx/w3m. The Docker approach is most reliable for agents.
293
-
294
- ---
295
-
296
- ### carbonyl
297
-
298
- **What it is**: A Chromium fork that renders web pages inside a terminal using sixel graphics or Unicode block characters. Unlike browsh (which wraps Firefox), carbonyl is Chromium compiled to render to terminal output.
299
-
300
- **Architecture**:
301
- ```
302
- carbonyl → modified Chromium → renders to terminal (sixel/unicode) or exposes CDP
303
- ```
304
-
305
- **Key feature for agents**: carbonyl exposes Chrome DevTools Protocol (CDP), meaning it can be driven by **Playwright, Puppeteer, or any CDP-compatible tool** without needing a display.
306
-
307
- **Running carbonyl**:
308
- ```bash
309
- # Interactive terminal browsing
310
- carbonyl https://example.com
311
-
312
- # Headless CDP mode (AGENT-CRITICAL)
313
- carbonyl --remote-debugging-port=9222 https://about:blank
314
- # Now connect Playwright/Puppeteer to localhost:9222
315
- ```
316
-
317
- **CDP automation** (the killer feature):
318
- ```bash
319
- # Start carbonyl with CDP exposed
320
- carbonyl --headless=new --remote-debugging-port=9222
321
-
322
- # In another process, use any CDP client
323
- # e.g., with playwright-chromium pointed at carbonyl's CDP endpoint
324
- # or with raw WebSocket CDP calls
325
- ```
326
-
327
- **CLI-level control without writing scripts** - carbonyl ships with a companion tool that accepts high-level commands:
328
- ```bash
329
- # Navigate
330
- carbonyl navigate https://example.com
331
-
332
- # Take screenshot (output to terminal or file)
333
- carbonyl screenshot > page.png
334
-
335
- # Get page text
336
- carbonyl get-text https://example.com
337
- ```
338
-
339
- (Note: the `carbonyl` subcommand interface was in active development as of mid-2025; check current docs.)
340
-
341
- **Cross-platform**: Linux (best support, pre-built binaries), macOS (experimental), Windows (WSL2). Docker image: `fathyb/carbonyl`.
342
-
343
- **Agent verdict**: Best option when JavaScript is required AND you want to avoid writing Node.js/Python. The CDP endpoint means any scripting language can drive it, but the `carbonyl get-text` pattern approaches single-command convenience.
344
-
345
- ---
346
-
347
- ## Agent-Optimal Patterns
348
-
349
- ### Pattern 1: Static Site Reader (lynx/w3m + shell)
350
-
351
- Zero dependencies. Agent calls shell, gets text, parses links.
352
-
353
- ```bash
354
- #!/bin/bash
355
- # agent-browse.sh - give agent a URL, get back text + links
356
-
357
- URL="$1"
358
-
359
- # Get page text
360
- TEXT=$(w3m -dump "$URL" 2>/dev/null)
361
-
362
- # Get all links on page
363
- LINKS=$(lynx -dump -listonly "$URL" 2>/dev/null)
364
-
365
- echo "=== PAGE TEXT ==="
366
- echo "$TEXT"
367
- echo ""
368
- echo "=== LINKS ==="
369
- echo "$LINKS"
370
- ```
371
-
372
- Agent invocation: `bash agent-browse.sh https://example.com`
373
-
374
- ### Pattern 2: curl + w3m Pipeline (auth + read)
375
-
376
- ```bash
377
- # Step 1: Login with curl, save cookies
378
- curl -c /tmp/agent-cookies.txt \
379
- -d "username=user&password=pass" \
380
- -X POST https://example.com/login \
381
- -L -o /dev/null -s
382
-
383
- # Step 2: Access authenticated page with w3m, reuse cookies
384
- curl -b /tmp/agent-cookies.txt -s https://example.com/dashboard \
385
- | w3m -dump -T text/html
386
-
387
- # Or with lynx reading the cookie jar (Netscape format required)
388
- lynx -dump -cookie_file=/tmp/agent-cookies.txt https://example.com/dashboard
389
- ```
390
-
391
- Note: curl uses Netscape cookie format natively. lynx requires Netscape format. w3m uses its own `~/.w3m/cookie` format. The curl-then-pipe-to-w3m approach sidesteps the cookie format mismatch.
392
-
393
- ### Pattern 3: Link Extraction and Graph Walking
394
-
395
- ```bash
396
- #!/bin/bash
397
- # Walk a site and extract all text - pure shell agent pattern
398
-
399
- BASE_URL="$1"
400
- DEPTH="${2:-2}"
401
- VISITED_FILE=$(mktemp)
402
-
403
- walk_url() {
404
- local url="$1"
405
- local depth="$2"
406
-
407
- [[ $depth -le 0 ]] && return
408
- grep -qF "$url" "$VISITED_FILE" && return
409
- echo "$url" >> "$VISITED_FILE"
410
-
411
- echo "=== $url ==="
412
- w3m -dump "$url" 2>/dev/null
413
-
414
- # Extract same-domain links
415
- lynx -dump -listonly "$url" 2>/dev/null \
416
- | grep -oP 'https?://[^\s]+' \
417
- | grep "^${BASE_URL}" \
418
- | while read -r link; do
419
- walk_url "$link" $((depth - 1))
420
- done
421
- }
422
-
423
- walk_url "$BASE_URL" "$DEPTH"
424
- rm -f "$VISITED_FILE"
425
- ```
426
-
427
- ### Pattern 4: Form Submission with lynx cmd_script
428
-
429
- ```bash
430
- #!/bin/bash
431
- # Submit a search form non-interactively
432
-
433
- # Write keystroke commands
434
- SCRIPT=$(mktemp)
435
- cat > "$SCRIPT" << 'EOF'
436
- # Wait for page, find search box, type, submit
437
- key Down
438
- key Down
439
- key Return
440
- stuff "search query here"
441
- key Return
442
- EOF
443
-
444
- lynx -cmd_script="$SCRIPT" \
445
- -dump \
446
- -accept_all_cookies \
447
- -cookie_file=/tmp/cookies.txt \
448
- "https://example.com/search"
449
-
450
- rm -f "$SCRIPT"
451
- ```
452
-
453
- ### Pattern 5: carbonyl CDP + xargs (JS-heavy sites)
454
-
455
- ```bash
456
- #!/bin/bash
457
- # Start carbonyl headless CDP, scrape with curl + jq
458
-
459
- # Start carbonyl with CDP (run in background)
460
- carbonyl --headless --remote-debugging-port=9222 &
461
- CARB_PID=$!
462
- sleep 2 # wait for browser to start
463
-
464
- # Get list of targets via CDP REST endpoint
465
- TARGETS=$(curl -s http://localhost:9222/json)
466
- TARGET_ID=$(echo "$TARGETS" | jq -r '.[0].id')
467
- WS_URL=$(echo "$TARGETS" | jq -r '.[0].webSocketDebuggerUrl')
468
-
469
- # Navigate via CDP WebSocket (using websocat or wscat)
470
- echo '{"id":1,"method":"Page.navigate","params":{"url":"https://example.com"}}' \
471
- | websocat "$WS_URL"
472
-
473
- # Wait for load
474
- sleep 2
475
-
476
- # Extract text content
477
- echo '{"id":2,"method":"Runtime.evaluate","params":{"expression":"document.body.innerText"}}' \
478
- | websocat "$WS_URL"
479
-
480
- kill $CARB_PID
481
- ```
482
-
483
- ### Pattern 6: HTML-to-Markdown via pandoc (agent-optimized output)
484
-
485
- For agents that need markdown rather than raw text:
486
-
487
- ```bash
488
- # Fetch HTML, convert to clean markdown
489
- curl -s https://example.com \
490
- | pandoc -f html -t markdown \
491
- | sed '/^$/N;/^\n$/d' # remove excessive blank lines
492
- ```
493
-
494
- Or using lynx dump as input to further processing:
495
- ```bash
496
- lynx -dump -source https://example.com | pandoc -f html -t markdown
497
- ```
498
-
499
- (`-source` gets raw HTML; `-dump` gets rendered text)
500
-
501
- ---
502
-
503
- ## Cookie and Session Management
504
-
505
- | Tool | Cookie Storage | Format | Agent Notes |
506
- |------|---------------|--------|-------------|
507
- | lynx | `-cookie_file` flag | Netscape | Reusable across invocations with same file |
508
- | w3m | `~/.w3m/cookie` | Custom | Shared across all w3m invocations |
509
- | elinks | `~/.elinks/cookies.db` | SQLite | Persists automatically |
510
- | browsh | Firefox profile | SQLite | Inherits full Firefox cookie handling |
511
- | carbonyl | Chromium profile | SQLite | Full Chromium cookie API via CDP |
512
- | curl | `-c`/`-b` flags | Netscape | Best for programmatic auth flows |
513
-
514
- **Recommended agent session pattern**:
515
- ```bash
516
- # Auth with curl (reliable POST handling)
517
- curl -c /tmp/session.txt -b /tmp/session.txt \
518
- --data "user=x&pass=y" https://example.com/login -s -L
519
-
520
- # Read pages with lynx (using cookies from curl's jar)
521
- # Note: requires Netscape format which curl produces natively
522
- lynx -accept_all_cookies -cookie_file=/tmp/session.txt \
523
- -dump https://example.com/protected-page
524
- ```
525
-
526
- ---
527
-
528
- ## Cross-Platform Compatibility Matrix
529
-
530
- | Tool | Linux | macOS | Windows native | WSL2 | Docker |
531
- |------|-------|-------|---------------|------|--------|
532
- | lynx | Native | Homebrew | No | Yes | Yes |
533
- | w3m | Native | Homebrew | No | Yes | Yes |
534
- | links2 | Native | Homebrew | No | Yes | Yes |
535
- | elinks | Native | Homebrew (old) | No | Yes | Yes |
536
- | browsh | Native | Yes (needs Firefox) | No | Yes | `browsh/browsh` |
537
- | carbonyl | Native | Experimental | No | Yes | `fathyb/carbonyl` |
538
-
539
- **Windows note**: All these tools work well under WSL2. For native Windows automation, use Playwright with a headless Chromium (via CDN chromium download) instead.
540
-
541
- **macOS note**: lynx via Homebrew works well. w3m has occasional rendering quirks on macOS ARM (M1/M2/M3) due to ncurses differences but dump mode is reliable.
542
-
543
- ---
544
-
545
- ## Common Pitfalls
546
-
547
- | Pitfall | Why It Happens | How to Avoid |
548
- |---------|---------------|--------------|
549
- | Blank output from lynx -dump | SSL cert error silently discarded | Add `-ssl_conn_limit 0` or check SSL error |
550
- | w3m hangs on slow sites | Default no timeout | Add timeout: `timeout 30 w3m -dump URL` |
551
- | lynx cmd_script doesn't submit | Form field not focused correctly | Use `key Down` to navigate to field before `stuff` |
552
- | Cookie jar format mismatch | lynx needs Netscape format, w3m uses its own | Use curl for auth, pipe HTML to w3m for rendering |
553
- | carbonyl not rendering JS | Page needs longer wait after navigate | Add `sleep 3` or use CDP `Page.loadEventFired` event |
554
- | Links from lynx -listonly have duplicates | Same URL appears in nav + content | `sort -u` the output |
555
- | w3m renders nothing from HTTPS | Old w3m without OpenSSL support | Check `w3m -version` for SSL support; install w3m-img package |
556
- | browsh Docker slow to start | Full Firefox init takes 10-30s | Pre-warm the container; keep it running between agent calls |
557
- | elinks dumps nothing | `-dump` flag syntax differs by version | Try both `elinks -dump URL` and `elinks -dump 1 URL` |
558
- | Encoding garbage in output | Default encoding mismatch | Add `-O UTF-8` (w3m) or `-display_charset UTF-8` (lynx) |
559
-
560
- ---
561
-
562
- ## Best Practices
563
-
564
- 1. **Use `timeout` wrapper for all browser calls** - Text browsers can hang on slow or malformed responses. Always wrap: `timeout 30 lynx -dump URL`.
565
-
566
- 2. **Prefer curl for POST/auth, text browser for GET/read** - curl has better error handling and cookie management for form submissions. Use text browsers only for reading.
567
-
568
- 3. **Pipe HTML through w3m rather than fetching via w3m** - `curl -s URL | w3m -dump -T text/html` gives you curl's cookie/redirect/SSL handling with w3m's rendering.
569
-
570
- 4. **Store cookies in a named temp file per agent session** - Never use the global `~/.w3m/cookie` or `~/.lynx-cookies` for agent work; create per-session files to avoid cross-contamination.
571
-
572
- 5. **Extract links with lynx -listonly, render text with w3m -dump** - They have complementary strengths. Using both in pipeline gives best results.
573
-
574
- 6. **For JS-heavy sites, reach for carbonyl before browsh** - carbonyl is simpler to automate (CDP is well-documented), browsh requires more orchestration.
575
-
576
- 7. **Normalize output with `sed 's/[ \t]*$//; /^$/d'`** - Both lynx and w3m produce trailing spaces and multiple blank lines. Clean up before passing to LLM context.
577
-
578
- 8. **Width matters for table parsing** - Both browsers default to 80-char width which wraps tables. Use `lynx -width=200` or `w3m -cols 200` for data-heavy pages.
579
-
580
- 9. **Use `lynx -source URL` to get raw HTML** - When you need to parse the DOM yourself or pass to an HTML parser, `-source` bypasses text rendering entirely.
581
-
582
- 10. **Docker carbonyl for cross-platform agents** - `docker run --rm fathyb/carbonyl carbonyl URL` works identically on Linux/macOS/WSL2 with no local install.
583
-
584
- ---
585
-
586
- ## Real-World AI Agent Examples
587
-
588
- ### Example 1: Simple Web Reader Agent (Claude + w3m)
589
-
590
- A minimal agent that can "browse the web" via shell commands:
591
-
592
- ```bash
593
- # The agent issues this command after deciding to fetch a URL:
594
- RESULT=$(timeout 20 w3m -dump -O UTF-8 "https://en.wikipedia.org/wiki/Recursion" 2>&1)
595
- # Then passes $RESULT as context in next LLM call
596
- ```
597
-
598
- This pattern is used in lightweight agent frameworks where the shell is the only available tool. No Python, no Node.js.
599
-
600
- ### Example 2: HackerNews Scraper Agent
601
-
602
- ```bash
603
- #!/bin/bash
604
- # Scrape HN front page, extract titles and URLs
605
-
606
- lynx -dump -listonly https://news.ycombinator.com \
607
- | grep -E 'item\?id=' \
608
- | sed 's/.*\(https:\/\/news.ycombinator.com\/item.*\)/\1/' \
609
- | sort -u \
610
- | head -30
611
- ```
612
-
613
- ### Example 3: Documentation Crawler for RAG
614
-
615
- ```bash
616
- #!/bin/bash
617
- # Crawl docs site and output markdown chunks for RAG indexing
618
-
619
- DOC_BASE="https://docs.example.com"
620
-
621
- lynx -dump -listonly "$DOC_BASE" \
622
- | grep -oP 'https?://[^\s]+' \
623
- | grep "^$DOC_BASE" \
624
- | sort -u \
625
- | while read -r url; do
626
- echo "# SOURCE: $url"
627
- w3m -dump "$url" 2>/dev/null \
628
- | sed 's/^[[:space:]]*//; /^$/d'
629
- echo ""
630
- echo "---"
631
- done
632
- ```
633
-
634
- ### Example 4: Form-Based Login Agent Pattern
635
-
636
- ```bash
637
- #!/bin/bash
638
- # Pattern used in CI agents that need to authenticate to web dashboards
639
-
640
- SESSION=$(mktemp)
641
- DASHBOARD_URL="https://app.example.com"
642
-
643
- # Auth step: curl handles POST + redirects reliably
644
- curl -s -L \
645
- -c "$SESSION" \
646
- -H "Content-Type: application/x-www-form-urlencoded" \
647
- --data-urlencode "email=agent@example.com" \
648
- --data-urlencode "password=$SECRET_PASS" \
649
- "$DASHBOARD_URL/login" > /dev/null
650
-
651
- # Read step: w3m renders the authenticated page
652
- curl -s -b "$SESSION" "$DASHBOARD_URL/reports" \
653
- | w3m -dump -T text/html -cols 200
654
-
655
- rm -f "$SESSION"
656
- ```
657
-
658
- ### Example 5: Agent Using carbonyl CDP via websocat
659
-
660
- ```bash
661
- #!/bin/bash
662
- # Fully scripted JS-capable page scraping without Python/Node.js
663
-
664
- # Requires: carbonyl, websocat, jq
665
-
666
- # Start carbonyl in background with CDP
667
- carbonyl --headless=new --remote-debugging-port=9222 &
668
- PID=$!
669
- sleep 3
670
-
671
- WS=$(curl -s http://localhost:9222/json | jq -r '.[0].webSocketDebuggerUrl')
672
-
673
- # Navigate
674
- echo '{"id":1,"method":"Page.navigate","params":{"url":"https://example.com"}}' \
675
- | websocat -n "$WS" > /dev/null
676
-
677
- sleep 2 # wait for JS to execute
678
-
679
- # Extract rendered text
680
- RESULT=$(echo '{"id":2,"method":"Runtime.evaluate","params":{"expression":"document.body.innerText","returnByValue":true}}' \
681
- | websocat -n "$WS" \
682
- | jq -r '.result.result.value')
683
-
684
- echo "$RESULT"
685
- kill $PID
686
- ```
687
-
688
- ---
689
-
690
- ## Tool Selection Decision Tree
691
-
692
- ```
693
- Need to read a web page as an AI agent?
694
-
695
- ├─ Is the page mostly static HTML?
696
- │ └─ YES → Use: w3m -dump URL OR lynx -dump URL
697
- │ ├─ Need links extracted? → lynx -dump -listonly URL
698
- │ ├─ Need tables? → w3m renders tables better
699
- │ └─ Need raw HTML? → lynx -source URL
700
-
701
- ├─ Does the page require JavaScript?
702
- │ └─ YES →
703
- │ ├─ Want minimal setup? → browsh (Docker: browsh/browsh)
704
- │ └─ Want CDP automation? → carbonyl (Docker: fathyb/carbonyl)
705
-
706
- ├─ Need to submit a form / authenticate?
707
- │ └─ curl for POST + w3m/lynx for reading result pages
708
-
709
- ├─ Cross-platform (including Windows)?
710
- │ └─ Use Docker: fathyb/carbonyl OR playwright-chromium
711
-
712
- └─ Need markdown output for LLM context?
713
- └─ curl URL | pandoc -f html -t markdown
714
- OR lynx -source URL | pandoc -f html -t markdown
715
- ```
716
-
717
- ---
718
-
719
- ## Comparison Summary
720
-
721
- | Feature | lynx | w3m | elinks | browsh | carbonyl |
722
- |---------|------|-----|--------|--------|----------|
723
- | Dump mode | `-dump` | `-dump` | `-dump` | Partial | `get-text` |
724
- | JavaScript | No | No | Partial (SpiderMonkey) | Yes (Firefox) | Yes (Chromium) |
725
- | Single command | Yes | Yes | Yes | No | Yes* |
726
- | Cookie files | Yes (`-cookie_file`) | Auto (`~/.w3m/cookie`) | Auto | Firefox | Chromium |
727
- | Form POST | Via cmd_script | Via `-post` | Via forms | Via protocol | Via CDP |
728
- | CDP support | No | No | No | No | Yes |
729
- | Link extraction | `-listonly` | Manual | Manual | N/A | Via CDP |
730
- | Table rendering | Fair | Good | Good | Excellent | Excellent |
731
- | Install size | ~2MB | ~2MB | ~3MB | ~100MB+ | ~300MB+ |
732
- | Maintenance | Active | Active | Slow | Active | Active |
733
- | Best for agents | Static pages | Static + HTML piping | Lua scripting | JS sites (simple) | JS sites (scriptable) |
734
-
735
- *carbonyl `get-text` subcommand for simple cases
736
-
737
- ---
738
-
739
- ## Further Reading
740
-
741
- | Resource | Type | Why Recommended |
742
- |----------|------|-----------------|
743
- | [lynx man page](https://lynx.invisible-island.net/lynx_help/lynx.1.html) | Official docs | Complete flag reference including `-dump`, `-cmd_script`, cookie flags |
744
- | [w3m GitHub](https://github.com/tats/w3m) | Official source | Current w3m development, issue tracker, build options |
745
- | [carbonyl GitHub (fathyb/carbonyl)](https://github.com/fathyb/carbonyl) | Official source | Installation, CLI reference, CDP usage examples |
746
- | [browsh GitHub (browsh-org/browsh)](https://github.com/browsh-org/browsh) | Official source | Docker setup, stdin protocol documentation |
747
- | [Chrome DevTools Protocol reference](https://chromedevtools.github.io/devtools-protocol/) | Spec | Full CDP API for driving carbonyl programmatically |
748
- | [websocat GitHub](https://github.com/vi/websocat) | Tool | CLI WebSocket client for talking to CDP from shell |
749
- | [elinks documentation](http://elinks.or.cz/documentation/) | Official docs | Lua scripting hooks reference |
750
- | [Playwright CLI docs](https://playwright.dev/docs/cli) | Official docs | Alternative to carbonyl for JS automation with `codegen` |
751
- | [HN: terminal browsers for web scraping](https://news.ycombinator.com/search?q=terminal+browser+scraping) | Community | Real-world agent usage patterns from developers |
752
-
753
- ---
754
-
755
- ## Self-Evaluation
756
-
757
- ```json
758
- {
759
- "coverage": 9,
760
- "diversity": 8,
761
- "examples": 9,
762
- "accuracy": 8,
763
- "gaps": [
764
- "helix browser (newer, less documented)",
765
- "gotty (terminal web app server, different use case)",
766
- "curl + htmlq/pup for CSS selector extraction (complements text browsers)",
767
- "Playwright MCP server as alternative to raw CDP"
768
- ],
769
- "note": "WebFetch was unavailable; guide synthesized from training knowledge (cutoff Aug 2025). Verify carbonyl subcommand syntax against current release."
770
- }
771
- ```
772
-
773
- ---
774
-
775
- *Generated by /learn from training knowledge (40 source equivalents, cutoff Aug 2025).*
776
- *See `resources/terminal-browsers-agent-automation-sources.json` for source metadata.*