Node.js
Use Crux in any Node.js script, CLI tool, or backend service. No framework required.
Crux works in any Node.js (or Bun, or Deno) script. This guide covers the basic setup, batch processing, and the alternative SDK adapters.
Crux is in alpha. The install commands below are the intended package set for the first public npm alpha; until that release lands, consume Crux from this repository workspace.
Install
bash npm install @crux/core @crux/ai @ai-sdk/openai zod bash pnpm add @crux/core @crux/ai @ai-sdk/openai zod bash yarn add @crux/core @crux/ai @ai-sdk/openai zod bash bun add @crux/core @crux/ai @ai-sdk/openai zod export OPENAI_API_KEY=sk-...Recommended layout
src/
evals/
support.eval.ts ← Quality evaluations discovered by convention
prompts/
index.ts ← Prompt definitions
contexts.ts ← Shared contexts
index.ts ← Entry pointBasic script
import { prompt } from '@crux/core'
import { generate } from '@crux/ai'
import { openai } from '@ai-sdk/openai'
import { z } from 'zod'
const classify = prompt({
id: 'classify',
input: z.object({ text: z.string() }),
output: z.object({
category: z.enum(['bug', 'feature', 'question', 'other']),
confidence: z.number(),
}),
system: 'Classify support tickets.',
prompt: ({ input }) => input.text,
})
const result = await generate(classify, {
model: openai('gpt-4o-mini'),
input: { text: 'The login button is broken on mobile' },
})
console.log(result.object)
// { category: 'bug', confidence: 0.95 }Batch processing
The same prompt can be reused across many inputs in parallel. The adapter is just a function call — there's no setup overhead per request.
import { generate } from '@crux/ai'
import { openai } from '@ai-sdk/openai'
import { classify } from './prompts'
const tickets = await loadTickets()
const results = await Promise.all(
tickets.map((ticket) =>
generate(classify, {
model: openai('gpt-4o-mini'),
input: { text: ticket.body },
}),
),
)
for (const [i, result] of results.entries()) {
console.log(`${tickets[i].id}: ${result.object.category}`)
}Using the OpenAI SDK directly
If you'd rather call the OpenAI SDK directly (no Vercel AI SDK), use @crux/openai:
import { createOpenAI } from '@crux/openai'
import OpenAI from 'openai'
import { classify } from './prompts'
const client = new OpenAI()
const adapter = createOpenAI(client)
const result = await adapter.generate(classify, {
model: 'gpt-4o-mini',
input: { text: 'How do I reset my password?' },
})Using the Anthropic SDK directly
import { createAnthropic } from '@crux/anthropic'
import Anthropic from '@anthropic-ai/sdk'
import { classify } from './prompts'
const client = new Anthropic()
const adapter = createAnthropic(client)
const result = await adapter.generate(classify, {
model: 'claude-haiku-4-5-20251001',
input: { text: 'How do I reset my password?' },
})Using Google GenAI directly
import { createGoogle } from '@crux/google'
import { GoogleGenAI } from '@google/genai'
import { classify } from './prompts'
const client = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY })
const adapter = createGoogle(client)
const result = await adapter.generate(classify, {
model: 'gemini-2.5-flash',
input: { text: 'How do I reset my password?' },
})The same classify prompt definition works with all four adapters. That's the SDK-agnostic guarantee — you can switch
providers (or use multiple) without touching prompt code.