Documentation menu

Docs

Node Adapter

NodeAgent runs against real files: point it at a working directory and it gets the full file toolset plus a Bash tool that runs sandboxed and can escalate to the host shell with approval. Build CLIs, servers, bots, and scripts.

npm install @nanocodana/nodejs @ai-sdk/anthropic ai
agent.ts
import { NodeAgent } from '@nanocodana/nodejs'
import { anthropic } from '@ai-sdk/anthropic'

const agent = NodeAgent({
  model: anthropic('claude-sonnet-5'),
  workingDirectory: process.cwd(),
  needsApproval: ['Write', 'Edit', 'MultiEdit', 'Delete'],
})

const result = await agent.stream({
  messages: [{ role: 'user', content: 'Add a CHANGELOG.md summarizing recent commits.' }],
})

Default tools#

The Node agent ships with Read, Write, Edit, MultiEdit, Delete, Glob, Grep, LS, TodoWrite, WebFetch, and a Bash tool that runs in a sandbox and can escalate to the host shell (with approval). The full list, with behavior notes, is in Built-in Tools.

The working directory#

workingDirectory is the root for every file tool — paths the model uses are resolved against it, and the agent can't wander outside. Skills are auto-discovered beneath it too, from .agents/skills/ and .claude/skills/.

The rule of thumb: this adapter is for files on a real disk — your laptop, a server, or a serverless function's own filesystem. If the files live anywhere else (a database, blob storage, a remote sandbox), that's core.

Search: ripgrep when possible, JS everywhere else#

Grep picks the best available engine at construction, automatically. Installing @nanocodana/nodejs brings real ripgrep along as an optionalDependency (npm fetches just the ~4 MB binary for your platform), and the agent resolves in order:

  • the bundled @vscode/ripgrep binary,
  • a system rg on PATH,
  • a zero-dependency JS search — ignore-aware (honors .gitignore, skips node_modules, build output, and binary files) and capped.

A missing binary can only make searches slower, never break the agent — environments that skip optional dependencies or install scripts land safely on the JS engine. To force a specific engine, override the tool (entries in tools replace built-ins by name):

force-an-engine.ts
import { NodeAgent, createNodeGrepTool, createRipgrepTool } from '@nanocodana/nodejs'

const cwd = process.cwd()
const agent = NodeAgent({
  model,
  workingDirectory: cwd,
  tools: { Grep: createNodeGrepTool(cwd) },   // force the JS engine
  // tools: { Grep: createRipgrepTool(cwd) }, // force ripgrep
})

The Bash sandbox#

Shell commands run in a virtual sandbox by default — fast, contained, and free of side effects on your machine. When the model genuinely needs the host (installing a dependency, running your test suite), it requests escalation with host: true, which always requires approval regardless of your needsApproval config.

Size#

Bundled, a Node agent is 3.58 MB (1.02 MB gzipped) — or a 387 kB entry chunk with code splitting, since each shell command loads on first use. That's what reaches production.

On disk, node_modules is bigger — 141 MB — because the shell brings wasm runtimes it loads on demand: a compiled CPython, SQLite, a JS interpreter. That's a build-time cost, not a deployed one, and it's payload rather than code: 80 of the ~83 commands are pure JavaScript under 2 MB. If it matters, --omit=optional takes it to 131 MB, and deleting just-bash/vendor saves another 10 MB unless you set python: true.

Prompting for decisions in a terminal? That's exactly what the CLI does — it's built on this adapter, and its source is a good reference for approval UX.