feed-the-machine 1.6.0 → 1.7.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 (269) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +170 -170
  3. package/bin/brain.py +1340 -0
  4. package/bin/convert_claude_skills_to_codex.py +490 -0
  5. package/bin/generate-manifest.mjs +463 -463
  6. package/bin/harden_codex_skills.py +141 -0
  7. package/bin/install.mjs +491 -491
  8. package/bin/migrate-eng-buddy-data.py +875 -0
  9. package/bin/playbook_engine/__init__.py +1 -0
  10. package/bin/playbook_engine/conftest.py +8 -0
  11. package/bin/playbook_engine/extractor.py +33 -0
  12. package/bin/playbook_engine/manager.py +102 -0
  13. package/bin/playbook_engine/models.py +84 -0
  14. package/bin/playbook_engine/registry.py +35 -0
  15. package/bin/playbook_engine/test_extractor.py +72 -0
  16. package/bin/playbook_engine/test_integration.py +129 -0
  17. package/bin/playbook_engine/test_manager.py +85 -0
  18. package/bin/playbook_engine/test_models.py +166 -0
  19. package/bin/playbook_engine/test_registry.py +67 -0
  20. package/bin/playbook_engine/test_tracer.py +86 -0
  21. package/bin/playbook_engine/tracer.py +93 -0
  22. package/bin/tasks_db.py +456 -0
  23. package/docs/HOOKS.md +243 -243
  24. package/docs/INBOX.md +233 -233
  25. package/ftm/SKILL.md +125 -122
  26. package/ftm-audit/SKILL.md +623 -623
  27. package/ftm-audit/references/protocols/PROJECT-PATTERNS.md +91 -91
  28. package/ftm-audit/references/protocols/RUNTIME-WIRING.md +66 -66
  29. package/ftm-audit/references/protocols/WIRING-CONTRACTS.md +135 -135
  30. package/ftm-audit/references/strategies/AUTO-FIX-STRATEGIES.md +69 -69
  31. package/ftm-audit/references/templates/REPORT-FORMAT.md +96 -96
  32. package/ftm-audit/scripts/run-knip.sh +23 -23
  33. package/ftm-audit.yml +2 -2
  34. package/ftm-brainstorm/SKILL.md +1003 -498
  35. package/ftm-brainstorm/evals/evals.json +180 -100
  36. package/ftm-brainstorm/evals/promptfoo.yaml +109 -109
  37. package/ftm-brainstorm/references/agent-prompts.md +552 -224
  38. package/ftm-brainstorm/references/plan-template.md +209 -121
  39. package/ftm-brainstorm.yml +2 -2
  40. package/ftm-browse/SKILL.md +454 -454
  41. package/ftm-browse/daemon/browser-manager.ts +206 -206
  42. package/ftm-browse/daemon/bun.lock +30 -30
  43. package/ftm-browse/daemon/cli.ts +347 -347
  44. package/ftm-browse/daemon/commands.ts +410 -410
  45. package/ftm-browse/daemon/main.ts +357 -357
  46. package/ftm-browse/daemon/package.json +17 -17
  47. package/ftm-browse/daemon/server.ts +189 -189
  48. package/ftm-browse/daemon/snapshot.ts +519 -519
  49. package/ftm-browse/daemon/tsconfig.json +22 -22
  50. package/ftm-browse.yml +4 -4
  51. package/ftm-capture/SKILL.md +370 -370
  52. package/ftm-capture.yml +4 -4
  53. package/ftm-codex-gate/SKILL.md +361 -361
  54. package/ftm-codex-gate.yml +2 -2
  55. package/ftm-config/SKILL.md +422 -345
  56. package/ftm-config.default.yml +125 -82
  57. package/ftm-config.yml +44 -2
  58. package/ftm-council/SKILL.md +416 -416
  59. package/ftm-council/references/prompts/CLAUDE-INVESTIGATION.md +60 -60
  60. package/ftm-council/references/prompts/CODEX-INVESTIGATION.md +58 -58
  61. package/ftm-council/references/prompts/GEMINI-INVESTIGATION.md +58 -58
  62. package/ftm-council/references/prompts/REBUTTAL-TEMPLATE.md +57 -57
  63. package/ftm-council/references/protocols/PREREQUISITES.md +47 -47
  64. package/ftm-council/references/protocols/STEP-0-FRAMING.md +46 -46
  65. package/ftm-council.yml +2 -2
  66. package/ftm-dashboard/SKILL.md +163 -163
  67. package/ftm-dashboard.yml +4 -4
  68. package/ftm-debug/SKILL.md +1037 -1037
  69. package/ftm-debug/references/phases/PHASE-0-INTAKE.md +58 -58
  70. package/ftm-debug/references/phases/PHASE-1-TRIAGE.md +46 -46
  71. package/ftm-debug/references/phases/PHASE-2-WAR-ROOM-AGENTS.md +279 -279
  72. package/ftm-debug/references/phases/PHASE-3-TO-6-EXECUTION.md +436 -436
  73. package/ftm-debug/references/protocols/BLACKBOARD.md +86 -86
  74. package/ftm-debug/references/protocols/EDGE-CASES.md +103 -103
  75. package/ftm-debug.yml +2 -2
  76. package/ftm-diagram/SKILL.md +277 -277
  77. package/ftm-diagram.yml +2 -2
  78. package/ftm-executor/SKILL.md +777 -777
  79. package/ftm-executor/references/STYLE-TEMPLATE.md +73 -73
  80. package/ftm-executor/references/phases/PHASE-0-VERIFICATION.md +62 -62
  81. package/ftm-executor/references/phases/PHASE-2-AGENT-ASSEMBLY.md +34 -34
  82. package/ftm-executor/references/phases/PHASE-3-WORKTREES.md +38 -38
  83. package/ftm-executor/references/phases/PHASE-4-5-AUDIT.md +72 -72
  84. package/ftm-executor/references/phases/PHASE-4-DISPATCH.md +66 -66
  85. package/ftm-executor/references/phases/PHASE-5-5-CODEX-GATE.md +73 -73
  86. package/ftm-executor/references/protocols/DOCUMENTATION-BOOTSTRAP.md +36 -36
  87. package/ftm-executor/references/protocols/MODEL-PROFILE.md +59 -59
  88. package/ftm-executor/references/protocols/PROGRESS-TRACKING.md +66 -66
  89. package/ftm-executor/runtime/ftm-runtime.mjs +252 -252
  90. package/ftm-executor/runtime/package.json +8 -8
  91. package/ftm-executor.yml +2 -2
  92. package/ftm-git/SKILL.md +441 -441
  93. package/ftm-git/evals/evals.json +26 -26
  94. package/ftm-git/evals/promptfoo.yaml +75 -75
  95. package/ftm-git/hooks/post-commit-experience.sh +92 -92
  96. package/ftm-git/references/patterns/SECRET-PATTERNS.md +104 -104
  97. package/ftm-git/references/protocols/REMEDIATION.md +139 -139
  98. package/ftm-git/scripts/pre-commit-secrets.sh +110 -110
  99. package/ftm-git.yml +2 -2
  100. package/ftm-inbox/backend/__pycache__/main.cpython-314.pyc +0 -0
  101. package/ftm-inbox/backend/adapters/_retry.py +64 -64
  102. package/ftm-inbox/backend/adapters/base.py +230 -230
  103. package/ftm-inbox/backend/adapters/freshservice.py +104 -104
  104. package/ftm-inbox/backend/adapters/gmail.py +125 -125
  105. package/ftm-inbox/backend/adapters/jira.py +136 -136
  106. package/ftm-inbox/backend/adapters/registry.py +192 -192
  107. package/ftm-inbox/backend/adapters/slack.py +110 -110
  108. package/ftm-inbox/backend/db/connection.py +54 -54
  109. package/ftm-inbox/backend/db/schema.py +78 -78
  110. package/ftm-inbox/backend/executor/__init__.py +7 -7
  111. package/ftm-inbox/backend/executor/engine.py +149 -149
  112. package/ftm-inbox/backend/executor/step_runner.py +98 -98
  113. package/ftm-inbox/backend/main.py +103 -103
  114. package/ftm-inbox/backend/models/__init__.py +1 -1
  115. package/ftm-inbox/backend/models/unified_task.py +36 -36
  116. package/ftm-inbox/backend/planner/__init__.py +6 -6
  117. package/ftm-inbox/backend/planner/__pycache__/__init__.cpython-314.pyc +0 -0
  118. package/ftm-inbox/backend/planner/__pycache__/generator.cpython-314.pyc +0 -0
  119. package/ftm-inbox/backend/planner/__pycache__/schema.cpython-314.pyc +0 -0
  120. package/ftm-inbox/backend/planner/generator.py +127 -127
  121. package/ftm-inbox/backend/planner/schema.py +34 -34
  122. package/ftm-inbox/backend/requirements.txt +5 -5
  123. package/ftm-inbox/backend/routes/__pycache__/plan.cpython-314.pyc +0 -0
  124. package/ftm-inbox/backend/routes/execute.py +186 -186
  125. package/ftm-inbox/backend/routes/health.py +52 -52
  126. package/ftm-inbox/backend/routes/inbox.py +68 -68
  127. package/ftm-inbox/backend/routes/plan.py +271 -271
  128. package/ftm-inbox/bin/launchagent.mjs +91 -91
  129. package/ftm-inbox/bin/setup.mjs +188 -188
  130. package/ftm-inbox/bin/start.sh +10 -10
  131. package/ftm-inbox/bin/status.sh +17 -17
  132. package/ftm-inbox/bin/stop.sh +8 -8
  133. package/ftm-inbox/config.example.yml +55 -55
  134. package/ftm-inbox/package-lock.json +2898 -2898
  135. package/ftm-inbox/package.json +26 -26
  136. package/ftm-inbox/postcss.config.js +6 -6
  137. package/ftm-inbox/src/app.css +199 -199
  138. package/ftm-inbox/src/app.html +18 -18
  139. package/ftm-inbox/src/lib/api.ts +166 -166
  140. package/ftm-inbox/src/lib/components/ExecutionLog.svelte +81 -81
  141. package/ftm-inbox/src/lib/components/InboxFeed.svelte +143 -143
  142. package/ftm-inbox/src/lib/components/PlanStep.svelte +271 -271
  143. package/ftm-inbox/src/lib/components/PlanView.svelte +206 -206
  144. package/ftm-inbox/src/lib/components/StreamPanel.svelte +99 -99
  145. package/ftm-inbox/src/lib/components/TaskCard.svelte +190 -190
  146. package/ftm-inbox/src/lib/components/ui/EmptyState.svelte +63 -63
  147. package/ftm-inbox/src/lib/components/ui/KawaiiCard.svelte +86 -86
  148. package/ftm-inbox/src/lib/components/ui/PillButton.svelte +106 -106
  149. package/ftm-inbox/src/lib/components/ui/StatusBadge.svelte +67 -67
  150. package/ftm-inbox/src/lib/components/ui/StreamDrawer.svelte +149 -149
  151. package/ftm-inbox/src/lib/components/ui/ThemeToggle.svelte +80 -80
  152. package/ftm-inbox/src/lib/theme.ts +47 -47
  153. package/ftm-inbox/src/routes/+layout.svelte +76 -76
  154. package/ftm-inbox/src/routes/+page.svelte +401 -401
  155. package/ftm-inbox/svelte.config.js +12 -12
  156. package/ftm-inbox/tailwind.config.ts +63 -63
  157. package/ftm-inbox/tsconfig.json +13 -13
  158. package/ftm-inbox/vite.config.ts +6 -6
  159. package/ftm-intent/SKILL.md +241 -241
  160. package/ftm-intent.yml +2 -2
  161. package/ftm-manifest.json +3794 -3794
  162. package/ftm-map/SKILL.md +291 -291
  163. package/ftm-map/scripts/db.py +712 -712
  164. package/ftm-map/scripts/index.py +415 -415
  165. package/ftm-map/scripts/parser.py +224 -224
  166. package/ftm-map/scripts/queries/go-tags.scm +20 -20
  167. package/ftm-map/scripts/queries/javascript-tags.scm +35 -35
  168. package/ftm-map/scripts/queries/python-tags.scm +31 -31
  169. package/ftm-map/scripts/queries/ruby-tags.scm +19 -19
  170. package/ftm-map/scripts/queries/rust-tags.scm +37 -37
  171. package/ftm-map/scripts/queries/typescript-tags.scm +41 -41
  172. package/ftm-map/scripts/query.py +301 -301
  173. package/ftm-map/scripts/ranker.py +377 -377
  174. package/ftm-map/scripts/requirements.txt +5 -5
  175. package/ftm-map/scripts/setup-hooks.sh +27 -27
  176. package/ftm-map/scripts/setup.sh +56 -56
  177. package/ftm-map/scripts/test_db.py +364 -364
  178. package/ftm-map/scripts/test_parser.py +174 -174
  179. package/ftm-map/scripts/test_query.py +183 -183
  180. package/ftm-map/scripts/test_ranker.py +199 -199
  181. package/ftm-map/scripts/views.py +591 -591
  182. package/ftm-map.yml +2 -2
  183. package/ftm-mind/SKILL.md +201 -1943
  184. package/ftm-mind/evals/promptfoo.yaml +142 -142
  185. package/ftm-mind/references/blackboard-protocol.md +110 -0
  186. package/ftm-mind/references/blackboard-schema.md +328 -328
  187. package/ftm-mind/references/complexity-guide.md +110 -110
  188. package/ftm-mind/references/complexity-sizing.md +138 -0
  189. package/ftm-mind/references/decide-act-protocol.md +172 -0
  190. package/ftm-mind/references/direct-execution.md +51 -0
  191. package/ftm-mind/references/environment-discovery.md +77 -0
  192. package/ftm-mind/references/event-registry.md +319 -319
  193. package/ftm-mind/references/mcp-inventory.md +300 -296
  194. package/ftm-mind/references/ops-routing.md +47 -0
  195. package/ftm-mind/references/orient-protocol.md +234 -0
  196. package/ftm-mind/references/personality.md +40 -0
  197. package/ftm-mind/references/protocols/COMPLEXITY-SIZING.md +72 -72
  198. package/ftm-mind/references/protocols/MCP-HEURISTICS.md +32 -32
  199. package/ftm-mind/references/protocols/PLAN-APPROVAL.md +80 -80
  200. package/ftm-mind/references/reflexion-protocol.md +249 -249
  201. package/ftm-mind/references/routing/SCENARIOS.md +22 -22
  202. package/ftm-mind/references/routing-scenarios.md +35 -35
  203. package/ftm-mind.yml +2 -2
  204. package/ftm-ops.yml +4 -0
  205. package/ftm-pause/SKILL.md +395 -395
  206. package/ftm-pause/references/protocols/SKILL-RESTORE-PROTOCOLS.md +186 -186
  207. package/ftm-pause/references/protocols/VALIDATION.md +80 -80
  208. package/ftm-pause.yml +2 -2
  209. package/ftm-researcher/SKILL.md +275 -275
  210. package/ftm-researcher/evals/agent-diversity.yaml +17 -17
  211. package/ftm-researcher/evals/synthesis-quality.yaml +12 -12
  212. package/ftm-researcher/evals/trigger-accuracy.yaml +39 -39
  213. package/ftm-researcher/references/adaptive-search.md +116 -116
  214. package/ftm-researcher/references/agent-prompts.md +193 -193
  215. package/ftm-researcher/references/council-integration.md +193 -193
  216. package/ftm-researcher/references/output-format.md +203 -203
  217. package/ftm-researcher/references/synthesis-pipeline.md +165 -165
  218. package/ftm-researcher/scripts/score_credibility.py +234 -234
  219. package/ftm-researcher/scripts/validate_research.py +92 -92
  220. package/ftm-researcher.yml +2 -2
  221. package/ftm-resume/SKILL.md +518 -518
  222. package/ftm-resume/references/protocols/VALIDATION.md +172 -172
  223. package/ftm-resume.yml +2 -2
  224. package/ftm-retro/SKILL.md +380 -380
  225. package/ftm-retro/references/protocols/SCORING-RUBRICS.md +89 -89
  226. package/ftm-retro/references/templates/REPORT-FORMAT.md +109 -109
  227. package/ftm-retro.yml +2 -2
  228. package/ftm-routine/SKILL.md +170 -170
  229. package/ftm-routine.yml +4 -4
  230. package/ftm-state/blackboard/capabilities.json +5 -5
  231. package/ftm-state/blackboard/capabilities.schema.json +27 -27
  232. package/ftm-state/blackboard/context.json +37 -23
  233. package/ftm-state/blackboard/experiences/doom-statusline-fix.json +26 -0
  234. package/ftm-state/blackboard/experiences/hackathon-pages-site.json +26 -0
  235. package/ftm-state/blackboard/experiences/hindsight-sso-kickoff.json +42 -0
  236. package/ftm-state/blackboard/experiences/index.json +58 -9
  237. package/ftm-state/blackboard/experiences/learning-ragnarok-api-access.json +23 -0
  238. package/ftm-state/blackboard/experiences/nordlayer-members-auto-assign.json +26 -0
  239. package/ftm-state/blackboard/experiences/saml2aws-stale-session-fix.json +41 -0
  240. package/ftm-state/blackboard/patterns.json +6 -6
  241. package/ftm-state/schemas/context.schema.json +130 -130
  242. package/ftm-state/schemas/experience-index.schema.json +77 -77
  243. package/ftm-state/schemas/experience.schema.json +78 -78
  244. package/ftm-state/schemas/patterns.schema.json +44 -44
  245. package/ftm-upgrade/SKILL.md +194 -194
  246. package/ftm-upgrade/scripts/check-version.sh +76 -76
  247. package/ftm-upgrade/scripts/upgrade.sh +143 -143
  248. package/ftm-upgrade.yml +2 -2
  249. package/ftm-verify.yml +2 -2
  250. package/ftm.yml +2 -2
  251. package/hooks/ftm-auto-log.sh +137 -0
  252. package/hooks/ftm-blackboard-enforcer.sh +93 -93
  253. package/hooks/ftm-discovery-reminder.sh +90 -90
  254. package/hooks/ftm-drafts-gate.sh +61 -61
  255. package/hooks/ftm-event-logger.mjs +107 -107
  256. package/hooks/ftm-install-hooks.sh +240 -0
  257. package/hooks/ftm-learning-capture.sh +117 -0
  258. package/hooks/ftm-map-autodetect.sh +79 -79
  259. package/hooks/ftm-pending-sync-check.sh +22 -22
  260. package/hooks/ftm-plan-gate.sh +92 -92
  261. package/hooks/ftm-post-commit-trigger.sh +57 -57
  262. package/hooks/ftm-post-compaction.sh +138 -0
  263. package/hooks/ftm-pre-compaction.sh +147 -0
  264. package/hooks/ftm-session-end.sh +52 -0
  265. package/hooks/ftm-session-snapshot.sh +213 -0
  266. package/hooks/settings-template.json +81 -81
  267. package/install.sh +363 -363
  268. package/package.json +84 -84
  269. package/uninstall.sh +25 -25
