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

> Learn how ego-browser's switchTab, openOrReuseTab, and closeTab functions simplify browser tab management for AI agents by wrapping Chrome DevTools Protocol commands.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: how-to-guide
- Published: 2026-08-04

---

**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](https://github.com/citrolabs/ego-lite) repository) abstracts tab lifecycle management into a clean TypeScript API. These functions live in [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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.

```typescript
// 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`](https://github.com/citrolabs/ego-lite/blob/main/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.

```typescript
// 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`](https://github.com/citrolabs/ego-lite/blob/main/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.

```typescript
// 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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) contains the implementations, agents typically interact with these functions through:

| File | Purpose |
|------|---------|
| [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) | Core implementations of `switchTab`, `openOrReuseTab`, `closeTab` |
| [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) | Public API bindings exported for agent consumption |
| [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) | Low-level CDP transport via `browserEgo()` |
| [`src/format.ts`](https://github.com/citrolabs/ego-lite/blob/main/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.