# ego-lite CLI Entry Point vs installEgoSdk: How the Runtime Chooses Its Mode

> Understand how the ego-lite CLI entry point and installEgoSdk command determine its runtime mode. Learn about script execution versus SDK bootstrapping.

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

---

**The ego-lite CLI entry point functions as a conditional router that either executes a one-off script via `runMain()` when invoked directly from the command line, or bootstraps the full SDK environment via `installEgoSdk()` when imported as a library module.**

The citrolabs/ego-lite repository implements a dual-mode architecture in [`package/ego-browser/src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts) that adapts its behavior based on the execution context. Understanding the relationship between the ego-lite CLI entry point and the `installEgoSdk` command reveals how the same codebase powers both standalone browser automation scripts and embedded runtime environments.

## Execution Mode Detection

The entry point determines its operating mode through the `isDirectCli()` function (lines 75-79), which compares `process.argv[1]` against `import.meta.url`. When these values match, the script recognizes itself as the main module of a Node.js process and activates CLI mode. The file includes a shebang (`#!/usr/bin/env node`) to enable direct execution as a system binary.

```typescript
// Conceptual representation of the detection logic in index.ts
if (isDirectCli()) {
  // CLI mode: runMain() is invoked
} else {
  // SDK mode: installEgoSdk() is invoked
}

```

## The CLI Path: Direct Script Execution

When `isDirectCli()` returns true, the entry point invokes `runMain()`, imported from [`./run.js`](https://github.com/citrolabs/ego-lite/blob/main/./run.js) (lines 58-60). This orchestrator executes the provided script against the browser runtime and returns an exit status code that the process stores in `process.exitCode`. Any errors encountered during execution are written to `stderr` (lines 60-61), ensuring proper error propagation in shell pipelines.

This path is designed for short-lived, heredoc-style invocations where users pipe JavaScript directly into the binary:

```bash

# Execute a script via the CLI entry point

echo "await page.goto('https://example.com'); console.log('Done');" |
  node package/ego-browser/dist/out/index.js

```

## The SDK Path: Runtime Installation

When the module is imported rather than executed directly, the `else` branch (line 64) calls `installEgoSdk()`. This function (lines 44-67 and 71-75) transforms the host environment into a fully-featured browser automation runtime by injecting helper functions, configuring output handling, and extending the host's `ego` object.

### Building the Helper Context

The installation begins by constructing a helper context via `helpers.helperContext()` (line 51). The function removes legacy global definitions to prevent conflicts, then exposes each helper method onto the provided target object—typically `globalThis`. This injection makes browser automation primitives available globally within the host environment.

### Configuring the Buffered Log Sink

The SDK replaces the native `console.log` implementation with a buffered sink (lines 75-81) to ensure output is captured correctly across asynchronous boundaries and short-lived execution contexts. This mechanism prevents log loss during rapid tab creation and destruction cycles common in automation workflows.

Developers can override this behavior by providing a custom `cliLog` function in the options parameter:

```javascript
import { installEgoSdk } from 'package/ego-browser/src/index.js';

// Install with custom logging
installEgoSdk(globalThis, {
  cliLog: (...args) => remoteLogger.log(...args)
});

```

### Wrapping the Host Ego Object

If an `ego` object exists on the target, `installEgoSdk` wraps its tab-creation and task-space methods using `wrapCreateTab` and `wrapInvalidating`. It then exposes additional ego methods via `exposeEgoMethods`, decorating the host object with the full runtime API required for sophisticated browser orchestration.

## Practical Implementation Examples

### Running Standalone Scripts

Use the CLI entry point for one-off automation tasks without setting up a host application:

```bash

# Navigate and capture screenshot via CLI

echo "
  await page.goto('https://github.com/citrolabs/ego-lite');
  await page.screenshot({ path: 'ego-lite.png' });
" | node package/ego-browser/dist/out/index.js

```

### Embedding in Host Applications

Import the module to install the SDK within a long-running Node.js process:

```javascript
// host.js - Embedded runtime setup
import { installEgoSdk } from 'package/ego-browser/src/index.js';

// Install all helpers globally
installEgoSdk(globalThis);

// Runtime is now ready for automation
await page.goto('https://example.com');
console.log('Navigation complete');

```

## Summary

- **Dual-mode architecture**: The [`package/ego-browser/src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts) file serves as both a CLI binary and a library entry point, selecting behavior via `isDirectCli()`.
- **CLI execution**: Direct invocations route to `runMain()` (imported from [`./run.js`](https://github.com/citrolabs/ego-lite/blob/main/./run.js)) for immediate script execution with proper exit code handling.
- **SDK installation**: Library usage triggers `installEgoSdk()`, which builds a helper context, configures buffered logging, and exposes browser automation APIs onto the global scope.
- **Extensible logging**: The SDK supports custom log sinks through the `cliLog` option, allowing integration with external logging systems.

## Frequently Asked Questions

### What determines whether ego-lite runs in CLI mode or SDK mode?

The `isDirectCli()` function checks if `process.argv[1]` matches `import.meta.url`. When they match, the script is the entry point and executes `runMain()`; otherwise, it calls `installEgoSdk()` to initialize the library mode.

### How does installEgoSdk modify the global environment?

The function exposes helper methods onto the target object (usually `globalThis`), replaces `console.log` with a buffered output sink, and wraps existing `ego` object methods to add runtime capabilities. It also cleans up legacy global definitions to prevent namespace pollution.

### Can I customize the logging behavior when using installEgoSdk?

Yes. Pass a `cliLog` function in the options object when calling `installEgoSdk(target, { cliLog: customFn })`. Your custom function will receive all console output instead of the default buffered sink, enabling integration with remote loggers or UI components.

### Where is the script execution logic located for CLI mode?

The actual execution logic resides in [`package/ego-browser/src/run.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/run.ts), which exports the `runMain` function. This module handles the browser session lifecycle, script evaluation, and error handling when ego-lite operates as a command-line tool.