This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
TanStack AI is a type-safe, provider-agnostic AI SDK for building AI-powered applications. The repository is a pnpm monorepo managed with Nx that includes TypeScript, PHP, and Python packages, plus multiple framework examples.
- Package Manager: pnpm@10.17.0 (required)
- Build System: Nx for task orchestration and caching
- TypeScript: 5.9.3
- Testing: Vitest for unit tests
- Linting: ESLint with custom TanStack config
- Formatting: Prettier
# Run all tests (full CI suite)
pnpm test
# Run tests for affected packages only (for PRs)
pnpm test:pr
# Run specific test suites
pnpm test:lib # Run unit tests for affected packages
pnpm test:lib:dev # Watch mode for unit tests
pnpm test:eslint # Lint affected packages
pnpm test:types # Type check affected packages
pnpm test:build # Verify build artifacts with publint
pnpm test:coverage # Generate coverage reports
pnpm test:knip # Check for unused dependencies
pnpm test:sherif # Check pnpm workspace consistency
pnpm test:docs # Verify documentation links# Navigate to package directory and run tests
cd packages/typescript/ai
pnpm test:lib # Run tests for this package
pnpm test:lib:dev # Watch mode
pnpm test:types # Type check
pnpm test:eslint # Lint# Build affected packages
pnpm build
# Build all packages
pnpm build:all
# Watch mode (build + watch for changes)
pnpm watch
pnpm dev # alias for watchpnpm format # Format all files with Prettierpnpm changeset # Create a new changeset
pnpm changeset:version # Bump versions based on changesets
pnpm changeset:publish # Publish to npmpackages/
├── typescript/ # TypeScript packages (main implementation)
│ ├── ai/ # Core AI library (@tanstack/ai)
│ ├── ai-client/ # Framework-agnostic chat client
│ ├── ai-react/ # React hooks (useChat)
│ ├── ai-solid/ # Solid hooks
│ ├── ai-svelte/ # Svelte integration
│ ├── ai-vue/ # Vue integration
│ ├── ai-openai/ # OpenAI adapter
│ ├── ai-anthropic/ # Anthropic/Claude adapter
│ ├── ai-gemini/ # Google Gemini adapter
│ ├── ai-ollama/ # Ollama adapter
│ ├── ai-devtools/ # DevTools integration
│ ├── react-ai-devtools/ # React DevTools component
│ └── solid-ai-devtools/ # Solid DevTools component
├── php/ # PHP packages (future)
└── python/ # Python packages (future)
examples/ # Example applications
├── ts-react-chat/ # React chat example
├── ts-solid-chat/ # Solid chat example
├── ts-vue-chat/ # Vue chat example
├── ts-svelte-chat/ # Svelte chat example
├── ts-group-chat/ # Multi-user group chat
├── vanilla-chat/ # Vanilla JS example
├── php-slim/ # PHP Slim framework example
└── python-fastapi/ # Python FastAPI example
The library uses a tree-shakeable adapter architecture where each provider (OpenAI, Anthropic, Gemini, Ollama) exports multiple specialized adapters:
- Text adapters (
openaiText,anthropicText) - Chat/completion - Embedding adapters (
openaiEmbed) - Text embeddings - Summarize adapters (
openaiSummarize) - Summarization - Image adapters (
openaiImage) - Image generation
Each adapter is a separate import to minimize bundle size:
import { openaiText } from '@tanstack/ai-openai/adapters'
import { ai } from '@tanstack/ai'
const textAdapter = openaiText()
const result = ai({ adapter: textAdapter, model: 'gpt-4o', messages: [...] })The @tanstack/ai package provides core functions:
ai()/generate()- Unified generation function for any adapter typechat()- Chat completion with streaming, tools, and agent loopsembedding()- Generate embeddingssummarize()- Summarize text- Legacy adapters (monolithic, deprecated) use
openai(),anthropic(), etc.
Tools are defined once with toolDefinition() and can have .server() or .client() implementations:
const tool = toolDefinition({
name: 'getTodos',
inputSchema: z.object({ userId: z.string() }),
outputSchema: z.array(z.object({ id: z.string(), title: z.string() })),
})
// Server implementation (runs on server)
const serverTool = tool.server(async ({ userId }) => db.todos.find({ userId }))
// Client implementation (runs in browser)
const clientTool = tool.client(async ({ userId }) =>
fetch(`/api/todos/${userId}`),
)@tanstack/ai-client- Headless chat state management with connection adapters (SSE, HTTP stream, custom)@tanstack/ai-react-useChathook for React@tanstack/ai-solid-useChathook for Solid@tanstack/ai-vue- Vue integration@tanstack/ai-svelte- Svelte integration
Each framework integration uses the headless ai-client under the hood.
- Per-model type safety - Provider options are typed based on selected model
- Multimodal content - Type-safe image, audio, video, document support based on model capabilities
- Zod schema inference - Tools use Zod for runtime validation and type inference
InferChatMessages- Type inference for message types based on tools and configuration
index.ts- Main exports (chat, embedding, summarize, toolDefinition, etc.)types.ts- Core type definitions (ModelMessage, ContentPart, StreamChunk, etc.)core/- Core functions (chat.ts, generate.ts, embedding.ts, summarize.ts)adapters/- Base adapter classes and interfacestools/- Tool definition system and Zod converterstream/- Stream processing (StreamProcessor, chunking strategies, partial JSON parsing)utilities/- Helpers (message converters, agent loop strategies, SSE utilities)
index.ts- Exports tree-shakeable adapters (openaiText, openaiEmbed, etc.)adapters/- Individual adapter implementations (text.ts, embed.ts, summarize.ts, image.ts)model-meta.ts- Model metadata for type safety (provider options per model)openai-adapter.ts- Legacy monolithic adapter (deprecated)
- Create a changeset:
pnpm changeset - Make changes in the appropriate package(s)
- Run tests:
pnpm test:lib(or package-specific tests) - Run type checks:
pnpm test:types - Run linter:
pnpm test:eslint - Format code:
pnpm format - Verify build:
pnpm test:buildorpnpm build
Examples are not built by Nx. To run an example:
cd examples/ts-react-chat
pnpm install # if needed
pnpm dev # start dev server- Uses Nx affected commands to only test/build changed packages
- Nx caching speeds up builds and tests
nx.jsonconfigures Nx behavior- Use
nx run-manyto run commands across multiple packages
- Use
workspace:*protocol for internal package dependencies inpackage.json - Example:
"@tanstack/ai": "workspace:*"
When adding new functionality to provider adapters, create separate adapters rather than adding to monolithic ones. Export from /adapters subpath.
Each package uses exports field in package.json for subpath exports (e.g., @tanstack/ai/adapters, @tanstack/ai/event-client)
- Unit tests in
*.test.tsfiles alongside source - Uses Vitest with happy-dom for DOM testing
- Test coverage via
pnpm test:coverage
- Docs are in
docs/directory (Markdown) - Auto-generated docs via
pnpm generate-docs(TypeDoc) - Link verification via
pnpm test:docs
zod- Schema validation (peer dependency)@alcyone-labs/zod-to-json-schema- Convert Zod schemas to JSON Schema for LLM toolspartial-json- Parse incomplete JSON from streaming responses
openai- OpenAI SDK@anthropic-ai/sdk- Anthropic SDK@google/generative-ai- Gemini SDKollama- Ollama SDK
@tanstack/devtools-event-client- TanStack DevTools integration