@browserbasehq/browse-cli 0.4.2 → 0.5.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 (3) hide show
  1. package/README.md +12 -11
  2. package/dist/index.js +128 -39
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -173,22 +173,23 @@ browse env
173
173
  # Switch current session to Browserbase (restarts daemon if needed)
174
174
  browse env remote
175
175
 
176
- # Switch back to local Chrome (auto-discovers existing Chrome, falls back to isolated)
176
+ # Switch back to local Chrome (clean isolated browser by default)
177
177
  browse env local
178
178
  ```
179
179
 
180
180
  #### Local Browser Strategies
181
181
 
182
- By default, `browse env local` auto-discovers an already-running Chrome with remote
183
- debugging enabled. This lets agents use your existing cookies, logins, and browser state.
184
- If no debuggable Chrome is found, it falls back to launching an isolated browser.
182
+ By default, `browse env local` launches a clean isolated local browser.
183
+ Use `browse env local --auto-connect` to opt into reusing an already-running
184
+ Chrome with remote debugging enabled. If no debuggable Chrome is found, it
185
+ falls back to launching an isolated browser.
185
186
 
186
187
  ```bash
187
- # Auto-discover local Chrome, fallback to isolated (default)
188
+ # Use a clean isolated browser (default)
188
189
  browse env local
189
190
 
190
- # Force a clean isolated browser (no auto-discovery)
191
- browse env local --isolated
191
+ # Auto-discover local Chrome, fallback to isolated
192
+ browse env local --auto-connect
192
193
 
193
194
  # Attach to a specific CDP target (port or URL)
194
195
  browse env local 9222
@@ -210,7 +211,7 @@ Use `browse status` to see which strategy was resolved:
210
211
 
211
212
  ```bash
212
213
  browse status
213
- # {"running":true,"session":"default","mode":"local","localStrategy":"auto","localSource":"attached-existing","resolvedCdpUrl":"ws://..."}
214
+ # {"running":true,"session":"default","mode":"local","localStrategy":"isolated","localSource":"isolated"}
214
215
  ```
215
216
 
216
217
  #### General Behavior
@@ -283,19 +284,19 @@ browse --session personal open https://twitter.com
283
284
 
284
285
  ## Direct CDP Connection
285
286
 
286
- Connect to an existing Chrome instance:
287
+ Opt into using an existing Chrome instance:
287
288
 
288
289
  To make your Chrome discoverable:
289
290
 
290
291
  1. Open `chrome://inspect/#remote-debugging`
291
292
  2. Check the box **"Allow remote debugging for this browser instance"**
292
- 3. Re-run the CLI and it will auto-connect!
293
+ 3. Re-run the CLI with auto-connect enabled.
293
294
 
