How to Use CDP Commands Directly in ego-browser with the cdp Helper

The cdp helper in ego-browser lets you send raw Chrome DevTools Protocol commands from agent scripts by calling await cdp(method, params?, sessionId?) without any import statements.

The ego-browser package from the citrolabs/ego-lite repository exposes a low-level cdp helper that bridges the gap between high-level automation APIs and the raw Chrome DevTools Protocol (CDP). This helper is injected directly into the global scope of agent scripts, allowing you to execute arbitrary CDP commands against the underlying browser instance. Whether you need to navigate pages, evaluate scripts, or manipulate network interception, the cdp helper provides direct access to the browser's debugging protocol.

What Is the cdp Helper?

The cdp helper is a thin wrapper around the runtime's CDP transport layer, defined in [src/cdp-eval.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/cdp-eval.ts). It routes commands through the shared state—checking for state.cdpOverride first, then falling back to the default send implementation—while maintaining internal bookkeeping for Network domain events.

According to the source code, the helper is re-exported from [src/helpers.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) and documented in the public API signature within [src/format.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts). This ensures that when you call cdp in your scripts, you're invoking a managed transport that properly tracks networkDomainEnabled states in [src/state.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/state.ts).

How the cdp Helper Works

When you invoke await cdp(method, params?, sessionId?), the execution flow follows this path:

  1. Command Routing: The call checks state.cdpOverride for custom transport handling or uses the default send implementation.
  2. Network Bookkeeping: If the command relates to the Network domain (e.g., Network.enable), the helper updates internal flags in the shared state to ensure higher-level helpers like waitForNetworkIdle remain synchronized.
  3. Session Targeting: The optional sessionId parameter routes the command to specific targets, such as child iframes or separate browser contexts.

This architecture ensures that direct CDP usage doesn't break the agent's internal consistency, particularly for network monitoring features implemented in [src/driver/waits.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/waits.ts).

Using the cdp Helper in Agent Scripts

Basic Syntax

All helpers are automatically injected into your script's global scope by the runtime. You call cdp without import statements using the signature:

await cdp(method, params?, sessionId?)
  • method: String matching the CDP domain and command (e.g., "Page.navigate", "Runtime.evaluate")
  • params: Object containing the method's required parameters
  • sessionId: Optional string for targeting specific sessions

Practical Examples

Navigate to a URL and wait for load:

// Navigate using CDP directly
await cdp('Page.navigate', { url: 'https://example.com' });

// Wait for the load event
await cdp('Page.loadEventFired');

Evaluate JavaScript in the page context:

const result = await cdp('Runtime.evaluate', {
  expression: 'document.title',
  returnByValue: true,
});

console.log('Page title:', result.result?.value);

Enable network monitoring and capture responses:

// Enable network domain
await cdp('Network.enable');

// Disable caching
await cdp('Network.setCacheDisabled', { cacheDisabled: true });

// Wait for specific response and get body
const response = await cdp('Network.responseReceived', { requestId: '123.1' });
const body = await cdp('Network.getResponseBody', { 
  requestId: response.response?.requestId 
});

console.log('Response body:', body.body);

Advanced Session Targeting

The cdp helper supports targeting specific browser sessions, enabling you to interact with child iframes or separate targets. This pattern is demonstrated in navigation utilities found in [src/driver/nav.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/nav.ts).

Attach to a specific target and execute commands:

// Attach to a frame or service worker
const { sessionId } = await cdp('Target.attachToTarget', {
  targetId: 'iframe-target-id',
  flatten: true,
});

// Execute in that specific context
const href = await cdp(
  'Runtime.evaluate', 
  { expression: 'window.location.href' }, 
  sessionId
);

console.log('Frame URL:', href.result?.value);

The flatten: true parameter creates a flat session hierarchy compatible with modern Chrome versions, returning a sessionId that you pass as the third argument to subsequent cdp calls.

Summary

  • The cdp helper provides direct access to Chrome DevTools Protocol commands within ego-browser agent scripts.
  • Implementation resides in src/cdp-eval.ts, with exports managed through src/helpers.ts and state tracking in src/state.ts.
  • Global scope injection means no imports are required; call cdp(method, params?, sessionId?) directly.
  • Network domain integration ensures that enabling Network commands via CDP doesn't break waitForNetworkIdle and other high-level helpers.
  • Session targeting via the optional sessionId parameter allows precise control over iframes and isolated browser contexts.

Frequently Asked Questions

Do I need to import the cdp helper in my ego-browser scripts?

No. The cdp helper is automatically injected into the global scope by the runtime environment along with other helpers. According to the implementation in src/helpers.ts, you can call cdp directly without any import statements, as the runtime pre-binds these utilities before script execution.

How does using the cdp helper affect waitForNetworkIdle and other high-level helpers?

The cdp helper in src/cdp-eval.ts maintains internal bookkeeping for the Network domain. When you execute Network.enable or related commands through cdp, it updates the networkDomainEnabled flag in the shared state (defined in src/state.ts). This synchronization ensures that utilities like waitForNetworkIdle in src/driver/waits.ts continue to function correctly alongside your raw CDP commands.

Can I use the cdp helper to interact with iframes or web workers?

Yes. Pass the sessionId as the third argument to target specific contexts. First attach to the target using Target.attachToTarget with flatten: true, which returns a session ID, then use that ID in subsequent cdp calls to execute commands within that specific frame, web worker, or service worker context.

What happens if a CDP command doesn't return a payload?

The cdp helper returns a Promise that resolves to the raw CDP response object. If the underlying transport does not return a payload (common with event-based commands like Page.loadEventFired), the helper resolves to an empty object {}. Always check the response structure or use optional chaining when accessing nested result properties.

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 →