Crux
Getting Started

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. Public packages are available on npm; use the install commands below to get started.

Install

bash npm install @use-crux/core @use-crux/ai @ai-sdk/openai zod

bash pnpm add @use-crux/core @use-crux/ai @ai-sdk/openai zod

bash yarn add @use-crux/core @use-crux/ai @ai-sdk/openai zod

bash bun add @use-crux/core @use-crux/ai @ai-sdk/openai zod

export OPENAI_API_KEY=sk-...
src/
  evals/
    support.eval.ts    ← one default Eval discovered by convention
  prompts/
    index.ts          ← Prompt definitions
    contexts.ts       ← Shared contexts
  index.ts            ← Entry point

Basic script

src/index.ts
import { prompt } from "@use-crux/core";
import { generate } from "@use-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.

src/batch.ts
import { generate } from "@use-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 @use-crux/openai:

src/openai-direct.ts
import { createOpenAI } from "@use-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

src/anthropic-direct.ts
import { createAnthropic } from "@use-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

src/google-direct.ts
import { createGoogle } from "@use-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.

Next steps

On this page