294
295
  For more information, see the [Chrome DevTools docs](https://developer.chrome.com/blog/chrome-devtools-mcp-debug-your-browser-session).
295
296
 
296
297
  ```bash
297
298
  # Auto-discover Chrome with remote debugging enabled
298
- browse env local
299
+ browse env local --auto-connect
299
300
  browse open https://example.com
300
301
 
301
302
  # Or target a specific port / WebSocket URL
package/dist/index.js CHANGED
@@ -164652,7 +164652,72 @@ var import_child_process4 = require("child_process");
164652
164652
  var readline = __toESM(require("readline"));
164653
164653
 
164654
164654
  // package.json
164655
- var version3 = "0.4.2";
164655
+ var version3 = "0.5.0";
164656
+
164657
+ // src/local-strategy.ts
164658
+ init_cjs_shims();
164659
+ var DEFAULT_LOCAL_CONFIG = { strategy: "isolated" };
164660
+ var ISOLATED_MODE_HINT = "Hint: Run `browse env local --auto-connect` to reuse your local browsing credentials and cookies.";
164661
+ var ATTACHED_EXISTING_HINT = "Hint: Run `browse env local` without `--auto-connect` to switch back to an isolated Chromium browser.";
164662
+ function getLocalModeHint(localConfig, localInfo) {
164663
+ if (localInfo?.localSource === "attached-existing") {
164664
+ return ATTACHED_EXISTING_HINT;
164665
+ }
164666
+ if (localInfo?.localSource === "isolated-fallback") {
164667
+ return null;
164668
+ }
164669
+ if (localConfig.strategy === "auto" && !localInfo) {
164670
+ return ATTACHED_EXISTING_HINT;
164671
+ }
164672
+ if (localInfo?.localSource === "isolated" || localConfig.strategy === "isolated" && !localInfo) {
164673
+ return ISOLATED_MODE_HINT;
164674
+ }
164675
+ return null;
164676
+ }
164677
+ async function resolveLocalStrategy({
164678
+ localConfig,
164679
+ headless,
164680
+ defaultViewport,
164681
+ discoverLocalCdp: discoverLocalCdp2,
164682
+ resolveWsTarget: resolveWsTarget2
164683
+ }) {
164684
+ if (localConfig.strategy === "isolated") {
164685
+ return {
164686
+ localLaunchOptions: { headless, viewport: defaultViewport },
164687
+ localInfo: { localSource: "isolated" }
164688
+ };
164689
+ }
164690
+ if (localConfig.strategy === "cdp") {
164691
+ if (!localConfig.cdpTarget) {
164692
+ throw new Error("Local CDP strategy requires a cdpTarget");
164693
+ }
164694
+ const cdpUrl = await resolveWsTarget2(localConfig.cdpTarget);
164695
+ return {
164696
+ localLaunchOptions: { cdpUrl },
164697
+ localInfo: {
164698
+ localSource: "attached-explicit",
164699
+ resolvedCdpUrl: cdpUrl
164700
+ }
164701
+ };
164702
+ }
164703
+ const discovered = await discoverLocalCdp2();
164704
+ if (discovered) {
164705
+ return {
164706
+ localLaunchOptions: { cdpUrl: discovered.wsUrl },
164707
+ localInfo: {
164708
+ localSource: "attached-existing",
164709
+ resolvedCdpUrl: discovered.wsUrl
164710
+ }
164711
+ };
164712
+ }
164713
+ return {
164714
+ localLaunchOptions: { headless, viewport: defaultViewport },
164715
+ localInfo: {
164716
+ localSource: "isolated-fallback",
164717
+ fallbackReason: "no debuggable local browser found"
164718
+ }
164719
+ };
164720
+ }
164656
164721
 
164657
164722
  // src/resolve-ws.ts
164658
164723
  init_cjs_shims();
@@ -164783,7 +164848,7 @@ async function readLocalConfig(session) {
164783
164848
  const raw = await import_fs11.promises.readFile(getLocalConfigPath(session), "utf-8");
164784
164849
  return JSON.parse(raw);
164785
164850
  } catch {
164786
- return { strategy: "auto" };
164851
+ return { ...DEFAULT_LOCAL_CONFIG };
164787
164852
  }
164788
164853
  }
164789
164854
  async function writeLocalConfig(session, config3) {
@@ -164800,6 +164865,23 @@ async function readLocalInfo(session) {
164800
164865
  return null;
164801
164866
  }
164802
164867
  }
164868
+ async function waitForLocalInfo(session, timeoutMs = 1500) {
164869
+ const startTime = Date.now();
164870
+ while (Date.now() - startTime < timeoutMs) {
164871
+ const localInfo = await readLocalInfo(session);
164872
+ if (localInfo) {
164873
+ return localInfo;
164874
+ }
164875
+ await new Promise((resolve4) => setTimeout(resolve4, 50));
164876
+ }
164877
+ return readLocalInfo(session);
164878
+ }
164879
+ function logLocalModeHint(localConfig, localInfo) {
164880
+ const hint = getLocalModeHint(localConfig, localInfo);
164881
+ if (hint) {
164882
+ console.error(hint);
164883
+ }
164884
+ }
164803
164885
  function hasBrowserbaseCredentials() {
164804
164886
  return Boolean(process.env.BROWSERBASE_API_KEY);
164805
164887
  }
@@ -165097,33 +165179,15 @@ async function runDaemon(session, headless) {
165097
165179
  let localLaunchOptions;
165098
165180
  let localInfo;
165099
165181
  if (!useBrowserbase) {
165100
- const localConfig = await readLocalConfig(session);
165101
- if (localConfig.strategy === "isolated") {
165102
- localLaunchOptions = { headless, viewport: DEFAULT_VIEWPORT2 };
165103
- localInfo = { localSource: "isolated" };
165104
- } else if (localConfig.strategy === "cdp") {
165105
- const cdpUrl = await resolveWsTarget(localConfig.cdpTarget);
165106
- localLaunchOptions = { cdpUrl };
165107
- localInfo = {
165108
- localSource: "attached-explicit",
165109
- resolvedCdpUrl: cdpUrl
165110
- };
165111
- } else {
165112
- const discovered = await discoverLocalCdp();
165113
- if (discovered) {
165114
- localLaunchOptions = { cdpUrl: discovered.wsUrl };
165115
- localInfo = {
165116
- localSource: "attached-existing",
165117
- resolvedCdpUrl: discovered.wsUrl
165118
- };
165119
- } else {
165120
- localLaunchOptions = { headless, viewport: DEFAULT_VIEWPORT2 };
165121
- localInfo = {
165122
- localSource: "isolated-fallback",
165123
- fallbackReason: "no debuggable local browser found"
165124
- };
165125
- }
165126
- }
165182
+ const resolvedLocalStrategy = await resolveLocalStrategy({
165183
+ localConfig: await readLocalConfig(session),
165184
+ headless,
165185
+ defaultViewport: DEFAULT_VIEWPORT2,
165186
+ discoverLocalCdp,
165187
+ resolveWsTarget
165188
+ });
165189
+ localLaunchOptions = resolvedLocalStrategy.localLaunchOptions;
165190
+ localInfo = resolvedLocalStrategy.localInfo;
165127
165191
  }
165128
165192
  stagehand = new V3({
165129
165193
  env: useBrowserbase ? "BROWSERBASE" : "LOCAL",
@@ -166072,7 +166136,8 @@ program.command("status").description("Check daemon status").action(async () =>
166072
166136
  }
166073
166137
  if (mode === "local") {
166074
166138
  const localConfig = await readLocalConfig(session);
166075
- const localInfo = await readLocalInfo(session);
166139
+ const localInfo = await readLocalInfo(session) ?? await waitForLocalInfo(session);
166140
+ logLocalModeHint(localConfig, localInfo);
166076
166141
  localDetails = {
166077
166142
  localStrategy: localConfig.strategy,
166078
166143
  ...localInfo ?? {}
@@ -166090,9 +166155,20 @@ program.command("status").description("Check daemon status").action(async () =>
166090
166155
  })
166091
166156
  );
166092
166157
  });
166093
- program.command("env [target] [cdpTarget]").description(
166094
- "Show or switch browser environment (local | remote)\n\n browse env Show current environment\n browse env local Auto-discover local Chrome, fallback to isolated\n browse env local --isolated Force clean isolated browser\n browse env local <port|url> Attach to specific CDP target\n browse env remote Use Browserbase (requires API key)"
166095
- ).option("--isolated", "Force isolated local browser (no auto-discovery)").action(
166158
+ var envUsage = "Usage: browse env [local|remote]\n browse env local [--auto-connect|<port|url>]";
166159
+ var envCommand = program.command("env [target] [cdpTarget]").description(
166160
+ "Show or switch browser environment (local | remote)\n\n browse env Show current environment\n browse env local Use clean isolated local browser (default)\n browse env local --auto-connect Auto-discover local Chrome, fallback to isolated\n browse env local <port|url> Attach to specific CDP target\n browse env remote Use Browserbase (requires API key)"
166161
+ ).option(
166162
+ "--auto-connect",
166163
+ "Auto-discover an existing local Chrome instance via CDP"
166164
+ );
166165
+ envCommand.addOption(
166166
+ new import_commander.Option(
166167
+ "--isolated",
166168
+ "Deprecated alias for the default isolated local browser"
166169
+ ).hideHelp()
166170
+ );
166171
+ envCommand.action(
166096
166172
  async (target, cdpTarget, cmdOpts) => {
166097
166173
  const opts = program.opts();
166098
166174
  const session = getSession(opts);
@@ -166123,9 +166199,7 @@ program.command("env [target] [cdpTarget]").description(
166123
166199
  };
166124
166200
  const mapped = modeMap[target];
166125
166201
  if (!mapped) {
166126
- console.error(
166127
- "Usage: browse env [local|remote]\n browse env local [--isolated] [<port|url>]"
166128
- );
166202
+ console.error(envUsage);
166129
166203
  process.exit(1);
166130
166204
  }
166131
166205
  try {
@@ -166134,10 +166208,22 @@ program.command("env [target] [cdpTarget]").description(
166134
166208
  console.error(err instanceof Error ? err.message : String(err));
166135
166209
  process.exit(1);
166136
166210
  }
166137
- let localConfig = { strategy: "auto" };
166211
+ let localConfig = { ...DEFAULT_LOCAL_CONFIG };
166138
166212
  if (mapped === "local") {
166139
- if (cmdOpts.isolated) {
166140
- localConfig = { strategy: "isolated" };
166213
+ const selectedLocalStrategies = [
166214
+ Boolean(cmdOpts.autoConnect),
166215
+ Boolean(cmdOpts.isolated),
166216
+ Boolean(cdpTarget)
166217
+ ].filter(Boolean);
166218
+ if (selectedLocalStrategies.length > 1) {
166219
+ console.error(envUsage);
166220
+ console.error(
166221
+ "Use only one of --auto-connect, --isolated, or <port|url>."
166222
+ );
166223
+ process.exit(1);
166224
+ }
166225
+ if (cmdOpts.autoConnect) {
166226
+ localConfig = { strategy: "auto" };
166141
166227
  } else if (cdpTarget) {
166142
166228
  localConfig = { strategy: "cdp", cdpTarget };
166143
166229
  }
@@ -166160,6 +166246,9 @@ program.command("env [target] [cdpTarget]").description(
166160
166246
  await stopDaemonAndCleanup(session);
166161
166247
  }
166162
166248
  await ensureDaemon(session, isHeadless(opts));
166249
+ if (mapped === "local") {
166250
+ logLocalModeHint(localConfig, await waitForLocalInfo(session));
166251
+ }
166163
166252
  console.log(
166164
166253
  JSON.stringify({
166165
166254
  mode: toModeTarget(mapped),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@browserbasehq/browse-cli",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "Browser automation CLI for AI agents, built on Stagehand",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",