Ego-Lite Entry Points Explained: CLI vs. Module API for Browser Automation

Ego-Lite exposes two main entry points—runMain() for command-line execution and installEgoSdk() for programmatic embedding—both defined in src/index.ts and sharing the same helper surface built by helperContext().

The citrolabs/ego-lite repository provides the core browser automation runtime that powers the Ego-Lite agent platform. Understanding how to invoke this runtime is essential whether you're running scripts from the terminal or embedding automation capabilities into a host application. The entire surface is implemented in TypeScript within the package/ego-browser/ directory, with clear separation between CLI orchestration and SDK installation.

The Two Main Entry Points for Ego-Lite

Ego-Lite's runtime is designed to work in both standalone and embedded contexts. The src/index.ts file detects its execution environment and branches accordingly, ensuring the same capabilities are available regardless of how you access them.

CLI Entry Point: runMain()

When the module is executed directly—either by the bundled ego-browser binary or via node dist/out/index.js—the runMain() function handles script execution.


# Direct Node execution with inline JavaScript

node dist/out/index.js <<'JS'
await nav('https://example.com')
await click('text=Login')
await waitFor('selector=#dashboard')
JS

The runMain() function, imported from src/run.ts, performs three critical operations:

  • Reads JavaScript code from stdin
  • Wraps the code in an asynchronous function context
  • Injects the helper surface from helperContext() before execution

This path is what the ego-browser binary uses internally, making it the primary entry point for headless automation workflows and CI/CD pipelines.

Module Entry Point: installEgoSdk()

For embedding scenarios—such as the closed-source Ego-Lite desktop application importing the runtime—installEgoSdk() provides programmatic access.

import { installEgoSdk } from 'ego-browser'

// Install the SDK onto the global object
installEgoSdk(globalThis)

// Helpers become available via globalThis.ego
await globalThis.ego.nav('https://example.com')
await globalThis.ego.click('text=Login')

The installEgoSdk() function attaches the entire helper surface to globalThis.ego, enabling host applications to drive browser automation without spawning a separate CLI process.

How the Entry Points Share Implementation

Both entry points converge on the same core implementation, ensuring behavioral consistency across invocation methods.

The helperContext() Factory

The src/helpers.ts file exports helperContext(), which constructs the public API surface. This factory returns an object containing all automation primitives:

Helper Category Examples
Navigation nav(), goBack(), reload()
Interaction click(), type(), press()
Waiting waitFor(), waitForSelector(), waitForFunction()
Inspection snapshot(), text(), attribute()
CDP Access cdp(), js()

When runMain() executes a script, it destructures these helpers into the global scope. When installEgoSdk() is called, it attaches the same object to globalThis.ego.

Environment Detection in src/index.ts

The branching logic is straightforward and explicit:

// From src/index.ts — simplified structure
if (require.main === module) {
  // Running as script → CLI mode
  runMain()
} else {
  // Running as module → export SDK installer
  module.exports = { installEgoSdk }
}

This pattern allows the same built artifact to serve dual purposes without configuration files or environment variables.

Low-Level Access: Direct Helper Context Usage

For testing or advanced scenarios, you can import helperContext() directly and invoke helpers without either entry point:

import { helperContext } from 'ego-browser/src/helpers.js'

const { nav, click, waitFor } = await helperContext()
await nav('https://example.com')
await click('#submit')
await waitFor('#thank-you')

This bypasses both runMain() and installEgoSdk(), giving you fine-grained control over helper instantiation while still leveraging the full runtime implementation from src/browser-runtime.ts and src/cdp-eval.ts.

Key Source Files Supporting Entry Points

File Responsibility
src/index.ts Entry point detection and routing
src/run.ts Script execution wrapper for CLI mode
src/helpers.ts Helper surface construction via helperContext()
src/browser-runtime.ts CDP transport layer and session management
src/cdp-eval.ts cdp() and js() evaluation primitives
src/nav.ts, src/pointer.ts, src/keyboard.ts Domain-specific driver implementations

Summary

  • Two entry points serve all Ego-Lite use cases: runMain() for CLI execution and installEgoSdk() for programmatic embedding
  • Single source of truth: both entry points use helperContext() from src/helpers.ts to build the identical public API
  • Environment auto-detection in src/index.ts eliminates configuration—running as script triggers CLI mode, importing as module exports the SDK installer
  • Direct helper access via helperContext() enables testing and custom integration scenarios

Frequently Asked Questions

How do I run Ego-Lite scripts from the command line?

Use the ego-browser binary or execute the built module with Node, passing your script via stdin. The runMain() function in src/run.ts handles stdin reading, async wrapping, and helper injection automatically. This is the standard approach for automation tasks and scheduled jobs.

Can I use Ego-Lite inside my own Node.js application?

Yes—import installEgoSdk from the ego-browser package and call it with globalThis. This embeds the entire automation surface without requiring CLI invocation. The closed-source Ego-Lite app uses this exact pattern to host the runtime internally.

What helpers are available through both entry points?

Both expose the complete set: navigation (nav, goBack), interaction (click, type, press), waiting primitives (waitFor, waitForSelector), inspection methods (snapshot, text), and raw CDP access (cdp, js). The full list is constructed by helperContext() in src/helpers.ts and documented in the source.

Why does Ego-Lite use require.main === module for detection?

This is the idiomatic Node.js pattern for distinguishing direct execution from module import. It allows src/index.ts to serve dual purposes—running as a standalone process or exporting installable functions—without external configuration, keeping the deployment artifact simple and predictable.

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 →