# JavaScript REPL

URL: https://docs.hanzo.ai/docs/dev/usage/js-repl

> Run JavaScript in a persistent Node-backed kernel with top-level await.

`js_repl` runs JavaScript in a persistent Node-backed kernel with top-level `await`.

## Feature Gate

`js_repl` is disabled by default and only appears when enabled:

```toml
[features]
js_repl = true
```

`js_repl_tools_only` can be enabled to force direct model tool calls through `js_repl`:

```toml
[features]
js_repl = true
js_repl_tools_only = true
```

When enabled, direct model tool calls are restricted to `js_repl` and `js_repl_reset`; other tools remain available via `await codex.tool(...)` inside js\_repl.

## Node Runtime

`js_repl` requires a Node version that meets or exceeds `codex-rs/node-version.txt`.

Runtime resolution order:

1. `CODEX_JS_REPL_NODE_PATH` environment variable
2. `js_repl_node_path` in config/profile
3. `node` discovered on `PATH`

Configure an explicit runtime path:

```toml
js_repl_node_path = "/absolute/path/to/node"
```

## Module Resolution

`js_repl` resolves **bare** specifiers (e.g. `await import("pkg")`) using an ordered search path. Local file imports are also supported for relative paths, absolute paths, and `file://` URLs that point to ESM `.js` / `.mjs` files.

Module resolution order:

1. `CODEX_JS_REPL_NODE_MODULE_DIRS` (PATH-delimited list)
2. `js_repl_node_module_dirs` in config/profile (array of absolute paths)
3. Thread working directory (cwd, always included as the last fallback)

Bare package imports always use this REPL-wide search path, even when they originate from an imported local file. They are not resolved relative to the imported file's location.

## Usage

- `js_repl` is a freeform tool: send raw JavaScript source text.
- Optional first-line pragma: `// codex-js-repl: timeout_ms=15000`
- Top-level bindings persist across calls.
- If a cell throws, prior bindings remain available. Lexical bindings whose initialization completed before the throw stay available in later calls.
- Top-level static import declarations (`import x from "pkg"`) are currently unsupported; use dynamic imports with `await import("pkg")`.
- Imported local files must be ESM `.js` / `.mjs` files and run in the same REPL VM context.
- Local file modules reload between execs, so a later `await import("./file.js")` picks up edits.
- `import.meta.resolve()` returns importable strings such as `file://...`, bare package names, and `node:fs`.
- Use `js_repl_reset` to clear the kernel state.

## Helper APIs

`js_repl` exposes these globals inside the kernel:

- **`codex.tmpDir`**: per-session scratch directory path.
- **`codex.tool(name, args?)`**: executes a normal tool call from inside `js_repl` (including shell tools like `shell` / `shell_command` when available).
- **`codex.emitImage(imageLike)`**: adds one image to the outer `js_repl` function output.

### Image Emission

`codex.emitImage(...)` accepts:

- A data URL
- A single `input_image` item
- An object like `{ bytes, mimeType }`
- A raw tool response object that contains exactly one image and no text

Call it multiple times for multiple images. It rejects mixed text-and-image content.

Examples:

```javascript
// Playwright screenshot
await codex.emitImage({
  bytes: await page.screenshot({ type: "jpeg", quality: 85 }),
  mimeType: "image/jpeg"
});

// Local image via tool
await codex.emitImage(codex.tool("view_image", { path: "/absolute/path" }));
```

Prefer JPEG at \~85 quality when lossy compression is acceptable; use PNG when transparency or lossless detail matters.

### Nested Tool Calls

- Nested `codex.tool(...)` outputs stay inside JavaScript unless you emit them explicitly.
- Each `codex.tool(...)` call emits a bounded summary at `info` level.
- At `trace` level, the exact raw response object or error string is also logged.

Avoid writing directly to `process.stdout` / `process.stderr` / `process.stdin`; the kernel uses a JSON-line transport over stdio.

## Debug Logging

Nested `codex.tool(...)` diagnostics are emitted through normal `tracing` output.

```bash
RUST_LOG=codex_core::tools::js_repl=info \
LOG_FORMAT=json \
dev app-server \
2> /tmp/dev-app-server.log
```

```bash
RUST_LOG=codex_core::tools::js_repl=trace \
LOG_FORMAT=json \
dev app-server \
2> /tmp/dev-app-server.log
```

## Vendored Parser

The kernel embeds a vendored Meriyah bundle at `codex-rs/core/src/tools/js_repl/meriyah.umd.min.js` (source: `meriyah@7.0.0` from npm). Licensing is tracked in `third_party/meriyah/LICENSE` and `NOTICE`.
