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

> Explore ego-lite entry points: CLI vs. Module API. Discover how to use runMain() or installEgoSdk() for browser automation and learn about their shared helper surface.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: deep-dive
- Published: 2026-08-03

---

**Ego-Lite exposes two main entry points—`runMain()` for command-line execution and `installEgoSdk()` for programmatic embedding—both defined in [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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.

```bash

# 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`](https://github.com/citrolabs/ego-lite/blob/main/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.

```javascript
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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts)

The branching logic is straightforward and explicit:

```typescript
// 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:

```javascript
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`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) and [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts).

## Key Source Files Supporting Entry Points

| File | Responsibility |
|------|--------------|
| [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts) | Entry point detection and routing |
| [`src/run.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/run.ts) | Script execution wrapper for CLI mode |
| [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) | Helper surface construction via `helperContext()` |
| [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) | CDP transport layer and session management |
| [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts) | `cdp()` and `js()` evaluation primitives |
| [`src/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/nav.ts), [`src/pointer.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/pointer.ts), [`src/keyboard.ts`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) to build the identical public API
- **Environment auto-detection** in [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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.