What Is the ego-browser Node.js Harness? A Complete Technical Guide

The ego-browser Node.js harness is a lightweight automation bridge that exposes a unified, Playwright-style API for AI agents to control the closed-source ego-lite browser runtime through Chrome DevTools Protocol (CDP) bindings.

The ego-browser package sits between your automation scripts and the underlying browser engine in the citrolabs/ego-lite repository. It transforms low-level CDP commands into high-level, agent-friendly helpers while managing session lifecycle, task-space ownership, and site-specific skill discovery automatically.

Unified Helper Surface Architecture

At the heart of the harness lies the helperContext() function in src/helpers.ts. This factory method constructs a set of facade objects that agents interact with instead of importing modules directly.

The helper surface includes:

  • page – Navigation and element interaction methods
  • browser – High-level browser control and CDP session management
  • taskSpaces – Task-space lifecycle API for isolated execution contexts
  • site – Site-specific skill discovery and execution
  • fetch – Network request utilities

These facades abstract the raw ego runtime bindings located in src/browser-runtime.ts, providing a consistent interface regardless of whether code runs as a CLI script or an imported module.

Global Environment Injection

The installEgoSdk() function in src/index.ts (lines 44-66) installs the helper facades onto a target object—by default globalThis. This ensures that automation scripts can access page, browser, and other globals without explicit imports.

The installation process performs two critical tasks:

  1. Binds underlying ego runtime methods to the global scope, connecting the JavaScript facade to the native CDP bridge
  2. Wraps asynchronous helpers to automatically await a "ready" signal before executing, preventing race conditions during harness initialization

This global injection pattern allows the harness to function as both a standalone CLI tool and a programmatic SDK.

Session and Task Space Management

The harness tracks CDP sessions and invalidates them automatically on navigation or tab changes. It exposes a high-level task-space API through taskSpaces (defined in src/helpers.ts, lines 52-78) that abstracts the native ego bindings:

  • newTaskSpace() – Creates isolated execution contexts
  • useOrCreateTaskSpace() – Reuses existing spaces or provisions new ones
  • claimTaskSpace() – Acquires ownership for user-controlled sessions

These methods handle the complex lifecycle of browser contexts, ensuring that agents maintain clean state between operations without manually managing CDP session attachments.

Site-Specific Skill Discovery

Through the learning subsystem in src/learning/index.ts, the harness can discover, load, and execute site-specific automation tools bundled under skills/ego-browser/learnings.

The site helper exposes:

  • site.skills – Lists available learned capabilities for the current domain
  • site.runTool() – Executes specific learned workflows (e.g., site.runTool("github", "fetchRepo", {owner: "octocat", repo: "hello-world"}))
  • site.learnContext() – Captures new site-specific interaction patterns

This allows the harness to extend its capabilities dynamically based on the target domain, moving beyond generic automation into specialized, learned behaviors.

Buffered Output and Error Handling

The harness implements a buffered output sink via src/output-sink.ts that captures console.log and error output during execution. Rather than streaming logs immediately, it buffers all output and flushes only at process teardown.

This design allows the harness to discard logs entirely if an agent aborts early or encounters a fatal error, preventing noise in partial execution scenarios and ensuring clean output for successful runs.

Key Source Files and Architecture

Understanding the codebase structure reveals how the harness components interact:

  • src/index.ts – CLI entry point and SDK installer containing installEgoSdk() and global binding logic
  • src/helpers.ts – Builds the public API facades (page, browser, taskSpaces, site, fetch) and exports helperContext()
  • src/browser-runtime.ts – Manages CDP transport, session attachment, and event buffering between Node.js and the ego-lite runtime
  • src/cdp-eval.ts – Low-level CDP evaluation utilities (cdp, evaluate) used internally by the facades
  • src/state.ts – Central mutable state including default timeouts and workspace locations
  • src/element-resolver.ts – Locator resolution and selector parsing for the page.locator() API
  • src/help-runtime.ts – Generates documentation strings for the help() introspection system

Practical Usage Examples

Install and initialize the harness in your automation script:

// Install the harness (normally done automatically by the runtime)
import { installEgoSdk } from "./src/index.js";
installEgoSdk();

// Navigate and interact with pages using the Playwright-style API
await page.goto("https://example.com");
await page.waitForLoadState("networkidle");

// Locate elements using text or CSS selectors
const loginBtn = page.locator("text=Log in");
await loginBtn.click();

// Manage task spaces for isolated sessions
const ts = await taskSpaces.useOrCreate("my-session");
await ts.claim();               // Optional: acquire user ownership
await ts.waitForAgentControl(); // Blocks until agent regains control

// Execute site-specific learned skills
const result = await site.runTool("github", "fetchRepo", { 
  owner: "octocat", 
  repo: "hello-world" 
});
console.log(result);

The harness automatically handles CDP session management behind these calls, invalidating cached sessions when navigation occurs and rebinding to new browser contexts as needed.

Summary

  • The ego-browser Node.js harness acts as a bridge between AI agents and the ego-lite browser runtime, exposing a unified facade API.
  • installEgoSdk() injects helpers into the global scope and wraps async operations to prevent race conditions.
  • helperContext() constructs the primary facades (page, browser, taskSpaces, site) that abstract raw CDP bindings.
  • The harness manages CDP session lifecycle automatically, invalidating and rebinding sessions on navigation events.
  • Task spaces provide isolated execution contexts with ownership semantics via useOrCreateTaskSpace() and claim().
  • The learning subsystem enables dynamic loading of site-specific skills from the skills/ego-browser/learnings directory.
  • Buffered output in src/output-sink.ts captures logs and only flushes at process teardown, allowing clean abort handling.

Frequently Asked Questions

What is the difference between ego-browser and Playwright?

While both provide high-level browser automation APIs, ego-browser specifically wraps the closed-source ego-lite runtime and manages CDP session bindings automatically. Unlike Playwright, which communicates directly with browser binaries, ego-browser acts as a harness that injects helpers into the global scope and handles task-space ownership patterns unique to the ego-lite architecture.

How does the harness handle navigation and session invalidation?

The harness monitors CDP events in src/browser-runtime.ts and automatically invalidates cached session references when navigation or tab changes occur. This prevents "detached frame" errors by ensuring that the page and browser facades always reference valid execution contexts, rebinding to new sessions transparently behind the API.

Can I use ego-browser without global installation?

Yes. While installEgoSdk() defaults to binding helpers on globalThis, you can pass a custom target object to install the SDK into a specific namespace. This allows multiple harness instances or scoped automation contexts within the same Node.js process without polluting the global scope.

Where are site-specific skills stored and how are they loaded?

Site-specific skills reside in the skills/ego-browser/learnings directory as bundled modules. The learning subsystem in src/learning/index.ts discovers these modules based on the current domain and loads them dynamically when site.runTool() is invoked, extending the harness capabilities without modifying core source code.

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 →