How Ego-Browser Tab Management Works: switchTab, openOrReuseTab, and closeTab Explained

Ego-Browser provides three high-level helpers—switchTab, openOrReuseTab, and closeTab—that wrap Chrome DevTools Protocol (CDP) commands to let AI agents control browser tabs without writing raw CDP calls.

The ego-browser package (part of the citrolabs/ego-lite repository) abstracts tab lifecycle management into a clean TypeScript API. These functions live in src/driver/nav.ts and handle target resolution, existence validation, and session cache invalidation automatically.

switchTab: Activate an Existing Tab

The switchTab function brings a specific tab to the foreground using its targetId.

Implementation Details

In src/driver/nav.ts (lines 53-61), switchTab performs four key steps:

  1. Resolve the target via targetIdFrom, which accepts either a string targetId or an object with a targetId property.
  2. Validate existence by calling listTabs() and currentTargetFrom to confirm the target is still alive.
  3. Activate via CDP by sending the Target.activateTarget command.
  4. Update session state by invalidating cached session data and storing the new preferred target.
// Activate a tab by its targetId
await browser.switchTab('A4B2C1D3E4F5G6H7I8J9K0L1M2N3O4P5');

// Or pass the tab object directly
const tab = await browser.listTabs().then(tabs => tabs[0]);
await browser.switchTab(tab);

The function throws a clear, actionable error if the targetId is missing or the tab no longer exists.

openOrReuseTab: Smart Tab Creation and Reuse

The openOrReuseTab function implements intelligent tab deduplication—ideal for AI agents that repeatedly navigate to the same URLs.

URL Matching Modes

The function supports four matching strategies (configured via the match option):

  • 'exact' — Full URL must match character-for-character.
  • 'origin' — Scheme and host must match (e.g., https://example.com matches any path).
  • 'origin+path' — Scheme, host, and path must match (query strings ignored).
  • 'includes' — Current URL contains the provided string.

Implementation Flow

In src/driver/nav.ts (lines 77-99), the function:

  1. Fetches user tabs via listTabs({includeChrome: false}) to exclude internal Chrome pages.
  2. Applies tabMatchesUrl with the selected matching mode to find candidates.
  3. If matched: calls switchTab, optionally waits for page load with wait and settle parameters.
  4. If no match: creates a new tab via newTab(url), then optionally waits.
  5. Returns a descriptor with targetId, url, title, and reused boolean.
// Open docs, reusing any tab from the same origin
const result = await browser.openOrReuseTab('https://docs.example.com/api/v2', {
  match: 'origin',
  wait: true,      // wait for load event
  settle: 200,     // extra 200ms after load
});

console.log(result.reused); // true if an existing tab was switched to

The reused flag lets agents distinguish between fresh navigation and tab recycling, which matters for cache invalidation logic.

closeTab: Clean Tab Termination

The closeTab function safely closes any tab and cleans up associated session state.

Implementation Details

In src/driver/nav.ts (lines 11-22), closeTab:

  1. Resolves targetId (defaults to the currently active tab if omitted).
  2. Validates the target still exists via currentTargetFrom.
  3. Issues Target.closeTarget CDP command.
  4. Invalidates the session cache, clears the preferred target if it matches, and blocks until waitForClosedTarget confirms removal.
  5. Returns the closed targetId for logging or verification.
// Close the current active tab
await browser.closeTab();

// Close a specific tab
await browser.closeTab('A4B2C1D3E4F5G6H7I8J9K0L1M2N3O4P5');

// Close a tab object from listTabs()
const tabToClose = await browser.listTabs().then(tabs => tabs.find(t => t.url.includes('/temp')));
if (tabToClose) {
  await browser.closeTab(tabToClose);
}

Shared Utilities Behind the Scenes

All three functions rely on internal helpers in src/driver/nav.ts:

  • targetIdFrom — Normalizes string or object inputs to a raw targetId string, throwing descriptive errors for malformed input.
  • currentTargetFrom — Verifies a targetId exists in the current tab list; on failure, includes a snapshot of available targets in the error message.
  • listTabs — Wraps browserEgo().listTabs() with optional Chrome-internal URL filtering.

These utilities ensure deterministic error behavior: every tab operation either succeeds or fails with enough context for AI agents to implement retry logic.

API Surface and Entry Points

While src/driver/nav.ts contains the implementations, agents typically interact with these functions through:

File Purpose
src/driver/nav.ts Core implementations of switchTab, openOrReuseTab, closeTab
src/helpers.ts Public API bindings exported for agent consumption
src/browser-runtime.ts Low-level CDP transport via browserEgo()
src/format.ts Documentation signatures and help() examples

Summary

  • switchTab activates an existing tab by targetId with full validation and session cache updates.
  • openOrReuseTab finds matching tabs by URL pattern or creates new ones, returning reuse status for agent logic.
  • closeTab terminates any tab cleanly, with automatic cleanup of session state and blocking confirmation of closure.
  • All functions in ego-browser wrap CDP commands behind deterministic validation, making tab management reliable for automated agents.

Frequently Asked Questions

What happens if switchTab is called with an invalid or closed targetId?

The function throws an error from currentTargetFrom that includes the invalid targetId and a snapshot of currently available tabs, allowing agents to recover or log debugging information.

Can openOrReuseTab match against page titles instead of URLs?

No—the matching logic in tabMatchesUrl only operates on URL strings. To match by title, use listTabs() to filter manually, then call switchTab directly.

Does closeTab automatically switch to another tab after closing?

No—closeTab does not activate a replacement tab. If the closed tab was active, the browser's default behavior determines which tab gains focus. Use switchTab explicitly if you need a specific successor.

How does ego-browser handle Chrome's internal pages in tab operations?

By default, listTabs({includeChrome: false}) excludes chrome:// and chrome-extension:// URLs from all operations. Pass includeChrome: true to override this filtering.

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 →