Apply AIP rule fixes to OpenAPI specs. Supports automated fixing via CLI or manual phase-by-phase implementation from a plan.
Applies automated or plan-based fixes to OpenAPI specifications with framework-specific code updates.
/plugin marketplace add getlarge/claude-aip-plugins/plugin install aip-api-design@getlarge-aip-pluginsApply fixes to OpenAPI specs. Two modes available:
Option A: MCP Tool (Recommended)
If the mcp__aip-reviewer__aip-apply-fixes tool is available, use it:
Use mcp__aip-reviewer__aip-apply-fixes with:
- reviewId: {review-id-from-aip-review}
- specPath: {absolute-path-to-spec} (for local files)
- OR specUrl: {http-url-to-spec} (for remote specs)
- writeBack: true (to save changes to specPath)
- dryRun: false (set true to preview changes)
The MCP tool will:
Option B: CLI Fixer (Fallback)
Use the CLI fixer for quick, automated spec corrections:
# Preview fixes (dry run)
npx aip-review openapi.yaml --fix --dry-run
# Apply fixes to a new file
npx aip-review openapi.yaml --fix --output openapi-fixed.yaml
# Apply fixes in-place (overwrite original)
npx aip-review openapi.yaml --fix --output openapi.yaml
| Flag | Description |
|---|---|
-F, --fix | Enable fix mode |
-o, --output <path> | Output path (default: <spec>.fixed.<ext>) |
--dry-run | Show what would be fixed without writing |
-c, --category <cat> | Only fix specific categories |
-x, --skip <rule> | Skip specific rules |
import { OpenAPIReviewer } from '@anthropic/aip-review';
import { OpenAPIFixer } from '@anthropic/aip-review/fixer';
// Review the spec
const reviewer = new OpenAPIReviewer();
const result = reviewer.review(spec, 'openapi.yaml');
// Apply all fixes
const fixer = new OpenAPIFixer(spec);
const fixResults = fixer.applyFixes(result.findings);
// Get the fixed spec
const fixedSpec = fixer.getSpec();
const summary = fixer.getSummary();
// { total: 5, applied: 4, failed: 1, changes: 12 }
/user/{id} → /users/{id})When fixes require code changes beyond the spec, use the plan-based workflow:
/api-fix {plan-path}
/api-fix {plan-path} --phase 1
/api-fix {plan-path} --task 1.2
/api-fix (uses most recent plan)
Load the plan document:
--phase specified, focus on that phase--task specified, focus on that specific taskBefore making changes:
For each task, based on framework:
Always update the spec file directly:
// Pagination DTO
export class PaginationParams {
@IsOptional()
@Type(() => Number)
@Min(1)
@Max(100)
page_size?: number = 20;
@IsOptional()
@IsString()
page_token?: string;
}
// Error filter
@Catch()
export class ApiExceptionFilter implements ExceptionFilter {
// ... standard error formatting
}
// Pagination schema
const paginationSchema = {
querystring: {
type: 'object',
properties: {
page_size: { type: 'integer', minimum: 1, maximum: 100, default: 20 },
page_token: { type: 'string' },
},
},
};
// Error handler
fastify.setErrorHandler((error, request, reply) => {
// ... standard error formatting
});
After implementing each task:
[x] completeUpdate plan frontmatter:
phases:
- name: Quick Wins
status: complete # was: pending
completed_at: { timestamp }
Do NOT:
After each task:
✓ Task 1.1 complete: Fixed resource naming
- Renamed /user/{id} → /users/{id}
- Updated openapi.yaml
- Updated src/routes/user.ts
Updated plan: thoughts/api/plans/2024-01-15-orders-api-plan.md
Continue with Task 1.2? [y/n]
After each phase:
✓ Phase 1 complete: Quick Wins
Summary:
- 3 tasks completed
- 5 files modified
- 0 tests broken
Run /api-validate to verify fixes, or continue with Phase 2?
If a fix fails or breaks tests:
For tasks marked as breaking changes:
Each finding includes machine-readable fix instructions. The CLI fixer processes these automatically, but you can also apply them manually when needed.
interface Fix {
type: FixType; // What kind of fix
jsonPath: string; // Where in the spec
target?: object; // Additional context
replacement?: unknown; // New value
specChanges: SpecChange[]; // Atomic operations
}
interface SpecChange {
operation: 'rename-key' | 'set' | 'add' | 'remove' | 'merge';
path: string; // JSONPath to target
from?: string; // For rename-key
to?: string; // For rename-key
value?: unknown; // For set/add/merge
}
The OpenAPIFixer processes specChanges array sequentially:
| Operation | Description | Example |
|---|---|---|
rename-key | Rename a key in an object | /user/{id} → /users/{id} |
set | Set a value at path (creates parents) | Add response schema |
add | Append to array (creates if missing) | Add parameter |
remove | Delete at path | Remove requestBody |
merge | Merge into object/array | Add multiple parameters |
| Fix Type | Description | Spec Change |
|---|---|---|
rename-path-segment | Rename a path segment | Rename key in $.paths |
rename-parameter | Rename a parameter | Update parameter name |
add-parameter | Add query/header param | Add to operation parameters array |
add-parameters | Add multiple params | Merge into parameters array |
remove-request-body | Remove requestBody | Delete requestBody key |
change-status-code | Change response code | Rename key in responses |
add-operation | Add HTTP method | Add method to path item |
add-schema | Add component schema | Set in $.components.schemas |
add-schema-property | Add schema property | Set in schema properties |
add-response | Add response | Set in operation responses |
set-schema-constraint | Set max/min/pattern | Set constraint on schema |
Given this fix block in the review:
type: rename-path-segment
jsonPath: "$.paths['/user/{id}']"
target:
segment: user
segmentIndex: 0
replacement: users
specChanges:
- operation: rename-key
path: '$.paths'
from: '/user/{id}'
to: '/users/{id}'
Steps to apply:
/user/{id} at $.paths['/user/{id}']/users/{id}@Get('/user/:id') → @Get('/users/:id'))Given this fix block:
type: add-parameter
jsonPath: "$.paths['/users'].post.parameters"
replacement:
name: Idempotency-Key
in: header
required: false
schema:
type: string
description: Unique key for idempotent requests
specChanges:
- operation: add
path: "$.paths['/users'].post.parameters"
value: { name: Idempotency-Key, in: header, ... }
Steps to apply:
$.paths['/users'].postparameters arrayreplacement@Headers('idempotency-key') parameterrequest.headersGiven this fix block:
type: add-schema
jsonPath: '$.components.schemas'
target:
schemaName: Error
replacement:
type: object
required: [error]
properties:
error:
type: object
required: [code, message]
properties:
code: { type: string }
message: { type: string }
details: { type: array }
specChanges:
- operation: set
path: "$.components.schemas['Error']"
value: { ... }
Steps to apply:
components.schemasError schema from replacement$ref: '#/components/schemas/Error'# Review and fix in one command
$ npx aip-review api.yaml --fix --dry-run
Found 3 fixable issue(s)
✓ aip122/plural-resources
✓ aip131/get-no-body
✓ aip158/list-pagination
Dry run: Would apply 3 fix(es) (5 change(s))
2 issue(s) require manual fixes:
- POST /orders: Missing error schema definition
- GET /orders: Should support filtering
$ npx aip-review api.yaml --fix -o api.yaml
Applied 3 fix(es) (5 change(s))
Fixed spec written to: api.yaml
User: /api-fix thoughts/api/plans/2024-01-15-orders-api-plan.md
Claude: "Phase 1 (Quick Wins) has 3 tasks pending.
Automated fixes available: Tasks 1.1 and 1.2 can be applied automatically.
Run npx aip-review openapi.yaml --fix first, then I'll handle Task 1.3 which needs code changes.
Or start with Task 1.1: Fix resource naming?"
User: /api-fix --phase 2
Claude: "Skipping to Phase 2 (Pagination). This has 2 tasks:
Ready to implement?"
For best results:
npx aip-review api.yaml --fix -o api.yamlnpx aip-review api.yaml/api-fix for manual code changes that remain