Compromise NLP Library
spencermountain/compromise
Helps write and debug JavaScript or TypeScript that uses the compromise English NLP library for matching, entity extraction, tagging and sentence transforms.
LLM-generated TypeScript execution in sandboxed environments: createCodeModeTool() with isolate drivers (createNodeIsolateDriver, createQuickJSIsolateDriver, createQuickJSBunIsolateDriver…
$ npx skills add TanStack/ai --skill ai-code-mode -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install TanStack/ai ai-code-mode --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/TanStack/ai.git skills-src && mkdir -p .claude/skills && cp -r skills-src/packages/ai-code-mode/skills/ai-code-mode .claude/skills/ai-code-mode && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "ai-code-mode" agent skill from https://github.com/TanStack/ai/tree/main/packages/ai-code-mode/skills/ai-code-mode into .claude/skills/ai-code-mode/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ai-code-mode", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/TanStack/ai/tree/main/packages/ai-code-mode/skills/ai-code-modeType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add TanStack/ai --skill ai-code-mode -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install TanStack/ai ai-code-mode --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/TanStack/ai.git skills-src && mkdir -p .agents/skills && cp -r skills-src/packages/ai-code-mode/skills/ai-code-mode .agents/skills/ai-code-mode && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ai-code-mode" agent skill from https://github.com/TanStack/ai/tree/main/packages/ai-code-mode/skills/ai-code-mode into .agents/skills/ai-code-mode/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ai-code-mode", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add TanStack/ai --skill ai-code-mode -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install TanStack/ai ai-code-mode --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/TanStack/ai.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/packages/ai-code-mode/skills/ai-code-mode .cursor/skills/ai-code-mode && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "ai-code-mode" agent skill from https://github.com/TanStack/ai/tree/main/packages/ai-code-mode/skills/ai-code-mode into .cursor/skills/ai-code-mode/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ai-code-mode", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/TanStack/ai.git --path packages/ai-code-mode/skills/ai-code-mode--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add TanStack/ai --skill ai-code-mode -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install TanStack/ai ai-code-mode --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/TanStack/ai.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/packages/ai-code-mode/skills/ai-code-mode .gemini/skills/ai-code-mode && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "ai-code-mode" agent skill from https://github.com/TanStack/ai/tree/main/packages/ai-code-mode/skills/ai-code-mode into .gemini/skills/ai-code-mode/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ai-code-mode", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install TanStack/ai ai-code-modeInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add TanStack/ai --skill ai-code-mode -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/TanStack/ai.git skills-src && mkdir -p .github/skills && cp -r skills-src/packages/ai-code-mode/skills/ai-code-mode .github/skills/ai-code-mode && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "ai-code-mode" agent skill from https://github.com/TanStack/ai/tree/main/packages/ai-code-mode/skills/ai-code-mode into .github/skills/ai-code-mode/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ai-code-mode", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add TanStack/ai --skill ai-code-mode -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install TanStack/ai ai-code-mode --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/TanStack/ai.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/packages/ai-code-mode/skills/ai-code-mode .opencode/skills/ai-code-mode && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "ai-code-mode" agent skill from https://github.com/TanStack/ai/tree/main/packages/ai-code-mode/skills/ai-code-mode into .opencode/skills/ai-code-mode/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ai-code-mode", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
ai-code-modeLLM-generated TypeScript execution in sandboxed environments: createCodeModeTool() with isolate drivers (createNodeIsolateDriver, createQuickJSIsolateDriver, createQuickJSBunIsolateDriver…
AI Code Mode is an agent skill from TanStack/ai. LLM-generated TypeScript execution in sandboxed environments: createCodeModeTool() with isolate drivers (createNodeIsolateDriver, createQuickJSIsolateDriver, createQuickJSBunIsolateDriver, createCloudflareIsolateDriver), codeModeWithSnippets() for persistent snippet libraries, trust strategies, snippet storage (FileSystem, LocalStorage, InMemory, Mongo), client-side execution progress via codemode: custom events in useChat.
Its SKILL.md is about 5.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in AI & LLM Engineering. It works with TypeScript, Node.js and WebAssembly. The repository describes itself as: 🤖 Type-safe, provider-agnostic TypeScript AI SDK for streaming chat, tool calling, agents, and multimodal apps across OpenAI, Anthropic, Gemini, React, Vue, Svelte, and Solid. The licence is MIT.
4 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 5a41239. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).
From the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
api.weather.comapi.stocks.comFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
CODE_MODE_WORKER_SECRETAPI_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
AI Code Mode loads about 5.6k tokens when it runs. Until then it costs about 111 tokens; SKILL.md has 921 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from TanStack/ai at commit 5a41239, republished under its MIT licence (© TanStack). 921 words, ~5,613 tokens.
.claude/skills/ai-code-mode/SKILL.md (or your agent's skills folder).Note: This skill requires familiarity with ai-core and ai-core/chat-experience. Code Mode is always used on top of a chat experience.
Complete Code Mode setup with Node.js isolate driver:
import { chat, toServerSentEventsResponse, toolDefinition } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'
import { createCodeModeTool } from '@tanstack/ai-code-mode'
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
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
export async function POST(request: Request) {
const { messages } = await request.json()
const stream = chat({
adapter: openaiText('gpt-5.5'),
messages,
tools: [codeModeTool],
})
return toServerSentEventsResponse(stream)
}The recommended higher-level entry point is createCodeMode(), which returns both the tool and a matching system prompt:
import { chat, toServerSentEventsResponse, toolDefinition } from '@tanstack/ai'
import { createCodeMode } from '@tanstack/ai-code-mode'
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
import { openaiText } from '@tanstack/ai-openai'
import { z } from 'zod'
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()
})
const { tool, systemPrompt } = createCodeMode({
driver: createNodeIsolateDriver(),
tools: [fetchWeather],
timeout: 30_000,
})
export async function POST(request: Request) {
const { messages } = await request.json()
const stream = chat({
adapter: openaiText('gpt-5.5'),
systemPrompts: ['You are a helpful assistant.', systemPrompt],
tools: [tool],
messages,
})
return toServerSentEventsResponse(stream)
}createCodeMode calls createCodeModeTool and createCodeModeSystemPrompt internally. The system prompt includes generated TypeScript type stubs for each tool so the LLM writes correct calls.
Four drivers implement the IsolateDriver interface. All are interchangeable.
Node.js (createNodeIsolateDriver) -- Full V8 with JIT. Fastest option. Requires isolated-vm native C++ addon.
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).
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
})QuickJS Bun (createQuickJSBunIsolateDriver) -- Native QuickJS on the Bun runtime via bun:ffi. Requires Bun >= 1.3.14 (throws a descriptive error on Node.js). No native deps or build step. Each context gets a dedicated QuickJS runtime with its own memory limit, stack size, and interrupt-based timeout. Recommended QuickJS option on Bun, where the WASM driver's asyncify bridge is unreliable for async host tool calls.
import { createQuickJSBunIsolateDriver } from '@tanstack/ai-isolate-quickjs-bun'
const driver = createQuickJSBunIsolateDriver({
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.
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) |
| QuickJS Bun | Bun servers | None | No | Fast (native QuickJS) |
| Cloudflare | Edge deployments | None | N/A | Fast (V8 on edge) |
Snippets let the LLM save reusable code snippets. On future requests, relevant snippets are loaded and exposed as callable tools.
import {
chat,
maxIterations,
toServerSentEventsResponse,
toolDefinition,
} from '@tanstack/ai'
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
import {
codeModeWithSnippets,
createDefaultTrustStrategy,
} from '@tanstack/ai-code-mode-snippets'
import { createFileSnippetStorage } from '@tanstack/ai-code-mode-snippets/storage'
import { openaiText } from '@tanstack/ai-openai'
import { z } from 'zod'
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()
})
// Trust strategies control how snippets earn trust through executions
// Default (createDefaultTrustStrategy): untrusted -> provisional (10+ runs, >=90%) -> trusted (100+ runs, >=95%)
// Relaxed (createRelaxedTrustStrategy): untrusted -> provisional (3+ runs, >=80%) -> trusted (10+ runs, >=90%)
// Always trusted (createAlwaysTrustedStrategy): immediately trusted (dev/testing)
// Custom (createCustomTrustStrategy): configurable thresholds
const trustStrategy = createDefaultTrustStrategy()
// Storage options: file system (production) or memory (testing)
const storage = createFileSnippetStorage({
directory: './.snippets',
trustStrategy,
})
const driver = createNodeIsolateDriver()
export async function POST(request: Request) {
const { messages } = await request.json()
// High-level API: automatic LLM-based snippet selection
const { toolsRegistry, systemPrompt } = await codeModeWithSnippets({
config: {
driver,
tools: [fetchWeather],
timeout: 60_000,
memoryLimit: 128,
},
adapter: openaiText('gpt-5-mini'), // cheap model for snippet selection
snippets: {
storage,
maxSnippetsInContext: 5,
},
messages,
})
const stream = chat({
adapter: openaiText('gpt-5.5'),
tools: toolsRegistry.getTools(),
messages,
systemPrompts: ['You are a helpful assistant.', systemPrompt],
agentLoopStrategy: maxIterations(15),
})
return toServerSentEventsResponse(stream)
}The registry includes: execute_typescript, search_snippets, get_snippet, register_snippet, and one tool per selected snippet.
Custom trust strategy example:
import { createCustomTrustStrategy } from '@tanstack/ai-code-mode-snippets'
const strategy = createCustomTrustStrategy({
initialLevel: 'untrusted',
provisionalThreshold: { executions: 5, successRate: 0.85 },
trustedThreshold: { executions: 50, successRate: 0.95 },
})Storage implementations:
// File storage (production) -- persists snippets as files on disk
import { createFileSnippetStorage } from '@tanstack/ai-code-mode-snippets/storage'
const fileStorage = createFileSnippetStorage({ directory: './.snippets' })
// Memory storage (testing) -- in-memory, lost on restart
import { createMemorySnippetStorage } from '@tanstack/ai-code-mode-snippets/storage'
const memStorage = createMemorySnippetStorage()Code Mode emits custom events during sandbox execution. Handle them in useChat via onCustomEvent.
Events emitted:
| Event | When | Key fields |
|---|---|---|
code_mode:execution_started | Sandbox begins | timestamp, codeLength |
code_mode:console | Each console.log/error/warn/info | level, message, timestamp |
code_mode:external_call | Before an external_* function runs | function, args, timestamp |
code_mode:external_result | After successful external_* call | function, result, duration |
code_mode:external_error | When external_* call fails | function, error, duration |
import { useCallback, useRef, useState } from 'react'
import { useChat, fetchServerSentEvents } from '@tanstack/ai-react'
interface VMEvent {
id: string
eventType: string
data: unknown
timestamp: number
}
export function CodeModeChat() {
const [toolCallEvents, setToolCallEvents] = useState<
Map<string, Array<VMEvent>>
>(new Map())
const eventIdCounter = useRef(0)
const handleCustomEvent = useCallback(
(eventType: string, data: unknown, context: { toolCallId?: string }) => {
const { toolCallId } = context
if (!toolCallId) return
const event: VMEvent = {
id: `event-${eventIdCounter.current++}`,
eventType,
data,
timestamp: Date.now(),
}
setToolCallEvents((prev) => {
const next = new Map(prev)
const events = next.get(toolCallId) || []
next.set(toolCallId, [...events, event])
return next
})
},
[],
)
const { messages, sendMessage, isLoading } = useChat({
connection: fetchServerSentEvents('/api/chat'),
onCustomEvent: handleCustomEvent,
})
return (
<div>
{messages.map((message) => (
<div key={message.id}>
{message.parts.map((part, index) => {
if (part.type === 'text') {
return <p key={index}>{part.content}</p>
}
if (
part.type === 'tool-call' &&
part.name === 'execute_typescript'
) {
const events = toolCallEvents.get(part.id) || []
return (
<div key={part.id}>
<pre>{JSON.parse(part.arguments)?.typescriptCode}</pre>
{events.map((evt) => (
<div key={evt.id}>
{evt.eventType}: {JSON.stringify(evt.data)}
</div>
))}
{part.output && (
<pre>{JSON.stringify(part.output, null, 2)}</pre>
)}
</div>
)
}
return null
})}
</div>
))}
</div>
)
}The onCustomEvent callback signature is identical across all framework integrations (@tanstack/ai-react, @tanstack/ai-solid, @tanstack/ai-vue, @tanstack/ai-svelte):
type OnCustomEvent = (
eventType: string,
data: unknown,
context: { toolCallId?: string },
) => voidSnippet-specific events (when using codeModeWithSnippets):
| Event | When | Key fields |
|---|---|---|
code_mode:snippet_call | Snippet tool invoked | snippet, input, timestamp |
code_mode:snippet_result | Snippet completed | snippet, result, duration |
code_mode:snippet_error | Snippet failed | snippet, error, duration |
snippet:registered | New snippet saved | id, name, description |
When a large tool catalog would bloat the execute_typescript system prompt, mark low-priority tools lazy: true. Lazy tools are kept out of the full type-stub documentation and listed in a compact "Discoverable APIs" catalog instead. All sandbox bindings are always injected — lazy defers documentation, not callability.
Marking a tool lazy:
import { toolDefinition } from '@tanstack/ai'
import { z } from 'zod'
const eagerTool = 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()
})
const rarelyUsedTool = toolDefinition({
name: 'fetchStocks',
description: 'Get stock prices for a ticker. Returns a price quote.',
inputSchema: z.object({ ticker: z.string() }),
outputSchema: z.object({ price: z.number() }),
lazy: true, // <-- opt out of full system-prompt documentation
}).server(async ({ ticker }) => {
const res = await fetch(`https://api.stocks.com/${ticker}`)
return res.json()
})createCodeMode return shape:
createCodeMode() returns { tool, discoveryTool, tools, systemPrompt }. When lazy tools are present discoveryTool is a discover_tools server tool; otherwise it is null. Always spread tools (not just tool) into chat() so the discovery tool is registered:
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
import { createCodeMode } from '@tanstack/ai-code-mode'
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
import { openaiText } from '@tanstack/ai-openai'
const { tools, systemPrompt } = createCodeMode({
driver: createNodeIsolateDriver(),
tools: [eagerTool, rarelyUsedTool], // rarelyUsedTool has lazy: true
})
export async function POST(request: Request) {
const { messages } = await request.json()
const stream = chat({
adapter: openaiText('gpt-5.5'),
systemPrompts: ['You are a helpful assistant.', systemPrompt],
tools: [...tools], // spread tools, not just tool
messages,
})
return toServerSentEventsResponse(stream)
}tools equals [tool] when there are no lazy tools (backward compatible) and [tool, discoveryTool] when lazy tools exist.
discover_tools flow:
When the model encounters a lazy tool it has not seen before, it calls discover_tools with the bare name (no external_ prefix). The tool returns each requested tool's TypeScript type stub and description. The model then writes correctly-typed external_<name> calls inside execute_typescript.
Model sees: "Discoverable APIs: external_fetchStocks"
Model calls: discover_tools({ toolNames: ["fetchStocks"] })
Response: { tools: [{ name: "external_fetchStocks", description: "...", typeStub: "declare function external_fetchStocks(...)" }] }
Model writes inside execute_typescript: const result = await external_fetchStocks({ ticker: "AAPL" })lazyToolsConfig.includeDescription:
Control how much of each lazy tool's description appears in the Discoverable APIs catalog (the pre-discovery list):
| Value | Catalog entry |
|---|---|
'none' | external_fetchStocks (name only — default) |
'first-sentence' | external_fetchStocks — Get stock prices. |
'full' | external_fetchStocks — Get stock prices. Returns a price quote. |
import { createCodeMode } from '@tanstack/ai-code-mode'
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
import { eagerTool, rarelyUsedTool } from './tools'
const { tools, systemPrompt } = createCodeMode({
driver: createNodeIsolateDriver(),
tools: [eagerTool, rarelyUsedTool],
lazyToolsConfig: { includeDescription: 'first-sentence' },
})The same lazyToolsConfig option is accepted by plain chat() for its own lazy-tool discovery catalog (see ai-core/tool-calling/SKILL.md).
Code Mode executes LLM-generated code. Any secrets available in the sandbox context are accessible to generated code, which could exfiltrate them via tool calls. Never pass API keys, database credentials, or tokens into the sandbox. Keep secrets in your tool server implementations, which run in the host process outside the sandbox.
Wrong:
import { toolDefinition } from '@tanstack/ai'
import { createCodeModeTool } from '@tanstack/ai-code-mode'
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
import { z } from 'zod'
const codeModeTool = createCodeModeTool({
driver: createNodeIsolateDriver(),
tools: [
toolDefinition({
name: 'callApi',
description: 'Call an HTTP API',
inputSchema: z.object({ url: z.string(), apiKey: z.string() }),
outputSchema: z.any(),
}).server(async ({ url, apiKey }) =>
fetch(url, {
headers: { Authorization: apiKey },
}),
),
],
})Right:
import { toolDefinition } from '@tanstack/ai'
import { createCodeModeTool } from '@tanstack/ai-code-mode'
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
import { z } from 'zod'
const codeModeTool = createCodeModeTool({
driver: createNodeIsolateDriver(),
tools: [
toolDefinition({
name: 'callApi',
description: 'Call an HTTP API',
inputSchema: z.object({ url: z.string() }),
outputSchema: z.any(),
}).server(async ({ url }) =>
fetch(url, {
headers: { Authorization: `Bearer ${process.env.API_KEY}` }, // secret stays in host
}),
),
],
})Source: docs/code-mode/code-mode.md
LLM-generated code may contain infinite loops. The default timeout is 30s, but developers may override to 0 (no timeout). Always set an explicit, finite timeout.
Wrong:
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
const driver = createNodeIsolateDriver({ timeout: 0 })Right:
import { createNodeIsolateDriver } from '@tanstack/ai-isolate-node'
const driver = createNodeIsolateDriver({ timeout: 30_000 })Source: ai-code-mode source (default timeout in CodeModeToolConfig)
isolated-vm requires native module compilation. An incompatible build (wrong Node.js version, missing build tools) causes segfaults that no JS error handling can catch. The driver runs a subprocess probe by default. Never set skipProbe: true unless you have independently verified compatibility. Use probeIsolatedVm() to check before creating the driver.
import {
createNodeIsolateDriver,
probeIsolatedVm,
} from '@tanstack/ai-isolate-node'
const probe = probeIsolatedVm()
if (!probe.compatible) {
console.error('isolated-vm not compatible:', probe.error)
// Fall back to QuickJS
}
// Never do this unless you verified compatibility yourself:
// const driver = createNodeIsolateDriver({ skipProbe: true })Source: ai-isolate-node source (probeIsolatedVm implementation)
The four drivers have different capabilities. Same code may work in Node but fail elsewhere.
bun:ffi, dedicated runtime per context with per-context memory/stack limits and normalized MemoryLimitError/StackOverflowError/TimeoutErrormaxToolRounds limit (default 10), requires deployed worker with UNSAFE_EVAL or eval unsafe bindingTest generated code against your target driver. If you need portability, target QuickJS's subset.
Source: docs/code-mode/code-mode-isolates.md
© TanStack, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in packages/ai-code-mode/skills/ai-code-mode of TanStack/ai.
Open the folder on GitHubat commit 5a41239
We found 1 copy of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in TanStack/ai, which our catalogue first saw on October 7, 2026.
AI Code Mode next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| AI Code Mode this skillTanStack/ai | 3.2k | 1 repos | ~5.6k | Automated safety check: Pass | MIT | |
| Compromise NLP Libraryspencermountain/compromise | 12k | — | ~2k | Automated safety check: Pass | MIT | |
| Agent Squad for TypeScript2FastLabs/agent-squad | 7.8k | — | ~4.3k | Automated safety check: Pass | Apache-2.0 | |
| Transformers.jshuggingface/skills | 11k | 1 repos | ~6.2k | Automated safety check: Pass | Apache-2.0 | |
| Transformers JSwaybarrios/opencode-power-pack | 533 | — | ~1.9k | Automated safety check: Pass | Apache-2.0 | |
| Golem Add npm Packagegolemcloud/golem | 1.5k | — | ~902 | Automated safety check: Pass | Custom licence |
spencermountain/compromise
Helps write and debug JavaScript or TypeScript that uses the compromise English NLP library for matching, entity extraction, tagging and sentence transforms.
2FastLabs/agent-squad
Guide to building Node.js and TypeScript apps on the agent-squad package: orchestrator, agent types, classifier routing, storage, retrievers and MCP tools.
huggingface/skills
Runs pre-trained Hugging Face models in JavaScript or TypeScript with Transformers.js, in browsers or Node.js, Bun and Deno, for text, vision, audio and multimodal tasks.
waybarrios/opencode-power-pack
Run Hugging Face models in JavaScript or TypeScript with Transformers.js, WebGPU, or WASM across browser, Node.js, Bun, and Deno.
golemcloud/golem
Add a new npm package dependency to a TypeScript Golem project.
golemcloud/golem
JavaScript runtime environment for TypeScript and Scala Golem agents.
TanStack/ai
A skill your agent uses when the user invokes /i-have-adhd, says they have ADHD, or asks for ADHD-friendly output.
TanStack/ai
Sweep open (or listed) PRs with up to 100 parallel agents: security-scan outside contributors, rebase onto main when behind (push --force-with-lease), approve pending first-time-contributor CI when…
TanStack/ai
A skill your agent uses when wiring honcho() from @tanstack/ai-memory/honcho — a hosted memory adapter where recall is a dialectic answer over the user's representation (no discrete fragments).
TanStack/ai
A skill your agent uses when wiring inMemory() from @tanstack/ai-memory/in-memory — explains setup, options (embedder, extract, topK/minScore), when to pick it (dev/tests/single-process demos), and…
TanStack/ai
A skill your agent uses when wiring redis() from @tanstack/ai-memory/redis in production — covers client setup (ioredis or node-redis via fromNodeRedis), the storage model, client-side ranking…
TanStack/ai
A skill your agent uses when adding a public teaching example or a docs tutorial.
Works with
Categories
LLM-generated TypeScript execution in sandboxed environments: createCodeModeTool() with isolate drivers (createNodeIsolateDriver, createQuickJSIsolateDriver, createQuickJSBunIsolateDriver…. AI Code Mode is an agent skill from TanStack/ai. LLM-generated TypeScript execution in sandboxed environments: createCodeModeTool() with isolate drivers (createNodeIsolateDriver, createQuickJSIsolateDriver, createQuickJSBunIsolateDriver, createCloudflareIsolateDriver), codeModeWithSnippets() for persistent snippet libraries, trust strategies, snippet storage (FileSystem, LocalStorage, InMemory, Mongo), client-side execution progress via codemode: custom events in useChat.
AI Code Mode fits situations like: AI & LLM Engineering work in your project.
Run `npx skills add TanStack/ai --skill ai-code-mode -a claude-code`. Or copy the skill folder (packages/ai-code-mode/skills/ai-code-mode in TanStack/ai) into .claude/skills/ai-code-mode in your project. Claude Code loads it when a task matches its description.
Run `npx skills add TanStack/ai --skill ai-code-mode -a codex`. Or copy the skill folder (packages/ai-code-mode/skills/ai-code-mode in TanStack/ai) into .agents/skills/ai-code-mode in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add TanStack/ai --skill ai-code-mode -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ai-code-mode, .gemini/skills/ai-code-mode, .github/skills/ai-code-mode and .opencode/skills/ai-code-mode in your project.
Going by SKILL.md and its folder, AI Code Mode needs credentials named CODE_MODE_WORKER_SECRET and API_KEY. Our summary lists: Node.js; A credential in CODE_MODE_WORKER_SECRET.
SKILL.md names 2 domains. In commands or code: api.weather.com and api.stocks.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
AI Code Mode is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.6k tokens (SKILL.md is roughly 22k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with AI Code Mode: Compromise NLP Library (spencermountain/compromise, 12k stars), Agent Squad for TypeScript (2FastLabs/agent-squad, 7.8k stars), Transformers.js (huggingface/skills, 11k stars) and Transformers JS (waybarrios/opencode-power-pack, 533 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
TanStack (a GitHub organization) maintains it in TanStack/ai, which has 3,169 GitHub stars. The repository holds 24 skills in this directory. The repository was last updated on October 7, 2026.
Source: TanStack/ai on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.