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 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
+ [![npm version](https://img.shields.io/npm/v/browser-flow-tracker.svg)](https://www.npmjs.com/package/browser-flow-tracker)
4
+ [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](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
+ });