@@ -1,454 +1,454 @@
1
- ---
2
- name: ftm-browse
3
- description: Headless browser daemon for visual verification and web interaction. Gives agents the ability to navigate, screenshot, click, fill forms, and inspect ARIA trees via CLI commands. Use when user says "browse", "screenshot", "visual", "look at the app", "open browser", "check the page", "navigate to", "take a screenshot", "visual verification".
4
- ---
5
-
6
- ## Events
7
-
8
- ### Emits
9
- - `task_completed` — when a visual verification or interaction workflow finishes successfully
10
-
11
- ### Listens To
12
- (none — ftm-browse is invoked on demand and does not respond to events)
13
-
14
- # ftm-browse
15
-
16
- ftm-browse is a persistent headless Chromium daemon controlled via a CLI binary at `~/.claude/skills/ftm-browse/bin/ftm-browse`. Each CLI invocation communicates with the daemon over a local HTTP server (bearer-auth, random port), so the browser stays alive across commands without the per-invocation startup penalty. The daemon auto-starts on first use and shuts itself down after 30 minutes of idle. This CLI-to-HTTP model is 4x more token-efficient than driving Playwright MCP directly, because tool calls remain terse and outputs are structured JSON rather than raw browser protocol noise.
17
-
18
- ---
19
-
20
- ## Setup
21
-
22
- **First run — install the browser engine:**
23
-
24
- ```bash
25
- npx playwright install chromium
26
- ```
27
-
28
- **Define the alias in any shell session before use:**
29
-
30
- ```bash
31
- PB="$HOME/.claude/skills/ftm-browse/bin/ftm-browse"
32
- ```
33
-
34
- **Verify the installation:**
35
-
36
- ```bash
37
- $PB goto https://example.com && $PB screenshot
38
- ```
39
-
40
- The first `goto` command will start the daemon (up to 10 seconds for cold start). All subsequent commands respond in ~100ms because the browser process stays alive.
41
-
42
- ---
43
-
44
- ## Command Reference
45
-
46
- ### WRITE commands — state-mutating
47
-
48
- These commands change browser state. Never retry blindly; check the returned `success` field.
49
-
50
- **`goto <url>`** — Navigate to a URL. Waits for `domcontentloaded`.
51
-
52
- ```bash
53
- $PB goto https://example.com
54
- $PB goto http://localhost:3000/dashboard
55
- ```
56
-
57
- Returns: `{ success, data: { url, title, status } }`
58
-
59
- **`click <@ref>`** — Click an interactive element by its `@e` ref. Performs a 5ms staleness check before clicking; fails immediately if the ref is stale rather than waiting.
60
-
61
- ```bash
62
- $PB click @e3
63
- $PB click @e12
64
- ```
65
-
66
- Returns: `{ success, data: { url, title } }` — includes the URL after any resulting navigation.
67
-
68
- **`fill <@ref> <value>`** — Fill a text input, textarea, or other fillable element. Values with spaces do not need quoting — remaining CLI args are joined.
69
-
70
- ```bash
71
- $PB fill @e2 hello world
72
- $PB fill @e5 user@example.com
73
- ```
74
-
75
- Returns: `{ success, data: { ref, value } }`
76
-
77
- **`press <key>`** — Send a keyboard key to the active page. Accepts any Playwright key name.
78
-
79
- ```bash
80
- $PB press Enter
81
- $PB press Tab
82
- $PB press Escape
83
- $PB press ArrowDown
84
- ```
85
-
86
- Returns: `{ success, data: { key, url } }`
87
-
88
- ---
89
-
90
- ### READ commands — safe to retry
91
-
92
- These commands do not change browser state. Safe to call multiple times.
93
-
94
- **`text`** — Get visible page text via `document.body.innerText`.
95
-
96
- ```bash
97
- $PB text
98
- ```
99
-
100
- Returns: `{ success, data: { text } }`
101
-
102
- **`html`** — Get full page HTML via `page.content()`.
103
-
104
- ```bash
105
- $PB html
106
- ```
107
-
108
- Returns: `{ success, data: { html } }`
109
-
110
- **`eval <js-expression>`** — Execute arbitrary JavaScript in the page context. Returns the result as a JSON-serializable value. DOM elements are returned as `{ type: "element", tagName, id, text }`. Functions are returned as `{ type: "function", name }`. Errors inside the expression are caught and returned as `{ error: "..." }` rather than crashing the daemon.
111
-
112
- ```bash
113
- $PB eval document.title
114
- $PB eval "document.querySelector('input[name=email]').value"
115
- $PB eval "Array.from(document.querySelectorAll('td')).map(td => td.textContent)"
116
- $PB eval window.location.href
117
- $PB eval "document.cookie"
118
- ```
119
-
120
- Returns: `{ success, data: { result } }` — `result` is whatever the expression evaluated to.
121
-
122
- Use cases:
123
- - Reading hidden or programmatically-set form field values not visible in the ARIA tree
124
- - Extracting data from dynamic tables or rendered lists
125
- - Checking feature toggle states or global JS variables (`window.featureFlags`)
126
- - Inspecting `localStorage` or `sessionStorage` values
127
- - Querying computed DOM state not exposed via accessibility roles
128
-
129
- ---
130
-
131
- ### META commands
132
-
133
- **`snapshot`** — Full ARIA accessibility tree of the current page. Includes both interactive and structural elements (headings, nav, main, etc.).
134
-
135
- ```bash
136
- $PB snapshot
137
- ```
138
-
139
- Returns: `{ success, data: { url, title, interactive_only: false, tree, refs, aria_text? } }`
140
-
141
- **`snapshot -i`** — Interactive elements only, each labeled with an `@e1`, `@e2`... ref. Use this before clicking or filling — never guess a ref.
142
-
143
- ```bash
144
- $PB snapshot -i
145
- ```
146
-
147
- Returns: same shape as `snapshot` with `interactive_only: true`; the `refs` map contains the locator entries for each `@eN`.
148
-
149
- **`screenshot`** — Capture a viewport screenshot (1280x800). Saves to `~/.ftm-browse/screenshots/screenshot-<timestamp>.png` by default and returns the path.
150
-
151
- ```bash
152
- $PB screenshot
153
- $PB screenshot --path /tmp/before.png
154
- $PB screenshot --path /tmp/after.png
155
- ```
156
-
157
- Returns: `{ success, data: { path, url, title } }`
158
-
159
- **`tabs`** — List all open browser tabs.
160
-
161
- ```bash
162
- $PB tabs
163
- ```
164
-
165
- Returns: `{ success, data: { tabs: [{ index, url, title, active }] } }`
166
-
167
- **`chain '<json-array>'`** — Execute multiple commands in sequence in a single CLI invocation. The chain stops at the first failure. Use this to reduce round-trips for multi-step operations.
168
-
169
- ```bash
170
- $PB chain '[
171
- {"command":"goto","args":{"url":"https://example.com"}},
172
- {"command":"snapshot","args":{"interactive_only":true}},
173
- {"command":"screenshot","args":{}}
174
- ]'
175
- ```
176
-
177
- Returns: `{ success, data: { results: [{ command, result }] } }`. On failure: adds `failed_at` field.
178
-
179
- **`health`** — Check that the daemon is alive and responding.
180
-
181
- ```bash
182
- $PB health
183
- ```
184
-
185
- Returns: `{ status: "ok", pid }` (wrapped in standard result envelope from the daemon's health handler — note this endpoint bypasses `executeCommand` and returns directly).
186
-
187
- **`stop`** (alias: `shutdown`) — Send SIGTERM to the daemon. The daemon cleans up its state file and exits.
188
-
189
- ```bash
190
- $PB stop
191
- ```
192
-
193
- ---
194
-
195
- ## The @e Ref System
196
-
197
- Refs are short handles (`@e1`, `@e2`, ...) that identify interactive elements. They are assigned fresh on each `snapshot` call and map to stable Playwright locator strategies (by label, by role+name, by placeholder, by name attribute, or by nth-position CSS fallback).
198
-
199
- **Getting refs:**
200
-
201
- ```bash
202
- $PB snapshot -i
203
- # Output includes tree nodes like:
204
- # { "ref": "@e3", "role": "button", "name": "Submit", "interactive": true }
205
- # { "ref": "@e5", "role": "textbox", "name": "Email", "interactive": true }
206
- ```
207
-
208
- **Using refs:**
209
-
210
- ```bash
211
- $PB fill @e5 user@example.com
212
- $PB click @e3
213
- ```
214
-
215
- **Staleness rule:** After any navigation event — whether from `goto`, a `click` that follows a link, or `press Enter` submitting a form — the current ref map is invalidated. The daemon detects stale refs in ~5ms and returns an error asking you to re-snapshot. Always re-run `snapshot -i` after navigation before using refs again.
216
-
217
- **Typical interaction workflow:**
218
-
219
- ```bash
220
- # 1. Navigate to the page
221
- $PB goto http://localhost:3000/login
222
-
223
- # 2. Get interactive refs
224
- $PB snapshot -i
225
-
226
- # 3. Identify target elements from the output, then interact
227
- $PB fill @e2 admin@example.com
228
- $PB fill @e3 password123
229
- $PB click @e4 # "Sign in" button
230
-
231
- # 4. Page navigated — refs are stale; re-snapshot
232
- $PB snapshot -i
233
-
234
- # 5. Continue on the new page
235
- $PB screenshot
236
- ```
237
-
238
- ---
239
-
240
- ## Common Workflows
241
-
242
- ### Visual smoke test
243
-
244
- ```bash
245
- PB="$HOME/.claude/skills/ftm-browse/bin/ftm-browse"
246
- $PB goto http://localhost:3000
247
- $PB screenshot --path /tmp/smoke.png
248
- # Read /tmp/smoke.png to verify layout
249
- ```
250
-
251
- ### Form filling
252
-
253
- ```bash
254
- $PB goto http://localhost:3000/signup
255
- $PB snapshot -i
256
- # Identify: @e1=name input, @e2=email input, @e3=password, @e4=submit button
257
- $PB fill @e1 Jane Doe
258
- $PB fill @e2 jane@example.com
259
- $PB fill @e3 s3cret!
260
- $PB click @e4
261
- $PB screenshot --path /tmp/after-signup.png
262
- ```
263
-
264
- ### Navigation verification
265
-
266
- ```bash
267
- $PB goto http://localhost:3000
268
- $PB snapshot -i
269
- # Find nav links
270
- $PB click @e7 # "Dashboard" link
271
- $PB text # Verify content changed
272
- $PB screenshot
273
- ```
274
-
275
- ### Before/after comparison
276
-
277
- ```bash
278
- $PB goto http://localhost:3000/widget
279
- $PB screenshot --path /tmp/before.png
280
- # ... make changes in code ...
281
- $PB goto http://localhost:3000/widget # reload after change
282
- $PB screenshot --path /tmp/after.png
283
- # Compare /tmp/before.png and /tmp/after.png visually
284
- ```
285
-
286
- ### Multi-step with chain (fewer round-trips)
287
-
288
- ```bash
289
- $PB chain '[
290
- {"command":"goto","args":{"url":"http://localhost:3000/login"}},
291
- {"command":"fill","args":{"ref":"@e2","value":"admin@example.com"}},
292
- {"command":"fill","args":{"ref":"@e3","value":"password"}},
293
- {"command":"click","args":{"ref":"@e4"}},
294
- {"command":"screenshot","args":{}}
295
- ]'
296
- ```
297
-
298
- Note: When using `chain` with refs, you must have called `snapshot -i` first in a separate command to populate the ref map. Refs set by a `snapshot` inside the same chain are available to subsequent steps in that chain.
299
-
300
- ---
301
-
302
- ## Integration with Other FTM Skills
303
-
304
- **ftm-debug** — Use ftm-browse to visually verify bug fixes. Take a screenshot before applying a fix, apply the fix, reload, screenshot again. Compare before/after to confirm the fix is visible. Also use `snapshot` to inspect DOM state when debugging rendering issues — the ARIA tree reveals whether components have mounted and populated correctly.
305
-
306
- **ftm-audit** — Use ftm-browse to verify runtime wiring. Navigate to each route the audit is checking, call `snapshot` to confirm the component appears in the ARIA tree with the correct role and name, and screenshot for documentation. This catches hydration failures, missing route registrations, and components that render blank.
307
-
308
- **ftm-executor** — After completing a task that touches frontend code, use ftm-browse as the post-task smoke test harness. If the project has a dev server running, `goto` the affected route, take a screenshot, and verify the page renders without errors. Include the screenshot path in the task completion report.
309
-
310
- ---
311
-
312
- ## Supervised Execution Mode
313
-
314
- When ftm-browse is executing browser steps within an approved plan (dispatched by ftm-executor or ftm-mind), activate supervised mode. This mode adds verification guardrails after every navigation action.
315
-
316
- ### Activation
317
-
318
- Supervised mode activates automatically when:
319
- - The browse command is part of a plan step (context includes plan step reference)
320
- - The caller provides expected page state (title pattern, URL pattern, or element selector)
321
-
322
- ### Post-Navigation Verification
323
-
324
- After every `goto`, `click` that triggers navigation, or `fill` + `submit` sequence:
325
-
326
- 1. **Wait for page load** — wait for `networkidle` or 5-second timeout, whichever comes first
327
- 2. **Check URL** — if expected URL pattern was provided, verify current URL matches
328
- 3. **Check title** — if expected title pattern was provided, verify page title matches
329
- 4. **Check for error indicators** — scan for common error patterns:
330
- - HTTP error codes in title (403, 404, 500, 502, 503)
331
- - Error modals or alert dialogs
332
- - "Access Denied", "Unauthorized", "Session Expired" text in page
333
- 5. **Check for auth redirects** — if current URL contains `/login`, `/signin`, `/sso`, `/oauth`, or `/saml` when it wasn't the intended destination, flag as auth redirect
334
-
335
- ### On Unexpected State
336
-
337
- When verification detects a mismatch or error:
338
-
339
- 1. **Stop execution immediately** — do not proceed to the next browser step
340
- 2. **Take a screenshot** — capture the current page state
341
- 3. **Present the situation** to the user:
342
-
343
- ```
344
- ⚠ Unexpected browser state during plan step [N]:
345
-
346
- Expected: [expected URL/title/state]
347
- Actual: [current URL/title]
348
- Issue: [description — wrong page / error page / auth redirect / modal detected]
349
-
350
- Screenshot: [path to screenshot]
351
-
352
- Options:
353
- 1. retry — navigate again
354
- 2. skip — skip this browser step, continue plan
355
- 3. abort — stop plan execution entirely
356
- 4. manual — open interactive browser for manual intervention
357
- ```
358
-
359
- 4. **Wait for user choice** — do not proceed without explicit selection
360
-
361
- ### Auth Redirect Detection
362
-
363
- Authentication redirects are especially dangerous because silently following them can:
364
- - Leak credentials to unexpected domains
365
- - Complete OAuth flows the user didn't intend
366
- - Grant permissions the user didn't approve
367
-
368
- When an auth redirect is detected:
369
- - NEVER automatically follow it
370
- - Flag it prominently: "Auth redirect detected — redirected to [domain]"
371
- - The user must explicitly choose to proceed
372
-
373
- ### Audit Trail
374
-
375
- Every browser step within a plan produces:
376
- - **Before screenshot** — taken just before the action
377
- - **After screenshot** — taken after the action completes (or after error)
378
- - **Timing** — how long the action took
379
- - **Verification result** — PASS or FAIL with details
380
-
381
- Screenshots saved to a temp directory, paths included in the step report.
382
-
383
- ### Non-Plan Usage
384
-
385
- When ftm-browse is used directly (not within a plan), supervised mode is OFF by default. The user gets the raw browse experience. They can enable it manually with `--supervised` flag.
386
-
387
- ---
388
-
389
- ## Error Handling
390
-
391
- | Symptom | Cause | Fix |
392
- |---|---|---|
393
- | First command hangs up to 10s | Daemon cold start | Normal — wait for it |
394
- | `Ref @eN not found. The page may have changed` | Stale ref after navigation | Re-run `snapshot -i` |
395
- | `Ref @eN no longer exists on the page` | Element removed from DOM | Re-run `snapshot -i` |
396
- | `Timeout` on goto | Page slow to load or wrong URL | Check URL, verify server is running |
397
- | `Browser not installed` or Chromium launch error | Playwright Chromium missing | Run `npx playwright install chromium` |
398
- | `Daemon failed to start within 10 seconds` | Bun or binary issue | Check `~/.ftm-browse/` for logs; verify binary is executable |
399
- | Connection refused | Daemon died (idle timeout or crash) | Next command will auto-restart it |
400
- | `commands must be an array` | Bad JSON passed to chain | Validate JSON before passing to chain |
401
- | `Evaluation failed: ...` | Playwright could not serialize or run the expression | Check for syntax errors; wrap complex expressions in quotes |
402
-
403
- ---
404
-
405
- ## Tips
406
-
407
- - Always run `snapshot -i` before `click` or `fill` — never guess or hardcode a ref number.
408
- - Use `chain` for multi-step flows to reduce round-trip overhead; each step result is available in the returned array.
409
- - Screenshots are cheap — take them liberally at key points (before interaction, after submit, after navigation) as a natural audit trail.
410
- - The daemon persists across all commands in a session. Cold start only happens once per 30-minute idle window.
411
- - `$PB text` is the fastest way to assert page content without parsing HTML.
412
- - `$PB html` is useful when you need to inspect the raw DOM, check for hidden elements, or verify server-rendered markup.
413
- - The daemon uses a 1280x800 headless Chromium viewport with a standard Mac Chrome user-agent, so most sites render predictably.
414
- - To stop the daemon explicitly: `$PB stop`. It will auto-restart on next use.
415
- - `$PB eval` is the escape hatch for anything the ARIA tree doesn't expose — hidden inputs, JS globals, localStorage, computed values.
416
-
417
- ## Requirements
418
-
419
- - tool: `$HOME/.claude/skills/ftm-browse/bin/ftm-browse` | required | headless browser CLI binary
420
- - tool: `npx playwright install chromium` | required | Chromium browser engine (first-time setup)
421
- - reference: none required
422
-
423
- ## Risk
424
-
425
- - level: low_write
426
- - scope: navigates browser, takes screenshots saved to ~/.ftm-browse/screenshots/; does not modify project source files; form fills and clicks can have side effects on the target application
427
- - rollback: no project file mutations; browser interactions on local dev servers are typically reversible by reloading
428
-
429
- ## Approval Gates
430
-
431
- - trigger: auth redirect detected during supervised execution | action: STOP immediately, present options (retry/skip/abort/manual), wait for user choice
432
- - trigger: unexpected browser state during plan step | action: STOP, take screenshot, present situation to user, wait for explicit choice
433
- - trigger: supervised mode enabled AND state mismatch detected | action: halt and report before proceeding
434
- - complexity_routing: micro → auto | small → auto | medium → auto | large → auto | xl → auto
435
-
436
- ## Fallbacks
437
-
438
- - condition: daemon binary not found at expected path | action: report installation instructions and stop
439
- - condition: Chromium not installed | action: instruct user to run "npx playwright install chromium" and stop
440
- - condition: daemon fails to start within 10 seconds | action: check ~/.ftm-browse/ logs, report binary or Bun issue
441
- - condition: dev server not running when navigating to localhost | action: report timeout error with the URL attempted
442
- - condition: stale ref after navigation | action: re-run snapshot -i before retrying click/fill
443
-
444
- ## Capabilities
445
-
446
- - cli: `$HOME/.claude/skills/ftm-browse/bin/ftm-browse` | required | headless Chromium control CLI
447
-
448
- ## Event Payloads
449
-
450
- ### task_completed
451
- - skill: string — "ftm-browse"
452
- - workflow: string — description of the visual verification or interaction performed
453
- - screenshots: string[] — absolute paths to screenshots taken
454
- - duration_ms: number — total workflow duration
1
+ ---
2
+ name: ftm-browse
3
+ description: Headless browser daemon for visual verification and web interaction. Gives agents the ability to navigate, screenshot, click, fill forms, and inspect ARIA trees via CLI commands. Use when user says "browse", "screenshot", "visual", "look at the app", "open browser", "check the page", "navigate to", "take a screenshot", "visual verification".
4
+ ---
5
+
6
+ ## Events
7
+
8
+ ### Emits
9
+ - `task_completed` — when a visual verification or interaction workflow finishes successfully
10
+
11
+ ### Listens To
12
+ (none — ftm-browse is invoked on demand and does not respond to events)
13
+
14
+ # ftm-browse
15
+
16
+ ftm-browse is a persistent headless Chromium daemon controlled via a CLI binary at `~/.claude/skills/ftm-browse/bin/ftm-browse`. Each CLI invocation communicates with the daemon over a local HTTP server (bearer-auth, random port), so the browser stays alive across commands without the per-invocation startup penalty. The daemon auto-starts on first use and shuts itself down after 30 minutes of idle. This CLI-to-HTTP model is 4x more token-efficient than driving Playwright MCP directly, because tool calls remain terse and outputs are structured JSON rather than raw browser protocol noise.
17
+
18
+ ---
19
+
20
+ ## Setup
21
+
22
+ **First run — install the browser engine:**
23
+
24
+ ```bash
25
+ npx playwright install chromium
26
+ ```
27
+
28
+ **Define the alias in any shell session before use:**
29
+
30
+ ```bash
31
+ PB="$HOME/.claude/skills/ftm-browse/bin/ftm-browse"
32
+ ```
33
+
34
+ **Verify the installation:**
35
+
36
+ ```bash
37
+ $PB goto https://example.com && $PB screenshot
38
+ ```
39
+
40
+ The first `goto` command will start the daemon (up to 10 seconds for cold start). All subsequent commands respond in ~100ms because the browser process stays alive.
41
+
42
+ ---
43
+
44
+ ## Command Reference
45
+
46
+ ### WRITE commands — state-mutating
47
+
48
+ These commands change browser state. Never retry blindly; check the returned `success` field.
49
+
50
+ **`goto <url>`** — Navigate to a URL. Waits for `domcontentloaded`.
51
+
52
+ ```bash
53
+ $PB goto https://example.com
54
+ $PB goto http://localhost:3000/dashboard
55
+ ```
56
+
57
+ Returns: `{ success, data: { url, title, status } }`
58
+
59
+ **`click <@ref>`** — Click an interactive element by its `@e` ref. Performs a 5ms staleness check before clicking; fails immediately if the ref is stale rather than waiting.
60
+
61
+ ```bash
62
+ $PB click @e3
63
+ $PB click @e12
64
+ ```
65
+
66
+ Returns: `{ success, data: { url, title } }` — includes the URL after any resulting navigation.
67
+
68
+ **`fill <@ref> <value>`** — Fill a text input, textarea, or other fillable element. Values with spaces do not need quoting — remaining CLI args are joined.
69
+
70
+ ```bash
71
+ $PB fill @e2 hello world
72
+ $PB fill @e5 user@example.com
73
+ ```
74
+
75
+ Returns: `{ success, data: { ref, value } }`
76
+
77
+ **`press <key>`** — Send a keyboard key to the active page. Accepts any Playwright key name.
78
+
79
+ ```bash
80
+ $PB press Enter
81
+ $PB press Tab
82
+ $PB press Escape
83
+ $PB press ArrowDown
84
+ ```
85
+
86
+ Returns: `{ success, data: { key, url } }`
87
+
88
+ ---
89
+
90
+ ### READ commands — safe to retry
91
+
92
+ These commands do not change browser state. Safe to call multiple times.
93
+
94
+ **`text`** — Get visible page text via `document.body.innerText`.
95
+
96
+ ```bash
97
+ $PB text
98
+ ```
99
+
100
+ Returns: `{ success, data: { text } }`
101
+
102
+ **`html`** — Get full page HTML via `page.content()`.
103
+
104
+ ```bash
105
+ $PB html
106
+ ```
107
+
108
+ Returns: `{ success, data: { html } }`
109
+
110
+ **`eval <js-expression>`** — Execute arbitrary JavaScript in the page context. Returns the result as a JSON-serializable value. DOM elements are returned as `{ type: "element", tagName, id, text }`. Functions are returned as `{ type: "function", name }`. Errors inside the expression are caught and returned as `{ error: "..." }` rather than crashing the daemon.
111
+
112
+ ```bash
113
+ $PB eval document.title
114
+ $PB eval "document.querySelector('input[name=email]').value"
115
+ $PB eval "Array.from(document.querySelectorAll('td')).map(td => td.textContent)"
116
+ $PB eval window.location.href
117
+ $PB eval "document.cookie"
118
+ ```
119
+
120
+ Returns: `{ success, data: { result } }` — `result` is whatever the expression evaluated to.
121
+
122
+ Use cases:
123
+ - Reading hidden or programmatically-set form field values not visible in the ARIA tree
124
+ - Extracting data from dynamic tables or rendered lists
125
+ - Checking feature toggle states or global JS variables (`window.featureFlags`)
126
+ - Inspecting `localStorage` or `sessionStorage` values
127
+ - Querying computed DOM state not exposed via accessibility roles
128
+
129
+ ---
130
+
131
+ ### META commands
132
+
133
+ **`snapshot`** — Full ARIA accessibility tree of the current page. Includes both interactive and structural elements (headings, nav, main, etc.).
134
+
135
+ ```bash
136
+ $PB snapshot
137
+ ```
138
+
139
+ Returns: `{ success, data: { url, title, interactive_only: false, tree, refs, aria_text? } }`
140
+
141
+ **`snapshot -i`** — Interactive elements only, each labeled with an `@e1`, `@e2`... ref. Use this before clicking or filling — never guess a ref.
142
+
143
+ ```bash
144
+ $PB snapshot -i
145
+ ```
146
+
147
+ Returns: same shape as `snapshot` with `interactive_only: true`; the `refs` map contains the locator entries for each `@eN`.
148
+
149
+ **`screenshot`** — Capture a viewport screenshot (1280x800). Saves to `~/.ftm-browse/screenshots/screenshot-<timestamp>.png` by default and returns the path.
150
+
151
+ ```bash
152
+ $PB screenshot
153
+ $PB screenshot --path /tmp/before.png
154
+ $PB screenshot --path /tmp/after.png
155
+ ```
156
+
157
+ Returns: `{ success, data: { path, url, title } }`
158
+
159
+ **`tabs`** — List all open browser tabs.
160
+
161
+ ```bash
162
+ $PB tabs
163
+ ```
164
+
165
+ Returns: `{ success, data: { tabs: [{ index, url, title, active }] } }`
166
+
167
+ **`chain '<json-array>'`** — Execute multiple commands in sequence in a single CLI invocation. The chain stops at the first failure. Use this to reduce round-trips for multi-step operations.
168
+
169
+ ```bash
170
+ $PB chain '[
171
+ {"command":"goto","args":{"url":"https://example.com"}},
172
+ {"command":"snapshot","args":{"interactive_only":true}},
173
+ {"command":"screenshot","args":{}}
174
+ ]'
175
+ ```
176
+
177
+ Returns: `{ success, data: { results: [{ command, result }] } }`. On failure: adds `failed_at` field.
178
+
179
+ **`health`** — Check that the daemon is alive and responding.
180
+
181
+ ```bash
182
+ $PB health
183
+ ```
184
+
185
+ Returns: `{ status: "ok", pid }` (wrapped in standard result envelope from the daemon's health handler — note this endpoint bypasses `executeCommand` and returns directly).
186
+
187
+ **`stop`** (alias: `shutdown`) — Send SIGTERM to the daemon. The daemon cleans up its state file and exits.
188
+
189
+ ```bash
190
+ $PB stop
191
+ ```
192
+
193
+ ---
194
+
195
+ ## The @e Ref System
196
+
197
+ Refs are short handles (`@e1`, `@e2`, ...) that identify interactive elements. They are assigned fresh on each `snapshot` call and map to stable Playwright locator strategies (by label, by role+name, by placeholder, by name attribute, or by nth-position CSS fallback).
198
+
199
+ **Getting refs:**
200
+
201
+ ```bash
202
+ $PB snapshot -i
203
+ # Output includes tree nodes like:
204
+ # { "ref": "@e3", "role": "button", "name": "Submit", "interactive": true }
205
+ # { "ref": "@e5", "role": "textbox", "name": "Email", "interactive": true }
206
+ ```
207
+
208
+ **Using refs:**
209
+
210
+ ```bash
211
+ $PB fill @e5 user@example.com
212
+ $PB click @e3
213
+ ```
214
+
215
+ **Staleness rule:** After any navigation event — whether from `goto`, a `click` that follows a link, or `press Enter` submitting a form — the current ref map is invalidated. The daemon detects stale refs in ~5ms and returns an error asking you to re-snapshot. Always re-run `snapshot -i` after navigation before using refs again.
216
+
217
+ **Typical interaction workflow:**
218
+
219
+ ```bash
220
+ # 1. Navigate to the page
221
+ $PB goto http://localhost:3000/login
222
+
223
+ # 2. Get interactive refs
224
+ $PB snapshot -i
225
+
226
+ # 3. Identify target elements from the output, then interact
227
+ $PB fill @e2 admin@example.com
228
+ $PB fill @e3 password123
229
+ $PB click @e4 # "Sign in" button
230
+
231
+ # 4. Page navigated — refs are stale; re-snapshot
232
+ $PB snapshot -i
233
+
234
+ # 5. Continue on the new page
235
+ $PB screenshot
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Common Workflows
241
+
242
+ ### Visual smoke test
243
+
244
+ ```bash
245
+ PB="$HOME/.claude/skills/ftm-browse/bin/ftm-browse"
246
+ $PB goto http://localhost:3000
247
+ $PB screenshot --path /tmp/smoke.png
248
+ # Read /tmp/smoke.png to verify layout
249
+ ```
250
+
251
+ ### Form filling
252
+
253
+ ```bash
254
+ $PB goto http://localhost:3000/signup
255
+ $PB snapshot -i
256
+ # Identify: @e1=name input, @e2=email input, @e3=password, @e4=submit button
257
+ $PB fill @e1 Jane Doe
258
+ $PB fill @e2 jane@example.com
259
+ $PB fill @e3 s3cret!
260
+ $PB click @e4
261
+ $PB screenshot --path /tmp/after-signup.png
262
+ ```
263
+
264
+ ### Navigation verification
265
+
266
+ ```bash
267
+ $PB goto http://localhost:3000
268
+ $PB snapshot -i
269
+ # Find nav links
270
+ $PB click @e7 # "Dashboard" link
271
+ $PB text # Verify content changed
272
+ $PB screenshot
273
+ ```
274
+
275
+ ### Before/after comparison
276
+
277
+ ```bash
278
+ $PB goto http://localhost:3000/widget
279
+ $PB screenshot --path /tmp/before.png
280
+ # ... make changes in code ...
281
+ $PB goto http://localhost:3000/widget # reload after change
282
+ $PB screenshot --path /tmp/after.png
283
+ # Compare /tmp/before.png and /tmp/after.png visually
284
+ ```
285
+
286
+ ### Multi-step with chain (fewer round-trips)
287
+
288
+ ```bash
289
+ $PB chain '[
290
+ {"command":"goto","args":{"url":"http://localhost:3000/login"}},
291
+ {"command":"fill","args":{"ref":"@e2","value":"admin@example.com"}},
292
+ {"command":"fill","args":{"ref":"@e3","value":"password"}},
293
+ {"command":"click","args":{"ref":"@e4"}},
294
+ {"command":"screenshot","args":{}}
295
+ ]'
296
+ ```
297
+
298
+ Note: When using `chain` with refs, you must have called `snapshot -i` first in a separate command to populate the ref map. Refs set by a `snapshot` inside the same chain are available to subsequent steps in that chain.
299
+
300
+ ---
301
+
302
+ ## Integration with Other FTM Skills
303
+
304
+ **ftm-debug** — Use ftm-browse to visually verify bug fixes. Take a screenshot before applying a fix, apply the fix, reload, screenshot again. Compare before/after to confirm the fix is visible. Also use `snapshot` to inspect DOM state when debugging rendering issues — the ARIA tree reveals whether components have mounted and populated correctly.
305
+
306
+ **ftm-audit** — Use ftm-browse to verify runtime wiring. Navigate to each route the audit is checking, call `snapshot` to confirm the component appears in the ARIA tree with the correct role and name, and screenshot for documentation. This catches hydration failures, missing route registrations, and components that render blank.
307
+
308
+ **ftm-executor** — After completing a task that touches frontend code, use ftm-browse as the post-task smoke test harness. If the project has a dev server running, `goto` the affected route, take a screenshot, and verify the page renders without errors. Include the screenshot path in the task completion report.
309
+
310
+ ---
311
+
312
+ ## Supervised Execution Mode
313
+
314
+ When ftm-browse is executing browser steps within an approved plan (dispatched by ftm-executor or ftm-mind), activate supervised mode. This mode adds verification guardrails after every navigation action.
315
+
316
+ ### Activation
317
+
318
+ Supervised mode activates automatically when:
319
+ - The browse command is part of a plan step (context includes plan step reference)
320
+ - The caller provides expected page state (title pattern, URL pattern, or element selector)
321
+
322
+ ### Post-Navigation Verification
323
+
324
+ After every `goto`, `click` that triggers navigation, or `fill` + `submit` sequence:
325
+
326
+ 1. **Wait for page load** — wait for `networkidle` or 5-second timeout, whichever comes first
327
+ 2. **Check URL** — if expected URL pattern was provided, verify current URL matches
328
+ 3. **Check title** — if expected title pattern was provided, verify page title matches
329
+ 4. **Check for error indicators** — scan for common error patterns:
330
+ - HTTP error codes in title (403, 404, 500, 502, 503)
331
+ - Error modals or alert dialogs
332
+ - "Access Denied", "Unauthorized", "Session Expired" text in page
333
+ 5. **Check for auth redirects** — if current URL contains `/login`, `/signin`, `/sso`, `/oauth`, or `/saml` when it wasn't the intended destination, flag as auth redirect
334
+
335
+ ### On Unexpected State
336
+
337
+ When verification detects a mismatch or error:
338
+
339
+ 1. **Stop execution immediately** — do not proceed to the next browser step
340
+ 2. **Take a screenshot** — capture the current page state
341
+ 3. **Present the situation** to the user:
342
+
343
+ ```
344
+ ⚠ Unexpected browser state during plan step [N]:
345
+
346
+ Expected: [expected URL/title/state]
347
+ Actual: [current URL/title]
348
+ Issue: [description — wrong page / error page / auth redirect / modal detected]
349
+
350
+ Screenshot: [path to screenshot]
351
+
352
+ Options:
353
+ 1. retry — navigate again
354
+ 2. skip — skip this browser step, continue plan
355
+ 3. abort — stop plan execution entirely
356
+ 4. manual — open interactive browser for manual intervention
357
+ ```
358
+
359
+ 4. **Wait for user choice** — do not proceed without explicit selection
360
+
361
+ ### Auth Redirect Detection
362
+
363
+ Authentication redirects are especially dangerous because silently following them can:
364
+ - Leak credentials to unexpected domains
365
+ - Complete OAuth flows the user didn't intend
366
+ - Grant permissions the user didn't approve
367
+
368
+ When an auth redirect is detected:
369
+ - NEVER automatically follow it
370
+ - Flag it prominently: "Auth redirect detected — redirected to [domain]"
371
+ - The user must explicitly choose to proceed
372
+
373
+ ### Audit Trail
374
+
375
+ Every browser step within a plan produces:
376
+ - **Before screenshot** — taken just before the action
377
+ - **After screenshot** — taken after the action completes (or after error)
378
+ - **Timing** — how long the action took
379
+ - **Verification result** — PASS or FAIL with details
380
+
381
+ Screenshots saved to a temp directory, paths included in the step report.
382
+
383
+ ### Non-Plan Usage
384
+
385
+ When ftm-browse is used directly (not within a plan), supervised mode is OFF by default. The user gets the raw browse experience. They can enable it manually with `--supervised` flag.
386
+
387
+ ---
388
+
389
+ ## Error Handling
390
+
391
+ | Symptom | Cause | Fix |
392
+ |---|---|---|
393
+ | First command hangs up to 10s | Daemon cold start | Normal — wait for it |
394
+ | `Ref @eN not found. The page may have changed` | Stale ref after navigation | Re-run `snapshot -i` |
395
+ | `Ref @eN no longer exists on the page` | Element removed from DOM | Re-run `snapshot -i` |
396
+ | `Timeout` on goto | Page slow to load or wrong URL | Check URL, verify server is running |
397
+ | `Browser not installed` or Chromium launch error | Playwright Chromium missing | Run `npx playwright install chromium` |
398
+ | `Daemon failed to start within 10 seconds` | Bun or binary issue | Check `~/.ftm-browse/` for logs; verify binary is executable |
399
+ | Connection refused | Daemon died (idle timeout or crash) | Next command will auto-restart it |
400
+ | `commands must be an array` | Bad JSON passed to chain | Validate JSON before passing to chain |
401
+ | `Evaluation failed: ...` | Playwright could not serialize or run the expression | Check for syntax errors; wrap complex expressions in quotes |
402
+
403
+ ---
404
+
405
+ ## Tips
406
+
407
+ - Always run `snapshot -i` before `click` or `fill` — never guess or hardcode a ref number.
408
+ - Use `chain` for multi-step flows to reduce round-trip overhead; each step result is available in the returned array.
409
+ - Screenshots are cheap — take them liberally at key points (before interaction, after submit, after navigation) as a natural audit trail.
410
+ - The daemon persists across all commands in a session. Cold start only happens once per 30-minute idle window.
411
+ - `$PB text` is the fastest way to assert page content without parsing HTML.
412
+ - `$PB html` is useful when you need to inspect the raw DOM, check for hidden elements, or verify server-rendered markup.
413
+ - The daemon uses a 1280x800 headless Chromium viewport with a standard Mac Chrome user-agent, so most sites render predictably.
414
+ - To stop the daemon explicitly: `$PB stop`. It will auto-restart on next use.
415
+ - `$PB eval` is the escape hatch for anything the ARIA tree doesn't expose — hidden inputs, JS globals, localStorage, computed values.
416
+
417
+ ## Requirements
418
+
419
+ - tool: `$HOME/.claude/skills/ftm-browse/bin/ftm-browse` | required | headless browser CLI binary
420
+ - tool: `npx playwright install chromium` | required | Chromium browser engine (first-time setup)
421
+ - reference: none required
422
+
423
+ ## Risk
424
+
425
+ - level: low_write
426
+ - scope: navigates browser, takes screenshots saved to ~/.ftm-browse/screenshots/; does not modify project source files; form fills and clicks can have side effects on the target application
427
+ - rollback: no project file mutations; browser interactions on local dev servers are typically reversible by reloading
428
+
429
+ ## Approval Gates
430
+
431
+ - trigger: auth redirect detected during supervised execution | action: STOP immediately, present options (retry/skip/abort/manual), wait for user choice
432
+ - trigger: unexpected browser state during plan step | action: STOP, take screenshot, present situation to user, wait for explicit choice
433
+ - trigger: supervised mode enabled AND state mismatch detected | action: halt and report before proceeding
434
+ - complexity_routing: micro → auto | small → auto | medium → auto | large → auto | xl → auto
435
+
436
+ ## Fallbacks
437
+
438
+ - condition: daemon binary not found at expected path | action: report installation instructions and stop
439
+ - condition: Chromium not installed | action: instruct user to run "npx playwright install chromium" and stop
440
+ - condition: daemon fails to start within 10 seconds | action: check ~/.ftm-browse/ logs, report binary or Bun issue
441
+ - condition: dev server not running when navigating to localhost | action: report timeout error with the URL attempted
442
+ - condition: stale ref after navigation | action: re-run snapshot -i before retrying click/fill
443
+
444
+ ## Capabilities
445
+
446
+ - cli: `$HOME/.claude/skills/ftm-browse/bin/ftm-browse` | required | headless Chromium control CLI
447
+
448
+ ## Event Payloads
449
+
450
+ ### task_completed
451
+ - skill: string — "ftm-browse"
452
+ - workflow: string — description of the visual verification or interaction performed
453
+ - screenshots: string[] — absolute paths to screenshots taken
454
+ - duration_ms: number — total workflow duration