browser-pilot 0.0.3 → 0.0.5

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/dist/cli.cjs CHANGED
@@ -214,6 +214,142 @@ async function actionsCommand() {
214
214
  console.log(ACTIONS_HELP);
215
215
  }
216
216
 
217
+ // src/cli/session.ts
218
+ var import_node_os = require("os");
219
+ var import_node_path = require("path");
220
+ var SESSION_DIR = (0, import_node_path.join)((0, import_node_os.homedir)(), ".browser-pilot", "sessions");
221
+ async function ensureSessionDir() {
222
+ const fs = await import("fs/promises");
223
+ await fs.mkdir(SESSION_DIR, { recursive: true });
224
+ }
225
+ async function saveSession(session) {
226
+ await ensureSessionDir();
227
+ const fs = await import("fs/promises");
228
+ const filePath = (0, import_node_path.join)(SESSION_DIR, `${session.id}.json`);
229
+ await fs.writeFile(filePath, JSON.stringify(session, null, 2));
230
+ }
231
+ async function loadSession(id) {
232
+ const fs = await import("fs/promises");
233
+ const filePath = (0, import_node_path.join)(SESSION_DIR, `${id}.json`);
234
+ try {
235
+ const content = await fs.readFile(filePath, "utf-8");
236
+ return JSON.parse(content);
237
+ } catch (error) {
238
+ if (error.code === "ENOENT") {
239
+ throw new Error(`Session not found: ${id}`);
240
+ }
241
+ throw error;
242
+ }
243
+ }
244
+ async function updateSession(id, updates) {
245
+ const session = await loadSession(id);
246
+ const mergedMetadata = updates.metadata !== void 0 ? { ...session.metadata ?? {}, ...updates.metadata ?? {} } : session.metadata;
247
+ const updated = {
248
+ ...session,
249
+ ...updates,
250
+ metadata: mergedMetadata,
251
+ lastActivity: (/* @__PURE__ */ new Date()).toISOString()
252
+ };
253
+ await saveSession(updated);
254
+ return updated;
255
+ }
256
+ async function deleteSession(id) {
257
+ const fs = await import("fs/promises");
258
+ const filePath = (0, import_node_path.join)(SESSION_DIR, `${id}.json`);
259
+ try {
260
+ await fs.unlink(filePath);
261
+ } catch (error) {
262
+ if (error.code !== "ENOENT") {
263
+ throw error;
264
+ }
265
+ }
266
+ }
267
+ async function listSessions() {
268
+ await ensureSessionDir();
269
+ const fs = await import("fs/promises");
270
+ try {
271
+ const files = await fs.readdir(SESSION_DIR);
272
+ const sessions = [];
273
+ for (const file of files) {
274
+ if (file.endsWith(".json")) {
275
+ try {
276
+ const content = await fs.readFile((0, import_node_path.join)(SESSION_DIR, file), "utf-8");
277
+ sessions.push(JSON.parse(content));
278
+ } catch {
279
+ }
280
+ }
281
+ }
282
+ return sessions.sort(
283
+ (a, b) => new Date(b.lastActivity).getTime() - new Date(a.lastActivity).getTime()
284
+ );
285
+ } catch {
286
+ return [];
287
+ }
288
+ }
289
+ function generateSessionId() {
290
+ const timestamp = Date.now().toString(36);
291
+ const random = Math.random().toString(36).slice(2, 8);
292
+ return `${timestamp}-${random}`;
293
+ }
294
+ async function getDefaultSession() {
295
+ const sessions = await listSessions();
296
+ return sessions[0] ?? null;
297
+ }
298
+
299
+ // src/cli/commands/clean.ts
300
+ function parseCleanArgs(args) {
301
+ const options = {};
302
+ for (let i = 0; i < args.length; i++) {
303
+ const arg = args[i];
304
+ if (arg === "--max-age") {
305
+ const value = args[++i];
306
+ options.maxAge = parseInt(value ?? "24", 10);
307
+ } else if (arg === "--dry-run") {
308
+ options.dryRun = true;
309
+ } else if (arg === "--all") {
310
+ options.all = true;
311
+ }
312
+ }
313
+ return options;
314
+ }
315
+ async function cleanCommand(args, globalOptions) {
316
+ const options = parseCleanArgs(args);
317
+ const maxAgeMs = (options.maxAge ?? 24) * 60 * 60 * 1e3;
318
+ const now = Date.now();
319
+ const sessions = await listSessions();
320
+ const stale = sessions.filter((s) => {
321
+ if (options.all) return true;
322
+ const age = now - new Date(s.lastActivity).getTime();
323
+ return age > maxAgeMs;
324
+ });
325
+ if (stale.length === 0) {
326
+ output({ message: "No stale sessions found", cleaned: 0 }, globalOptions.output);
327
+ return;
328
+ }
329
+ if (options.dryRun) {
330
+ output(
331
+ {
332
+ message: `Would clean ${stale.length} session(s)`,
333
+ sessions: stale.map((s) => s.id),
334
+ dryRun: true
335
+ },
336
+ globalOptions.output
337
+ );
338
+ return;
339
+ }
340
+ for (const session of stale) {
341
+ await deleteSession(session.id);
342
+ }
343
+ output(
344
+ {
345
+ message: `Cleaned ${stale.length} session(s)`,
346
+ cleaned: stale.length,
347
+ sessions: stale.map((s) => s.id)
348
+ },
349
+ globalOptions.output
350
+ );
351
+ }
352
+
217
353
  // src/actions/executor.ts
