
Fetcher Openapi Generator
- 1 installs
- 15 repo stars
- Updated August 4, 2026
- ahoo-wang/fetcher
fetcher-openapi-generator is a Claude Code skill that generates type-safe TypeScript Fetcher API clients and models from OpenAPI 3.x specs, with Wow CQRS support.
About
fetcher-openapi-generator is a Claude Code skill that generates type-safe TypeScript API clients from OpenAPI 3.x specs using the @ahoo-wang/fetcher-generator package. It covers the fetcher-generator CLI, config files, and the programmatic CodeGenerator API, plus the parse-to-generation pipeline and Wow CQRS command/query client generation. A developer uses it to produce typed clients, models, and barrel exports from an OpenAPI document rather than hand-writing API clients.
- Generates type-safe Fetcher API clients from OpenAPI 3.x specs
- Covers the fetcher-generator CLI, config file, and programmatic CodeGenerator API
- Supports Wow CQRS command/query client generation from bounded-context metadata
Fetcher Openapi Generator by the numbers
- 1 all-time installs (skills.sh)
- Ranked #3,830 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
fetcher-openapi-generator capabilities & compatibility
- Capabilities
- openapi codegen · api client generation · cqrs client generation · type generation
- Use cases
- api development
- Pricing
- Free
What fetcher-openapi-generator says it does
Use when generating type-safe Fetcher API clients from OpenAPI 3.x specs, including fetcher-generator CLI usage, CodeGenerator API
TypeScript code generator producing type-safe API clients from OpenAPI 3.0+ specs via `@ahoo-wang/fetcher-generator`, with specialized Wow CQRS/DDD framework support.
npx skills add https://github.com/ahoo-wang/fetcher --skill fetcher-openapi-generatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 15 |
| Last updated | August 4, 2026 |
| Repository | ahoo-wang/fetcher ↗ |
What it does
Generate type-safe TypeScript Fetcher API clients from an OpenAPI 3.x spec via CLI or the CodeGenerator API.
Who is it for?
Developers who want typed Fetcher API clients auto-generated from an OpenAPI 3.x contract.
Skip if: Hand-editing generated clients; the skill treats generated code as an output boundary.
When should I use this skill?
Generating TypeScript client code from an OpenAPI spec, using fetcher-generator CLI or config, or generating Wow CQRS command/query clients.
What you get
- generated TypeScript API clients, models, and barrel exports
By the numbers
- 5 CLI options
- 6-stage generation pipeline
- 3 bundled eval specs (petstore, ecommerce, user-service)
Files
fetcher-openapi-generator
Use This Skill When
- The user wants TypeScript client code generated from an OpenAPI spec.
- The task mentions
fetcher-generator, CLI options, config files, or programmatic generation. - The task involves generated models, API clients, barrel exports, or post-processing.
- The task needs Wow CQRS command/query clients generated from OpenAPI metadata.
Workflow
1. Choose CLI generation for project usage and CodeGenerator only for embedded tooling. 2. Resolve input, output, config, and tsconfig paths before generating. 3. Enable Wow CQRS generation only when bounded-context and aggregate metadata are present and intended. 4. Inspect generated structure and barrel exports after generation. 5. Load references/api.md for CLI flags, config shape, pipeline stages, and Wow CQRS generation rules.
Key Practices
- Treat generated code as an output boundary; adjust generator config rather than hand-editing generated clients.
- Use explicit type mappings when OpenAPI schemas need domain-specific TypeScript types.
- Keep API client tag exclusion and CQRS generation rules aligned so duplicate clients are not emitted.
References
references/api.md: Detailed package API, examples, and edge-case guidance. Load it only when the task needs CLI commands, CodeGenerator usage, configuration fields, output structure, pipeline stages, and Wow CQRS generation examples.
Related Skills
- $fetcher-openapi-types: Use for raw OpenAPI TypeScript modeling.
- $fetcher-wow-cqrs: Use for runtime Wow command and query client behavior.
- $fetcher-integration: Use for the generated clients' Fetcher runtime assumptions.
interface:
display_name: 'Fetcher OpenAPI Generator'
short_description: 'Generate Fetcher OpenAPI clients'
default_prompt: 'Use $fetcher-openapi-generator to generate a typed Fetcher client from an OpenAPI spec.'
{
"skill_name": "fetcher-openapi-generator",
"evals": [
{
"id": 1,
"prompt": "Generate a type-safe TypeScript API client from this OpenAPI spec at ./evals/files/petstore.yaml. Use the fetcher-generator CLI tool to generate the client code into a src/generated/petstore directory. The generated code should include proper TypeScript types and an API client class for the pets endpoints.",
"expected_output": "Generated TypeScript API client with types.ts and PetApiClient.ts, properly structured with API client classes",
"files": ["evals/files/petstore.yaml"],
"expectations": [
"Generated TypeScript types are properly defined",
"API client class is generated for pets endpoints",
"Generated code compiles without errors",
"Output directory structure follows the standard pattern"
]
},
{
"id": 2,
"prompt": "Generate a type-safe TypeScript API client from this OpenAPI spec at ./evals/files/ecommerce.yaml. This is a CQRS-style API with bounded context 'ecommerce.cart'. Generate the client into src/generated/ecommerce directory using the Wow CQRS pattern support. Include command clients for operations like add_cart_item and query clients for snapshot_state and event queries.",
"expected_output": "Generated CQRS-style client with CartCommandClient, CartQueryClient factory, and proper bounded context structure",
"files": ["evals/files/ecommerce.yaml"],
"expectations": [
"CartCommandClient is generated with addCartItem method",
"QueryClientFactory is generated for snapshot queries",
"Event query client is generated for event.list_query operations",
"Generated code uses Wow CQRS patterns correctly"
]
},
{
"id": 3,
"prompt": "Generate a type-safe TypeScript API client from this OpenAPI spec at ./evals/files/user-service.yaml. This is a multi-tenant API with bounded context 'user_service' and users aggregate. Generate into src/generated/user-service directory. Also create a .fetcherrc.json config file that enables verbose output and custom type mappings for this generation.",
"expected_output": "Generated API client with proper tenant-based resource attribution and configuration file",
"files": ["evals/files/user-service.yaml"],
"expectations": [
"Users aggregate command and query clients are generated",
"Tenant-based resource attribution is properly configured",
".delete_aggregate operation generates delete method",
".fetcherrc.json configuration file is created with appropriate settings"
]
}
]
}
openapi: 3.0.3
info:
title: E-commerce API
version: 1.0.0
paths:
/owner/{ownerId}/cart:
get:
operationId: ecommerce.cart.snapshot_state.single
tags:
- ecommerce.cart
summary: Get cart state
parameters:
- name: ownerId
in: path
required: true
schema:
type: string
responses:
'200':
description: Cart state
content:
application/json:
schema:
$ref: '#/components/schemas/CartState'
delete:
operationId: ecommerce.cart.default_delete_aggregate
tags:
- ecommerce.cart
summary: Delete cart
parameters:
- name: ownerId
in: path
required: true
schema:
type: string
responses:
'204':
description: Cart deleted
/owner/{ownerId}/cart/items:
post:
operationId: ecommerce.cart.add_cart_item
tags:
- ecommerce.cart
summary: Add item to cart
parameters:
- name: ownerId
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AddCartItemCommand'
responses:
'200':
description: Item added
content:
application/json:
schema:
$ref: '#/components/schemas/CommandResult'
components:
schemas:
CartState:
type: object
properties:
ownerId:
type: string
items:
type: array
items:
$ref: '#/components/schemas/CartItem'
total:
type: number
CartItem:
type: object
properties:
productId:
type: string
quantity:
type: integer
price:
type: number
AddCartItemCommand:
type: object
required:
- productId
- quantity
properties:
productId:
type: string
quantity:
type: integer
CommandResult:
type: object
properties:
success:
type: boolean
aggregateId:
type: string
openapi: 3.0.3
info:
title: Pet Store API
version: 1.0.0
paths:
/pets:
get:
operationId: listPets
tags:
- pets
summary: List all pets
responses:
'200':
description: A list of pets
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
post:
operationId: createPet
tags:
- pets
summary: Create a new pet
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PetInput'
responses:
'201':
description: Pet created
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
/pets/{petId}:
get:
operationId: getPet
tags:
- pets
summary: Get a pet by ID
parameters:
- name: petId
in: path
required: true
schema:
type: string
responses:
'200':
description: Pet details
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
'404':
description: Pet not found
delete:
operationId: deletePet
tags:
- pets
summary: Delete a pet
parameters:
- name: petId
in: path
required: true
schema:
type: string
responses:
'204':
description: Pet deleted
components:
schemas:
Pet:
type: object
properties:
id:
type: string
name:
type: string
species:
type: string
age:
type: integer
PetInput:
type: object
required:
- name
- species
properties:
name:
type: string
species:
type: string
age:
type: integer
openapi: 3.0.3
info:
title: User Service API
version: 1.0.0
paths:
/tenant/{tenantId}/users:
get:
operationId: user_service.users.snapshot_state.single
tags:
- user_service.users
summary: List users in tenant
parameters:
- name: tenantId
in: path
required: true
schema:
type: string
responses:
'200':
description: User list
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/UserState'
post:
operationId: user_service.users.create_user
tags:
- user_service.users
summary: Create user
parameters:
- name: tenantId
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserCommand'
responses:
'201':
description: User created
/tenant/{tenantId}/users/{userId}:
get:
operationId: getUser
tags:
- users
summary: Get user by ID
parameters:
- name: tenantId
in: path
required: true
schema:
type: string
- name: userId
in: path
required: true
schema:
type: string
responses:
'200':
description: User details
content:
application/json:
schema:
$ref: '#/components/schemas/UserState'
put:
operationId: user_service.users.update_user
tags:
- user_service.users
summary: Update user
parameters:
- name: tenantId
in: path
required: true
schema:
type: string
- name: userId
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateUserCommand'
responses:
'200':
description: User updated
delete:
operationId: user_service.users.default_delete_aggregate
tags:
- user_service.users
summary: Delete user
parameters:
- name: tenantId
in: path
required: true
schema:
type: string
- name: userId
in: path
required: true
schema:
type: string
responses:
'204':
description: User deleted
components:
schemas:
UserState:
type: object
properties:
id:
type: string
tenantId:
type: string
email:
type: string
name:
type: string
status:
type: string
enum:
- active
- inactive
- suspended
CreateUserCommand:
type: object
required:
- email
- name
properties:
email:
type: string
name:
type: string
UpdateUserCommand:
type: object
properties:
email:
type: string
name:
type: string
status:
type: string
Fetcher OpenAPI Generator API Reference
Contents
- Installation
- CLI Usage
- CLI Options
- Programmatic API (CodeGenerator)
- Key Exports
- Code Generation Pipeline
- Generated Output Structure
- Configuration (fetcher-generator.config.json)
- Wow CQRS Pattern Support
- Aggregate Identification
- Operation Patterns
- API Client Tag Exclusion
- Command Clients
- Query Clients
- API Clients
- Integration with Fetcher
- Package Reference
TypeScript code generator producing type-safe API clients from OpenAPI 3.0+ specs via @ahoo-wang/fetcher-generator, with specialized Wow CQRS/DDD framework support.
Installation
pnpm add -D @ahoo-wang/fetcher-generatorCLI Usage
# Basic usage
npx fetcher-generator generate -i ./openapi.yaml -o ./src/generated
# With config file
npx fetcher-generator generate -i ./openapi.yaml -o ./src/generated -c ./fetcher-generator.config.json
# From URL
npx fetcher-generator generate -i https://api.example.com/openapi.json -o ./src/generated
# With TypeScript config
npx fetcher-generator generate -i ./openapi.yaml -o ./src/generated -t ./tsconfig.jsonCLI Options
| Flag | Description | Default |
|---|---|---|
-i, --input <file> | OpenAPI spec file (JSON/YAML) or HTTP/HTTPS URL | required |
-o, --output <path> | Output directory path | src/generated |
-c, --config <file> | Configuration file path | ./fetcher-generator.config.json |
-t, --ts-config-file-path <file> | TypeScript config file path | — |
-v, --version | Display version | — |
Programmatic API (CodeGenerator)
import { CodeGenerator } from '@ahoo-wang/fetcher-generator';
const generator = new CodeGenerator({
inputPath: './openapi.yaml',
outputDir: './src/generated',
tsConfigFilePath: './tsconfig.json',
});
await generator.generate();Key Exports
CodeGenerator, DEFAULT_CONFIG_PATH (./fetcher-generator.config.json)
Code Generation Pipeline
parseOpenAPI(inputPath) → AggregateResolver(openAPI).resolve()
→ ModelGenerator.generate() → ClientGenerator.generate()
→ Index Generator → Optimize (formatText, organizeImports, fixMissingImports)1. parseOpenAPI - Parse JSON/YAML spec (local file or URL) 2. AggregateResolver - Identifies aggregates from tags ({context}.{aggregate} pattern), extracts commands, state, events, fields 3. ModelGenerator - Generates TypeScript types/enums from schemas (skips wow.* schemas and aggregated types) 4. ClientGenerator - Generates QueryClient, CommandClient, StreamCommandClient, ApiClient per aggregate 5. Index Generator - Creates index.ts barrel exports at every directory level 6. Post-processing - formatText(), organizeImports(), fixMissingImports() on all files
Generated Output Structure
output/
├── index.ts # Root barrel exports
├── {bounded-context}/
│ ├── index.ts # Context barrel exports
│ ├── boundedContext.ts # Context alias constant (e.g., EXAMPLE_BOUNDED_CONTEXT_ALIAS)
│ ├── types.ts # Shared types for this context path
│ ├── {Tag}ApiClient.ts # API client per non-CQRS tag
│ └── {aggregate}/
│ ├── index.ts
│ ├── commandClient.ts # CommandClient + StreamCommandClient + CommandEndpointPaths
│ └── queryClient.ts # QueryClientFactory + DomainEventType + DomainEventTypeMapTitle
├── {other-schema-path}/
│ ├── types.ts # Types for schemas in other dot-separated paths
│ └── ...Model files use types.ts named by schema path prefix (e.g., schema key ai.AiMessage.Assistant maps to ai/types.ts with type AiMessageAssistant).
Configuration (fetcher-generator.config.json)
{
"apiClients": {
"TagName": {
"ignorePathParameters": ["tenantId", "ownerId"]
}
}
}apiClients- Map of tag name to API client configurationignorePathParameters- Path parameters to exclude from generated methods (default:['tenantId', 'ownerId'])
Wow CQRS Pattern Support
Aggregate Identification
Tags following {contextAlias}.{aggregateName} pattern identify aggregates (e.g., example.cart).
Operation Patterns
- Commands: Operation IDs matching
{context}.{aggregate}.{command}with a request body and an OK response$ref: #/components/responses/wow.CommandOk - State Snapshots: Operation IDs ending with
.snapshot_state.single - Events: Operation IDs ending with
.event.list_query - Fields: Operation IDs ending with
.snapshot.count
API Client Tag Exclusion
Tags named wow, Actuator, or matching aggregate names are excluded from API client generation.
Command Clients
// Regular command client
export class CartCommandClient<
R = CommandResult,
> implements ApiMetadataCapable {
constructor(
public readonly apiMetadata: ApiMetadata = DEFAULT_COMMAND_CLIENT_OPTIONS,
) {}
@put(CartCommandEndpointPaths.ADD_CART_ITEM)
addCartItem(
@request() commandRequest: CommandRequest<AddCartItemCommand>,
@attribute() attributes?: Record<string, any>,
): Promise<R> {
throw autoGeneratedError(commandRequest, attributes);
}
}
// Stream variant (extends CommandClient<CommandResultEventStream>)
export class CartStreamCommandClient extends CartCommandClient<CommandResultEventStream> {}Command types use CommandBody<T> wrapper. CommandEndpointPaths enum maps command names to paths.
Query Clients
export const cartQueryClientFactory = new QueryClientFactory<
CartState,
CartAggregatedFields | string,
CartDomainEventType
>({
contextAlias: EXAMPLE_BOUNDED_CONTEXT_ALIAS,
aggregateName: 'cart',
resourceAttribution: ResourceAttributionPathSpec.OWNER,
});Resource attribution inferred from command paths: ResourceAttributionPathSpec.OWNER (/owner/{ownerId}), ResourceAttributionPathSpec.TENANT (/tenant/{tenantId}), or NONE.
API Clients
Generated for non-CQRS endpoints. Parameters tenantId/ownerId are ignored by default.
Integration with Fetcher
import { Fetcher } from '@ahoo-wang/fetcher';
import { cartQueryClientFactory } from './generated/example/cart/queryClient';
import { CartCommandClient } from './generated/example/cart/commandClient';
const fetcher = new Fetcher({ baseURL: 'https://api.example.com' });
const snapshotClient = cartQueryClientFactory.createSnapshotQueryClient({
fetcher,
});
const commandClient = new CartCommandClient();Package Reference
- Package Source - Source code and README
- Key types:
GeneratorOptions,GeneratorConfiguration,ApiClientConfiguration,GenerateContextInit,Logger