# How the Open-Source ego-browser Package Drives the ego-lite Browser App

> Discover how the open-source ego-browser package, a Node.js harness, translates commands into CDP messages for the ego-lite browser app. Explore the inner workings.

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

---

**The open-source ego-browser package acts as a lightweight Node.js harness that translates high-level browser commands into Chrome DevTools Protocol (CDP) messages sent to the embedded ego-lite runtime via the `globalThis.ego.sendCDPMessage` interface.**

The **ego-browser** package from the `citrolabs/ego-lite` repository provides the bridge between AI agents and the ego-lite browser application. This open-source SDK exposes intuitive helper functions like `navigate`, `click`, and `type` that abstract the complexity of direct Chrome DevTools Protocol communication. By leveraging the global `ego` object injected by the ego-lite binary, the package enables seamless browser automation without requiring external dependencies or direct Chromium connections.

## Architecture Overview

The ego-browser package operates as a thin translation layer between JavaScript automation scripts and the ego-lite binary. When the package executes, it establishes communication with the embedded browser runtime through a singleton state object that tracks active CDP sessions and pending requests.

The architecture consists of three primary layers: the **entry point layer** ([`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts)) handling CLI and module imports, the **runtime layer** ([`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts)) managing CDP transport, and the **driver layer** (`src/driver/*`) implementing concrete browser actions. This separation allows the open-source ego-browser package to remain lightweight while providing comprehensive browser control capabilities.

## Core Communication Layer

The heart of the integration lies in [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts), which maintains a singleton `state` object tracking active CDP sessions and pending requests. This file implements the critical `handleSendFailure` function that routes errors when CDP calls fail, such as when tasks become inactive.

Communication flows through `globalThis.ego.sendCDPMessage(message)`, the single required method injected by the ego-lite binary. The runtime handles session attachment automatically, implementing a 2-second TTL cache for session handles to optimize performance while ensuring automatic re-attachment when sessions drop.

## SDK Installation and Entry Points

In [`package/ego-browser/src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts), the package distinguishes between CLI execution and module import contexts. When executed as a CLI, the package reads scripts from STDIN, wraps them in an async function, and invokes `runMain()`. When imported as a module, it exposes `installEgoSdk(globalThis)`, which registers the SDK on the global object so the host environment can initialize browser controls.

The `helperContext()` function in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) constructs the public API surface, gathering helper functions for navigation, pointer actions, keyboard input, and element operations. It attaches JSDoc-driven documentation to enable the `help()` command for interactive exploration of available methods.

## Element Resolution System

Before executing actions, the package must translate human-readable locators into CDP-compatible selectors. The [`package/ego-browser/src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/element-resolver.ts) module handles this translation, supporting multiple locator syntaxes including numeric references (`@N`), CSS selectors (`loc=css:`), and XPath expressions (`xpath=`).

When resolution fails, the system throws `ElementResolutionError` with `transient` or `permanent` flags. This distinction enables intelligent retry loops in higher-level helpers, allowing the package to recover from temporary DOM changes while failing fast on permanent resolution failures.

## Driver Implementations

The `package/ego-browser/src/driver/` directory contains concrete implementations of browser actions, each mapping high-level commands to specific CDP domains:

- **[`nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/nav.ts)** manages tab creation, URL navigation, and page load events, coordinating with the runtime to ensure proper lifecycle handling.
- **[`pointer.ts`](https://github.com/citrolabs/ego-lite/blob/main/pointer.ts)** implements mouse movements, clicks, and drag-and-drop operations using CDP Input domain commands.
- **[`keyboard.ts`](https://github.com/citrolabs/ego-lite/blob/main/keyboard.ts)** handles key presses and text entry, translating JavaScript strings into CDP key events.
- **[`locator.ts`](https://github.com/citrolabs/ego-lite/blob/main/locator.ts)** executes low-level CDP locator queries against the current page context.
- **[`observe.ts`](https://github.com/citrolabs/ego-lite/blob/main/observe.ts)** provides snapshot, screenshot, and event streaming capabilities for monitoring page state changes.

## Learning Subsystem

Located in `package/ego-browser/src/learning/`, the optional learning subsystem contains site-specific automation patterns validated at build time. These "learnings" provide custom tools for complex sites like Amazon and Reddit, accessible via `runSiteTool` and `runSiteBrowserTool` functions. The system loads these patterns dynamically, allowing the open-source ego-browser package to ship with pre-optimized automation strategies for high-traffic websites.

## Usage Examples

### CLI Execution

Pass automation scripts directly through STDIN for immediate execution:

```bash
cat <<'EOF' | npx ego-browser
await navigate('https://example.com')
await click('loc=css:button.submit')
await waitForSelector('loc=role:heading[name="Success"]')
EOF

```

### Programmatic SDK Integration

Import the package to register helpers on the global object:

```javascript
import { installEgoSdk } from 'ego-browser'

installEgoSdk(globalThis)
const { navigate, click, waitFor } = globalThis.ego.helpers

await navigate('https://news.ycombinator.com')
await click('loc=css:a.storylink')
await waitFor('loc=role:heading[name="Comments"]')

```

### Task Space Management

Create isolated browser sessions for multi-task automation:

```javascript
import { useOrCreateTaskSpace, completeTaskSpace } from 'ego-browser'

const ts = await useOrCreateTaskSpace('my-session')
await ts.navigate('https://github.com')
await ts.click('loc=css:a[href="/login"]')
await completeTaskSpace(ts.id, { keep: false })

```

## Summary

- The **open-source ego-browser package** translates high-level JavaScript commands into CDP messages without directly connecting to Chrome.
- All communication flows through `globalThis.ego.sendCDPMessage`, injected by the ego-lite binary.
- **Element resolution** supports CSS selectors, XPath, and numeric references with intelligent error classification.
- The **driver layer** separates concerns into navigation, pointer, keyboard, locator, and observation modules.
- **Session management** includes automatic re-attachment and a 2-second TTL cache for handles.
- Site-specific **learning modules** provide optimized automation patterns for complex websites.

## Frequently Asked Questions

### How does the ego-browser package communicate with the ego-lite binary?

The package communicates exclusively through `globalThis.ego.sendCDPMessage(message)`, a method injected into the JavaScript environment by the ego-lite binary. This method forwards Chrome DevTools Protocol commands to the embedded Chromium instance, allowing the open-source package to control the browser without maintaining direct WebSocket connections to Chrome.

### What locator syntaxes does the ego-browser package support?

The element resolver in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) supports multiple syntaxes: numeric references (`@N` for previously captured elements), CSS selectors (`loc=css:` or implicit), and XPath expressions (`xpath=`). Each syntax is parsed and translated into the appropriate CDP runtime call, with failures wrapped in `ElementResolutionError` objects that indicate whether the failure is transient or permanent.

### Can I use the ego-browser package without installing the ego-lite binary?

No. The ego-browser package depends on the `globalThis.ego` object provided by the ego-lite runtime. While the package itself is open-source and can be imported in any Node.js environment, it requires the closed-source ego-lite binary to actually execute CDP commands. Without the binary, the `sendCDPMessage` method would not exist, causing all browser operations to fail.

### What happens when a CDP session disconnects during automation?

The [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) module implements automatic re-attachment logic. When a connection drops, the runtime detects the failure through `handleSendFailure`, clears the cached session handle, and attempts to re-establish the session on the next command. The 2-second TTL cache for session handles balances performance with resilience, ensuring that temporary disconnections do not terminate long-running automation tasks.