browser-flow-tracker 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +392 -0
- package/bin/bft.js +183 -0
- package/mcp/server.js +177 -0
- package/package.json +54 -0
- package/src/browsers.js +104 -0
- package/src/cdpRecorder.js +200 -0
- package/src/exporters/har.js +62 -0
- package/src/exporters/markdown.js +111 -0
- package/src/filter.js +89 -0
- package/src/normalize.js +109 -0
- package/src/session.js +185 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gaurav Chauhan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
# π΅οΈ browser-flow-tracker
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/browser-flow-tracker)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
### *"What is this website actually doing behind the scenes?"*
|
|
7
|
+
|
|
8
|
+
You know that feeling when you click a button on a website and a bunch of invisible
|
|
9
|
+
stuff happens β data flies back and forth, APIs get called, magic occurs β but you
|
|
10
|
+
have **no idea what's going on** unless you open the scary black DevTools console and
|
|
11
|
+
squint at a wall of text?
|
|
12
|
+
|
|
13
|
+
**This tool is your spy. π**
|
|
14
|
+
|
|
15
|
+
It quietly watches a web page while you click around, notes down every important
|
|
16
|
+
conversation the page has with its servers (the "APIs"), and then hands you a
|
|
17
|
+
**clean, human-readable document** explaining the whole flow β complete with a
|
|
18
|
+
diagram. No more squinting. No more console.
|
|
19
|
+
|
|
20
|
+
You can use it **by typing one command**, or just **ask Claude / Cursor to do it for you**.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## π― What you get out of it
|
|
25
|
+
|
|
26
|
+
After you record a flow, the tool drops **3 files** in a folder for you:
|
|
27
|
+
|
|
28
|
+
| File | Emoji | What it's for | Who reads it |
|
|
29
|
+
|------|-------|---------------|--------------|
|
|
30
|
+
| `something.md` | π | A nice, readable document: overview, a **diagram**, a table of every API call in order, and the details | **You!** (and Claude/Cursor) |
|
|
31
|
+
| `something.flow.json` | π€ | The same info in "robot language" | Claude / Cursor, to help you write even better docs |
|
|
32
|
+
| `something.har` | π§ | An industry-standard file | Developers, tools like Postman/DevTools |
|
|
33
|
+
|
|
34
|
+
π **The one you'll actually open and read is the `.md` file.** Open it in any Markdown
|
|
35
|
+
viewer, VS Code, or even just a text editor.
|
|
36
|
+
|
|
37
|
+
### π Where do the files go?
|
|
38
|
+
|
|
39
|
+
By default, everything is saved into a folder called **`recordings/`** right inside
|
|
40
|
+
this project:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Scrapper/
|
|
44
|
+
βββ recordings/
|
|
45
|
+
βββ flow-2026-07-01T14-30-00.md β π open this one
|
|
46
|
+
βββ flow-2026-07-01T14-30-00.flow.json
|
|
47
|
+
βββ flow-2026-07-01T14-30-00.har
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Each recording is automatically named with the **date and time** so they never
|
|
51
|
+
overwrite each other. Want a nicer name or a different folder? See
|
|
52
|
+
[the options](#-handy-options) below.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## π¬ What a finished document looks like
|
|
57
|
+
|
|
58
|
+
Here's a taste of what ends up in your `.md` file:
|
|
59
|
+
|
|
60
|
+
> ## Sequence diagram
|
|
61
|
+
> ```mermaid
|
|
62
|
+
> sequenceDiagram
|
|
63
|
+
> participant B as Browser
|
|
64
|
+
> participant S0 as api.myapp.com
|
|
65
|
+
> B->>S0: GET /products
|
|
66
|
+
> S0-->>B: 200
|
|
67
|
+
> B->>S0: POST /cart/add
|
|
68
|
+
> S0-->>B: 201
|
|
69
|
+
> ```
|
|
70
|
+
>
|
|
71
|
+
> ## Call sequence
|
|
72
|
+
> | # | Method | Endpoint | Status | Time |
|
|
73
|
+
> |---|--------|----------|--------|------|
|
|
74
|
+
> | 1 | GET | `api.myapp.com/products` | 200 | 120ms |
|
|
75
|
+
> | 2 | POST | `api.myapp.com/cart/add` | 201 | 340ms |
|
|
76
|
+
|
|
77
|
+
β¦plus the full request and response details for each call. π
|
|
78
|
+
|
|
79
|
+
It's smart, too: it **throws away the boring noise** (images, fonts, styling,
|
|
80
|
+
tracking/analytics pixels) and keeps only the meaningful stuff. And it **hides your
|
|
81
|
+
passwords and login tokens** by default so you can share the doc safely.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## π First-time setup (do this once)
|
|
86
|
+
|
|
87
|
+
> β
**Using it through Claude or Cursor?** You can skip this whole section β just add the
|
|
88
|
+
> tiny config in [Connecting to Claude / Cursor](#-connecting-to-claude--cursor) and `npx`
|
|
89
|
+
> handles the rest. The steps below are only for the **Terminal / `bft` command** usage.
|
|
90
|
+
|
|
91
|
+
You need this **one-time** setup. It's two steps.
|
|
92
|
+
|
|
93
|
+
**1. Make sure you have Node.js.** Open the **Terminal** app and paste this:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
node --version
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If you see a number like `v18` or higher, you're good. If it says "command not found",
|
|
100
|
+
download Node from [nodejs.org](https://nodejs.org) and install it (just click Next β Next β Done).
|
|
101
|
+
|
|
102
|
+
**2. Install the tool's bits.** Paste this into Terminal:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
cd path/to/browser-flow-tracker # π the folder where this tool lives
|
|
106
|
+
npm install
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Wait a few seconds. Done forever. β
|
|
110
|
+
|
|
111
|
+
> π‘ **What's "Terminal"?** It's the app on your Mac where you type commands.
|
|
112
|
+
> Press `Cmd + Space`, type "Terminal", hit Enter.
|
|
113
|
+
|
|
114
|
+
> π **What do I put instead of `path/to/browser-flow-tracker`?** The easiest trick:
|
|
115
|
+
> type `cd ` (with a space), then **drag the tool's folder from Finder into the
|
|
116
|
+
> Terminal window** and hit Enter β the correct path fills itself in. From then on,
|
|
117
|
+
> the `cd ...` line is the same in every command below.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## π¬ How to use it β 3 ways
|
|
122
|
+
|
|
123
|
+
Pick whichever feels comfortable. They all produce the same nice files.
|
|
124
|
+
|
|
125
|
+
### Way 1: π£οΈ Just ask Claude or Cursor (easiest β zero commands)
|
|
126
|
+
|
|
127
|
+
Once the tool is connected (it already is β see [Connecting to Claude/Cursor](#-connecting-to-claude--cursor)),
|
|
128
|
+
you literally just **say the magic phrase**:
|
|
129
|
+
|
|
130
|
+
> ### *"Let's record the session for this url `https://your-website.com`"*
|
|
131
|
+
|
|
132
|
+
Here's what happens automatically:
|
|
133
|
+
|
|
134
|
+
1. πͺ The AI opens a **real browser window** at that URL (it picks a free port itself β
|
|
135
|
+
nothing for you to configure).
|
|
136
|
+
2. π±οΈ **You** click through the flow you want documented. *You* drive β the AI does not
|
|
137
|
+
click for you.
|
|
138
|
+
3. π When you're finished, either **say "done"** *or just **close the browser window***.
|
|
139
|
+
4. π The AI writes the `.flow.json` / `.har` / `.md` files and hands you a clean doc of
|
|
140
|
+
the APIs it saw.
|
|
141
|
+
|
|
142
|
+
You don't type a single command. β¨
|
|
143
|
+
|
|
144
|
+
> π **Logging in?** The window uses its own saved profile, so you only log in the
|
|
145
|
+
> **first** time β future recordings remember you.
|
|
146
|
+
|
|
147
|
+
> β οΈ **If your AI ignores the phrase** and starts poking around on its own instead of
|
|
148
|
+
> using the tool, you haven't installed the rule yet β see
|
|
149
|
+
> [Make your AI always use it](#-make-your-ai-always-use-it).
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### Way 2: π§Ό Let the tool open a browser for you (Terminal)
|
|
154
|
+
|
|
155
|
+
Paste this into Terminal (change the website):
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
cd path/to/browser-flow-tracker # π the folder where this tool lives
|
|
159
|
+
node bin/bft.js record --launch --browser brave --url https://your-website.com
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
A browser window pops open on its own **private profile** (it never touches your normal
|
|
163
|
+
Brave). **Click around, do the thing you want to document** β logging in if you need to.
|
|
164
|
+
When you're done, either press **`Ctrl + C`** in Terminal **or just close the browser
|
|
165
|
+
window** β both save the recording.
|
|
166
|
+
|
|
167
|
+
π₯ Your files appear in the `recordings/` folder.
|
|
168
|
+
|
|
169
|
+
> π You only log in the **first** time β the private profile remembers you for next time.
|
|
170
|
+
|
|
171
|
+
> Don't have Brave? Run `node bin/bft.js list` to see which browsers you have,
|
|
172
|
+
> then swap `brave` for `arc`, `chrome`, etc.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### Way 3: π Watch your *own* main browser (advanced)
|
|
177
|
+
|
|
178
|
+
Usually **Way 1 or Way 2 is enough** even for logged-in sites (you log in once in the
|
|
179
|
+
tool's own window and it's remembered). Use this only if you specifically need to record
|
|
180
|
+
inside your **existing, already-open** browser session.
|
|
181
|
+
|
|
182
|
+
**Step 1.** Ask the tool for the magic command:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
cd path/to/browser-flow-tracker # π the folder where this tool lives
|
|
186
|
+
node bin/bft.js attach-help brave
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
It prints an exact command β **copy it, quit Brave completely, and paste that command**
|
|
190
|
+
into Terminal. Brave reopens in "watch me" mode.
|
|
191
|
+
|
|
192
|
+
**Step 2.** Log in and go to where the flow starts. Then, in a **new** Terminal window:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
cd path/to/browser-flow-tracker # π the folder where this tool lives
|
|
196
|
+
node bin/bft.js record --attach --url-match your-website.com
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Step 3.** Do your thing in the browser, then press **`Ctrl + C`** in Terminal.
|
|
200
|
+
|
|
201
|
+
π₯ Files appear in `recordings/`.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## ποΈ Handy options
|
|
206
|
+
|
|
207
|
+
Add any of these to the end of a `record` command:
|
|
208
|
+
|
|
209
|
+
| Option | What it does | Example |
|
|
210
|
+
|--------|--------------|---------|
|
|
211
|
+
| `--name checkout` | Name the files `checkout` instead of a timestamp | `--name checkout` |
|
|
212
|
+
| `--out ~/Desktop/docs` | Save files somewhere else (like your Desktop) | `--out ~/Desktop/docs` |
|
|
213
|
+
| `--title "Checkout Flow"` | Give the document a proper title | `--title "Checkout Flow"` |
|
|
214
|
+
| `--url-match myapp` | Watch the correct browser tab | `--url-match myapp` |
|
|
215
|
+
| `--include-noise` | Keep *everything* (images, fonts, tracking too) | `--include-noise` |
|
|
216
|
+
| `--no-redact` | Show passwords/tokens (β οΈ don't share the file then) | `--no-redact` |
|
|
217
|
+
|
|
218
|
+
Full example:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
node bin/bft.js record --launch --browser brave \
|
|
222
|
+
--url https://shop.example.com \
|
|
223
|
+
--name checkout-flow \
|
|
224
|
+
--title "Shop Checkout Flow" \
|
|
225
|
+
--out ~/Desktop
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## π€ Connecting to Claude / Cursor
|
|
231
|
+
|
|
232
|
+
You give Claude/Cursor a tiny **settings snippet** that tells them how to run the tool.
|
|
233
|
+
There's nothing to download β it runs straight from npm with `npx`.
|
|
234
|
+
|
|
235
|
+
### The one snippet you need
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"mcpServers": {
|
|
240
|
+
"browser-flow-tracker": {
|
|
241
|
+
"command": "npx",
|
|
242
|
+
"args": ["-y", "browser-flow-tracker@latest"]
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
That's it β `npx` fetches and runs the tool automatically. It uses the browsers already
|
|
249
|
+
installed on your computer; nothing extra to install.
|
|
250
|
+
|
|
251
|
+
### Where to put it
|
|
252
|
+
|
|
253
|
+
- **Claude Code (easiest):** run this one command and it's added everywhere:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
claude mcp add browser-flow-tracker -- npx -y browser-flow-tracker@latest
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
(Or paste the snippet into a project's `.mcp.json`.)
|
|
260
|
+
|
|
261
|
+
- **Cursor:** open your MCP settings file and add the `browser-flow-tracker` block, then
|
|
262
|
+
restart Cursor and enable it in **Settings β MCP**. Your config lives at
|
|
263
|
+
`.cursor/mcp.json` (per project) or `~/.cursor/mcp.json` (global, all projects).
|
|
264
|
+
|
|
265
|
+
> β οΈ **Already using other MCP tools?** Don't replace your file β **add** the
|
|
266
|
+
> `browser-flow-tracker` block *inside* your existing `mcpServers`, with a **comma** after
|
|
267
|
+
> your previous tool. Valid JSON = matching `{ }` and commas between entries but not after
|
|
268
|
+
> the last one. The `claude mcp add` command above does this merge for you automatically.
|
|
269
|
+
|
|
270
|
+
Ready-made copies of the snippet are in this repo as `.mcp.json.example` and
|
|
271
|
+
`.cursor/mcp.json.example`.
|
|
272
|
+
|
|
273
|
+
### Prefer to run from source? (for the CLI or development)
|
|
274
|
+
|
|
275
|
+
You don't need this for the AI use case, but if you want the `bft` command-line tool or
|
|
276
|
+
want to hack on the code:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
git clone https://github.com/devggaurav/web-Api-scrapper.git
|
|
280
|
+
cd web-Api-scrapper
|
|
281
|
+
npm install
|
|
282
|
+
# MCP: point your config's command at "node" with args ["<full-path>/mcp/server.js"]
|
|
283
|
+
# CLI: node bin/bft.js record --launch --browser brave --url https://example.com
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
Behind the scenes it has four skills it uses automatically:
|
|
289
|
+
|
|
290
|
+
| Skill | What it does |
|
|
291
|
+
|-------|--------------|
|
|
292
|
+
| `list_browsers` | See which browsers you have |
|
|
293
|
+
| `start_tracking` | Start watching |
|
|
294
|
+
| `get_flow` | Peek at what's been captured so far (without stopping) |
|
|
295
|
+
| `stop_tracking` | Stop and save the files |
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## π§² Make your AI always use it
|
|
300
|
+
|
|
301
|
+
Sometimes an AI will "helpfully" try to analyze a page **its own way** (poking around with
|
|
302
|
+
scripts) instead of using this tool. To stop that, give it a standing rule so the phrase
|
|
303
|
+
**"let's record the session for this url β¦"** always triggers the tool. Do it once and it
|
|
304
|
+
works in every project.
|
|
305
|
+
|
|
306
|
+
### Cursor
|
|
307
|
+
|
|
308
|
+
Add a **User Rule** (applies in all projects): **Settings β Rules & Memories β User Rules
|
|
309
|
+
β + Add**, and paste:
|
|
310
|
+
|
|
311
|
+
```
|
|
312
|
+
When I say "let's record the session for this url <URL>" β or ask you to record/
|
|
313
|
+
analyze/document the API or network flow of a page β ALWAYS use the browser-flow-
|
|
314
|
+
tracker MCP tools (start_tracking, get_flow, stop_tracking). Do not launch browsers,
|
|
315
|
+
touch debug ports, or sniff traffic yourself.
|
|
316
|
+
Loop: call start_tracking with launch:true, browser:"brave", url:<URL>. Then let ME
|
|
317
|
+
navigate β do not click for me. The recording ends when I say "done" (call
|
|
318
|
+
stop_tracking with a name+title) OR I close the browser (it auto-finalizes; detect via
|
|
319
|
+
get_flow returning status:"ended"). Both write .flow.json/.har/.md β read the
|
|
320
|
+
.flow.json and write me a clean flow doc.
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
*(A copy of this rule also ships in `.cursor/rules/browser-flow-tracker.mdc`, which
|
|
324
|
+
applies automatically whenever you work inside this project.)*
|
|
325
|
+
|
|
326
|
+
### Claude Code
|
|
327
|
+
|
|
328
|
+
Add the same guidance to your **global** `~/.claude/CLAUDE.md` (create the file if it
|
|
329
|
+
doesn't exist) so it applies in every project. The exact text is in
|
|
330
|
+
[`.cursor/rules/browser-flow-tracker.mdc`](.cursor/rules/browser-flow-tracker.mdc) β copy
|
|
331
|
+
the body into `~/.claude/CLAUDE.md`.
|
|
332
|
+
|
|
333
|
+
> After adding a rule, **restart the AI app** so it picks it up.
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## β Common questions & fixes
|
|
338
|
+
|
|
339
|
+
**"My AI didn't use the tool β it started doing its own thing."**
|
|
340
|
+
You haven't given it the standing rule yet. See
|
|
341
|
+
[Make your AI always use it](#-make-your-ai-always-use-it), then restart the AI app.
|
|
342
|
+
|
|
343
|
+
**"How do I stop a recording?"**
|
|
344
|
+
Two ways, whichever you like: **say "done"** to your AI, **or just close the browser
|
|
345
|
+
window**. Both save the files automatically. (In Terminal, `Ctrl + C` also works.)
|
|
346
|
+
|
|
347
|
+
**"Do I have to log in every time?"**
|
|
348
|
+
No β the tool's browser window keeps its own saved profile, so you log in the **first**
|
|
349
|
+
time and it's remembered afterwards.
|
|
350
|
+
|
|
351
|
+
**"It says 'No known browsers found'."**
|
|
352
|
+
Run `node bin/bft.js list`. If it's empty, you don't have a supported browser
|
|
353
|
+
installed. Install Brave or Chrome (both free) and try again.
|
|
354
|
+
|
|
355
|
+
**"Nothing showed up in my recording."**
|
|
356
|
+
Make sure you actually *did the thing* in the browser before you stopped. Some pages need
|
|
357
|
+
a click or a page load to fire their APIs.
|
|
358
|
+
|
|
359
|
+
**"Where are my files again?"**
|
|
360
|
+
In the `recordings/` folder β unless you used `--out` (or the AI set a different location).
|
|
361
|
+
The tool prints the exact file paths when it finishes, and the AI can read them back to you.
|
|
362
|
+
|
|
363
|
+
**"Can I use Safari?"**
|
|
364
|
+
Not yet π β Safari and Firefox work differently under the hood. For now use Brave,
|
|
365
|
+
Chrome, Arc, or Edge. (Safari support is on the roadmap.)
|
|
366
|
+
|
|
367
|
+
**"Is it safe to share the document?"**
|
|
368
|
+
By default, **yes** β passwords, cookies, and login tokens are automatically hidden.
|
|
369
|
+
Only if you used `--no-redact` should you be careful.
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## π§ How it works (the 20-second version)
|
|
374
|
+
|
|
375
|
+
The tool speaks the same secret language browsers use to talk to their own developer
|
|
376
|
+
tools (it's called the "Chrome DevTools Protocol"). So it can listen in on every
|
|
377
|
+
network request a page makes β the same info you'd see in that scary DevTools tab β
|
|
378
|
+
and then it cleans it up, filters out the junk, and formats it into something a human
|
|
379
|
+
can actually read. That's it. π©
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## πΊοΈ Roadmap (coming later)
|
|
384
|
+
|
|
385
|
+
- π§ Safari & Firefox support (via a different listening method)
|
|
386
|
+
- πͺ Watch multiple browser tabs at once
|
|
387
|
+
- π "Diff" mode β compare two recordings to see what changed
|
|
388
|
+
- π§© Auto-group calls into logical steps in the doc
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
Made to save you from ever having to open the browser console again. Happy tracking! π΅οΈββοΈ
|
package/bin/bft.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// browser-flow-tracker CLI
|
|
3
|
+
|
|
4
|
+
import { TrackingSession } from '../src/session.js';
|
|
5
|
+
import { detectInstalled, resolveBrowser, UNSUPPORTED_CDP } from '../src/browsers.js';
|
|
6
|
+
|
|
7
|
+
function parseArgs(argv) {
|
|
8
|
+
const args = { _: [] };
|
|
9
|
+
for (let i = 0; i < argv.length; i++) {
|
|
10
|
+
const a = argv[i];
|
|
11
|
+
if (a.startsWith('--')) {
|
|
12
|
+
const key = a.slice(2);
|
|
13
|
+
const next = argv[i + 1];
|
|
14
|
+
if (next === undefined || next.startsWith('--')) {
|
|
15
|
+
args[key] = true;
|
|
16
|
+
} else {
|
|
17
|
+
args[key] = next;
|
|
18
|
+
i++;
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
args._.push(a);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return args;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const HELP = `browser-flow-tracker (bft) β record & document a page's API flow
|
|
28
|
+
|
|
29
|
+
USAGE
|
|
30
|
+
bft record [options] Record until you press Ctrl+C, then write outputs
|
|
31
|
+
bft list List Chromium browsers installed on this machine
|
|
32
|
+
bft attach-help [browser] Show how to start a browser for --attach mode
|
|
33
|
+
|
|
34
|
+
RECORD OPTIONS
|
|
35
|
+
--browser <id> brave | arc | chrome | edge | vivaldi | opera | chromium
|
|
36
|
+
--launch Launch a fresh browser (throwaway profile) with debugging on
|
|
37
|
+
--attach Attach to a browser already running with --remote-debugging-port
|
|
38
|
+
(default when --launch is not given)
|
|
39
|
+
--port <n> CDP port (default 9222)
|
|
40
|
+
--url <url> URL to open (only with --launch)
|
|
41
|
+
--url-match <s> When attaching, pick the tab whose URL contains this string
|
|
42
|
+
--headless Launch headless (only with --launch)
|
|
43
|
+
--out <dir> Output directory (default ./recordings)
|
|
44
|
+
--name <base> Output file basename (default flow-<timestamp>)
|
|
45
|
+
--title <t> Title for the generated Markdown doc
|
|
46
|
+
--include-noise Keep filtered (static/analytics) requests too
|
|
47
|
+
--no-redact Do NOT redact auth/cookie headers (default: redact)
|
|
48
|
+
|
|
49
|
+
EXAMPLES
|
|
50
|
+
# Launch Brave, open a page, record the flow, Ctrl+C to finish
|
|
51
|
+
bft record --launch --browser brave --url https://example.com
|
|
52
|
+
|
|
53
|
+
# Attach to the browser you're already logged into (see: bft attach-help brave)
|
|
54
|
+
bft record --attach --port 9222 --url-match myapp.com
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
async function cmdList() {
|
|
58
|
+
const found = detectInstalled();
|
|
59
|
+
if (!found.length) {
|
|
60
|
+
console.log('No known Chromium browsers found.');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
console.log('Installed Chromium browsers (CDP-capable):');
|
|
64
|
+
for (const { id, bin } of found) console.log(` ${id.padEnd(10)} ${bin}`);
|
|
65
|
+
console.log('\nNote: Safari/Firefox are not CDP-capable β proxy mode is on the roadmap.');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function cmdAttachHelp(browser) {
|
|
69
|
+
const id = browser || 'brave';
|
|
70
|
+
if (UNSUPPORTED_CDP[id]) {
|
|
71
|
+
console.log(UNSUPPORTED_CDP[id]);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
let bin;
|
|
75
|
+
try { bin = resolveBrowser(id); } catch (e) { console.error(e.message); process.exit(1); }
|
|
76
|
+
console.log(`To attach to your real ${id} session, fully quit ${id}, then run:\n`);
|
|
77
|
+
console.log(` "${bin}" --remote-debugging-port=9222\n`);
|
|
78
|
+
console.log('Then, in another terminal:\n');
|
|
79
|
+
console.log(' bft record --attach --port 9222 --url-match <part-of-your-app-url>\n');
|
|
80
|
+
console.log('Browse/click through the flow, then press Ctrl+C to write the recording.');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function cmdRecord(args) {
|
|
84
|
+
const launch = Boolean(args.launch) && !args.attach;
|
|
85
|
+
if (launch && !args.browser) {
|
|
86
|
+
console.error('--launch requires --browser <id>. Try: bft list');
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const session = new TrackingSession({
|
|
91
|
+
launch,
|
|
92
|
+
browser: args.browser,
|
|
93
|
+
port: args.port ? Number(args.port) : 9222,
|
|
94
|
+
url: typeof args.url === 'string' ? args.url : undefined,
|
|
95
|
+
urlMatch: typeof args['url-match'] === 'string' ? args['url-match'] : undefined,
|
|
96
|
+
headless: Boolean(args.headless),
|
|
97
|
+
includeNoise: Boolean(args['include-noise']),
|
|
98
|
+
redact: !args['no-redact'],
|
|
99
|
+
title: typeof args.title === 'string' ? args.title : undefined,
|
|
100
|
+
// Used if the user closes the browser instead of pressing Ctrl+C.
|
|
101
|
+
outDir: typeof args.out === 'string' ? args.out : undefined,
|
|
102
|
+
name: typeof args.name === 'string' ? args.name : undefined,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
console.log(launch ? `Launching ${args.browser}β¦` : `Attaching to CDP on port ${args.port || 9222}β¦`);
|
|
106
|
+
let info;
|
|
107
|
+
try {
|
|
108
|
+
info = await session.start();
|
|
109
|
+
} catch (e) {
|
|
110
|
+
console.error(`\nFailed to start: ${e.message}`);
|
|
111
|
+
if (!launch) console.error('\nIs the browser running with --remote-debugging-port? See: bft attach-help');
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
console.log(`Attached to: ${info.attachedTo?.url || '(page)'}`);
|
|
116
|
+
console.log('β Recordingβ¦ interact with the page, then press Ctrl+C β or just close the browser β to save.\n');
|
|
117
|
+
|
|
118
|
+
// Periodic live count so the user sees it's working. Also detects the user
|
|
119
|
+
// closing the browser (session auto-finalizes) and reports the written files.
|
|
120
|
+
const ticker = setInterval(() => {
|
|
121
|
+
if (session.finalized) {
|
|
122
|
+
clearInterval(ticker);
|
|
123
|
+
const { session: result, files } = session.finalized;
|
|
124
|
+
process.stdout.write('\n\nBrowser closed β recording saved.\n');
|
|
125
|
+
console.log(`\nCaptured ${result.stats.kept} API calls (${result.stats.droppedCount} filtered).`);
|
|
126
|
+
console.log('\nWrote:');
|
|
127
|
+
console.log(` JSON (for Claude/Cursor): ${files.json}`);
|
|
128
|
+
console.log(` HAR (DevTools/Postman): ${files.har}`);
|
|
129
|
+
console.log(` Doc (Markdown draft): ${files.markdown}`);
|
|
130
|
+
process.exit(0);
|
|
131
|
+
}
|
|
132
|
+
const snap = session.snapshot();
|
|
133
|
+
process.stdout.write(`\r ${snap.stats.kept || 0} API calls captured⦠`);
|
|
134
|
+
}, 1000);
|
|
135
|
+
|
|
136
|
+
const finish = async () => {
|
|
137
|
+
clearInterval(ticker);
|
|
138
|
+
process.stdout.write('\n\nStoppingβ¦\n');
|
|
139
|
+
try {
|
|
140
|
+
const { session: result, files } = await session.stop({
|
|
141
|
+
outDir: typeof args.out === 'string' ? args.out : undefined,
|
|
142
|
+
name: typeof args.name === 'string' ? args.name : undefined,
|
|
143
|
+
closeBrowser: launch,
|
|
144
|
+
});
|
|
145
|
+
console.log(`\nCaptured ${result.stats.kept} API calls (${result.stats.droppedCount} filtered).`);
|
|
146
|
+
console.log('\nWrote:');
|
|
147
|
+
console.log(` JSON (for Claude/Cursor): ${files.json}`);
|
|
148
|
+
console.log(` HAR (DevTools/Postman): ${files.har}`);
|
|
149
|
+
console.log(` Doc (Markdown draft): ${files.markdown}`);
|
|
150
|
+
} catch (e) {
|
|
151
|
+
console.error(`Error while stopping: ${e.message}`);
|
|
152
|
+
}
|
|
153
|
+
process.exit(0);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
process.on('SIGINT', finish);
|
|
157
|
+
process.on('SIGTERM', finish);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function main() {
|
|
161
|
+
const args = parseArgs(process.argv.slice(2));
|
|
162
|
+
const cmd = args._[0];
|
|
163
|
+
switch (cmd) {
|
|
164
|
+
case 'record': return cmdRecord(args);
|
|
165
|
+
case 'list': return cmdList();
|
|
166
|
+
case 'attach-help': return cmdAttachHelp(args._[1]);
|
|
167
|
+
case undefined:
|
|
168
|
+
case 'help':
|
|
169
|
+
case '--help':
|
|
170
|
+
case '-h':
|
|
171
|
+
console.log(HELP);
|
|
172
|
+
return;
|
|
173
|
+
default:
|
|
174
|
+
console.error(`Unknown command: ${cmd}\n`);
|
|
175
|
+
console.log(HELP);
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
main().catch((e) => {
|
|
181
|
+
console.error(e);
|
|
182
|
+
process.exit(1);
|
|
183
|
+
});
|