| name | openapi-types |
| description | Generate TypeScript types and client SDKs from OpenAPI specs |
| disable-model-invocation | true |
OpenAPI Type Generator
I'll generate TypeScript types, client SDKs, and Zod schemas from OpenAPI 3.0 specifications.
Arguments: $ARGUMENTS - path to OpenAPI spec file
Features:
- TypeScript types from OpenAPI schemas
- Type-safe fetch/axios client SDK
- Zod schemas for runtime validation
- React hooks for data fetching
- Integration with
/api-docs-generate
Token Optimization
This skill uses code generation-specific patterns to minimize token usage:
1. OpenAPI Spec Caching (800 token savings)
Pattern: Cache parsed OpenAPI specification structure
- Store spec analysis in
.openapi-types-cache (1 hour TTL)
- Cache: schemas, endpoints, parameters, responses
- Read cached spec on subsequent runs (50 tokens vs 850 tokens fresh)
- Invalidate on spec file changes
- Savings: 94% on repeat type generations
2. Bash-Based OpenAPI Validation (600 token savings)
Pattern: Use openapi-generator-cli or swagger-cli for validation
- Run
swagger-cli validate spec.yaml (200 tokens)
- Parse validation errors with grep
- No Task agents for spec validation
- Savings: 75% vs LLM-based validation
3. Template-Based Type Generation (2,000 token savings)
Pattern: Use openapi-typescript or openapi-generator templates
- Standard tool:
openapi-typescript spec.yaml -o types.ts (300 tokens)
- Pre-defined type generation templates
- No creative type generation logic needed
- Savings: 87% vs LLM-generated TypeScript types
4. Early Exit for Current Types (95% savings)
Pattern: Detect if types already generated and current
- Check for existing types file matching spec name (50 tokens)
- Compare spec mtime with types file mtime
- If types current: return types location (100 tokens)
- Distribution: ~50% of runs check existing types
- Savings: 100 vs 2,500 tokens for type regeneration checks
5. Sample-Based Schema Analysis (700 token savings)
Pattern: Analyze first 20 schemas for patterns
- Identify common patterns: pagination, errors, IDs (400 tokens)
- Apply patterns to remaining schemas
- Full analysis only if explicitly requested
- Savings: 65% vs analyzing every schema definition
6. Incremental Type Updates (1,000 token savings)
Pattern: Generate only changed schemas
- Compare new spec with cached version
- Generate types only for modified schemas
- Merge with existing types file
- Savings: 75% vs full type regeneration
7. Cached Tool Detection (400 token savings)
Pattern: Cache openapi-typescript installation status
- Check tool installation once, cache result
- Don't re-check npm ls on each run
- Standard installation instructions
- Savings: 80% on tool detection
8. Bash-Based Code Generation (800 token savings)
Pattern: Use openapi-typescript tool directly
- Generate all types with single command (300 tokens)
- Post-process with sed/awk if needed (100 tokens)
- No Task agents for code generation
- Savings: 75% vs Task-based generation
Real-World Token Usage Distribution
Typical operation patterns:
- Check existing types (current): 100 tokens
- Generate types (first time): 2,500 tokens
- Update types (spec changed): 1,500 tokens
- Regenerate (tool changed): 2,000 tokens
- Incremental update (few schemas): 800 tokens
- Most common: Check existing types or tool-based generation
Expected per-generation: 2,000-3,000 tokens (50% reduction from 4,000-6,000 baseline)
Real-world average: 900 tokens (due to cached specs, early exit, tool-based generation)
Phase 1: OpenAPI Spec Detection
#!/bin/bash
echo "=== Detecting OpenAPI Specifications ==="
echo ""
find_openapi_specs() {
find . -type f \( \
-name "openapi*.yaml" -o \
-name "openapi*.yml" -o \
-name "swagger*.json" -o \
-name "swagger*.yaml" -o \
-name "api-spec*.yaml" \
\) ! -path "*/node_modules/*" 2>/dev/null
}
SPECS=$(find_openapi_specs)
if [ -z "$SPECS" ]; then
echo "❌ No OpenAPI specifications found"
echo ""
echo "Looking for files like:"
echo " - openapi.yaml"
echo " - swagger.json"
echo " - docs/api-spec.yaml"
echo ""
echo "💡 Generate OpenAPI spec with: claude \"/api-docs-generate\""
exit 1
fi
echo "✓ Found OpenAPI specifications:"
echo "$SPECS" | sed 's/^/ /'
echo ""
if [ -n "" ];
SPEC_FILE=
SPEC_FILE=$( | -1)
[ ! -f ];
1
() {
-v swagger-cli &> /dev/null;
npx swagger-cli validate
}
validate_spec
Phase 2: Generate TypeScript Types
export namespace API {
export type UUID = string;
export type ISODate = string;
export type Email = string;
export interface User {
id: UUID;
email: Email;
name: string;
role: 'admin' | 'user' | 'guest';
createdAt: ISODate;
updatedAt: ISODate;
profile?: UserProfile;
}
export {
?: ;
?: ;
?: ;
?: {
?: ;
?: ;
?: ;
};
}
{
: ;
: ;
: ;
?: | ;
}
{
?: ;
?: <>;
}
{
: ;
: ;
}
{
: ;
?: ;
}
{
: [];
: ;
}
{
: ;
: ;
: ;
}
{
: {
: ;
: ;
?: <, >;
};
: ;
}
{
: ;
: ;
: ;
: ;
: ;
: ;
}
{
?: ;
?: ;
?: ;
?: | | ;
?: | ;
}
{
: ;
}
{
= ;
= ;
= ;
= ;
= ;
= ;
= ;
}
}
Phase 3: Generate Zod Schemas
import { z } from 'zod';
export const UserSchema = z.object({
id: z.string().uuid(),
email: z.string().email(),
name: z.string().min(1).max(255),
role: z.enum(['admin', 'user', 'guest']),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
profile: z
.object({
bio: z.string().optional(),
avatarUrl: z.string().url().optional(),
location: z.string().optional(),
socialLinks: z
.object({
twitter: z.string().url().optional(),
github: z.().().(),
: z.().().(),
})
.(),
})
.(),
});
= z.< >;
= z.({
: z.().(),
: z.().().(),
: z.().().(),
: z.([, ]).(),
});
= z.< >;
= z.({
: z.().().().(),
: z
.({
: z.().(),
: z.().().(),
: z.().(),
})
.()
.(),
});
= z.< >;
= z.({
: z.().(),
: z.().(),
});
= z.< >;
= z.({
: ,
: z.().(),
});
= z.< >;
= z.({
: z.(),
: z.({
: z.().().(),
: z.().().(),
: z.().().(),
: z.().().(),
: z.(),
: z.(),
}),
});
= z.< >;
= z.({
: z.({
: z.(),
: z.(),
: z.(z.()).(),
}),
: z.().(),
});
= z.< >;
(): {
.(data);
}
(): {
.(data);
}
(): data is {
.(data).;
}
Phase 4: Generate Fetch Client SDK
import type { API } from './types';
export interface ClientConfig {
baseURL: string;
headers?: Record<string, string>;
timeout?: number;
}
export class APIError extends Error {
constructor(
public status: number,
public code: string,
message: string,
public details?: unknown
) {
super(message);
this.name = 'APIError';
}
}
export class APIClient {
private baseURL: string;
private headers: Record<string, string>;
: ;
() {
. = config..(, );
. = {
: ,
...config.,
};
. = config. || ;
}
(: ): {
.[] = ;
}
(): {
.[];
}
request<T>(
: ,
: ,
?: {
?: <, >;
?: ;
?: <, >;
}
): <T> {
url = ();
(options?.) {
.(options.).( {
(value !== && value !== ) {
url..(key, (value));
}
});
}
controller = ();
timeoutId = ( controller.(), .);
{
response = (url.(), {
method,
: { ...., ...options?. },
: options?. ? .(options.) : ,
: controller.,
});
(timeoutId);
(!response.) {
error = response.().( ({}));
(
response.,
error.?. || ,
error.?. || response.,
error.?.
);
}
(response. === ) {
T;
}
response.();
} (error) {
(timeoutId);
(error ) {
error;
}
(error && error. === ) {
(, , );
}
(
,
,
error ? error. :
);
}
}
users = {
:
.<.>(, , { params }),
:
.<.>(, ),
:
.<.>(, , { : data }),
:
.<.>(, , {
: data,
}),
:
.<>(, ),
};
auth = {
:
.<.>(, , {
: data,
}),
: .<>(, ),
};
}
(): {
(config);
}
apiClient = ({
: process.. || ,
});
Phase 5: Generate React Hooks
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import type { API } from './types';
import { apiClient } from './client';
export function useUsers(params?: API.ListUsersParams) {
return useQuery({
queryKey: ['users', params],
queryFn: () => apiClient.users.list(params),
});
}
export function useUser(userId: string) {
return useQuery({
queryKey: ['users', userId],
queryFn: () => apiClient.users.get(userId),
enabled: !!userId,
});
}
export function useCreateUser() {
const queryClient = useQueryClient();
return ({
:
apiClient..(data),
: {
queryClient.({ : [] });
},
});
}
() {
queryClient = ();
({
: apiClient..(userId, data),
: {
queryClient.({ : [, variables.] });
queryClient.({ : [] });
},
});
}
() {
queryClient = ();
({
: apiClient..(userId),
: {
queryClient.({ : [] });
},
});
}
() {
({
: apiClient..(data),
: {
apiClient.(response.);
.(, response.);
},
});
}
() {
queryClient = ();
({
: apiClient..(),
: {
apiClient.();
.();
queryClient.();
},
});
}
Phase 6: Usage Examples
import { useUsers, useCreateUser } from './api/hooks';
export function UsersPage() {
const { data, isLoading, error } = useUsers({ page: 1, limit: 10 });
const createUser = useCreateUser();
const handleCreateUser = async () => {
try {
await createUser.mutateAsync({
email: 'user@example.com',
name: 'John Doe',
password: 'secure-password',
});
alert('User created!');
} catch (error) {
console.error('Failed to create user:', error);
}
};
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
Users
Create User
{data?.data.map((user) => (
{user.name}
))}
);
}
import { apiClient } from './api/client';
async function fetchUsers() {
try {
const response = await apiClient.users.list({ page: 1, limit: 10 });
console.log('Users:', response.data);
console.log('Pagination:', response.pagination);
} catch (error) {
if (error instanceof APIError) {
console.error(`API Error (${error.status}):`, error.message);
} else {
console.error('Unknown error:', error);
}
}
}
Summary
echo ""
echo "=== ✓ OpenAPI Type Generation Complete ==="
echo ""
echo "📁 Generated files:"
echo " - src/api/types.ts # TypeScript types"
echo " - src/api/schemas.ts # Zod validation schemas"
echo " - src/api/client.ts # Fetch client SDK"
echo " - src/api/hooks.ts # React hooks"
echo ""
echo "📦 Install dependencies:"
echo " npm install zod @tanstack/react-query"
echo ""
echo "🚀 Usage:"
echo ""
echo "# In React components:"
echo "import { useUsers, useCreateUser } from './api/hooks';"
echo ""
echo "# Direct client usage:"
echo "import { apiClient } from './api/client';"
echo "const users = await apiClient.users.list();"
echo ""
echo "💡 Integration points:"
echo " - /api-docs-generate - Generate OpenAPI spec"
echo " - /api-test-generate - Generate API tests"
echo
Best Practices
Type Safety:
- Generate types from single source of truth
- Use Zod for runtime validation
- Keep types in sync with API
Client SDK:
- Type-safe methods
- Proper error handling
- Request/response validation
Integration Points:
/api-docs-generate - OpenAPI spec generation
/api-test-generate - API tests
/mock-generate - Mock data
What I'll Actually Do
- Find OpenAPI spec - Detect spec files
- Generate types - TypeScript interfaces
- Create Zod schemas - Runtime validation
- Build client SDK - Type-safe fetch client
- Generate hooks - React Query hooks
- Add examples - Usage documentation
Important: I will NEVER add AI attribution.
Credits: Based on openapi-typescript, Zod, React Query, and API client patterns from tRPC, GraphQL clients, and REST API best practices.