Skip to main content
ClaudeWave
Skill2.8k repo starsupdated today

ai-code-mode

Code Mode is a TanStack AI tool that enables Claude to execute JavaScript code in an isolated, sandboxed environment during conversations. Use it when you need Claude to write and run code that can call server-side tools, perform calculations, or interact with external APIs, with full type safety through TypeScript.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/TanStack/ai /tmp/ai-code-mode && cp -r /tmp/ai-code-mode/packages/ai-code-mode/skills/ai-code-mode ~/.claude/skills/ai-code-mode
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

> **Note**: This skill requires familiarity with ai-core and ai-core/chat-experience. Code Mode is always used on top of a chat experience.

## Setup

Complete Code Mode setup with Node.js isolate driver:

```typescript
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'
import { createCodeModeTool } from '@tanstack/ai-code-mode'
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
import { toolDefinition } from '@tanstack/ai'
import { z } from 'zod'

// Define a tool that code can call
const fetchWeather = toolDefinition({
  name: 'fetchWeather',
  description: 'Get current weather for a city',
  inputSchema: z.object({ city: z.string() }),
  outputSchema: z.object({ temp: z.number(), condition: z.string() }),
}).server(async ({ city }) => {
  const res = await fetch(`https://api.weather.com/${city}`)
  return res.json()
})

// Create code mode tool with Node isolate
const codeModeTool = createCodeModeTool({
  driver: createNodeIsolateDriver({
    memoryLimit: 128,
    timeout: 30000,
  }),
  tools: [fetchWeather],
})

// Use in chat
const stream = chat({
  adapter: openaiText('gpt-5.2'),
  messages,
  tools: [codeModeTool],
})

return toServerSentEventsResponse(stream)
```

The recommended higher-level entry point is `createCodeMode()`, which returns both the tool and a matching system prompt:

```typescript
import { chat } from '@tanstack/ai'
import { createCodeMode } from '@tanstack/ai-code-mode'
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
import { openaiText } from '@tanstack/ai-openai'

const { tool, systemPrompt } = createCodeMode({
  driver: createNodeIsolateDriver(),
  tools: [fetchWeather],
  timeout: 30_000,
})

const stream = chat({
  adapter: openaiText('gpt-4o'),
  systemPrompts: ['You are a helpful assistant.', systemPrompt],
  tools: [tool],
  messages,
})
```

`createCodeMode` calls `createCodeModeTool` and `createCodeModeSystemPrompt` internally. The system prompt includes generated TypeScript type stubs for each tool so the LLM writes correct calls.

## Core Patterns

### 1. Choosing an Isolate Driver

Three drivers implement the `IsolateDriver` interface. All are interchangeable.

**Node.js** (`createNodeIsolateDriver`) -- Full V8 with JIT. Fastest option. Requires `isolated-vm` native C++ addon.

```typescript
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'

const driver = createNodeIsolateDriver({
  memoryLimit: 128, // MB, default 128
  timeout: 30_000, // ms, default 30000
  // skipProbe: false -- set true only after verifying compatibility
})
```

**QuickJS** (`createQuickJSIsolateDriver`) -- WASM-based, no native deps. Works in Node.js, browsers, Deno, Bun, and edge runtimes. Slower (interpreted, no JIT). Limited stdlib (no File I/O).

```typescript
import { createQuickJSIsolateDriver } from '@tanstack/ai-isolate-quickjs'

const driver = createQuickJSIsolateDriver({
  memoryLimit: 128, // MB, default 128
  timeout: 30_000, // ms, default 30000
  maxStackSize: 524288, // bytes, default 512 KiB
})
```

**Cloudflare** (`createCloudflareIsolateDriver`) -- Edge execution via a deployed Cloudflare Worker. Requires a `workerUrl` pointing to your deployed worker. Network latency on each tool call.

```typescript
import { createCloudflareIsolateDriver } from '@tanstack/ai-isolate-cloudflare'

const driver = createCloudflareIsolateDriver({
  workerUrl: 'https://my-code-mode-worker.my-account.workers.dev',
  authorization: process.env.CODE_MODE_WORKER_SECRET,
  timeout: 30_000, // ms, default 30000
  maxToolRounds: 10, // max tool-call/result cycles, default 10
})
```

| Driver     | Best for                    | Native deps     | Browser support | Performance          |
| ---------- | --------------------------- | --------------- | --------------- | -------------------- |
| Node       | Server-side Node.js         | Yes (C++ addon) | No              | Fast (V8 JIT)        |
| QuickJS    | Browsers, edge, portability | None (WASM)     | Yes             | Slower (interpreted) |
| Cloudflare | Edge deployments            | None            | N/A             | Fast (V8 on edge)    |

### 2. Adding Persistent Skills with codeModeWithSkills()

Skills let the LLM save reusable code snippets. On future requests, relevant skills are loaded and exposed as callable tools.

```typescript
import { chat, maxIterations } from '@tanstack/ai'
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
import { codeModeWithSkills } from '@tanstack/ai-code-mode-skills'
import { createFileSkillStorage } from '@tanstack/ai-code-mode-skills/storage'
import {
  createDefaultTrustStrategy,
  createAlwaysTrustedStrategy,
  createCustomTrustStrategy,
} from '@tanstack/ai-code-mode-skills'
import { openaiText } from '@tanstack/ai-openai'

// Trust strategies control how skills earn trust through executions
// Default: untrusted -> provisional (10+ runs, >=90%) -> trusted (100+ runs, >=95%)
// Relaxed: untrusted -> provisional (3+ runs, >=80%) -> trusted (10+ runs, >=90%)
// Always trusted: immediately trusted (dev/testing)
// Custom: configurable thresholds
const trustStrategy = createDefaultTrustStrategy()

// Storage options: file system (production) or memory (testing)
const storage = createFileSkillStorage({
  directory: './.skills',
  trustStrategy,
})

const driver = createNodeIsolateDriver()

// High-level API: automatic LLM-based skill selection
const { toolsRegistry, systemPrompt, selectedSkills } =
  await codeModeWithSkills({
    config: {
      driver,
      tools: [myTool1, myTool2],
      timeout: 60_000,
      memoryLimit: 128,
    },
    adapter: openaiText('gpt-4o-mini'), // cheap model for skill selection
    skills: {
      storage,
      maxSkillsInContext: 5,
    },
    messages,
  })

const stream = chat({
  adapter: openaiText('gpt-4o'),
  tools: toolsRegistry.getTools(),
  messages,
  systemPrompts: ['You are a helpful assistant.', systemPrompt],