orval
Generate type-safe API clients, TanStack Query/SWR hooks, Zod schemas, MSW mocks, Hono server handlers, MCP servers, and SolidStart actions from OpenAPI specs using Orval. Covers all clients (React/Vue/Svelte/Solid/Angular Query, Fetch, Axios), custom HTTP mutators, authentication patterns, NDJSON streaming, programmatic API, and advanced configuration.
install
source · Clone the upstream repo
git clone https://github.com/orval-labs/orval
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/orval-labs/orval "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/orval" ~/.claude/skills/orval-labs-orval-orval && rm -rf "$T"
manifest:
skills/orval/SKILL.mdsource content
Orval - OpenAPI to TypeScript Code Generator
Orval generates type-safe TypeScript clients, hooks, schemas, mocks, and server handlers from OpenAPI v3/Swagger v2 specifications.
Quick Start
Installation
npm install orval -D # or yarn add orval -D # or pnpm add orval -D # or bun add orval -D
Minimal Configuration
import { defineConfig } from 'orval'; export default defineConfig({ petstore: { input: { target: './petstore.yaml', }, output: { target: './src/api/petstore.ts', schemas: './src/api/model', client: 'react-query', }, }, });
Run
npx orval npx orval --config ./orval.config.ts npx orval --project petstore npx orval --watch
Choosing Your Setup
Client Selection Guide
| Use Case | Client | httpClient | Notes |
|---|---|---|---|
| React with server state | | or | TanStack Query hooks |
| Vue 3 with server state | | or | TanStack Query for Vue |
| Svelte with server state | | or | TanStack Query for Svelte |
| SolidJS standalone app | | or | TanStack Query for Solid |
| SolidStart full-stack | | native fetch | Uses / primitives |
| Angular with signals | | | Injectable functions, signal reactivity |
| Angular traditional | | — | HttpClient services |
| React with SWR | | or | Vercel SWR hooks |
| Lightweight / Edge | | — | Zero dependencies, works everywhere |
| Node.js / existing Axios | | — | Factory functions (default) |
| Axios with DI | | — | Injectable Axios instance |
| Validation only | | — | Zod schemas, no HTTP client |
| Backend API server | | — | Hono handlers with Zod validation |
| AI agent tools | | — | Model Context Protocol servers |
Mode Selection Guide
— Everything in one file. Best for small APIs.single
— Separate files:split
,petstore.ts
,petstore.schemas.ts
. Good for medium APIs.petstore.msw.ts
— One file per OpenAPI tag + shared schemas. Organizes by domain.tags
— Folder per tag with split files. Best for large APIs. Recommended.tags-split
httpClient Option
For
react-query, vue-query, svelte-query, and swr clients:
output: { client: 'react-query', httpClient: 'fetch', // 'fetch' (default) | 'axios' }
For
angular-query:
output: { client: 'angular-query', httpClient: 'angular', // Uses Angular HttpClient }
Configuration Reference
Config Structure
import { defineConfig } from 'orval'; export default defineConfig({ [projectName]: { input: InputOptions, output: OutputOptions, hooks: HooksOptions, }, });
Multiple projects can share the same config file with different input/output settings.
Input Options
input: { target: './spec.yaml', // Path or URL to OpenAPI spec (required) override: { transformer: './transform.js', // Transform spec before generation }, filters: { mode: 'include', // 'include' | 'exclude' tags: ['pets', /health/], // Filter by OpenAPI tags schemas: ['Pet', /Error/], // Filter by schema names }, parserOptions: { headers: [ // Auth headers for remote spec URLs { domains: ['api.example.com'], headers: { Authorization: 'Bearer YOUR_TOKEN', 'X-API-Key': 'your-api-key', }, }, ], }, }
Output Options
output: { target: './src/api/endpoints.ts', // Output path (required) client: 'react-query', // Client type (see table above) httpClient: 'fetch', // 'fetch' (default) | 'axios' | 'angular' mode: 'tags-split', // 'single' | 'split' | 'tags' | 'tags-split' schemas: './src/api/model', // Output path for model types operationSchemas: './src/api/params', // Separate path for operation-derived types workspace: 'src/', // Base folder for all files fileExtension: '.ts', // Custom file extension namingConvention: 'camelCase', // File naming: camelCase | PascalCase | snake_case | kebab-case indexFiles: true, // Generate index.ts barrel files clean: true, // Clean output before generating prettier: true, // Format with Prettier biome: true, // Format with Biome headers: true, // Generate header parameters baseUrl: '/api/v2', // API base URL // or from spec: // baseUrl: { getBaseUrlFromSpecification: true, index: 0, variables: { environment: 'api.dev' } }, mock: true, // Generate MSW handlers (boolean or config object) docs: true, // Generate TypeDoc documentation // docs: { configPath: './typedoc.config.mjs' }, allParamsOptional: true, // Make all params optional (except path params) urlEncodeParameters: true, // URL-encode path/query parameters optionsParamRequired: false, // Make options parameter required propertySortOrder: 'Specification', // 'Alphabetical' | 'Specification' tsconfig: './tsconfig.json', // Custom tsconfig path override: { ... }, // Advanced overrides (see below) }
Multiple API Specs
export default defineConfig({ petstoreV1: { input: { target: './specs/v1.yaml' }, output: { target: 'src/api/v1', client: 'react-query' }, }, petstoreV2: { input: { target: './specs/v2.yaml' }, output: { target: 'src/api/v2', client: 'react-query' }, }, });
Filter Endpoints
input: { target: './spec.yaml', filters: { mode: 'include', tags: ['pets'], }, }
Detailed Guides
When the user's question involves a specific topic below, read the corresponding file from this skill's directory.
| Topic | File | Load when user asks about... |
|---|---|---|
| TanStack Query / SWR | tanstack-query.md | React Query, Vue Query, Svelte Query, Solid Query, SWR, query hooks, invalidation, infinite queries, suspense, prefetch |
| Angular | angular.md | Angular Query, Angular HttpClient, signals, inject functions, Angular services, providedIn |
| SolidStart | solid-start.md | SolidStart, @solidjs/router, query(), action(), createAsync, revalidate |
| Custom HTTP / Auth | custom-http-clients.md | Custom mutator, authentication, tokens, interceptors, custom fetch/axios, baseURL, hook-based mutator |
| Zod Validation | zod-validation.md | Zod schemas, validation, runtime validation, coerce, strict, preprocess |
| Mocking / MSW | mocking-msw.md | MSW mocks, testing, test setup, faker, Vitest, mock handlers, useExamples |
| Hono Server | hono.md | Hono handlers, zValidator, composite routes, context types, server-side generation |
| Advanced Config | advanced-config.md | Type generation, enums, per-operation overrides, FormData, JSDoc, params serializer, full example |
| Tooling / Workflow | tooling-workflow.md | Programmatic API, transformers, hooks, NDJSON streaming, MCP, afterAllFilesWrite |
OpenAPI Specification Best Practices
- Use unique
for every operation — Orval uses these for function and hook namesoperationId - Define reusable schemas in
— reduces duplication in generated typescomponents/schemas - Use tags to group operations — works with
andtags
modestags-split - Define response types for all operations — enables full type safety
- Mark required fields — affects optional/required in generated TypeScript interfaces
- Use
for numeric enums — generates readable const namesx-enumNames - Provide
values — used by mock generation whenexampleuseExamples: true - Use
content type for streaming endpoints — enables typed NDJSON generationapplication/x-ndjson
CLI Reference
orval # Generate using auto-discovered config orval --config ./api/orval.config.ts # Specify config file orval --project petstore # Run specific project(s) orval --watch # Watch mode orval --watch ./src # Watch specific directory orval --clean # Clean generated files orval --prettier # Format with Prettier orval --biome # Format with Biome orval --tsconfig ./src/tsconfig.json # Custom tsconfig path orval --mode split # Override output mode orval --client react-query # Override client orval --mock # Override mock generation orval --input ./spec.yaml --output ./api.ts # Direct generation