@pencil-agent/nano-pencil 2.0.0-beta.8 → 2.0.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 (241) hide show
  1. package/README.md +267 -267
  2. package/dist/build-meta.json +3 -3
  3. package/dist/core/export-html/AGENT.md +11 -11
  4. package/dist/core/export-html/template.css +971 -971
  5. package/dist/core/export-html/template.html +54 -54
  6. package/dist/core/extensions-host/index.d.ts +1 -1
  7. package/dist/core/extensions-host/loader.js +1 -1
  8. package/dist/core/extensions-host/runner.d.ts +1 -0
  9. package/dist/core/extensions-host/runner.js +2 -2
  10. package/dist/core/extensions-host/types.d.ts +17 -22
  11. package/dist/core/lib/ai/src/types.d.ts +12 -2
  12. package/dist/core/persona/persona-manager.js +5 -2
  13. package/dist/core/runtime/agent-session.js +3 -3
  14. package/dist/core/runtime/extension-core-bindings.d.ts +1 -0
  15. package/dist/core/runtime/extension-core-bindings.js +2 -2
  16. package/dist/extensions/builtin/AGENT.md +115 -115
  17. package/dist/extensions/builtin/browser/AGENT.md +17 -17
  18. package/dist/extensions/builtin/browser/agent-workspace/agent_helpers.py +12 -12
  19. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/amazon/product-search.md +198 -198
  20. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/archive-org/scraping.md +341 -341
  21. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/arxiv/scraping.md +311 -311
  22. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/arxiv-bulk/scraping.md +333 -333
  23. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/atlas/overview.md +70 -70
  24. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/booking-com/scraping.md +578 -578
  25. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/capterra/scraping.md +440 -440
  26. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/centilebrain/generate-estimates.md +110 -110
  27. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coingecko/scraping.md +325 -325
  28. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coinmarketcap/scraping.md +463 -463
  29. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coursera/scraping.md +360 -360
  30. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/craigslist/scraping.md +390 -390
  31. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/crossref/scraping.md +568 -568
  32. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/dev-to/scraping.md +323 -323
  33. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/duckduckgo/scraping.md +349 -349
  34. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/ebay/scraping.md +435 -435
  35. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/etsy/scraping.md +506 -506
  36. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/eventbrite/scraping.md +363 -363
  37. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/expedia/automation.md +168 -168
  38. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/facebook/groups.md +236 -236
  39. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/facebook/pages.md +295 -295
  40. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/framer/editor.md +108 -108
  41. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/fred/scraping.md +493 -493
  42. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/g2/scraping.md +580 -580
  43. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/genius/scraping.md +511 -511
  44. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/github/repo-actions.md +65 -65
  45. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/github/scraping.md +184 -184
  46. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/glassdoor/scraping.md +543 -543
  47. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/gmail/compose.md +122 -122
  48. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/goodreads/scraping.md +461 -461
  49. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/gutenberg/scraping.md +383 -383
  50. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/hackernews/scraping.md +243 -243
  51. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/howlongtobeat/scraping.md +473 -473
  52. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/imdb/scraping.md +271 -271
  53. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/itch-io/scraping.md +436 -436
  54. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/job-boards/indeed-glassdoor.md +1021 -1021
  55. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/letterboxd/scraping.md +349 -349
  56. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/linkedin/invitation-manager.md +109 -109
  57. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/loom/folder-enumeration.md +170 -170
  58. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/macrotrends/scraping.md +537 -537
  59. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/medium/article-hydration.md +120 -120
  60. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/medium/scraping.md +414 -414
  61. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/metacritic/scraping.md +477 -477
  62. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/musicbrainz/scraping.md +478 -478
  63. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/nasa/scraping.md +339 -339
  64. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/news-aggregation/multi-source.md +205 -205
  65. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/open-library/scraping.md +472 -472
  66. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/openalex/scraping.md +470 -470
  67. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/openstreetmap/scraping.md +490 -490
  68. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/package-registries/npm-pypi.md +478 -478
  69. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/polymarket/scraping.md +234 -234
  70. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/producthunt/scraping.md +307 -307
  71. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/pubmed/scraping.md +421 -421
  72. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/quora/scraping.md +364 -364
  73. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/rawg/scraping.md +352 -352
  74. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/reddit/scraping.md +124 -124
  75. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/rest-countries/scraping.md +233 -233
  76. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/sec-edgar/scraping.md +361 -361
  77. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/README.md +36 -36
  78. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/embedded-apps.md +72 -72
  79. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/knowledge-base.md +109 -109
  80. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/polaris-inputs.md +137 -137
  81. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/soundcloud/scraping.md +362 -362
  82. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/spotify/scraping.md +339 -339
  83. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/stackoverflow/scraping.md +435 -435
  84. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/steam/scraping.md +575 -575
  85. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/substack/scraping.md +338 -338
  86. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/thetechgeeks/pricing.md +52 -52
  87. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/tiktok/upload.md +107 -107
  88. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/tradingview/scraping.md +309 -309
  89. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/trello/boards-and-lists.md +88 -88
  90. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/trustpilot/scraping.md +375 -375
  91. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/walmart/scraping.md +444 -444
  92. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/wayback-machine/scraping.md +306 -306
  93. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/weather/scraping.md +398 -398
  94. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/wellfound/scraping.md +596 -596
  95. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/world-bank/scraping.md +356 -356
  96. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/xiaohongshu/scraping.md +84 -84
  97. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/youtube/scraping.md +418 -418
  98. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/zillow/scraping.md +433 -433
  99. package/dist/extensions/builtin/browser/browser.md +73 -73
  100. package/dist/extensions/builtin/browser/install.md +142 -142
  101. package/dist/extensions/builtin/browser/interaction-skills/connection.md +48 -48
  102. package/dist/extensions/builtin/browser/interaction-skills/cookies.md +3 -3
  103. package/dist/extensions/builtin/browser/interaction-skills/cross-origin-iframes.md +3 -3
  104. package/dist/extensions/builtin/browser/interaction-skills/dialogs.md +64 -64
  105. package/dist/extensions/builtin/browser/interaction-skills/downloads.md +3 -3
  106. package/dist/extensions/builtin/browser/interaction-skills/drag-and-drop.md +3 -3
  107. package/dist/extensions/builtin/browser/interaction-skills/dropdowns.md +3 -3
  108. package/dist/extensions/builtin/browser/interaction-skills/iframes.md +3 -3
  109. package/dist/extensions/builtin/browser/interaction-skills/network-requests.md +3 -3
  110. package/dist/extensions/builtin/browser/interaction-skills/print-as-pdf.md +3 -3
  111. package/dist/extensions/builtin/browser/interaction-skills/profile-sync.md +90 -90
  112. package/dist/extensions/builtin/browser/interaction-skills/screenshots.md +17 -17
  113. package/dist/extensions/builtin/browser/interaction-skills/scrolling.md +3 -3
  114. package/dist/extensions/builtin/browser/interaction-skills/shadow-dom.md +3 -3
  115. package/dist/extensions/builtin/browser/interaction-skills/tabs.md +69 -69
  116. package/dist/extensions/builtin/browser/interaction-skills/uploads.md +1 -1
  117. package/dist/extensions/builtin/browser/interaction-skills/viewport.md +3 -3
  118. package/dist/extensions/builtin/browser/src/browser_harness/AGENT.md +15 -15
  119. package/dist/extensions/builtin/browser/src/browser_harness/__init__.py +8 -8
  120. package/dist/extensions/builtin/browser/src/browser_harness/_ipc.py +90 -90
  121. package/dist/extensions/builtin/browser/src/browser_harness/admin.py +722 -722
  122. package/dist/extensions/builtin/browser/src/browser_harness/daemon.py +328 -328
  123. package/dist/extensions/builtin/browser/src/browser_harness/helpers.py +396 -396
  124. package/dist/extensions/builtin/browser/src/browser_harness/run.py +103 -103
  125. package/dist/extensions/builtin/discipline/skills/brainstorming/SKILL.md +33 -33
  126. package/dist/extensions/builtin/discipline/skills/executing-plans/SKILL.md +25 -25
  127. package/dist/extensions/builtin/discipline/skills/finishing-development-branch/SKILL.md +25 -25
  128. package/dist/extensions/builtin/discipline/skills/receiving-code-review/SKILL.md +22 -22
  129. package/dist/extensions/builtin/discipline/skills/requesting-code-review/SKILL.md +31 -31
  130. package/dist/extensions/builtin/discipline/skills/systematic-debugging/SKILL.md +28 -28
  131. package/dist/extensions/builtin/discipline/skills/test-driven-development/SKILL.md +32 -32
  132. package/dist/extensions/builtin/discipline/skills/using-git-worktrees/SKILL.md +25 -25
  133. package/dist/extensions/builtin/discipline/skills/verification-before-completion/SKILL.md +27 -27
  134. package/dist/extensions/builtin/discipline/skills/writing-plans/SKILL.md +26 -26
  135. package/dist/extensions/builtin/goal/README.md +67 -67
  136. package/dist/extensions/builtin/goal/goal-controller.d.ts +39 -10
  137. package/dist/extensions/builtin/goal/goal-controller.js +1 -1
  138. package/dist/extensions/builtin/goal/goal-format.js +1 -1
  139. package/dist/extensions/builtin/goal/goal-prompts.d.ts +2 -0
  140. package/dist/extensions/builtin/goal/goal-prompts.js +5 -4
  141. package/dist/extensions/builtin/goal/goal-store.js +1 -1
  142. package/dist/extensions/builtin/goal/index.d.ts +1 -1
  143. package/dist/extensions/builtin/goal/index.js +10 -7
  144. package/dist/extensions/builtin/grub/README.md +112 -112
  145. package/dist/extensions/builtin/link-world/agent-workspace/README.md +16 -16
  146. package/dist/extensions/builtin/link-world/index.js +6 -6
  147. package/dist/extensions/builtin/link-world/internet-search/internet-search.md +65 -65
  148. package/dist/extensions/builtin/link-world/link-world-agent.md +82 -82
  149. package/dist/extensions/builtin/link-world/linkworld.md +313 -313
  150. package/dist/extensions/builtin/link-world/{network-routing.md → network-routing/network-routing.md} +67 -67
  151. package/dist/extensions/builtin/loop/README.md +92 -92
  152. package/dist/extensions/builtin/mcp/figma-design.md +68 -68
  153. package/dist/extensions/builtin/mcp/mcp-management.md +85 -85
  154. package/dist/extensions/builtin/plan/index.js +1 -1
  155. package/dist/extensions/builtin/recap/AGENT.md +15 -15
  156. package/dist/extensions/builtin/sal/README.md +72 -72
  157. package/dist/extensions/builtin/security-audit/README.md +289 -289
  158. package/dist/extensions/builtin/task/task-store.d.ts +4 -0
  159. package/dist/extensions/builtin/task/task-store.js +1 -1
  160. package/dist/extensions/builtin/team/AGENT.md +112 -112
  161. package/dist/extensions/builtin/team/TESTING.md +299 -299
  162. package/dist/extensions/builtin/token-save/README.md +56 -56
  163. package/dist/extensions/optional/AGENT.md +10 -10
  164. package/dist/index.d.ts +5 -30
  165. package/dist/index.js +1 -1
  166. package/dist/models.d.ts +7 -0
  167. package/dist/models.js +1 -0
  168. package/dist/modes/interactive/components/footer.js +1 -1
  169. package/dist/modes/interactive/components/task-status-panel.d.ts +36 -0
  170. package/dist/modes/interactive/components/task-status-panel.js +1 -0
  171. package/dist/modes/interactive/controllers/stream-render-controller.d.ts +7 -0
  172. package/dist/modes/interactive/controllers/stream-render-controller.js +2 -2
  173. package/dist/modes/interactive/interactive-mode.js +40 -40
  174. package/dist/modes/interactive/state/interactive-state.d.ts +2 -0
  175. package/dist/modes/interactive/state/interactive-state.js +1 -1
  176. package/dist/modes/interactive/theme/dark.json +85 -85
  177. package/dist/modes/interactive/theme/light.json +84 -84
  178. package/dist/modes/interactive/theme/theme-schema.json +335 -335
  179. package/dist/modes/interactive/theme/warm.json +81 -81
  180. package/dist/node_modules/@pencil-agent/ai/dist/cli.js +0 -0
  181. package/dist/node_modules/@pencil-agent/ai/dist/models.generated.js +1 -1
  182. package/dist/node_modules/@pencil-agent/ai/dist/providers/anthropic.js +2 -2
  183. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-completions.js +5 -5
  184. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-responses.js +1 -1
  185. package/dist/node_modules/@pencil-agent/ai/dist/stream.js +1 -1
  186. package/dist/packages/protocol/src/commands.d.ts +33 -0
  187. package/dist/packages/protocol/src/flags.d.ts +20 -0
  188. package/dist/packages/protocol/src/hooks.d.ts +17 -0
  189. package/dist/packages/protocol/src/hooks.js +0 -0
  190. package/dist/packages/{extension-sdk → protocol}/src/index.d.ts +7 -4
  191. package/dist/packages/protocol/src/index.js +1 -0
  192. package/dist/packages/{extension-sdk → protocol}/src/lifecycle.d.ts +15 -27
  193. package/dist/packages/protocol/src/lifecycle.js +0 -0
  194. package/dist/packages/{extension-sdk → protocol}/src/tools.d.ts +1 -1
  195. package/dist/packages/protocol/src/tools.js +0 -0
  196. package/dist/public-config.d.ts +12 -0
  197. package/dist/public-config.js +1 -0
  198. package/dist/runtime.d.ts +9 -0
  199. package/dist/runtime.js +1 -0
  200. package/dist/session-compaction.d.ts +7 -0
  201. package/dist/session-compaction.js +1 -0
  202. package/dist/session.d.ts +7 -0
  203. package/dist/session.js +1 -0
  204. package/dist/skills.d.ts +7 -0
  205. package/dist/skills.js +1 -0
  206. package/dist/tools.d.ts +7 -0
  207. package/dist/tools.js +1 -0
  208. package/docs/ACP/345/215/217/350/256/256/351/233/206/346/210/220/345/274/200/345/217/221/346/226/207/346/241/243.md +851 -0
  209. package/docs/SDK-TESTING.md +364 -0
  210. package/docs/codex-goal-command-impl.md +1055 -1055
  211. package/docs/codex-goal-vs-grub.md +500 -500
  212. package/docs/custom-provider.md +27 -27
  213. package/docs/extensions.md +27 -27
  214. package/docs/keybindings.md +27 -27
  215. package/docs/loop /351/207/215/346/236/204/345/256/214/346/210/220/346/200/273/347/273/223.md" +250 -250
  216. package/docs/loop /351/207/215/346/236/204/345/256/214/346/210/220/346/212/245/345/221/212.md" +122 -122
  217. package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210.md" +1222 -1222
  218. package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210/345/256/236/347/216/260/346/212/245/345/221/212.md" +158 -158
  219. package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210/345/257/271/346/257/224/345/210/206/346/236/220.md" +128 -128
  220. package/docs/loop /351/207/215/346/236/204/350/256/241/345/210/222.md" +320 -320
  221. package/docs/loop-usage-examples.md +214 -214
  222. package/docs/mem-core/346/212/200/346/234/257/346/226/207/346/241/243.md +593 -0
  223. package/docs/models.md +27 -27
  224. package/docs/packages.md +27 -27
  225. package/docs/pi-design-philosophy.md +457 -457
  226. package/docs/planmode.md +1987 -1987
  227. package/docs/prompt-templates.md +27 -27
  228. package/docs/providers.md +27 -27
  229. package/docs/sdk.md +27 -27
  230. package/docs/skills.md +27 -27
  231. package/docs/startup-performance-optimization.md +301 -0
  232. package/docs/themes.md +27 -27
  233. package/docs/tui.md +27 -27
  234. package/docs//350/256/244/347/237/245/345/234/260/345/233/276.md +47 -0
  235. package/package.json +190 -162
  236. package/dist/packages/extension-sdk/src/index.js +0 -1
  237. package/docs/cc-agent-design.md +0 -1297
  238. package/docs/cc-tui-design.md +0 -1333
  239. package/docs//345/257/271/346/240/207Claude-Code.md +0 -1775
  240. /package/dist/packages/{extension-sdk/src/lifecycle.js → protocol/src/commands.js} +0 -0
  241. /package/dist/packages/{extension-sdk/src/tools.js → protocol/src/flags.js} +0 -0
