From nest-forge-sdk
Generates a fully-typed NestJS client SDK module from an OpenAPI specification using nest-forge-sdk, then wires it into the user's NestJS application. Use this skill whenever the user wants to integrate with an external API or third-party service, generate an API client, create an SDK wrapper, or build a NestJS module that communicates with another service — even if they don't say "SDK" or "generate". Also trigger when the user mentions OpenAPI, Swagger specs, API integration, REST client generation, service-to-service communication, or asks how to call an external REST API from NestJS. If the user is discussing a new service integration, proactively ask whether an API spec is available.
How this skill is triggered — by the user, by Claude, or both
Slash command
/nest-forge-sdk:nestjs-sdk-generatorThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate production-ready NestJS client SDK modules from OpenAPI specifications using `nest-forge-sdk`, then integrate them into the user's application.
Generate production-ready NestJS client SDK modules from OpenAPI specifications using nest-forge-sdk, then integrate them into the user's application.
From a single OpenAPI spec (JSON or YAML, local file or URL), nest-forge-sdk generates a complete NestJS module:
{kebab-name}/
├── {kebab-name}.service.ts # @Injectable() service — one async method per operation
├── {kebab-name}.module.ts # @Module with forRoot() and forRootAsync()
├── index.ts # Barrel: service, module, data, exceptions, types
├── data/ # Injection tokens + default route map
├── exceptions/ # {Name}HttpException, {Name}ValidationException
├── interfaces/ # RouteMap, ModuleOptions, ModuleAsyncOptions
├── schemas/ # Zod schemas (batched by OpenAPI tag)
├── types/ # z.infer<> TypeScript types
└── utils/ # renderRoute, mergeRouteMap
Every response is validated through Zod safeParse. Routes use {{param}} Mustache templates resolved at runtime. Custom exceptions extend NestJS HttpException.
Follow these phases in order. Each one builds on the previous.
Ask the user: "Do you have an OpenAPI (Swagger) spec for this API?"
If yes: accept a local file path (.json, .yaml, .yml) or an HTTP URL. Verify the file exists and is parseable — read the first few lines to confirm it has an openapi or swagger version field and at least one path under paths.
If no: help them get one:
/docs, /swagger, /api-docs, /openapi.json, /v3/api-docs, or a link in their developer docs.For large specs: after loading, list the available tags. If there are many (say, 8+), ask the user which ones they actually need — generating everything creates a lot of code they may never use.
Check the user's package.json before installing anything — only add what is missing.
| Package | Type | Install command |
|---|---|---|
nest-forge-sdk | devDependency | npm install -D nest-forge-sdk |
axios | dependency | npm install axios |
zod | dependency | npm install zod |
@nestjs/common is almost certainly already present in a NestJS project. If it is not, the user likely has a non-standard setup — ask before installing.
Pick the output directory:
libs/, src/modules/, src/integrations/)nest-forge-sdk creates a subfolder named after the API's info.titlePick tag filters (if applicable):
--tags tag1,tag2 to include only certain tags--exclude-tags tag1,tag2 to exclude certain tagsRun the generator:
npx nest-forge-sdk <spec-path-or-url> --output <output-dir> [--tags <tags>] [--exclude-tags <tags>]
After generation: read the generated index.ts barrel to confirm the module, service, and types were created. Show the user the generated file tree so they know what they got.
This phase connects the generated SDK into the user's NestJS app. The generated module supports two configuration patterns: forRoot (static) and forRootAsync (dynamic/factory-based).
Ask the user how they manage configuration. Adapt your wiring to their pattern:
This is the cleanest approach when config values come from a JSON file or environment loaded via @nestjs/config.
Add the base URL to the user's configuration source (e.g., config.json, .env, or a config factory):
{
"someApi": {
"baseUrl": "https://api.example.com"
}
}
Wire up with forRootAsync:
import { ConfigModule, ConfigService } from '@nestjs/config';
import { SomeApiModule } from './some-api';
@Module({
imports: [
SomeApiModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
baseUrl: configService.getOrThrow<string>('someApi.baseUrl'),
}),
}),
],
})
export class AppModule {}
If the user follows a key-path-as-constant convention (like the nest-forge project itself does), create a constant:
// data/some-api-config-keys.data.ts
export const SOME_API_CONFIG_PATH = 'someApi';
export const SOME_API_BASE_URL_CONFIG_KEY = `${SOME_API_CONFIG_PATH}.baseUrl`;
SomeApiModule.forRoot({
baseUrl: process.env.SOME_API_BASE_URL ?? 'http://localhost:3000',
})
SomeApiModule.forRoot({
baseUrl: 'https://api.example.com',
})
If the user needs auth headers, timeouts, or interceptors:
SomeApiModule.forRoot({
baseUrl: 'https://api.example.com',
axiosConfig: {
headers: { Authorization: `Bearer ${token}` },
timeout: 5000,
},
})
If certain endpoints are proxied or versioned differently:
SomeApiModule.forRoot({
baseUrl: 'https://api.example.com',
routes: {
getUser: '/v2/users/{{id}}',
},
})
npx tsc --noEmit or equivalent) to verify the module compilesimport { SomeApiService } from './some-api';
@Injectable()
export class MyService {
constructor(private readonly someApiService: SomeApiService) {}
async fetchData(): Promise<SomeType> {
return await this.someApiService.getSomething({ id: '123' });
}
}
{Name}HttpException (preserving the upstream status code), and unexpected response shapes become {Name}ValidationException (502 Bad Gateway) — so the consumer gets clear, typed errors without extra try/catch boilerplate| Flag | Short | Description |
|---|---|---|
--input <path|url> | -i | Path or URL to the OpenAPI spec |
--output <dir> | -o | Output directory (default: current directory) |
--tags <csv> | -t | Comma-separated tags to include |
--exclude-tags <csv> | Comma-separated tags to exclude | |
--version | -v | Print version |
--help | -h | Print help |
The first positional argument is treated as --input, so npx nest-forge-sdk ./spec.json works without the flag.
OpenAPI info.title | Module folder | Service class | Module class |
|---|---|---|---|
user-service | user/ | UserService | UserModule |
Payment Gateway | payment-gateway/ | PaymentGatewayService | PaymentGatewayModule |
SSH Session Service | ssh-session/ | SshSessionService | SshSessionModule |
Operation names come from operationId (with controller prefixes like UserController_ stripped). If no operationId exists, they are derived from the HTTP verb and path (e.g., GET /users/{id} becomes getUsersById).
npx claudepluginhub romtaugranot/nest-forge --plugin nest-forge-sdkGenerates type-safe client SDKs in TypeScript, Python, Go, Java from OpenAPI specs with auth, retries, pagination, and tests.
Extracts OpenAPI specs from existing API codebases in FastAPI, Flask, Django REST, Spring Boot, NestJS, Hono, Rails, and Laravel using framework-specific guides.
Applies opinionated NestJS conventions for backends: modules, dependency injection, controllers/services, DTOs with class-validator, guards/interceptors/pipes, JWT auth, TypeORM/Prisma. Use for REST/GraphQL APIs.