api-change
Propagates a FastAPI route or schema change to the generated TypeScript client and API docs. Use when editing apps/api/fastapi/src/**/router.py, routes.py, schemas.py or routers/, or when a web app ne
SKILL.md.claude/skills/api-change/SKILL.md
GitHubFastAPI Contract Change
This is the procedure the repo's own Blast-Radius Gate table names in one
cell ("A FastAPI route or schema → regen openapi.json → pnpm generate:api-client → pnpm check:drift; docs/api/contracts.md") — this
skill is that cell, spelled out. packages/api-client/src/gen/ is Never-tier
(mechanically blocked by .claude/hooks/protect-files.mjs) — you cannot hand-edit
around this procedure even if it would be faster.
When this applies
Any edit under apps/api/fastapi/src/**/router.py, routes.py, schemas.py,
schemas/, or routers/ (the same file patterns
scripts/guardrails/check-blast-radius.mjs treats as FastAPI contract files),
or apps/api/fastapi/src/main.py. Also applies in reverse: a web app needs a
field or endpoint @barrelsgd/api-client doesn't expose yet.
Compatible route and OpenAPI changes required by an authorized task can proceed
with the complete procedure below. Ask first for breaking contracts, widened
public access or permissions, or work outside the authorized scope, as defined
in AGENTS.md; do not request existing session authorization again.
Procedure
- Make the FastAPI change (route, schema, or model) in
apps/api/fastapi/src/. - Regenerate
openapi.json(fromapps/api/fastapi):PROJECT_NAME='Barrels Grenada' uv run --frozen --package fast-back python -c "from src.main import app; import json; json.dump(app.openapi(), open('openapi.json', 'w'), indent=2)" - Regenerate the TypeScript client (from repo root):
pnpm generate:api-client - Verify no drift:
A failure here means step 2 or 3 was skipped or produced something inconsistent — fix forward, don't hand-editpnpm check:driftpackages/api-client/src/gen/to make drift-check pass. - Update
docs/api/contracts.mdif the change is a new endpoint, a breaking field change, or anything else that document already describes. - Update every consumer of the changed types/endpoints across the web
apps — grep for the generated hook/client function name
(
@barrelsgd/api-client's generated names follow the FastAPI operation ID). This is the Blast-Radius Gate step;pnpm guardrails:stagedonly checks that the contract-file change and a client regen both happened, not that every consumer was updated. - Commit
openapi.jsonand the generated client changes together (perdocs/api/contracts.md) — never split them across commits.
Verification
pnpm check:driftpasses.pnpm type-checkpasses (a removed/renamed field surfaces here across every consuming app).pnpm guardrails:stagedpasses (checks the contract-file/client-regen pairing mechanically).- Every consumer found in step 6 is updated, or explicitly reported to the user per the Scope Gate if it's outside what was asked.
What NOT to do
- Don't hand-edit anything under
packages/api-client/src/gen/— it's Never-tier and mechanically blocked. - Don't regenerate the client without first regenerating
openapi.json— the client would just re-encode the stale contract. - Don't skip
docs/api/contracts.mdfor a breaking change because "the code is the source of truth" — the doc is what the next agent (or the next session of you) reads before touching this surface again.