How Ego‑Browser Handles Browser Navigation, Tab Management, and the openOrReuseTab Function

Ego‑Browser abstracts Chrome DevTools Protocol (CDP) operations into high‑level JavaScript helpers, with all tab lifecycle logic centralized in src/driver/nav.ts and exposed through the browser façade in src/helpers.ts.

The ego‑browser navigation system provides deterministic tab handling for automation agents. Rather than managing raw CDP commands, developers interact with a unified API that handles listing, switching, creating, reusing, and closing tabs while abstracting low‑level protocol complexity.

Core Navigation Architecture

The navigation subsystem lives in three primary locations:

According to the citrolabs/ego‑browser source code, the browser object is assembled around line 770 in src/helpers.ts:

// src/helpers.ts (excerpt)
export const browser = {
  listTabs,
  currentTab,
  switchTab,
  newTab,
  openOrReuseTab,
  closeTab,
  // …
};

Tab Listing and Selection

listTabs

The listTabs function queries the Ego runtime for all browser tabs. In src/driver/nav.ts (lines 112–130), it filters internal Chrome tabs unless includeChrome: true is passed.

Returns: Array<{targetId, title, url, active, index}>

currentTab

Located at lines 135–146 in src/driver/nav.ts, currentTab retrieves the list from listTabs() and returns the active tab—or the first tab if none are explicitly active. Throws if no tabs exist.

Tab Switching and Creation

switchTab

The switchTab implementation (lines 151–161) validates the supplied target ID, activates it via CDP's Target.activateTarget, invalidates the session cache, and records the new preferred target.

newTab

At lines 165–174, newTab calls browserEgo().createTab(url) with a default of about:blank, returning the freshly created targetId.

The openOrReuseTab Helper: Deep Dive

The openOrReuseTab function (lines 176–200 in src/driver/nav.ts) is the centerpiece of ego‑browser's browser navigation system. It implements intelligent tab reuse with configurable matching logic.

Implementation Flow

  1. Fetch current tab list via listTabs()
  2. Match requested URL against existing tabs using the match option
  3. Reuse: If matched, call switchTab, optionally wait for document load, apply settle delay
  4. Create: If no match, invoke newTab
  5. Return: Unified object {targetId, url, title, active, reused}

Match Modes

Mode Description
exact Full URL equality
origin Same protocol + host
origin+path Same origin including path
includes URL contains the match string

Options Interface

{
  match?: 'exact' | 'origin' | 'origin+path' | 'includes';
  wait?: boolean;           // wait for document load
  timeout?: number;         // load wait timeout (ms)
  settle?: number;          // extra pause after load (ms)
}

Code Examples

Reuse exact match with full load waiting:

await browser.openOrReuseTab('https://news.ycombinator.com', {
  match: 'exact',
  wait: true,
  timeout: 15000,
  settle: 500,
});

Reuse any tab from same origin:

await browser.openOrReuseTab('https://example.com/page', {
  match: 'origin',
  wait: true,
});

Force new tab behavior:

// Returns { reused: false } when new tab created
const result = await browser.openOrReuseTab('https://github.com', {
  match: 'none',  // or omit match entirely for guaranteed new tab
});

The public signature is documented in src/format.ts:

// src/format.ts (excerpt)
"browser.openOrReuseTab": {
  signature: "browser.openOrReuseTab(url, options?) => Promise<object>",
  examples: [
    "await browser.openOrReuseTab('https://example.com', { wait: true, timeout: 20000 })",
  ],
},

Closing Tabs

The closeTab function (lines 212–233 in src/driver/nav.ts) handles tab cleanup:

  • Defaults to active tab if no target specified
  • Validates target via CDP
  • Sends Target.closeTarget
  • Clears preferred target if closed tab was recorded as preferred
  • Waits for tab disappearance when multiple tabs remain
// Close active tab
await browser.closeTab();

// Close specific tab
await browser.closeTab({ targetId: 'ABC123...' });

Supporting Infrastructure

Wait Utilities

The waitForDocumentLoad helper used by openOrReuseTab resides in src/driver/waits.ts, providing robust page load detection beyond basic CDP events.

Summary

  • Centralized implementation: All tab operations live in src/driver/nav.ts
  • Façade pattern: src/helpers.ts exposes clean browser.* API
  • Smart reuse: openOrReuseTab eliminates redundant tabs via configurable URL matching
  • CDP abstraction: No direct protocol handling required for common workflows
  • Deterministic behavior: Clear reused flag in return values enables conditional logic

Frequently Asked Questions

What is the default match behavior in openOrReuseTab?

When no match option is provided, openOrReuseTab creates a new tab unconditionally. To enable reuse, explicitly set match to one of the supported modes: exact, origin, origin+path, or includes.

How does ego‑browser handle waiting for page loads?

When wait: true is passed to openOrReuseTab, the function invokes waitForDocumentLoad from src/driver/waits.ts, which monitors CDP lifecycle events until the document reaches a stable state or the timeout expires.

Can I switch to a tab without knowing its targetId?

Direct switchTab requires a targetId. However, you can use openOrReuseTab with match: 'origin' or match: 'includes' to find and activate a tab by URL pattern without manually iterating through listTabs() results.

What happens when closeTab removes the last tab?

The closeTab implementation only waits for tab disappearance when more than one tab remains. Closing the final tab triggers normal browser behavior—typically creating a fresh blank tab or closing the window, depending on Chrome configuration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →