mcp-subagents-opencode 1.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 (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +602 -0
  3. package/build/config/timeouts.d.ts +9 -0
  4. package/build/config/timeouts.d.ts.map +1 -0
  5. package/build/config/timeouts.js +18 -0
  6. package/build/config/timeouts.js.map +1 -0
  7. package/build/helpers.d.ts +6 -0
  8. package/build/helpers.d.ts.map +1 -0
  9. package/build/helpers.js +47 -0
  10. package/build/helpers.js.map +1 -0
  11. package/build/index.d.ts +3 -0
  12. package/build/index.d.ts.map +1 -0
  13. package/build/index.js +245 -0
  14. package/build/index.js.map +1 -0
  15. package/build/models.d.ts +32 -0
  16. package/build/models.d.ts.map +1 -0
  17. package/build/models.js +58 -0
  18. package/build/models.js.map +1 -0
  19. package/build/server/register-notifications.d.ts +3 -0
  20. package/build/server/register-notifications.d.ts.map +1 -0
  21. package/build/server/register-notifications.js +77 -0
  22. package/build/server/register-notifications.js.map +1 -0
  23. package/build/server/register-resources.d.ts +3 -0
  24. package/build/server/register-resources.d.ts.map +1 -0
  25. package/build/server/register-resources.js +210 -0
  26. package/build/server/register-resources.js.map +1 -0
  27. package/build/server/register-retry-execution.d.ts +2 -0
  28. package/build/server/register-retry-execution.d.ts.map +1 -0
  29. package/build/server/register-retry-execution.js +28 -0
  30. package/build/server/register-retry-execution.js.map +1 -0
  31. package/build/server/register-tasks.d.ts +3 -0
  32. package/build/server/register-tasks.d.ts.map +1 -0
  33. package/build/server/register-tasks.js +52 -0
  34. package/build/server/register-tasks.js.map +1 -0
  35. package/build/server/register-tools.d.ts +3 -0
  36. package/build/server/register-tools.d.ts.map +1 -0
  37. package/build/server/register-tools.js +32 -0
  38. package/build/server/register-tools.js.map +1 -0
  39. package/build/server/resource-helpers.d.ts +21 -0
  40. package/build/server/resource-helpers.d.ts.map +1 -0
  41. package/build/server/resource-helpers.js +84 -0
  42. package/build/server/resource-helpers.js.map +1 -0
  43. package/build/services/account-manager.d.ts +88 -0
  44. package/build/services/account-manager.d.ts.map +1 -0
  45. package/build/services/account-manager.js +239 -0
  46. package/build/services/account-manager.js.map +1 -0
  47. package/build/services/claude-code-runner.d.ts +15 -0
  48. package/build/services/claude-code-runner.d.ts.map +1 -0
  49. package/build/services/claude-code-runner.js +475 -0
  50. package/build/services/claude-code-runner.js.map +1 -0
  51. package/build/services/client-context.d.ts +31 -0
  52. package/build/services/client-context.d.ts.map +1 -0
  53. package/build/services/client-context.js +44 -0
  54. package/build/services/client-context.js.map +1 -0
  55. package/build/services/exhaustion-fallback.d.ts +27 -0
  56. package/build/services/exhaustion-fallback.d.ts.map +1 -0
  57. package/build/services/exhaustion-fallback.js +30 -0
  58. package/build/services/exhaustion-fallback.js.map +1 -0
  59. package/build/services/fallback-orchestrator.d.ts +16 -0
  60. package/build/services/fallback-orchestrator.d.ts.map +1 -0
  61. package/build/services/fallback-orchestrator.js +48 -0
  62. package/build/services/fallback-orchestrator.js.map +1 -0
  63. package/build/services/opencode-client.d.ts +40 -0
  64. package/build/services/opencode-client.d.ts.map +1 -0
  65. package/build/services/opencode-client.js +147 -0
  66. package/build/services/opencode-client.js.map +1 -0
  67. package/build/services/opencode-spawner.d.ts +56 -0
  68. package/build/services/opencode-spawner.d.ts.map +1 -0
  69. package/build/services/opencode-spawner.js +426 -0
  70. package/build/services/opencode-spawner.js.map +1 -0
  71. package/build/services/output-file.d.ts +24 -0
  72. package/build/services/output-file.d.ts.map +1 -0
  73. package/build/services/output-file.js +90 -0
  74. package/build/services/output-file.js.map +1 -0
  75. package/build/services/progress-registry.d.ts +12 -0
  76. package/build/services/progress-registry.d.ts.map +1 -0
  77. package/build/services/progress-registry.js +97 -0
  78. package/build/services/progress-registry.js.map +1 -0
  79. package/build/services/question-registry.d.ts +79 -0
  80. package/build/services/question-registry.d.ts.map +1 -0
  81. package/build/services/question-registry.js +249 -0
  82. package/build/services/question-registry.js.map +1 -0
  83. package/build/services/retry-queue.d.ts +41 -0
  84. package/build/services/retry-queue.d.ts.map +1 -0
  85. package/build/services/retry-queue.js +195 -0
  86. package/build/services/retry-queue.js.map +1 -0
  87. package/build/services/sdk-client-manager.d.ts +149 -0
  88. package/build/services/sdk-client-manager.d.ts.map +1 -0
  89. package/build/services/sdk-client-manager.js +632 -0
  90. package/build/services/sdk-client-manager.js.map +1 -0
  91. package/build/services/sdk-session-adapter.d.ts +203 -0
  92. package/build/services/sdk-session-adapter.d.ts.map +1 -0
  93. package/build/services/sdk-session-adapter.js +1088 -0
  94. package/build/services/sdk-session-adapter.js.map +1 -0
  95. package/build/services/sdk-spawner.d.ts +42 -0
  96. package/build/services/sdk-spawner.d.ts.map +1 -0
  97. package/build/services/sdk-spawner.js +488 -0
  98. package/build/services/sdk-spawner.js.map +1 -0
  99. package/build/services/session-hooks.d.ts +24 -0
  100. package/build/services/session-hooks.d.ts.map +1 -0
  101. package/build/services/session-hooks.js +130 -0
  102. package/build/services/session-hooks.js.map +1 -0
  103. package/build/services/session-snapshot.d.ts +19 -0
  104. package/build/services/session-snapshot.d.ts.map +1 -0
  105. package/build/services/session-snapshot.js +203 -0
  106. package/build/services/session-snapshot.js.map +1 -0
  107. package/build/services/subscription-registry.d.ts +12 -0
  108. package/build/services/subscription-registry.d.ts.map +1 -0
  109. package/build/services/subscription-registry.js +27 -0
  110. package/build/services/subscription-registry.js.map +1 -0
  111. package/build/services/task-manager.d.ts +150 -0
  112. package/build/services/task-manager.d.ts.map +1 -0
  113. package/build/services/task-manager.js +765 -0
  114. package/build/services/task-manager.js.map +1 -0
  115. package/build/services/task-persistence.d.ts +29 -0
  116. package/build/services/task-persistence.d.ts.map +1 -0
  117. package/build/services/task-persistence.js +159 -0
  118. package/build/services/task-persistence.js.map +1 -0
  119. package/build/services/task-status-mapper.d.ts +21 -0
  120. package/build/services/task-status-mapper.d.ts.map +1 -0
  121. package/build/services/task-status-mapper.js +171 -0
  122. package/build/services/task-status-mapper.js.map +1 -0
  123. package/build/templates/index.d.ts +22 -0
  124. package/build/templates/index.d.ts.map +1 -0
  125. package/build/templates/index.js +147 -0
  126. package/build/templates/index.js.map +1 -0
  127. package/build/templates/overlays/coder-csharp.mdx +58 -0
  128. package/build/templates/overlays/coder-go.mdx +53 -0
  129. package/build/templates/overlays/coder-java.mdx +54 -0
  130. package/build/templates/overlays/coder-kotlin.mdx +56 -0
  131. package/build/templates/overlays/coder-nextjs.mdx +65 -0
  132. package/build/templates/overlays/coder-python.mdx +53 -0
  133. package/build/templates/overlays/coder-react.mdx +55 -0
  134. package/build/templates/overlays/coder-ruby.mdx +59 -0
  135. package/build/templates/overlays/coder-rust.mdx +48 -0
  136. package/build/templates/overlays/coder-supabase.mdx +268 -0
  137. package/build/templates/overlays/coder-supastarter.mdx +313 -0
  138. package/build/templates/overlays/coder-swift.mdx +56 -0
  139. package/build/templates/overlays/coder-tauri.mdx +566 -0
  140. package/build/templates/overlays/coder-triggerdev.mdx +296 -0
  141. package/build/templates/overlays/coder-typescript.mdx +45 -0
  142. package/build/templates/overlays/coder-vue.mdx +62 -0
  143. package/build/templates/overlays/planner-architecture.mdx +78 -0
  144. package/build/templates/overlays/planner-bugfix.mdx +36 -0
  145. package/build/templates/overlays/planner-feature.mdx +38 -0
  146. package/build/templates/overlays/planner-migration.mdx +50 -0
  147. package/build/templates/overlays/planner-refactor.mdx +57 -0
  148. package/build/templates/overlays/researcher-library.mdx +59 -0
  149. package/build/templates/overlays/researcher-performance.mdx +68 -0
  150. package/build/templates/overlays/researcher-security.mdx +86 -0
  151. package/build/templates/overlays/tester-graphql.mdx +191 -0
  152. package/build/templates/overlays/tester-playwright.mdx +621 -0
  153. package/build/templates/overlays/tester-rest.mdx +101 -0
  154. package/build/templates/overlays/tester-suite.mdx +177 -0
  155. package/build/templates/super-coder.mdx +529 -0
  156. package/build/templates/super-planner.mdx +568 -0
  157. package/build/templates/super-researcher.mdx +406 -0
  158. package/build/templates/super-tester.mdx +243 -0
  159. package/build/tools/answer-question.d.ts +30 -0
  160. package/build/tools/answer-question.d.ts.map +1 -0
  161. package/build/tools/answer-question.js +108 -0
  162. package/build/tools/answer-question.js.map +1 -0
  163. package/build/tools/cancel-task.d.ts +44 -0
  164. package/build/tools/cancel-task.d.ts.map +1 -0
  165. package/build/tools/cancel-task.js +144 -0
  166. package/build/tools/cancel-task.js.map +1 -0
  167. package/build/tools/send-message.d.ts +39 -0
  168. package/build/tools/send-message.d.ts.map +1 -0
  169. package/build/tools/send-message.js +124 -0
  170. package/build/tools/send-message.js.map +1 -0
  171. package/build/tools/shared-spawn.d.ts +56 -0
  172. package/build/tools/shared-spawn.d.ts.map +1 -0
  173. package/build/tools/shared-spawn.js +114 -0
  174. package/build/tools/shared-spawn.js.map +1 -0
  175. package/build/tools/spawn-agent.d.ts +85 -0
  176. package/build/tools/spawn-agent.d.ts.map +1 -0
  177. package/build/tools/spawn-agent.js +133 -0
  178. package/build/tools/spawn-agent.js.map +1 -0
  179. package/build/tools/spawn-coder.d.ts +70 -0
  180. package/build/tools/spawn-coder.d.ts.map +1 -0
  181. package/build/tools/spawn-coder.js +71 -0
  182. package/build/tools/spawn-coder.js.map +1 -0
  183. package/build/tools/spawn-planner.d.ts +70 -0
  184. package/build/tools/spawn-planner.d.ts.map +1 -0
  185. package/build/tools/spawn-planner.js +71 -0
  186. package/build/tools/spawn-planner.js.map +1 -0
  187. package/build/tools/spawn-researcher.d.ts +70 -0
  188. package/build/tools/spawn-researcher.d.ts.map +1 -0
  189. package/build/tools/spawn-researcher.js +70 -0
  190. package/build/tools/spawn-researcher.js.map +1 -0
  191. package/build/tools/spawn-task.d.ts +74 -0
  192. package/build/tools/spawn-task.d.ts.map +1 -0
  193. package/build/tools/spawn-task.js +107 -0
  194. package/build/tools/spawn-task.js.map +1 -0
  195. package/build/tools/spawn-tester.d.ts +70 -0
  196. package/build/tools/spawn-tester.d.ts.map +1 -0
  197. package/build/tools/spawn-tester.js +69 -0
  198. package/build/tools/spawn-tester.js.map +1 -0
  199. package/build/types.d.ts +101 -0
  200. package/build/types.d.ts.map +1 -0
  201. package/build/types.js +28 -0
  202. package/build/types.js.map +1 -0
  203. package/build/utils/brief-validator.d.ts +30 -0
  204. package/build/utils/brief-validator.d.ts.map +1 -0
  205. package/build/utils/brief-validator.js +254 -0
  206. package/build/utils/brief-validator.js.map +1 -0
  207. package/build/utils/format.d.ts +34 -0
  208. package/build/utils/format.d.ts.map +1 -0
  209. package/build/utils/format.js +55 -0
  210. package/build/utils/format.js.map +1 -0
  211. package/build/utils/sanitize.d.ts +240 -0
  212. package/build/utils/sanitize.d.ts.map +1 -0
  213. package/build/utils/sanitize.js +89 -0
  214. package/build/utils/sanitize.js.map +1 -0
  215. package/build/utils/task-id-generator.d.ts +10 -0
  216. package/build/utils/task-id-generator.d.ts.map +1 -0
  217. package/build/utils/task-id-generator.js +22 -0
  218. package/build/utils/task-id-generator.js.map +1 -0
  219. package/package.json +62 -0
@@ -0,0 +1,621 @@
1
+ ## PLAYWRIGHT BROWSER TESTING GUIDELINES
2
+
3
+ You are testing a **web application** using Playwright via the `playwright-cli` tool. This overlay provides battle-tested patterns for browser-based E2E testing.
4
+
5
+ **Command discovery:** Run `playwright-cli --help` for all commands. Run `playwright-cli --help <command>` for details on any specific command.
6
+
7
+ **ALWAYS clean up when done:** `playwright-cli session-stop-all`
8
+
9
+ ---
10
+
11
+ ### BOOTSTRAP
12
+
13
+ Run this ONCE at the start of any browser testing session:
14
+
15
+ ```bash
16
+ which playwright-cli || npm install -g @anthropic-ai/playwright-cli@latest
17
+ PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true npx playwright install chromium
18
+ playwright-cli session-stop 2>/dev/null # Kill stale sessions from crashed agents
19
+ playwright-cli config --browser=chromium
20
+ ```
21
+
22
+ **Why each step matters:**
23
+ - `which` check — skip reinstall if already present
24
+ - `PLAYWRIGHT_SKIP_*` — prevents false install failures in containers and non-standard environments
25
+ - `session-stop` — a stale session from a previous run blocks everything. This is silent if nothing is running
26
+ - `config` — ensures chromium is the active browser
27
+
28
+ After bootstrap, `playwright-cli open <url>` will work. The session is a background daemon that persists between commands.
29
+
30
+ ---
31
+
32
+ ### TRAPS THAT WILL DERAIL YOU
33
+
34
+ Read these BEFORE your first command. These come from real testing sessions where assumptions failed. Each one will save you from getting stuck.
35
+
36
+ #### TRAP 1: Element refs die after ANY page change
37
+ When you run `snapshot`, you get refs like `e1`, `e23`. These refs are tied to THAT specific snapshot. After `open`, `click` that navigates, `hover`, `reload`, `tab-select`, `go-back`, or ANY action that changes the page — ALL refs are stale.
38
+
39
+ **The scariest case:** After a session restart, the same ref number (e.g. `e426`) can point to a COMPLETELY DIFFERENT element. No error — you just interact with the wrong thing.
40
+
41
+ **Rule:** After any action that might change the page, take a new `snapshot` before using refs. The safe pattern is always: `action → snapshot → use new refs`.
42
+
43
+ #### TRAP 2: `tab-new <url>` does NOT navigate
44
+ ```bash
45
+ tab-new https://example.com
46
+ # Result: new tab opens at about:blank — NOT example.com
47
+ ```
48
+ This is a silent failure — no error. You'll snapshot `about:blank` and wonder why the page is empty.
49
+
50
+ **Fix:** Always use two steps:
51
+ ```bash
52
+ tab-new
53
+ open https://example.com
54
+ ```
55
+
56
+ #### TRAP 3: `close` KILLS the entire session
57
+ ```bash
58
+ close
59
+ # Result: "Session 'default' stopped." — ALL cookies, localStorage, browser state GONE
60
+ ```
61
+ If you use `close` thinking you're closing a tab, you destroy everything. Any login state, any test setup — gone.
62
+
63
+ **Fix:** NEVER use `close`. Use `tab-close <index>` to close individual tabs. Use `session-stop` when you're truly done.
64
+
65
+ #### TRAP 4: console and network return FILE PATHS, not content
66
+ ```bash
67
+ console error
68
+ # Output: "- [Console](.playwright-cli/console-xxx.log)"
69
+ ```
70
+ The path IS the output. You MUST read that file to see the actual errors.
71
+
72
+ #### TRAP 5: Snapshots don't show form values or focus state
73
+ You filled a form with `fill e53 "John"`. The snapshot YAML will NOT show "John" in the field. You cannot verify form state by reading the snapshot.
74
+
75
+ **Fix for form values:** `eval "(el) => el.value" e53` — returns "John"
76
+ **Fix for focus:** `eval "() => document.activeElement?.tagName"` — snapshots never show which element has keyboard focus.
77
+
78
+ #### TRAP 6: eval only fails on DOM nodes
79
+ Returning DOM elements gives useless `"ref: <Node>"`. But primitives, plain objects, and arrays all work fine:
80
+ ```bash
81
+ eval "() => 42" # works: 42
82
+ eval "() => document.title" # works: "My Page"
83
+ eval "() => ({ links: 92, images: 14 })" # works: { links: 92, images: 14 }
84
+ eval "() => [...document.querySelectorAll('a')].map(a => a.href)" # works: ["url1", ...]
85
+ eval "() => document.querySelectorAll('a')" # FAILS: { "0": "ref: <Node>", ... }
86
+ ```
87
+ **Rule:** Don't wrap everything in `JSON.stringify()` — only use `.map()` to extract data from NodeLists.
88
+
89
+ #### TRAP 7: Multi-tab "Page URL" header is WRONG
90
+ When using multiple tabs, the "Page" section in snapshot output shows the WRONG tab's URL. Only the "Open tabs" section correctly shows which tab is `(current)`.
91
+
92
+ **Fix:** To verify your current URL in multi-tab mode:
93
+ ```bash
94
+ eval "() => window.location.href"
95
+ ```
96
+
97
+ #### TRAP 8: Soft 404s — HTTP 200 on error pages
98
+ Many SPAs and Next.js sites serve 404 pages with HTTP 200 status:
99
+ ```bash
100
+ run-code 'async (page) => { const r = await page.goto("https://example.com/nonexistent"); return r.status(); }'
101
+ # Returns: 200 — even though the page says "Not Found"
102
+ ```
103
+
104
+ **Fix:** Check page content, not HTTP status:
105
+ ```bash
106
+ eval "() => document.title" # "Page Not Found | MySite"
107
+ eval "() => document.querySelector('h1')?.textContent" # "Lost your way?"
108
+ ```
109
+
110
+ #### TRAP 9: Dialogs block EVERYTHING
111
+ If a site triggers an `alert()`, `confirm()`, or `prompt()`, ALL other commands fail:
112
+ ```
113
+ Error: Tool "browser_click" does not handle the modal state.
114
+ ```
115
+
116
+ **Fix:** The CLI output will show a `### Modal state` section telling you exactly what dialog is open. Dismiss it before doing anything else:
117
+ ```bash
118
+ dialog-accept # OK/Accept
119
+ dialog-accept "value" # Accept with text (for prompt dialogs)
120
+ dialog-dismiss # Cancel/Dismiss
121
+ ```
122
+
123
+ #### TRAP 10: `type` and `fill` are fundamentally different
124
+ - `fill <ref> <text>` — targets a specific element by ref, REPLACES all content, uses Playwright's `locator.fill()`
125
+ - `type <text>` — types into whatever has focus (NO ref), APPENDS to existing content, uses `keyboard.type()`
126
+
127
+ **Default to `fill` for form testing.** It's more reliable and doesn't depend on focus state. Use `type` only for keyboard-specific behavior testing.
128
+
129
+ #### TRAP 11: `fill --submit` fills THEN presses Enter
130
+ ```bash
131
+ fill e53 "test@example.com" --submit
132
+ # Fills the field, then immediately presses Enter
133
+ ```
134
+ This is a shortcut for fill + submit. Useful for search fields and login forms.
135
+
136
+ #### TRAP 12: run-code quote escaping
137
+ Single quotes for outer wrapper, double quotes inside:
138
+ ```bash
139
+ # CORRECT:
140
+ run-code 'async (page) => { await page.locator("h1").textContent(); }'
141
+
142
+ # WRONG (shell eats the quotes):
143
+ run-code "async (page) => { await page.locator('h1').textContent(); }"
144
+ ```
145
+
146
+ #### TRAP 13: Tab index shifts after tab-close
147
+ When you close tab 1, the former tab 2 becomes tab 1. Use `tab-list` after closing to confirm the new order.
148
+
149
+ #### TRAP 14: network --static vs default
150
+ ```bash
151
+ network # Only dynamic requests (API calls, XHR, fetch)
152
+ network --static # ALL resources (CSS, JS, fonts, images too)
153
+ ```
154
+ Use `--static` for full resource audits. Use default for API call monitoring.
155
+
156
+ #### TRAP 15: Playwright auto-scrolls for you
157
+ You do NOT need to scroll to an element before clicking, filling, or hovering. Playwright scrolls to the target automatically. Only scroll manually for:
158
+ - Checking what's "above the fold" at different scroll positions
159
+ - Testing lazy-loaded content
160
+ - Taking viewport screenshots at specific positions
161
+ - Testing infinite scroll behavior
162
+
163
+ ---
164
+
165
+ ### THE CORE TESTING LOOP
166
+
167
+ Every browser test follows this loop. Internalize it.
168
+
169
+ ```
170
+ open <url>
171
+
172
+ [health check: console error + network for 4xx/5xx]
173
+
174
+ snapshot → get refs → interact (click, fill, etc.)
175
+
176
+ [after any page change: snapshot again → get new refs]
177
+
178
+ screenshot + eval → capture evidence
179
+
180
+ repeat for next test step
181
+ ```
182
+
183
+ **The golden rule:** After ANY action that might change the page (click, navigate, hover, reload, tab-select, go-back), take a new `snapshot` before using refs.
184
+
185
+ #### Health Check Pattern
186
+ Run this immediately after opening any page:
187
+
188
+ ```bash
189
+ open https://example.com
190
+ console error # Get the log file path
191
+ # READ that file — look for JS errors
192
+ network # Get the network log path
193
+ # READ that file — look for failed requests (4xx, 5xx)
194
+ ```
195
+
196
+ **Use `--clear` to isolate phases:**
197
+ ```bash
198
+ console --clear # Clear log before next test phase
199
+ network --clear # Clear log before next test phase
200
+ ```
201
+
202
+ ---
203
+
204
+ ### TAB-BASED TESTING — THE GOLD PATTERN
205
+
206
+ Instead of creating separate browser sessions for each test scenario, use tabs within one session. This is memory-efficient, preserves shared state (cookies, localStorage), and gives you a clear "done" signal.
207
+
208
+ #### Why tabs are superior
209
+ 1. **One browser, multiple contexts** — 10 tabs use far less memory than 10 sessions
210
+ 2. **Shared state** — cookies and localStorage persist across tabs, like real users
211
+ 3. **Progress tracking** — open tabs = remaining work, closed = done
212
+ 4. **Easy comparison** — `tab-select` between viewports instantly
213
+
214
+ #### The tab workflow
215
+ ```bash
216
+ # Tab 0: Your home base (desktop, light mode)
217
+ open https://example.com
218
+ screenshot --full-page --filename=desktop-light.png
219
+
220
+ # Tab 1: Mobile
221
+ tab-new
222
+ open https://example.com # ALWAYS open after tab-new!
223
+ resize 375 812
224
+ screenshot --full-page --filename=mobile-light.png
225
+
226
+ # Tab 2: Desktop dark mode
227
+ tab-new
228
+ open https://example.com
229
+ run-code 'async (page) => { await page.emulateMedia({ colorScheme: "dark" }); }'
230
+ screenshot --full-page --filename=desktop-dark.png
231
+
232
+ # Tab 3: Mobile dark mode
233
+ tab-new
234
+ open https://example.com
235
+ resize 375 812
236
+ run-code 'async (page) => { await page.emulateMedia({ colorScheme: "dark" }); }'
237
+ screenshot --full-page --filename=mobile-dark.png
238
+ ```
239
+
240
+ #### Working with tabs
241
+ ```bash
242
+ tab-list # See all tabs with indexes and URLs
243
+ tab-select <index> # Switch to a specific tab
244
+ tab-close <index> # Close a tab (NOT close! close kills the session)
245
+ ```
246
+
247
+ #### Tab completion signal
248
+ - All test tabs open = all scenarios in progress
249
+ - Tab closed = that scenario is complete
250
+ - Only tab 0 remains = ALL testing complete
251
+
252
+ #### Critical tab gotchas
253
+ - `tab-new <url>` opens about:blank — ALWAYS follow with `open <url>`
254
+ - "Page URL" in snapshot is wrong when multiple tabs are open — trust "Open tabs" section
255
+ - After `tab-close`, remaining tab indexes shift — use `tab-list` to re-orient
256
+ - NEVER use `close` — it kills the session. ALWAYS use `tab-close <index>`
257
+
258
+ ---
259
+
260
+ ### MULTI-VIEWPORT TESTING
261
+
262
+ #### Standard breakpoints
263
+ | Device | Width | Height |
264
+ |--------|-------|--------|
265
+ | Desktop | 1280 | 720 |
266
+ | Tablet | 768 | 1024 |
267
+ | Mobile | 375 | 812 |
268
+
269
+ #### Single-page approach (when you just need screenshots)
270
+ ```bash
271
+ open https://example.com
272
+ screenshot --full-page --filename=desktop.png
273
+
274
+ resize 768 1024
275
+ screenshot --full-page --filename=tablet.png
276
+
277
+ resize 375 812
278
+ screenshot --full-page --filename=mobile.png
279
+
280
+ resize 1280 720 # Reset to desktop
281
+ ```
282
+
283
+ #### Multi-tab approach (when you need to compare or interact)
284
+ Use the tab workflow above — one tab per viewport. This lets you switch between viewports to compare specific elements.
285
+
286
+ #### What to check at each viewport
287
+ 1. **Layout** — does content reflow properly? No horizontal overflow?
288
+ ```bash
289
+ eval "() => ({ hasHScroll: document.body.scrollWidth > window.innerWidth })"
290
+ ```
291
+ 2. **Navigation** — is the hamburger menu working? Are nav items accessible?
292
+ 3. **Text** — is text readable? No truncation?
293
+ 4. **Interactive elements** — are buttons large enough to tap? No overlapping clickables?
294
+ 5. **Images** — do they scale properly? Any broken images?
295
+
296
+ #### Automated breakpoint sweep (for comprehensive audits)
297
+ ```bash
298
+ run-code 'async (page) => {
299
+ const breakpoints = [320, 375, 425, 768, 1024, 1280, 1440, 1920];
300
+ for (const w of breakpoints) {
301
+ await page.setViewportSize({ width: w, height: 800 });
302
+ await page.screenshot({ fullPage: true, path: `.playwright-cli/responsive-${w}.png` });
303
+ }
304
+ return "Done: " + breakpoints.length + " screenshots at all breakpoints";
305
+ }'
306
+ ```
307
+
308
+ ---
309
+
310
+ ### DARK MODE TESTING
311
+
312
+ Dark mode is a standard feature now. When testing UI, you should check both light and dark variants.
313
+
314
+ #### Approach hierarchy — try in this order
315
+ Different sites implement dark mode differently. Try these approaches in order until one works:
316
+
317
+ **1. System preference emulation (MOST RELIABLE — works for standards-compliant sites):**
318
+ ```bash
319
+ run-code 'async (page) => { await page.emulateMedia({ colorScheme: "dark" }); }'
320
+ ```
321
+
322
+ **2. Check if emulation worked — if not, try class-based themes:**
323
+ ```bash
324
+ # Check what CSS classes the site uses
325
+ eval "() => document.documentElement.className"
326
+ # If Tailwind/Next.js themes: add the class
327
+ eval "() => document.documentElement.classList.add('dark')"
328
+ # Or data-attribute based:
329
+ eval "() => document.documentElement.setAttribute('data-theme', 'dark')"
330
+ ```
331
+
332
+ **3. If no class-based theme, look for a toggle in the snapshot:**
333
+ ```bash
334
+ snapshot
335
+ # Find a theme toggle button, then click it
336
+ click <toggle-ref>
337
+ ```
338
+
339
+ **4. If no toggle visible, check localStorage:**
340
+ ```bash
341
+ eval "() => JSON.stringify(localStorage)"
342
+ # Look for theme-related keys and set them:
343
+ eval "() => { localStorage.setItem('theme', 'dark'); location.reload(); }"
344
+ ```
345
+
346
+ #### The four-screenshot matrix
347
+ For comprehensive visual testing, capture all combinations:
348
+
349
+ | Viewport | Theme | Filename |
350
+ |----------|-------|----------|
351
+ | Desktop (1280x720) | Light | `desktop-light.png` |
352
+ | Desktop (1280x720) | Dark | `desktop-dark.png` |
353
+ | Mobile (375x812) | Light | `mobile-light.png` |
354
+ | Mobile (375x812) | Dark | `mobile-dark.png` |
355
+
356
+ Use the tab workflow to set up all four scenarios efficiently.
357
+
358
+ ---
359
+
360
+ ### SCREENSHOT STRATEGY
361
+
362
+ #### Three screenshot modes
363
+
364
+ **1. Full page** — entire scrollable page in one image:
365
+ ```bash
366
+ screenshot --full-page --filename=homepage-full.png
367
+ ```
368
+ Use for: visual baselines, layout overview, content audit, initial assessment.
369
+
370
+ **2. Viewport only** — just what's visible in current viewport:
371
+ ```bash
372
+ screenshot --filename=above-the-fold.png
373
+ ```
374
+ Use for: above-the-fold checks, specific sections after scrolling, detail inspection.
375
+
376
+ **3. Element** — just one element:
377
+ ```bash
378
+ screenshot e426 --filename=login-form.png
379
+ ```
380
+ Use for: form states, button styles, component-level comparisons. Saved as `element-*.png`.
381
+
382
+ #### Use `--filename` for predictable names
383
+ Without it, screenshots get auto-generated timestamps. Named files are easier to reference in reports.
384
+
385
+ #### Scroll-and-snap pattern (fold-by-fold inspection)
386
+ ```bash
387
+ screenshot --filename=fold-1.png
388
+ mousewheel 0 720
389
+ screenshot --filename=fold-2.png
390
+ mousewheel 0 720
391
+ screenshot --filename=fold-3.png
392
+ ```
393
+
394
+ ---
395
+
396
+ ### FORM TESTING
397
+
398
+ #### The reliable pattern: fill → verify → screenshot → submit
399
+
400
+ ```bash
401
+ # 1. Fill all fields using fill (not type)
402
+ fill e53 "John"
403
+ fill e56 "Doe"
404
+ fill e59 "john@example.com"
405
+ fill e62 "Acme Corp"
406
+
407
+ # 2. Verify values were set (snapshots DON'T show form values!)
408
+ eval "() => {
409
+ const inputs = document.querySelectorAll('input[type=text], input[type=email]');
410
+ return Array.from(inputs).map(i => ({ name: i.name, value: i.value }));
411
+ }"
412
+
413
+ # 3. Screenshot the filled form (visual evidence)
414
+ screenshot --filename=form-filled.png
415
+
416
+ # 4. Submit
417
+ click e64 # Click submit button
418
+ # Or: fill e62 "Acme Corp" --submit # Fill last field + press Enter
419
+ ```
420
+
421
+ #### When to use `fill` vs `type`
422
+ - **fill** — for setting form field values. Cleaner, more reliable, targets by ref, REPLACES content
423
+ - **type** — for testing keyboard behavior. Appends to focused element, tests autocomplete triggers, input event handlers
424
+
425
+ #### Verifying form state
426
+ **Snapshots don't show input values.** You MUST use eval:
427
+ ```bash
428
+ eval "(el) => el.value" e53 # Check one field
429
+ eval "(el) => el.checked" e72 # Check checkbox
430
+ ```
431
+
432
+ #### Select dropdowns and file uploads
433
+ ```bash
434
+ select e80 "option-value" # Select dropdown option
435
+ upload /path/to/file.pdf # Upload a file
436
+ ```
437
+
438
+ ---
439
+
440
+ ### EVAL & RUN-CODE — YOUR POWER TOOLS
441
+
442
+ #### eval: quick data extraction
443
+
444
+ Without ref — runs on page (window context):
445
+ ```bash
446
+ eval "() => document.title"
447
+ eval "() => window.location.href"
448
+ eval "() => document.querySelectorAll('a').length"
449
+ ```
450
+
451
+ With ref — function receives that element:
452
+ ```bash
453
+ eval "(el) => el.value" e53 # Input value
454
+ eval "(el) => getComputedStyle(el).fontSize" e156 # CSS property
455
+ eval "(el) => el.getBoundingClientRect()" e9 # Dimensions
456
+ eval "(el) => el.getAttribute('aria-label')" e42 # Attribute
457
+ ```
458
+
459
+ #### run-code: full Playwright API
460
+
461
+ When the CLI commands aren't enough, `run-code` gives you the full `page` object:
462
+
463
+ **Response interception:**
464
+ ```bash
465
+ run-code 'async (page) => {
466
+ let calls = [];
467
+ page.on("response", r => {
468
+ if (r.url().includes("api")) calls.push({ url: r.url(), status: r.status() });
469
+ });
470
+ await page.reload();
471
+ await page.waitForTimeout(2000);
472
+ return calls;
473
+ }'
474
+ ```
475
+
476
+ **Wait for specific conditions:**
477
+ ```bash
478
+ run-code 'async (page) => {
479
+ await page.waitForSelector(".loading-spinner", { state: "hidden" });
480
+ return "page loaded";
481
+ }'
482
+ ```
483
+
484
+ **Cookie manipulation:**
485
+ ```bash
486
+ run-code 'async (page) => {
487
+ const ctx = page.context();
488
+ await ctx.addCookies([{ name: "test", value: "123", url: "https://example.com" }]);
489
+ return "cookie set";
490
+ }'
491
+ ```
492
+
493
+ **Rule:** Use CLI commands for common operations (click, fill, screenshot). Use `run-code` for things CLI commands can't do.
494
+
495
+ ---
496
+
497
+ ### VERIFICATION PATTERNS
498
+
499
+ When you need to verify something, don't guess — use the right method.
500
+
501
+ #### Verifying navigation succeeded
502
+ ```
503
+ 1. eval "() => window.location.href" ← ground truth
504
+ 2. Check "Open tabs" section (NOT "Page URL" header in multi-tab mode)
505
+ 3. eval "() => document.title"
506
+ ```
507
+
508
+ #### Checking for errors
509
+ ```
510
+ 1. Check page content (catches soft 404s):
511
+ eval "() => document.title"
512
+
513
+ 2. Check HTTP status (catches hard errors):
514
+ run-code 'async (page) => { const r = await page.goto(url); return r.status(); }'
515
+
516
+ 3. Check console for JavaScript errors:
517
+ console error → read the log file
518
+ ```
519
+
520
+ #### Verifying an element exists and is visible
521
+ ```
522
+ 1. Check snapshot for the element
523
+ 2. If not in snapshot: eval "() => document.querySelector('#myElement') !== null"
524
+ 3. Check visibility: eval "(el) => { const r = el.getBoundingClientRect(); return r.width > 0 && r.height > 0; }" <ref>
525
+ ```
526
+
527
+ #### Verifying form submission worked
528
+ ```
529
+ 1. Check URL changed: eval "() => window.location.href"
530
+ 2. Check for success message in snapshot
531
+ 3. Check network log for the submission request
532
+ 4. Check console for errors
533
+ ```
534
+
535
+ ---
536
+
537
+ ### WHEN THINGS GO WRONG — SELF-RECOVERY
538
+
539
+ These are the patterns where agents derail. If you find yourself stuck, check this section.
540
+
541
+ #### "Ref not found" errors
542
+ **Cause:** Refs are stale. You did something that changed the page since your last snapshot.
543
+ **Fix:** Run `snapshot` to get fresh refs. Then use the new refs.
544
+
545
+ #### All commands fail with "does not handle modal state"
546
+ **Cause:** A dialog (alert/confirm/prompt) is blocking the page.
547
+ **Fix:** Run `dialog-accept` or `dialog-dismiss`. Then continue.
548
+
549
+ #### Page is blank / empty snapshot
550
+ **Cause 1:** You used `tab-new` without `open`. Tab is at `about:blank`.
551
+ **Fix:** Run `open <url>`.
552
+
553
+ **Cause 2:** Page is still loading.
554
+ **Fix:** `run-code 'async (page) => { await page.waitForSelector("body > *"); return "loaded"; }'`
555
+
556
+ #### Session died unexpectedly
557
+ **Cause:** You used `close` instead of `tab-close`, or the session crashed.
558
+ **Fix:** Run the bootstrap sequence again:
559
+ ```bash
560
+ playwright-cli session-stop 2>/dev/null
561
+ playwright-cli config --browser=chromium
562
+ playwright-cli open <url>
563
+ ```
564
+
565
+ #### Command behaves unexpectedly
566
+ **Fix:** Run `playwright-cli --help <command>` to see the exact syntax and flags. Don't assume — verify.
567
+
568
+ #### You're stuck in a loop
569
+ **Fix:** Stop. Use `sequential_thinking` to analyze what went wrong. Often the issue is stale refs, a dialog, or wrong URL.
570
+
571
+ ---
572
+
573
+ ### VIDEO & TRACING
574
+
575
+ #### Video recording (for human stakeholders)
576
+ ```bash
577
+ video-start # Start recording
578
+ # ... do your testing ...
579
+ video-stop # Stop and save → .playwright-cli/video-*.webm
580
+ ```
581
+ Video is for humans — LLMs can't process .webm files. For your own analysis, prefer screenshots + text notes at key moments.
582
+
583
+ #### Tracing (for performance debugging)
584
+ ```bash
585
+ tracing-start # Start trace
586
+ # ... do actions ...
587
+ tracing-stop # Stop → .playwright-cli/traces/trace-*.trace
588
+ ```
589
+
590
+ #### PDF generation (for print testing)
591
+ ```bash
592
+ pdf # Save page as PDF → .playwright-cli/page-*.pdf
593
+ ```
594
+ Only works in Chromium. Uses print stylesheet. Useful for testing print layouts or generating report artifacts.
595
+
596
+ ---
597
+
598
+ ### PLAYWRIGHT-SPECIFIC RULES
599
+
600
+ #### ALWAYS
601
+ - Run `snapshot` after any page-changing action before using refs
602
+ - Use `fill` (not `type`) for setting form field values
603
+ - Use `tab-close <index>` (NEVER `close`) to close tabs
604
+ - Use `eval` to verify form values and current URL (not snapshot text)
605
+ - Use `--help <command>` when unsure about syntax
606
+ - Clean up: `session-stop-all` when done
607
+
608
+ #### NEVER
609
+ - Use stale refs — always re-snapshot after page changes
610
+ - Trust "Page URL" in snapshot when multiple tabs are open
611
+ - Trust HTTP status codes for 404 detection on SPAs
612
+ - Use `close` to close a tab — it kills the session
613
+ - Assume `tab-new <url>` navigates — it opens about:blank
614
+
615
+ #### SELF-CHECK
616
+ If you're stuck or confused:
617
+ 1. Check for dialogs blocking you (`dialog-accept` / `dialog-dismiss`)
618
+ 2. Check if your refs are stale (run `snapshot`)
619
+ 3. Check which tab you're on (`tab-list` + `eval "() => window.location.href"`)
620
+ 4. Check `--help <command>` for correct syntax
621
+ 5. Use `sequential_thinking` to step back and analyze