# How to Set or Clear the Preferred Tab for a CDP Session in ego-lite

> Learn to set or clear the preferred tab for a CDP session in ego-lite. Easily pin or revert to the active tab using setPreferredTarget and clearPreferredTarget functions.

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

---

**You can pin an ego-lite Chrome DevTools Protocol (CDP) session to a specific browser tab by calling `setPreferredTarget(targetId)`, or revert to the active tab by calling `clearPreferredTarget()`.**

The **ego-lite** runtime maintains a single CDP session that attaches to one browser tab at a time. While it defaults to the currently active tab, you can override this behavior by storing a **preferred target ID** in the runtime state. This mechanism is implemented across [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts), [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts), and [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts), and is exposed through two simple helper functions that any injected agent script can invoke.

## Understanding the Preferred Target Mechanism

The runtime stores the preferred tab reference in `state.preferredTargetId` (defined in **src/state.ts**, lines 24-37). When a CDP session is established or re-created, the `ensureSession()` routine in **src/browser-runtime.ts** (lines 56-63) checks this value:

- If `state.preferredTargetId` is a string, `ensureSession()` searches the list of available targets and attaches the session to the matching `targetId`.
- If the value is `null` (the default), the runtime attaches to the currently active tab, or falls back to the last tab in the list if none is active.

This allows long-running automation scripts to remain bound to a specific tab even if the user switches focus elsewhere in the browser.

## Setting a Preferred Tab

Use the `setPreferredTarget(targetId)` helper to lock the CDP session to a specific tab. You typically obtain the `targetId` from the `ego.listTabs()` response.

```javascript
// List all available tabs and find the one you need
const tabs = await ego.listTabs();
const dashboardTab = tabs.find(t => t.title?.includes('Dashboard'));

if (!dashboardTab) {
  throw new Error('Target tab not found');
}

// Pin the session to this tab
await setPreferredTarget(dashboardTab.targetId);

// All subsequent CDP calls now target the Dashboard tab
await click('button#refresh');
const title = await js('return document.title');
console.log(title); // "Dashboard"

```

The `setPreferredTarget` function is exported from **src/browser-runtime.ts** and updates the mutable state in **src/state.ts** immediately. Future calls to navigation helpers in **src/driver/nav.ts** will respect this preference without requiring you to pass the target ID again.

## Clearing the Preferred Tab

To return to the default behavior—where the runtime automatically selects the active tab—call `clearPreferredTarget()`. This sets `state.preferredTargetId` to `null`.

```javascript
// Remove the explicit preference
await clearPreferredTarget();

// The next CDP action will attach to whichever tab is currently active
await navigate('https://example.com');

```

Clearing the preference is useful when your automation workflow finishes with a specific tab and needs to switch context dynamically based on user activity.

## Core Implementation Details

Three source files coordinate the preferred-tab logic:

- **src/state.ts**: Holds the mutable `preferredTargetId` field. This is the single source of truth for the runtime’s tab preference.
- **src/browser-runtime.ts**: Implements `ensureSession()`, which queries `state.preferredTargetId` before attaching the CDP session. This file also exports the public helpers `setPreferredTarget()` and `clearPreferredTarget()`.
- **src/driver/nav.ts**: Consumes the preference when executing navigation commands. If a preferred target is set, navigation helpers automatically target that tab; otherwise, they default to the active tab.

Because the state is held in memory within the browser runtime, the preference persists for the duration of the CDP connection but does not survive a full browser restart unless your host application re-sets it on initialization.

## Summary

- **`setPreferredTarget(targetId)`** stores a tab ID in `state.preferredTargetId`, forcing the CDP session to attach to that specific tab.
- **`clearPreferredTarget()`** resets the preference to `null`, causing the runtime to fall back to the active tab.
- The logic lives in **src/browser-runtime.ts** (`ensureSession()`) and reads from **src/state.ts**.
- Navigation helpers in **src/driver/nav.ts** transparently respect the preferred target when executing commands.

## Frequently Asked Questions

### What happens if the preferred target tab is closed?

If the tab referenced by `state.preferredTargetId` is closed before the next CDP command, `ensureSession()` in **src/browser-runtime.ts** will fail to find a matching target and typically throw an error or detach the session. You should verify tab existence with `ego.listTabs()` before critical operations, or wrap calls in try-catch blocks to handle disconnection gracefully.

### Can I switch preferred targets without calling clearPreferredTarget first?

Yes. Calling `setPreferredTarget(newTargetId)` immediately overwrites the previous value in `state.preferredTargetId`. The next CDP command will automatically re-attach to the new tab via the `ensureSession()` logic.

### Does the preferred target persist after a page navigation or reload?

Yes. The `targetId` assigned by the Chrome DevTools Protocol is stable across navigations within the same tab. As long as the tab itself remains open, `ensureSession()` will continue to attach to it using the stored `preferredTargetId`, regardless of how many times the page reloads.

### Where are setPreferredTarget and clearPreferredTarget exported?

Both helpers are exported from **src/browser-runtime.ts**. They are injected into the agent script’s global scope when the ego-lite runtime initializes, allowing you to call them directly without importing them explicitly in your automation scripts.