# How to Start ego-browser in SDK Mode: A Complete Guide to Embedded Browser Automation

> Learn how to start ego-browser in SDK mode with this guide. Import the package to automatically inject browser automation helpers onto globalThis for seamless embedded browser automation.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: how-to-guide
- Published: 2026-08-23

---

**To start ego-browser in SDK mode, simply import the package via `import 'ego-browser'` or `require('ego-browser')`, which automatically triggers `installEgoSdk()` and injects browser automation helpers onto `globalThis`.**

The **ego-browser** package from the [citrolabs/ego-lite](https://github.com/citrolabs/ego-lite) repository provides two distinct execution paths: CLI mode for terminal-based scripting and SDK mode for embedding within existing Node.js applications. Starting ego-browser in SDK mode allows you to integrate the full browser automation runtime directly into your codebase without spawning separate child processes. This guide explains the detection logic, installation mechanisms, and practical implementation patterns based on the actual source code in [`package/ego-browser/src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts).

## Understanding SDK Mode vs CLI Mode

ego-browser determines its execution context automatically at runtime. The dual-mode architecture works as follows:

- **CLI Mode**: Activated when the binary executes directly from the terminal. The process reads a heredoc script from *stdin* and invokes `runMain()` to execute it.
- **SDK Mode**: Activated when the package is imported or required by another Node.js process. This path automatically calls `installEgoSdk()` to inject automation helpers into the host environment.

The distinction hinges on the `isDirectCli()` check located at lines 75-79 in [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts). When this check returns `false`, the SDK initialization sequence begins immediately.

## How SDK Mode Detection Works

The entry point uses a conditional guard to route between CLI and SDK execution:

```typescript
if (isDirectCli()) {
  // CLI: runMain() handles stdin script execution
} else {
  installEgoSdk();  // SDK mode activation
}

```

Source: [`index.ts#L75-L79`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L75)

The `isDirectCli()` function examines the module context to determine if the file is the main entry point. When you `import` or `require` the package from another file, this check fails, triggering the SDK installation path that prepares the helper context and exposes the browser automation API.

## The `installEgoSdk` Function

The core SDK initialization happens in `installEgoSdk()`, defined at lines 44-74 and 126-165 of [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts). This function creates the execution environment for embedded browser automation.

### Function Signature and Parameters

The function accepts two parameters:

```typescript
export function installEgoSdk(target = globalThis, options = {}) {
  const context = options.context || helpers.helperContext();
  // Helper wrapping and installation logic
}

```

- **`target`**: The object receiving the injected helpers (defaults to `globalThis`).
- **`options`**: Configuration object supporting:
  - `context`: Custom helper context from `helpers.helperContext()`.
  - `ready`: Promise that gates helper availability until async initialization completes.
  - `cliLog`: Custom logging function to replace the default buffered sink.

### What Gets Exposed

After installation, the target object receives:

- **Global Helpers**: All methods defined in `LEGACY_GLOBAL_HELPERS` (lines 76-100), including `click`, `snapshotText`, `js`, `cdp`, and navigation utilities.
- **Runtime Object**: An `ego` property containing underlying browser methods like `createTab` and `listTaskSpaces`.
- **Buffered Logging**: A replaced `console.log` implementation that captures output for the host process to flush.

Source: [`index.ts#L76-L100`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L76)

## Methods to Start ego-browser in SDK Mode

### Method 1: Implicit Installation via Import

The simplest approach requires no explicit function calls. Importing the package automatically executes `installEgoSdk()` with default settings:

```javascript
// Minimal SDK start - helpers attach to globalThis
import 'ego-browser';

await useOrCreateTaskSpace('demo');
await openOrReuseTab('https://github.com', { wait: true });
cliLog('Page title: ' + (await pageInfo()).title);

```

This pattern mirrors the quick-start implementation shown in the project's [`SKILL.md`](https://github.com/citrolabs/ego-lite/blob/main/SKILL.md) and is the recommended approach for most use cases.

### Method 2: Explicit Installation with Custom Target

For controlled environments or namespace isolation, import the function explicitly and specify a custom target object:

```javascript
import { installEgoSdk } from 'ego-browser';

const agentEnv = {};
installEgoSdk(agentEnv, {});

await agentEnv.useOrCreateTaskSpace('api-test');
await agentEnv.openOrReuseTab('https://api.example.com');
agentEnv.cliLog('Automation complete');

```

This method prevents global namespace pollution by containing all browser automation helpers within the `agentEnv` object.

### Method 3: Custom Ready Signals and Logging

Advanced integrations can control the initialization lifecycle and output destinations:

```javascript
import { installEgoSdk } from 'ego-browser';

installEgoSdk(globalThis, {
  ready: (async () => {
    // Wait for external configuration before enabling helpers
    const config = await fetch('https://my.api/config').then(r => r.json());
    return config;
  })(),
  cliLog: (msg) => process.stdout.write('[AGENT] ' + msg + '\n')
});

await openOrReuseTab('https://news.ycombinator.com');
cliLog('HN front page loaded');

```

The `ready` option wraps asynchronous helpers with a promise gate, ensuring they only resolve after your initialization logic completes. The `cliLog` option redirects captured console output to your preferred destination.

## Complete Implementation Examples

### Example A: Basic SDK Integration

```javascript
// --------------------------------------------------------
// Minimal SDK start (implicit install)
// --------------------------------------------------------
import 'ego-browser';               // triggers installEgoSdk()
await useOrCreateTaskSpace('demo'); // create or reuse a task space
await openOrReuseTab('https://github.com', { wait: true });
cliLog('Page title: ' + (await pageInfo()).title);

```

### Example B: Isolated Environment with Async Setup

```javascript
// --------------------------------------------------------
// Explicit SDK install on a custom object
// --------------------------------------------------------
import { installEgoSdk } from 'ego-browser';

const agentEnv = {};
installEgoSdk(agentEnv, {
  // optional: wait for async init before helpers become usable
  ready: (async () => {
    const cfg = await agentEnv.serverFetch('https://my.api/config');
    return cfg;
  })(),
});

await agentEnv.useOrCreateTaskSpace('api-test');
await agentEnv.openOrReuseTab('https://api.example.com/docs');
agentEnv.cliLog('Fetched docs');

```

### Example C: Custom Output Sink

```javascript
// --------------------------------------------------------
// Overriding the console output sink
// --------------------------------------------------------
import { installEgoSdk } from 'ego-browser';

installEgoSdk(globalThis, {
  cliLog: (msg) => process.stdout.write('[AGENT] ' + msg + '\n')
});

await openOrReuseTab('https://news.ycombinator.com');
cliLog('HN front page loaded');

```

## Summary

- **SDK mode activates automatically** when you import or require `ego-browser` from another Node.js file, detected via the `isDirectCli()` function in [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts).
- **`installEgoSdk(target, options)`** injects browser automation helpers onto your chosen target object (defaulting to `globalThis`).
- **Three implementation patterns** exist: implicit import for quick starts, explicit calls with custom targets for isolation, and configured installations with `ready` promises and custom logging.
- **Key source files** include [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts) (entry logic), [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) (helper definitions), and [`src/output-sink.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/output-sink.ts) (logging capture).
- **Exposed capabilities** include navigation helpers (`openOrReuseTab`), DOM interaction (`click`, `snapshotText`), CDP access (`cdp`), and the underlying `ego` runtime object.

## Frequently Asked Questions

### How does ego-browser distinguish between CLI and SDK mode?

The package uses the `isDirectCli()` function located at lines 75-79 of [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts) to check if the current file is the main entry point. When the binary executes directly from the terminal, this returns `true` and triggers `runMain()` to process stdin scripts. When imported as a module, it returns `false` and automatically invokes `installEgoSdk()` to initialize the SDK environment.

### Can I prevent ego-browser from polluting the global scope?

Yes. Instead of using the implicit import pattern, explicitly import `installEgoSdk` from `ego-browser` and pass a custom target object as the first argument. This contains all helpers (`click`, `js`, `cliLog`, etc.) within your specified object rather than attaching them to `globalThis`.

### What is the purpose of the `ready` option in `installEgoSdk`?

The `ready` option accepts a Promise that gates the availability of asynchronous helpers. When provided, SDK methods that rely on browser initialization will wait for this promise to resolve before executing. This is useful for scenarios requiring external configuration fetching or delayed browser runtime setup before allowing automation commands to run.

### Where are the helper methods defined that become available in SDK mode?

The helper methods are generated by `helpers.helperContext()` implemented in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts). The specific list of exposed helpers is controlled by `LEGACY_GLOBAL_HELPERS` defined at lines 76-100 of [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts), which includes navigation utilities, DOM interaction methods, and CDP access functions that get injected onto the target object during SDK initialization.