218
354
  var DEFAULT_TIMEOUT = 3e4;
219
355
  var BatchExecutor = class {
@@ -299,7 +435,8 @@ var BatchExecutor = class {
299
435
  await this.page.fill(step.selector, step.value, {
300
436
  timeout,
301
437
  optional,
302
- clear: step.clear ?? true
438
+ clear: step.clear ?? true,
439
+ blur: step.blur
303
440
  });
304
441
  return { selectorUsed: this.getUsedSelector(step.selector) };
305
442
  }
@@ -1477,7 +1614,7 @@ var Page = class {
1477
1614
  * Fill an input field (clears first by default)
1478
1615
  */
1479
1616
  async fill(selector, value, options = {}) {
1480
- const { clear = true } = options;
1617
+ const { clear = true, blur = false } = options;
1481
1618
  return this.withStaleNodeRetry(async () => {
1482
1619
  const element = await this.findElement(selector, options);
1483
1620
  if (!element) {
@@ -1491,7 +1628,11 @@ var Page = class {
1491
1628
  const el = document.querySelector(${JSON.stringify(element.selector)});
1492
1629
  if (el) {
1493
1630
  el.value = '';
1494
- el.dispatchEvent(new Event('input', { bubbles: true }));
1631
+ el.dispatchEvent(new InputEvent('input', {
1632
+ bubbles: true,
1633
+ cancelable: true,
1634
+ inputType: 'deleteContent'
1635
+ }));
1495
1636
  }
1496
1637
  })()`
1497
1638
  );
@@ -1501,11 +1642,21 @@ var Page = class {
1501
1642
  `(() => {
1502
1643
  const el = document.querySelector(${JSON.stringify(element.selector)});
1503
1644
  if (el) {
1504
- el.dispatchEvent(new Event('input', { bubbles: true }));
1645
+ el.dispatchEvent(new InputEvent('input', {
1646
+ bubbles: true,
1647
+ cancelable: true,
1648
+ inputType: 'insertText',
1649
+ data: ${JSON.stringify(value)}
1650
+ }));
1505
1651
  el.dispatchEvent(new Event('change', { bubbles: true }));
1506
1652
  }
1507
1653
  })()`
1508
1654
  );
1655
+ if (blur) {
1656
+ await this.evaluateInFrame(
1657
+ `document.querySelector(${JSON.stringify(element.selector)})?.blur()`
1658
+ );
1659
+ }
1509
1660
  return true;
1510
1661
  });
1511
1662
  }
@@ -2974,88 +3125,6 @@ function connect(options) {
2974
3125
  return Browser.connect(options);
2975
3126
  }
2976
3127
 
2977
- // src/cli/session.ts
2978
- var import_node_os = require("os");
2979
- var import_node_path = require("path");
2980
- var SESSION_DIR = (0, import_node_path.join)((0, import_node_os.homedir)(), ".browser-pilot", "sessions");
2981
- async function ensureSessionDir() {
2982
- const fs = await import("fs/promises");
2983
- await fs.mkdir(SESSION_DIR, { recursive: true });
2984
- }
2985
- async function saveSession(session) {
2986
- await ensureSessionDir();
2987
- const fs = await import("fs/promises");
2988
- const filePath = (0, import_node_path.join)(SESSION_DIR, `${session.id}.json`);
2989
- await fs.writeFile(filePath, JSON.stringify(session, null, 2));
2990
- }
2991
- async function loadSession(id) {
2992
- const fs = await import("fs/promises");
2993
- const filePath = (0, import_node_path.join)(SESSION_DIR, `${id}.json`);
2994
- try {
2995
- const content = await fs.readFile(filePath, "utf-8");
2996
- return JSON.parse(content);
2997
- } catch (error) {
2998
- if (error.code === "ENOENT") {
2999
- throw new Error(`Session not found: ${id}`);
3000
- }
3001
- throw error;
3002
- }
3003
- }
3004
- async function updateSession(id, updates) {
3005
- const session = await loadSession(id);
3006
- const mergedMetadata = updates.metadata !== void 0 ? { ...session.metadata ?? {}, ...updates.metadata ?? {} } : session.metadata;
3007
- const updated = {
3008
- ...session,
3009
- ...updates,
3010
- metadata: mergedMetadata,
3011
- lastActivity: (/* @__PURE__ */ new Date()).toISOString()
3012
- };
3013
- await saveSession(updated);
3014
- return updated;
3015
- }
3016
- async function deleteSession(id) {
3017
- const fs = await import("fs/promises");
3018
- const filePath = (0, import_node_path.join)(SESSION_DIR, `${id}.json`);
3019
- try {
3020
- await fs.unlink(filePath);
3021
- } catch (error) {
3022
- if (error.code !== "ENOENT") {
3023
- throw error;
3024
- }
3025
- }
3026
- }
3027
- async function listSessions() {
3028
- await ensureSessionDir();
3029
- const fs = await import("fs/promises");
3030
- try {
3031
- const files = await fs.readdir(SESSION_DIR);
3032
- const sessions = [];
3033
- for (const file of files) {
3034
- if (file.endsWith(".json")) {
3035
- try {
3036
- const content = await fs.readFile((0, import_node_path.join)(SESSION_DIR, file), "utf-8");
3037
- sessions.push(JSON.parse(content));
3038
- } catch {
3039
- }
3040
- }
3041
- }
3042
- return sessions.sort(
3043
- (a, b) => new Date(b.lastActivity).getTime() - new Date(a.lastActivity).getTime()
3044
- );
3045
- } catch {
3046
- return [];
3047
- }
3048
- }
3049
- function generateSessionId() {
3050
- const timestamp = Date.now().toString(36);
3051
- const random = Math.random().toString(36).slice(2, 8);
3052
- return `${timestamp}-${random}`;
3053
- }
3054
- async function getDefaultSession() {
3055
- const sessions = await listSessions();
3056
- return sessions[0] ?? null;
3057
- }
3058
-
3059
3128
  // src/cli/commands/close.ts
3060
3129
  async function closeCommand(args, globalOptions) {
3061
3130
  let session;
@@ -3174,6 +3243,17 @@ async function connectCommand(args, globalOptions) {
3174
3243
  }
3175
3244
 
3176
3245
  // src/cli/commands/exec.ts
3246
+ async function validateSession(session) {
3247
+ try {
3248
+ const wsUrl = new URL(session.wsUrl);
3249
+ const protocol = wsUrl.protocol === "wss:" ? "https:" : "http:";
3250
+ const httpUrl = `${protocol}//${wsUrl.host}/json/version`;
3251
+ const response = await fetch(httpUrl, { signal: AbortSignal.timeout(3e3) });
3252
+ return response.ok;
3253
+ } catch {
3254
+ return false;
3255
+ }
3256
+ }
3177
3257
  function parseExecArgs(args) {
3178
3258
  const options = {};
3179
3259
  let actionsJson;
@@ -3194,15 +3274,6 @@ function parseExecArgs(args) {
3194
3274
  }
3195
3275
  async function execCommand(args, globalOptions) {
3196
3276
  const { actionsJson, options: execOptions } = parseExecArgs(args);
3197
- let session;
3198
- if (globalOptions.session) {
3199
- session = await loadSession(globalOptions.session);
3200
- } else {
3201
- session = await getDefaultSession();
3202
- if (!session) {
3203
- throw new Error('No session found. Run "bp connect" first.');
3204
- }
3205
- }
3206
3277
  if (!actionsJson) {
3207
3278
  throw new Error(
3208
3279
  `No actions provided. Usage: bp exec '{"action":"goto","url":"..."}'
@@ -3218,6 +3289,23 @@ Run 'bp actions' for complete action reference.`
3218
3289
  "Invalid JSON. Actions must be valid JSON.\n\nRun 'bp actions' for complete action reference."
3219
3290
  );
3220
3291
  }
3292
+ let session;
3293
+ if (globalOptions.session) {
3294
+ session = await loadSession(globalOptions.session);
3295
+ } else {
3296
+ session = await getDefaultSession();
3297
+ if (!session) {
3298
+ throw new Error('No session found. Run "bp connect" first.');
3299
+ }
3300
+ }
3301
+ const isValid = await validateSession(session);
3302
+ if (!isValid) {
3303
+ await deleteSession(session.id);
3304
+ throw new Error(
3305
+ `Session "${session.id}" is no longer valid (browser may have closed).
3306
+ Session file has been cleaned up. Run "bp connect" to create a new session.`
3307
+ );
3308
+ }
3221
3309
  const browser = await connect({
3222
3310
  provider: session.provider,
3223
3311
  wsUrl: session.wsUrl,
@@ -3317,67 +3405,62 @@ function getAge(date) {
3317
3405
 
3318
3406
  // src/cli/commands/quickstart.ts
3319
3407
  var QUICKSTART = `
3320
- browser-pilot - CDP-based browser automation for AI agents
3321
-
3322
- Zero production dependencies. Works in Node.js, Bun, and Cloudflare Workers.
3323
-
3324
- RUNNING
3325
- npx browser-pilot ... # Node.js projects
3326
- bunx browser-pilot ... # Bun projects (faster)
3327
-
3328
- CONNECTING
3329
- npx browser-pilot connect <wsUrl> Connect to existing browser
3330
- npx browser-pilot connect --provider browserbase --api-key <key>
3331
-
3332
- BASIC USAGE (Code)
3333
- import { Browser } from 'browser-pilot';
3334
-
3335
- const browser = await Browser.connect({ wsUrl: '...' });
3336
- const page = await browser.newPage();
3337
- await page.goto('https://example.com');
3338
- await page.click('#button');
3339
- await page.fill('#input', 'text');
3340
- await browser.close();
3341
-
3342
- KEY PATTERNS
3343
- Multi-Selector await page.click(['#primary', '.fallback', 'button']);
3344
- Smart Waiting Every action waits for visibility automatically
3345
- Optional Actions await page.click('#banner', { optional: true });
3346
-
3347
- BATCH EXECUTION
3348
- await page.batch([
3349
- { action: 'goto', url: 'https://example.com' },
3350
- { action: 'fill', selector: '#email', value: 'test@test.com' },
3351
- { action: 'submit', selector: 'form' },
3352
- ]);
3353
-
3354
- SNAPSHOTS (FOR AI AGENTS)
3355
- const snapshot = await page.snapshot();
3356
- // Returns accessibility tree with refs: e1, e2, e3...
3357
- await page.click({ ref: 'e5' });
3358
-
3359
- PROVIDERS
3360
- BrowserBase Browser.connect({ provider: 'browserbase', apiKey })
3361
- Browserless Browser.connect({ provider: 'browserless', apiKey })
3362
- Generic Browser.connect({ wsUrl: 'ws://...' })
3408
+ browser-pilot CLI - Quick Start Guide
3409
+
3410
+ STEP 1: CONNECT TO A BROWSER
3411
+ bp connect --provider generic --name mysite
3412
+
3413
+ This creates a session. The CLI remembers it for subsequent commands.
3414
+
3415
+ STEP 2: NAVIGATE
3416
+ bp exec '{"action":"goto","url":"https://example.com"}'
3417
+
3418
+ STEP 3: GET PAGE SNAPSHOT
3419
+ bp snapshot --format text
3420
+
3421
+ Output shows the page as an accessibility tree with element refs:
3422
+ - heading "Welcome" [ref=e1]
3423
+ - button "Sign In" [ref=e2]
3424
+ - textbox "Email" [ref=e3]
3425
+
3426
+ STEP 4: INTERACT USING REFS
3427
+ bp exec '{"action":"fill","selector":"ref:e3","value":"test@example.com"}'
3428
+ bp exec '{"action":"click","selector":"ref:e2"}'
3429
+
3430
+ STEP 5: BATCH MULTIPLE ACTIONS
3431
+ bp exec '[
3432
+ {"action":"fill","selector":"ref:e3","value":"user@test.com"},
3433
+ {"action":"click","selector":"ref:e2"},
3434
+ {"action":"snapshot"}
3435
+ ]'
3436
+
3437
+ FOR AI AGENTS
3438
+ Use -o json for machine-readable output:
3439
+ bp snapshot --format text -o json
3440
+ bp exec '{"action":"click","selector":"ref:e3"}' -o json
3441
+
3442
+ TIPS
3443
+ \u2022 Refs (e1, e2...) are stable within a page - prefer them over CSS selectors
3444
+ \u2022 After navigation, take a new snapshot to get updated refs
3445
+ \u2022 Use multi-selectors for resilience: ["ref:e3", "#email", "input[type=email]"]
3446
+ \u2022 Add "optional":true to skip elements that may not exist
3447
+
3448
+ SELECTOR PRIORITY
3449
+ 1. ref:e5 From snapshot - most reliable
3450
+ 2. #id CSS ID selector
3451
+ 3. [data-testid] Test attributes
3452
+ 4. .class CSS class (less stable)
3363
3453
 
3364
3454
  COMMON ACTIONS
3365
- page.goto(url) Navigate to URL
3366
- page.click(selector) Click element
3367
- page.fill(selector, value) Fill input field
3368
- page.submit(selector) Submit form
3369
- page.select(selector, val) Select dropdown option
3370
- page.screenshot() Capture screenshot
3371
- page.snapshot() Get accessibility tree
3372
-
3373
- AGENT INTEGRATION
3374
- - Use snapshot() to get page state as accessibility tree
3375
- - Refs (e1, e2...) identify elements without fragile selectors
3376
- - Multi-selector arrays handle UI variations
3377
- - optional: true prevents failures on transient elements
3378
-
3379
- Ready to automate!
3380
- Run: npx browser-pilot connect <wsUrl>
3455
+ goto {"action":"goto","url":"https://..."}
3456
+ click {"action":"click","selector":"ref:e3"}
3457
+ fill {"action":"fill","selector":"ref:e3","value":"text"}
3458
+ submit {"action":"submit","selector":"form"}
3459
+ select {"action":"select","selector":"ref:e5","value":"option"}
3460
+ snapshot {"action":"snapshot"}
3461
+ screenshot {"action":"screenshot"}
3462
+
3463
+ Run 'bp actions' for the complete action reference.
3381
3464
  `;
3382
3465
  async function quickstartCommand() {
3383
3466
  console.log(QUICKSTART);
@@ -3553,56 +3636,31 @@ Usage:
3553
3636
  bp <command> [options]
3554
3637
 
3555
3638
  Commands:
3556
- quickstart Show getting started guide
3557
- connect Create or resume browser session
3558
- exec Execute actions on current session
3559
- snapshot Get page accessibility snapshot (includes element refs)
3560
- text Extract text content from page
3639
+ quickstart Getting started guide (start here!)
3640
+ connect Create browser session
3641
+ exec Execute actions
3642
+ snapshot Get page with element refs
3643
+ text Extract text content
3561
3644
  screenshot Take screenshot
3562
3645
  close Close session
3563
- list List all sessions
3564
- actions Show all available actions with examples
3565
-
3566
- Global Options:
3567
- -s, --session <id> Session ID to use
3568
- -o, --output <fmt> Output format: json | pretty (default: pretty)
3569
- --trace Enable execution tracing
3570
- -h, --help Show this help message
3646
+ list List sessions
3647
+ clean Clean up old sessions
3648
+ actions Complete action reference
3571
3649
 
3572
- Exec Options:
3573
- --dialog <mode> Auto-handle dialogs: accept | dismiss
3574
-
3575
- Ref Selectors (Recommended for AI Agents):
3576
- 1. Navigate + snapshot: bp exec '[{"action":"goto","url":"..."},{"action":"snapshot"}]'
3577
- Output shows: button "Submit" [ref=e4], textbox "Email" [ref=e5]
3578
- 2. Use refs (snapshot cached for same session+URL):
3579
- bp exec '[{"action":"click","selector":"ref:e4"}]'
3580
-
3581
- Refs are cached per session+URL after snapshot. Use new snapshot after navigation.
3582
- Combine with CSS fallbacks:
3583
- {"selector": ["ref:e4", "#submit", "button[type=submit]"]}
3650
+ Options:
3651
+ -s, --session <id> Session ID
3652
+ -o, --output <fmt> json | pretty (default: pretty)
3653
+ --trace Enable debug tracing
3654
+ --dialog <mode> Handle dialogs: accept | dismiss
3655
+ -h, --help Show help
3584
3656
 
3585
3657
  Examples:
3586
- # Connect to browser
3587
3658
  bp connect --provider generic --name dev
3659
+ bp exec '{"action":"goto","url":"https://example.com"}'
3660
+ bp snapshot --format text
3661
+ bp exec '{"action":"click","selector":"ref:e3"}'
3588
3662
 
3589
- # Navigate and get snapshot with refs
3590
- bp exec '[{"action":"goto","url":"https://example.com"},{"action":"snapshot"}]'
3591
-
3592
- # Use refs (snapshot cached for same session+URL)
3593
- bp exec '[{"action":"fill","selector":"ref:e5","value":"test@example.com"},{"action":"click","selector":"ref:e4"}]'
3594
-
3595
- # Handle native dialogs (alert/confirm/prompt)
3596
- bp exec --dialog accept '{"action":"click","selector":"#delete-btn"}'
3597
-
3598
- # Batch multiple actions (snapshot optional if already cached)
3599
- bp exec '[
3600
- {"action":"snapshot"},
3601
- {"action":"fill","selector":"ref:e5","value":"user@example.com"},
3602
- {"action":"click","selector":"ref:e4"},
3603
- {"action":"snapshot"}
3604
- ]'
3605
-
3663
+ Run 'bp quickstart' for CLI workflow guide.
3606
3664
  Run 'bp actions' for complete action reference.
3607
3665
  `;
3608
3666
  function parseGlobalOptions(args) {
@@ -3633,7 +3691,10 @@ function output(data, format = "pretty") {
3633
3691
  if (typeof data === "string") {
3634
3692
  console.log(data);
3635
3693
  } else if (typeof data === "object" && data !== null) {
3636
- prettyPrint(data);
3694
+ const { truncated } = prettyPrint(data);
3695
+ if (truncated) {
3696
+ console.log("\n(Output truncated. Use -o json for full data)");
3697
+ }
3637
3698
  } else {
3638
3699
  console.log(data);
3639
3700
  }
@@ -3641,16 +3702,20 @@ function output(data, format = "pretty") {
3641
3702
  }
3642
3703
  function prettyPrint(obj, indent = 0) {
3643
3704
  const prefix = " ".repeat(indent);
3705
+ let truncated = false;
3644
3706
  for (const [key, value] of Object.entries(obj)) {
3645
3707
  if (typeof value === "object" && value !== null && !Array.isArray(value)) {
3646
3708
  console.log(`${prefix}${key}:`);
3647
- prettyPrint(value, indent + 1);
3709
+ const result = prettyPrint(value, indent + 1);
3710
+ if (result.truncated) truncated = true;
3648
3711
  } else if (Array.isArray(value)) {
3649
3712
  console.log(`${prefix}${key}: [${value.length} items]`);
3713
+ truncated = true;
3650
3714
  } else {
3651
3715
  console.log(`${prefix}${key}: ${value}`);
3652
3716
  }
3653
3717
  }
3718
+ return { truncated };
3654
3719
  }
3655
3720
  async function main() {
3656
3721
  const args = process.argv.slice(2);
@@ -3690,6 +3755,9 @@ async function main() {
3690
3755
  case "list":
3691
3756
  await listCommand(remaining, options);
3692
3757
  break;
3758
+ case "clean":
3759
+ await cleanCommand(remaining, options);
3760
+ break;
3693
3761
  case "actions":
3694
3762
  await actionsCommand();
3695
3763
  break;
package/dist/cli.d.cts CHANGED
@@ -15,6 +15,7 @@
15
15
  * screenshot Take screenshot
16
16
  * close Close session
17
17
  * list List sessions
18
+ * clean Clean up old sessions
18
19
  * actions Complete action reference
19
20
  *
20
21
  * Run 'bp quickstart' for getting started guide.
package/dist/cli.d.ts CHANGED
@@ -15,6 +15,7 @@
15
15
  * screenshot Take screenshot
16
16
  * close Close session
17
17
  * list List sessions
18
+ * clean Clean up old sessions
18
19
  * actions Complete action reference
19
20
  *
20
21
  * Run 'bp quickstart' for getting started guide.