@@ -1,73 +1,73 @@
1
- ---
2
- name: browser
3
- description: Direct browser control via NanoPencil's built-in Browser Harness. Use when the user wants to automate, scrape, test, or interact with web pages.
4
- ---
5
-
6
- # Browser Harness
7
-
8
- NanoPencil includes a vendored Browser Harness CDP bridge. Use the `browser` tool for normal work and `browser_admin` or `/browser` for install, setup, and diagnostics.
9
-
10
- For current facts or general web research, prefer NanoPencil's `web_search` tool first. If the user already has a target URL and only needs the content, prefer `web_fetch`. Use `browser` when the task requires interacting with a page.
11
-
12
- ## Core Tool Shape
13
-
14
- ```json
15
- {
16
- "code": "new_tab('https://example.com')\nwait_for_load()\nprint(page_info())",
17
- "timeout": 120
18
- }
19
- ```
20
-
21
- Common helpers are pre-imported inside the Python snippet:
22
-
23
- - `new_tab(url)`, `goto_url(url)`, `wait_for_load()`, `page_info()`
24
- - `capture_screenshot(...)`
25
- - `click_at_xy(x, y)`, `type_text(text)`, `press_key(key)`, `scroll(x, y)`
26
- - `js(expression)`, `cdp(method, **params)`, `drain_events()`
27
- - `list_tabs()`, `switch_tab(target)`, `current_tab()`, `ensure_real_tab()`
28
- - `upload_file(selector, path)`, `http_get(url, headers=None)`
29
- - Remote helpers: `start_remote_daemon()`, `stop_remote_daemon()`, `list_cloud_profiles()`, `sync_local_profile()`
30
-
31
- Treat the list above as the common surface, not a full inventory. If you need something lower-level, use raw `cdp(...)` or inspect the vendored helper module.
32
-
33
- First navigation should be `new_tab(url)`, not `goto_url(url)`, so the user's current tab is not overwritten.
34
-
35
- ## Workflow
36
-
37
- 1. If Python dependencies are missing, run `browser_admin` with `{ "action": "install" }` or `/browser install`.
38
- 2. For setup or connection problems, run `browser_admin` with `{ "action": "doctor" }` or `/browser status`.
39
- 3. If the daemon is not attached, run `browser_admin` with `{ "action": "setup" }` or `/browser setup`.
40
- 4. If the user only needs knowledge retrieval, use `web_search` instead of browser automation.
41
- 5. For a page interaction task, search `.nanopencil/browser-workspace/domain-skills/` first for site-specific knowledge.
42
- 6. Use screenshots to understand and verify visible browser state.
43
- 7. After every meaningful action, verify with `capture_screenshot()` or `page_info()`.
44
-
45
- ## Editable Workspace
46
-
47
- NanoPencil copies the bundled Browser Harness workspace to:
48
-
49
- ```text
50
- .nanopencil/browser-workspace/
51
- ```
52
-
53
- Use this project-local workspace for reusable browser knowledge:
54
-
55
- - `agent_helpers.py` for task-specific helper functions.
56
- - `domain-skills/<site>/` for durable site knowledge.
57
-
58
- If you learn a reusable site pattern, update the relevant domain skill before finishing. Capture selectors, URL patterns, private APIs, waits, framework quirks, and traps. Do not write secrets, cookies, session tokens, pixel-only instructions, or run narration.
59
-
60
- ## Tactics
61
-
62
- - Prefer screenshot-driven coordinate clicks for visible UI: `capture_screenshot()` -> inspect image -> `click_at_xy(x, y)` -> screenshot again.
63
- - Drop to DOM/JS only when the target has no useful visible geometry.
64
- - Use `http_get()` for static pages or APIs instead of spending browser time.
65
- - If redirected to an auth wall, stop and ask the user. Do not type credentials from screenshots.
66
- - For raw CDP, use `cdp("Domain.method", param=value)`.
67
-
68
- ## Interaction Skills
69
-
70
- When a mechanic gets tricky, consult the bundled interaction skills:
71
-
72
- - cookies, dialogs, downloads, drag-and-drop, dropdowns, iframes, cross-origin iframes
73
- - network requests, print as PDF, profile sync, screenshots, scrolling, shadow DOM, tabs, uploads, viewport
1
+ ---
2
+ name: browser
3
+ description: Direct browser control via NanoPencil's built-in Browser Harness. Use when the user wants to automate, scrape, test, or interact with web pages.
4
+ ---
5
+
6
+ # Browser Harness
7
+
8
+ NanoPencil includes a vendored Browser Harness CDP bridge. Use the `browser` tool for normal work and `browser_admin` or `/browser` for install, setup, and diagnostics.
9
+
10
+ For current facts or general web research, prefer NanoPencil's `web_search` tool first. If the user already has a target URL and only needs the content, prefer `web_fetch`. Use `browser` when the task requires interacting with a page.
11
+
12
+ ## Core Tool Shape
13
+
14
+ ```json
15
+ {
16
+ "code": "new_tab('https://example.com')\nwait_for_load()\nprint(page_info())",
17
+ "timeout": 120
18
+ }
19
+ ```
20
+
21
+ Common helpers are pre-imported inside the Python snippet:
22
+
23
+ - `new_tab(url)`, `goto_url(url)`, `wait_for_load()`, `page_info()`
24
+ - `capture_screenshot(...)`
25
+ - `click_at_xy(x, y)`, `type_text(text)`, `press_key(key)`, `scroll(x, y)`
26
+ - `js(expression)`, `cdp(method, **params)`, `drain_events()`
27
+ - `list_tabs()`, `switch_tab(target)`, `current_tab()`, `ensure_real_tab()`
28
+ - `upload_file(selector, path)`, `http_get(url, headers=None)`
29
+ - Remote helpers: `start_remote_daemon()`, `stop_remote_daemon()`, `list_cloud_profiles()`, `sync_local_profile()`
30
+
31
+ Treat the list above as the common surface, not a full inventory. If you need something lower-level, use raw `cdp(...)` or inspect the vendored helper module.
32
+
33
+ First navigation should be `new_tab(url)`, not `goto_url(url)`, so the user's current tab is not overwritten.
34
+
35
+ ## Workflow
36
+
37
+ 1. If Python dependencies are missing, run `browser_admin` with `{ "action": "install" }` or `/browser install`.
38
+ 2. For setup or connection problems, run `browser_admin` with `{ "action": "doctor" }` or `/browser status`.
39
+ 3. If the daemon is not attached, run `browser_admin` with `{ "action": "setup" }` or `/browser setup`.
40
+ 4. If the user only needs knowledge retrieval, use `web_search` instead of browser automation.
41
+ 5. For a page interaction task, search `.nanopencil/browser-workspace/domain-skills/` first for site-specific knowledge.
42
+ 6. Use screenshots to understand and verify visible browser state.
43
+ 7. After every meaningful action, verify with `capture_screenshot()` or `page_info()`.
44
+
45
+ ## Editable Workspace
46
+
47
+ NanoPencil copies the bundled Browser Harness workspace to:
48
+
49
+ ```text
50
+ .nanopencil/browser-workspace/
51
+ ```
52
+
53
+ Use this project-local workspace for reusable browser knowledge:
54
+
55
+ - `agent_helpers.py` for task-specific helper functions.
56
+ - `domain-skills/<site>/` for durable site knowledge.
57
+
58
+ If you learn a reusable site pattern, update the relevant domain skill before finishing. Capture selectors, URL patterns, private APIs, waits, framework quirks, and traps. Do not write secrets, cookies, session tokens, pixel-only instructions, or run narration.
59
+
60
+ ## Tactics
61
+
62
+ - Prefer screenshot-driven coordinate clicks for visible UI: `capture_screenshot()` -> inspect image -> `click_at_xy(x, y)` -> screenshot again.
63
+ - Drop to DOM/JS only when the target has no useful visible geometry.
64
+ - Use `http_get()` for static pages or APIs instead of spending browser time.
65
+ - If redirected to an auth wall, stop and ask the user. Do not type credentials from screenshots.
66
+ - For raw CDP, use `cdp("Domain.method", param=value)`.
67
+
68
+ ## Interaction Skills
69
+
70
+ When a mechanic gets tricky, consult the bundled interaction skills:
71
+
72
+ - cookies, dialogs, downloads, drag-and-drop, dropdowns, iframes, cross-origin iframes
73
+ - network requests, print as PDF, profile sync, screenshots, scrolling, shadow DOM, tabs, uploads, viewport
@@ -1,142 +1,142 @@
1
- ---
2
- name: browser-install
3
- description: Install and bootstrap browser-harness into the current agent, then connect it to the user's real Chrome with minimal prompting.
4
- ---
5
-
6
- # browser-harness install
7
-
8
- Use this file only for first-time install, reconnect, or cold-start browser bootstrap. For day-to-day browser work, read `SKILL.md`. Task-specific edits belong in `agent-workspace/agent_helpers.py` and `agent-workspace/domain-skills/`.
9
-
10
- ## Install prompt contract
11
-
12
- When you open a setup or verification tab, activate it so the user can actually see the active browser tab.
13
-
14
- ## Best everyday setup
15
-
16
- Clone the repo once into a durable location, then install it as an editable tool so `browser-harness` works from any directory:
17
-
18
- ```bash
19
- git clone https://github.com/browser-use/browser-harness
20
- cd browser-harness
21
- uv tool install -e .
22
- command -v browser-harness
23
- ```
24
-
25
- That keeps the command global while still pointing at the real repo checkout, so when the agent edits `agent-workspace/agent_helpers.py` the next `browser-harness` uses the new code immediately. Prefer a stable path like `~/Developer/browser-harness`, not `/tmp`.
26
-
27
- ## Make it global for the current agent
28
-
29
- After the repo is installed, register this repo's `SKILL.md` with the agent you are using:
30
-
31
- - **Codex**: add this file as a global skill at `$CODEX_HOME/skills/browser-harness/SKILL.md` (often `~/.codex/skills/browser-harness/SKILL.md`). A symlink to this repo's `SKILL.md` is fine.
32
- - **Claude Code**: add an import to `~/.claude/CLAUDE.md` that points at this repo's `SKILL.md`, for example `@~/src/browser-harness/SKILL.md`.
33
-
34
- Codex command:
35
-
36
- ```bash
37
- mkdir -p "${CODEX_HOME:-$HOME/.codex}/skills/browser-harness" && ln -sf "$PWD/SKILL.md" "${CODEX_HOME:-$HOME/.codex}/skills/browser-harness/SKILL.md"
38
- ```
39
-
40
- That makes new Codex or Claude Code sessions in other folders load the runtime browser harness instructions automatically. An empty `~/.codex/skills/browser-harness/` directory is fine; the symlink command above populates it.
41
-
42
- ## Browser bootstrap
43
-
44
- Prefer `browser-harness --setup` — it runs the full attach-and-escalate flow below as one interactive command. The manual steps that follow are only for when `--setup` is unavailable or you need to debug a specific failure.
45
-
46
- 1. Run `uv sync`.
47
- If `browser-harness` is still missing after that, run `command -v browser-harness >/dev/null || uv tool install -e .`.
48
- 2. First try the harness directly. If this works, skip manual browser setup:
49
-
50
- ```bash
51
- uv run browser-harness -c 'print(page_info())'
52
- ```
53
-
54
- Reuse an existing healthy daemon if it is already responding. Do not kill it during setup unless the attach is clearly stale and you are confident no other agent is using the same `BU_NAME`. For parallel agents, use distinct `BU_NAME`s so they do not fight over the same default session.
55
-
56
- 3. If it failed, **read the error and escalate from there — do not assume you need `chrome://inspect`**. The remote-debugging checkbox is per-profile sticky in Chrome, so any profile that has had it toggled on once will auto-enable CDP on every future launch; the inspect page is only needed the first time per profile.
57
-
58
- - **No Chrome process running** → just start Chrome and re-run the harness. On macOS: `open -a "Google Chrome"`. Do *not* navigate to `chrome://inspect` yet — if the user has ever ticked the checkbox on this profile, the harness will attach on its own.
59
- - **`DevToolsActivePort` missing or empty after Chrome is up** → remote-debugging has never been enabled on this profile. *This* is when you open `chrome://inspect/#remote-debugging` and ask the user to tick the checkbox and click `Allow`. Once ticked, the setting sticks.
60
- - **Port present but `connection refused` / `DevTools not live yet` / `/json/version` 404** → Chrome is mid-startup. Just keep polling for up to 30 seconds; do not restart Chrome and do not open the inspect page.
61
- - **`no close frame received or sent` / stale websocket** → the daemon (not Chrome) is the problem. Run `restart_daemon()` once and retry — see step 7 below.
62
-
63
- When you do need to open the inspect page on macOS and Chrome is already running, prefer AppleScript so it reuses the current profile instead of going through the picker:
64
-
65
- ```bash
66
- osascript -e 'tell application "Google Chrome" to activate' \
67
- -e 'tell application "Google Chrome" to open location "chrome://inspect/#remote-debugging"'
68
- ```
69
-
70
- On Linux: open that URL manually in the existing Chrome window.
71
- If Chrome shows the profile picker first, tell the user to choose their normal profile, *then* (only if `DevToolsActivePort` is still missing) open the inspect page in that profile. Keep polling instead of waiting for the user to type a follow-up.
72
- 4. Be explicit with the user about the two possible Chrome actions: choose their normal profile if the profile picker is open, and in the remote-debugging tab tick the checkbox and click `Allow` once if Chrome shows it.
73
- 5. Try to do everything yourself. Only ask the user to do something if it is truly necessary, like selecting the Chrome profile or clicking `Allow`. While the user is doing that, sleep and check every 3 seconds whether it is completed. After asking, keep retrying for at least 30 seconds even if you see connection-refused, stale websocket, or other weird transient attach errors.
74
- 6. If setup still lands on the profile picker, have the user choose their normal profile, then (only if `DevToolsActivePort` is still missing) open `chrome://inspect/#remote-debugging` in that profile and keep polling instead of restarting the explanation. As soon as attach succeeds, continue immediately with the verification task without asking again.
75
- 7. Verify with:
76
-
77
- ```bash
78
- uv run browser-harness -c "$(cat <<'PY'
79
- goto_url("https://github.com/browser-use/browser-harness")
80
- wait_for_load()
81
- print(page_info())
82
- PY
83
- )"
84
- ```
85
-
86
- If that fails with a stale websocket or stale socket, restart the daemon once and retry:
87
-
88
- ```bash
89
- uv run python - <<'PY'
90
- from browser_harness.admin import restart_daemon
91
- restart_daemon()
92
- PY
93
- ```
94
-
95
- If restart_daemon() also hangs, kill Chrome entirely, clean sockets, and reopen:
96
-
97
- ```bash
98
- pkill -9 -f "Google Chrome"
99
- rm -f /tmp/bu-default.sock /tmp/bu-default.pid
100
- open -a "Google Chrome"
101
- ```
102
-
103
- Wait 5 seconds, then reconnect. This resets all CDP state.
104
-
105
- 8. After install and browser bootstrap succeed, navigate to `https://github.com/browser-use/browser-harness` so the user can see the harness has attached to their browser. If the user is logged in to GitHub, **ask the user whether you should star the repo for them** as a quick demo that the interaction works — only click the star if they say yes. Then ask the user what they want to do next.
106
-
107
- ## Maintenance commands
108
-
109
- - browser-harness --doctor — show version, install mode, daemon and Chrome state, and whether an update is pending.
110
- - browser-harness --setup — re-run the full interactive browser-attach flow.
111
- - browser-harness --update -y — pull the latest version and restart the daemon. Run this yourself when you see the `[browser-harness] update available: X -> Y` banner — don't ask the user. The banner is rate-limited to once per day.
112
-
113
- ## Architecture
114
-
115
- ```text
116
- Chrome / Browser Use cloud -> CDP WS -> browser_harness.daemon -> /tmp/bu-<NAME>.sock -> browser_harness.run
117
- ```
118
-
119
- - Protocol is one JSON line each way.
120
- - Requests are {method, params, session_id} for CDP or {meta: ...} for daemon control.
121
- - Responses are {result} / {error} / {events} / {session_id}.
122
- - BU_NAME namespaces socket, pid, and log files.
123
- - BU_CDP_WS overrides local Chrome discovery for remote browsers.
124
- - BU_BROWSER_ID + BROWSER_USE_API_KEY lets the daemon stop a Browser Use cloud browser on shutdown.
125
-
126
- ## Keeping the harness current
127
-
128
- - On each run, `browser-harness` prints `[browser-harness] update available: X -> Y` (once per day) when a newer GitHub release exists.
129
- - When you see that banner, run `browser-harness --update -y` yourself — don't ask the user. It pulls the new code (`git pull --ff-only` for editable clones, `uv tool upgrade browser-harness` for PyPI installs) and stops the running daemon so the next call picks up the new code. With `-y` it won't prompt.
130
- - `--update` refuses to run on an editable clone with uncommitted changes. If that happens, tell the user and let them resolve the dirty worktree.
131
- - Use `browser-harness --doctor` any time to see version, install mode, daemon and Chrome state, and whether an update is pending.
132
-
133
- ## Cold-start reminders
134
-
135
- - Try attaching before asking the user to change anything. Decide what to escalate based on the harness's error message, not on whether Chrome is visibly running.
136
- - The remote-debugging checkbox is per-profile sticky in Chrome. If it has ever been ticked on a profile, just launching Chrome is enough — only navigate to `chrome://inspect/#remote-debugging` when `DevToolsActivePort` is genuinely missing.
137
- - The first connect may block on Chrome's `Allow` dialog, and Chrome may also stop first on the profile picker.
138
- - `DevToolsActivePort` can exist before the port is actually listening. Treat connection refused as "still enabling" and keep polling briefly.
139
- - If the port is listening but `/json/version` returns `404`, treat that as expected on newer Chrome builds and retry `browser-harness`.
140
- - Chrome may open the profile picker before any real tab exists.
141
- - On macOS, prefer AppleScript `open location` over `open -a ... URL` when Chrome is already running.
142
- - Microsoft Edge (including Beta/Dev/Canary) works too — substitute the app name; steps are identical.
1
+ ---
2
+ name: browser-install
3
+ description: Install and bootstrap browser-harness into the current agent, then connect it to the user's real Chrome with minimal prompting.
4
+ ---
5
+
6
+ # browser-harness install
7
+
8
+ Use this file only for first-time install, reconnect, or cold-start browser bootstrap. For day-to-day browser work, read `SKILL.md`. Task-specific edits belong in `agent-workspace/agent_helpers.py` and `agent-workspace/domain-skills/`.
9
+
10
+ ## Install prompt contract
11
+
12
+ When you open a setup or verification tab, activate it so the user can actually see the active browser tab.
13
+
14
+ ## Best everyday setup
15
+
16
+ Clone the repo once into a durable location, then install it as an editable tool so `browser-harness` works from any directory:
17
+
18
+ ```bash
19
+ git clone https://github.com/browser-use/browser-harness
20
+ cd browser-harness
21
+ uv tool install -e .
22
+ command -v browser-harness
23
+ ```
24
+
25
+ That keeps the command global while still pointing at the real repo checkout, so when the agent edits `agent-workspace/agent_helpers.py` the next `browser-harness` uses the new code immediately. Prefer a stable path like `~/Developer/browser-harness`, not `/tmp`.
26
+
27
+ ## Make it global for the current agent
28
+
29
+ After the repo is installed, register this repo's `SKILL.md` with the agent you are using:
30
+
31
+ - **Codex**: add this file as a global skill at `$CODEX_HOME/skills/browser-harness/SKILL.md` (often `~/.codex/skills/browser-harness/SKILL.md`). A symlink to this repo's `SKILL.md` is fine.
32
+ - **Claude Code**: add an import to `~/.claude/CLAUDE.md` that points at this repo's `SKILL.md`, for example `@~/src/browser-harness/SKILL.md`.
33
+
34
+ Codex command:
35
+
36
+ ```bash
37
+ mkdir -p "${CODEX_HOME:-$HOME/.codex}/skills/browser-harness" && ln -sf "$PWD/SKILL.md" "${CODEX_HOME:-$HOME/.codex}/skills/browser-harness/SKILL.md"
38
+ ```
39
+
40
+ That makes new Codex or Claude Code sessions in other folders load the runtime browser harness instructions automatically. An empty `~/.codex/skills/browser-harness/` directory is fine; the symlink command above populates it.
41
+
42
+ ## Browser bootstrap
43
+
44
+ Prefer `browser-harness --setup` — it runs the full attach-and-escalate flow below as one interactive command. The manual steps that follow are only for when `--setup` is unavailable or you need to debug a specific failure.
45
+
46
+ 1. Run `uv sync`.
47
+ If `browser-harness` is still missing after that, run `command -v browser-harness >/dev/null || uv tool install -e .`.
48
+ 2. First try the harness directly. If this works, skip manual browser setup:
49
+
50
+ ```bash
51
+ uv run browser-harness -c 'print(page_info())'
52
+ ```
53
+
54
+ Reuse an existing healthy daemon if it is already responding. Do not kill it during setup unless the attach is clearly stale and you are confident no other agent is using the same `BU_NAME`. For parallel agents, use distinct `BU_NAME`s so they do not fight over the same default session.
55
+
56
+ 3. If it failed, **read the error and escalate from there — do not assume you need `chrome://inspect`**. The remote-debugging checkbox is per-profile sticky in Chrome, so any profile that has had it toggled on once will auto-enable CDP on every future launch; the inspect page is only needed the first time per profile.
57
+
58
+ - **No Chrome process running** → just start Chrome and re-run the harness. On macOS: `open -a "Google Chrome"`. Do *not* navigate to `chrome://inspect` yet — if the user has ever ticked the checkbox on this profile, the harness will attach on its own.
59
+ - **`DevToolsActivePort` missing or empty after Chrome is up** → remote-debugging has never been enabled on this profile. *This* is when you open `chrome://inspect/#remote-debugging` and ask the user to tick the checkbox and click `Allow`. Once ticked, the setting sticks.
60
+ - **Port present but `connection refused` / `DevTools not live yet` / `/json/version` 404** → Chrome is mid-startup. Just keep polling for up to 30 seconds; do not restart Chrome and do not open the inspect page.
61
+ - **`no close frame received or sent` / stale websocket** → the daemon (not Chrome) is the problem. Run `restart_daemon()` once and retry — see step 7 below.
62
+
63
+ When you do need to open the inspect page on macOS and Chrome is already running, prefer AppleScript so it reuses the current profile instead of going through the picker:
64
+
65
+ ```bash
66
+ osascript -e 'tell application "Google Chrome" to activate' \
67
+ -e 'tell application "Google Chrome" to open location "chrome://inspect/#remote-debugging"'
68
+ ```
69
+
70
+ On Linux: open that URL manually in the existing Chrome window.
71
+ If Chrome shows the profile picker first, tell the user to choose their normal profile, *then* (only if `DevToolsActivePort` is still missing) open the inspect page in that profile. Keep polling instead of waiting for the user to type a follow-up.
72
+ 4. Be explicit with the user about the two possible Chrome actions: choose their normal profile if the profile picker is open, and in the remote-debugging tab tick the checkbox and click `Allow` once if Chrome shows it.
73
+ 5. Try to do everything yourself. Only ask the user to do something if it is truly necessary, like selecting the Chrome profile or clicking `Allow`. While the user is doing that, sleep and check every 3 seconds whether it is completed. After asking, keep retrying for at least 30 seconds even if you see connection-refused, stale websocket, or other weird transient attach errors.
74
+ 6. If setup still lands on the profile picker, have the user choose their normal profile, then (only if `DevToolsActivePort` is still missing) open `chrome://inspect/#remote-debugging` in that profile and keep polling instead of restarting the explanation. As soon as attach succeeds, continue immediately with the verification task without asking again.
75
+ 7. Verify with:
76
+
77
+ ```bash
78
+ uv run browser-harness -c "$(cat <<'PY'
79
+ goto_url("https://github.com/browser-use/browser-harness")
80
+ wait_for_load()
81
+ print(page_info())
82
+ PY
83
+ )"
84
+ ```
85
+
86
+ If that fails with a stale websocket or stale socket, restart the daemon once and retry:
87
+
88
+ ```bash
89
+ uv run python - <<'PY'
90
+ from browser_harness.admin import restart_daemon
91
+ restart_daemon()
92
+ PY
93
+ ```
94
+
95
+ If restart_daemon() also hangs, kill Chrome entirely, clean sockets, and reopen:
96
+
97
+ ```bash
98
+ pkill -9 -f "Google Chrome"
99
+ rm -f /tmp/bu-default.sock /tmp/bu-default.pid
100
+ open -a "Google Chrome"
101
+ ```
102
+
103
+ Wait 5 seconds, then reconnect. This resets all CDP state.
104
+
105
+ 8. After install and browser bootstrap succeed, navigate to `https://github.com/browser-use/browser-harness` so the user can see the harness has attached to their browser. If the user is logged in to GitHub, **ask the user whether you should star the repo for them** as a quick demo that the interaction works — only click the star if they say yes. Then ask the user what they want to do next.
106
+
107
+ ## Maintenance commands
108
+
109
+ - browser-harness --doctor — show version, install mode, daemon and Chrome state, and whether an update is pending.
110
+ - browser-harness --setup — re-run the full interactive browser-attach flow.
111
+ - browser-harness --update -y — pull the latest version and restart the daemon. Run this yourself when you see the `[browser-harness] update available: X -> Y` banner — don't ask the user. The banner is rate-limited to once per day.
112
+
113
+ ## Architecture
114
+
115
+ ```text
116
+ Chrome / Browser Use cloud -> CDP WS -> browser_harness.daemon -> /tmp/bu-<NAME>.sock -> browser_harness.run
117
+ ```
118
+
119
+ - Protocol is one JSON line each way.
120
+ - Requests are {method, params, session_id} for CDP or {meta: ...} for daemon control.
121
+ - Responses are {result} / {error} / {events} / {session_id}.
122
+ - BU_NAME namespaces socket, pid, and log files.
123
+ - BU_CDP_WS overrides local Chrome discovery for remote browsers.
124
+ - BU_BROWSER_ID + BROWSER_USE_API_KEY lets the daemon stop a Browser Use cloud browser on shutdown.
125
+
126
+ ## Keeping the harness current
127
+
128
+ - On each run, `browser-harness` prints `[browser-harness] update available: X -> Y` (once per day) when a newer GitHub release exists.
129
+ - When you see that banner, run `browser-harness --update -y` yourself — don't ask the user. It pulls the new code (`git pull --ff-only` for editable clones, `uv tool upgrade browser-harness` for PyPI installs) and stops the running daemon so the next call picks up the new code. With `-y` it won't prompt.
130
+ - `--update` refuses to run on an editable clone with uncommitted changes. If that happens, tell the user and let them resolve the dirty worktree.
131
+ - Use `browser-harness --doctor` any time to see version, install mode, daemon and Chrome state, and whether an update is pending.
132
+
133
+ ## Cold-start reminders
134
+
135
+ - Try attaching before asking the user to change anything. Decide what to escalate based on the harness's error message, not on whether Chrome is visibly running.
136
+ - The remote-debugging checkbox is per-profile sticky in Chrome. If it has ever been ticked on a profile, just launching Chrome is enough — only navigate to `chrome://inspect/#remote-debugging` when `DevToolsActivePort` is genuinely missing.
137
+ - The first connect may block on Chrome's `Allow` dialog, and Chrome may also stop first on the profile picker.
138
+ - `DevToolsActivePort` can exist before the port is actually listening. Treat connection refused as "still enabling" and keep polling briefly.
139
+ - If the port is listening but `/json/version` returns `404`, treat that as expected on newer Chrome builds and retry `browser-harness`.
140
+ - Chrome may open the profile picker before any real tab exists.
141
+ - On macOS, prefer AppleScript `open location` over `open -a ... URL` when Chrome is already running.
142
+ - Microsoft Edge (including Beta/Dev/Canary) works too — substitute the app name; steps are identical.
@@ -1,48 +1,48 @@
1
- # Connection & Tab Visibility
2
-
3
- ## The omnibox popup problem
4
-
5
- When Chrome opens fresh, the only CDP `type: "page"` targets are `chrome://inspect` and `chrome://omnibox-popup.top-chrome/` (a 1px invisible viewport). If the daemon attaches to the omnibox popup, all subsequent work — including `new_tab()` and `goto_url()` — happens on tabs that exist in CDP but may not be visible in the Chrome UI.
6
-
7
- The daemon's `attach_first_page()` handles this by creating an `about:blank` tab when no real pages exist. If you still end up on an invisible tab, use `switch_tab()` which calls `Target.activateTarget` to bring the tab to front.
8
-
9
- ## Startup sequence
10
-
11
- 1. Check if a daemon is already running with `daemon_alive()`
12
- 2. If stale sockets exist but daemon is dead, clean them up
13
- 3. List open tabs with `list_tabs()` to see what's available
14
- 4. `ensure_real_tab()` attaches to a real page
15
- 5. `switch_tab(target_id)` both attaches AND activates (brings to front)
16
-
17
- ```python
18
- if not daemon_alive():
19
- import os, ipc
20
- ipc.cleanup_endpoint("default")
21
- pid = ipc.pid_path("default")
22
- if pid.exists(): pid.unlink()
23
- ensure_daemon()
24
-
25
- tabs = list_tabs()
26
- for t in tabs:
27
- print(t["url"][:60])
28
-
29
- tab = ensure_real_tab()
30
- ```
31
-
32
- ## Bringing Chrome to front
33
-
34
- If Chrome is behind other windows or on another desktop:
35
-
36
- ```python
37
- import subprocess
38
- subprocess.run(["osascript", "-e", 'tell application "Google Chrome" to activate'])
39
- ```
40
-
41
- ## Navigating
42
-
43
- Prefer navigating an existing tab over `new_tab()`. Tabs created via CDP's `Target.createTarget` are visible but may open behind the active tab.
44
-
45
- ```python
46
- tab = ensure_real_tab()
47
- goto_url("https://example.com")
48
- ```
1
+ # Connection & Tab Visibility
2
+
3
+ ## The omnibox popup problem
4
+
5
+ When Chrome opens fresh, the only CDP `type: "page"` targets are `chrome://inspect` and `chrome://omnibox-popup.top-chrome/` (a 1px invisible viewport). If the daemon attaches to the omnibox popup, all subsequent work — including `new_tab()` and `goto_url()` — happens on tabs that exist in CDP but may not be visible in the Chrome UI.
6
+
7
+ The daemon's `attach_first_page()` handles this by creating an `about:blank` tab when no real pages exist. If you still end up on an invisible tab, use `switch_tab()` which calls `Target.activateTarget` to bring the tab to front.
8
+
9
+ ## Startup sequence
10
+
11
+ 1. Check if a daemon is already running with `daemon_alive()`
12
+ 2. If stale sockets exist but daemon is dead, clean them up
13
+ 3. List open tabs with `list_tabs()` to see what's available
14
+ 4. `ensure_real_tab()` attaches to a real page
15
+ 5. `switch_tab(target_id)` both attaches AND activates (brings to front)
16
+
17
+ ```python
18
+ if not daemon_alive():
19
+ import os, ipc
20
+ ipc.cleanup_endpoint("default")
21
+ pid = ipc.pid_path("default")
22
+ if pid.exists(): pid.unlink()
23
+ ensure_daemon()
24
+
25
+ tabs = list_tabs()
26
+ for t in tabs:
27
+ print(t["url"][:60])
28
+
29
+ tab = ensure_real_tab()
30
+ ```
31
+
32
+ ## Bringing Chrome to front
33
+
34
+ If Chrome is behind other windows or on another desktop:
35
+
36
+ ```python
37
+ import subprocess
38
+ subprocess.run(["osascript", "-e", 'tell application "Google Chrome" to activate'])
39
+ ```
40
+
41
+ ## Navigating
42
+
43
+ Prefer navigating an existing tab over `new_tab()`. Tabs created via CDP's `Target.createTarget` are visible but may open behind the active tab.
44
+
45
+ ```python
46
+ tab = ensure_real_tab()
47
+ goto_url("https://example.com")
48
+ ```
@@ -1,3 +1,3 @@
1
- # Cookies
2
-
3
- Document how to get cookies, save cookies, and set cookies without confusing browser state with page state.
1
+ # Cookies
2
+
3
+ Document how to get cookies, save cookies, and set cookies without confusing browser state with page state.
@@ -1,3 +1,3 @@
1
- # Cross-Origin Iframes
2
-
3
- Focus on `iframe_target(...)`, target attachment, and when compositor-level coordinate clicks are lower-friction than cross-target DOM work.
1
+ # Cross-Origin Iframes
2
+
3
+ Focus on `iframe_target(...)`, target attachment, and when compositor-level coordinate clicks are lower-friction than cross-target DOM work.