How ego-browser SDK Installs and Injects Helpers into the Global Scope

The ego-browser SDK uses installEgoSdk() in src/index.ts to automatically inject a suite of browser automation helpers into globalThis when loaded as a library, making methods like page.goto() and browser.listTabs() instantly available without explicit imports.

The ego-browser SDK is the runtime foundation of the ego-lite browser automation framework. When you load your automation scripts, the SDK transparently wires up a complete API surface—page controls, browser management, task spaces, and more—directly onto the global object. This deep dive examines the exact mechanism that makes this "zero-import" developer experience possible.

The Entry Point: installEgoSdk in src/index.ts

The orchestration begins in [src/index.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts), specifically lines 44-65. When the module detects it's being loaded as a library (not via CLI), it invokes installEgoSdk() automatically:

// From src/index.ts - automatic installation path
if (require.main !== module) {
  installEgoSdk();
}

This unconditional auto-install is what eliminates the need for manual setup in most user scripts.

Step-by-Step Installation Flow

1. Target Selection

By default, installEgoSdk targets globalThis, but accepts any object as the target parameter. This flexibility enables sandboxed testing environments or custom runtime containers.

2. Helper Context Assembly

The helperContext() function (defined in [src/helpers.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts), lines 22-35) constructs a façade object grouping all public helpers:

Helper Category Key Methods
page goto(), locator(), waitFor(), evaluate()
browser listTabs(), createTab(), closeTab()
taskSpaces useOrCreate(), list(), cleanup()
site Domain-specific navigation utilities
fetch HTTP requests with SDK integration
cdp Chrome DevTools Protocol access

3. Legacy Global Cleanup

Before injection, the SDK scrubs legacy helper names to prevent namespace collisions (lines 52-56). Legacy identifiers like click and goto are explicitly deleted from the target object.

4. Readiness Wrapper Application

Most helpers are wrapped with wrapReady, which defers execution until an optional ready promise resolves. This ensures the underlying browser runtime is fully initialized before any automation command executes. Synchronous helpers—notably help—bypass this wrapper for immediate availability (lines 63-67).

5. Non-Enumerable Property Definition

Helpers are attached via Object.defineProperty with precise configuration (lines 67-73):

Object.defineProperty(target, helperName, {
  value: wrappedHelper,
  writable: true,
  enumerable: false,  // Hidden from for...in loops
  configurable: true
});

This design choice keeps the helpers operationally global while preventing them from polluting enumerations of globalThis.

6. Console Redirection

SDK output capture begins at lines 80-86, where console.log is overridden to route through a buffered sink or host-provided logger. This ensures all automation output is controllable and testable.

7. Runtime Integration

If the target already contains an ego object (the native host runtime), the SDK enhances it with:

  • ego.helpers — map of all injected helper functions
  • ego.learnings — accumulated automation insights
  • Wrapped task space methods (createTab, useTaskSpace, etc.) for session state consistency

Practical Usage Examples

Automatic Installation (Standard Usage)

// No installation code needed—SDK auto-injects on import
// File: my-script.js
await page.goto("https://example.com");
await page.locator("button#submit").click();
const title = await page.locator("h1").textContent();
console.log(`Page title: ${title}`);

Manual Installation with Custom Target

import { installEgoSdk } from "ego-browser";

const isolatedScope = {};
installEgoSdk(isolatedScope);

// Helpers exist only on the custom object
await isolatedScope.page.goto("https://example.org");
await isolatedScope.browser.listTabs();

Custom Readiness Signal and Logging

import { installEgoSdk } from "ego-browser";

// Simulate async infrastructure warmup
const readySignal = new Promise<void>(resolve => {
  setTimeout(resolve, 500);
});

installEgoSdk(globalThis, {
  ready: readySignal,
  cliLog: (...args) => {
    process.stderr.write(`[SDK] ${args.join(" ")}\n`);
  }
});

// Helpers await readySignal before executing
await page.goto("https://example.com");

Core Source Files Reference

File Responsibility
[src/index.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts) installEgoSdk implementation; global injection orchestration
[src/helpers.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) helperContext() definition; helper façade assembly
[src/state.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/state.ts) Runtime configuration—timeouts, workspace paths
[src/run.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/run.ts) Script execution harness; helper injection trigger
[src/ego-errors.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/ego-errors.ts) Error taxonomy for SDK-thrown exceptions

Summary

  • installEgoSdk() in src/index.ts is the sole entry point for SDK bootstrapping, invoked automatically when loaded as a library.
  • helperContext() assembles the complete helper API from discrete functional domains (page, browser, taskSpaces, etc.).
  • Legacy cleanup, readiness wrapping, and non-enumerable properties ensure clean, predictable global injection without namespace pollution.
  • Console redirection and runtime integration complete the SDK initialization, unifying output capture and host communication.

Frequently Asked Questions

Can I prevent automatic global injection?

No built-in flag exists to disable auto-installation when importing the SDK as a library. However, you can import individual helpers directly from src/helpers.ts and avoid the global-target path entirely. For test isolation, pass a custom target object to installEgoSdk(sandbox) instead of globalThis.

What happens if helpers conflict with existing globals?

The SDK proactively deletes known legacy names (click, goto, etc.) from the target before injection. For unknown conflicts, Object.defineProperty with writable: true allows subsequent code to overwrite SDK helpers if necessary, though this is discouraged.

How do I await SDK readiness before executing commands?

Pass a ready promise in the options parameter: installEgoSdk(globalThis, { ready: myInitPromise }). All wrapped helpers (page, browser, taskSpaces) will automatically queue until this promise resolves. Synchronous helpers like help() execute immediately regardless of readiness state.

Where is the best place to customize helper behavior?

Runtime customization belongs in [src/state.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/state.ts), which exports the state object holding default timeouts and workspace configuration. For helper-level changes, extend or replace the corresponding function in helperContext() before calling installEgoSdk.

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 →