From fastloom-sdk
Use when the user wants to add a new HTTP route, endpoint, or APIRouter to an existing fastloom-based service. Handles auth dependencies, pagination, request/response schemas, and updates app.py to register the new router. Triggers on "add a route", "new endpoint", "scaffold a router".
How this skill is triggered — by the user, by Claude, or both
Slash command
/fastloom-sdk:add-fastloom-routeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Scaffold a FastAPI router that follows the project's conventions, wire it into `app.py`, and produce the matching request/response schemas.
Scaffold a FastAPI router that follows the project's conventions, wire it into app.py, and produce the matching request/response schemas.
Look for these files at cwd:
app.py — must export app: fastloom.launcher.schemas.App. Read it to find the routes=[...] list and any module aliases.settings.py — confirm TC: type[Configs[Settings, TenantSettings]] = Configs or similar.api/ (or similar) package — routers usually live there. If multiple naming conventions exist (e.g. <pkg>/api/), follow whichever is already in use.If the project doesn't look like a fastloom service, ask the user to confirm before continuing.
Ask in one round:
/users)."Users").required (default), optional, public.GET (list with pagination), GET /{id}, POST (create), PATCH /{id}, DELETE /{id}.User) so schemas can be named <Resource>In, <Resource>Out, <Resource>SearchIn.<pkg>/api/<resource>.pyfrom typing import Annotated
from fastapi import APIRouter, Depends, Query
from fastloom.auth.schemas import UserClaims
from fastloom.db.schemas import BasePaginationQuery, PaginatedResponse
from settings import TC
from <pkg>.schemas.<resource> import <Resource>In, <Resource>Out, <Resource>SearchIn
router = APIRouter()
@router.get("", response_model=PaginatedResponse[<Resource>Out])
async def list_<resource>s(
query: Annotated[<Resource>SearchIn, Query()],
claims: Annotated[UserClaims, Depends(TC.auth.get_claims)],
) -> PaginatedResponse[<Resource>Out]:
...
Annotated[UserClaims, Depends(TC.auth.get_claims)].Annotated[UserClaims | None, Depends(TC.optional_auth.get_claims)].BasePaginationQuery for list endpoints; return PaginatedResponse[T].fastloom.i18n.base.DoesNotExist(_("<Resource>")) for 404s — let the launcher's i18n handler produce the response shape.<pkg>/schemas/<resource>.pyfrom pydantic import BaseModel, Field
from fastloom.db.schemas import BasePaginationQuery
class <Resource>In(BaseModel):
name: str
class <Resource>Out(<Resource>In):
id: str
class <Resource>SearchIn(BasePaginationQuery):
name: str | None = None
Use BeforeValidator / AfterValidator / model_validator(mode="after") / validation_alias for anything beyond plain fields — do not write post-ingestion if …: checks in the handler.
app.py updateAdd an import for the new router and a new tuple to the routes=[...] list:
from <pkg>.api import <resource>
routes = [
...
(<resource>.router, "/<resource>s", "<Tag>"),
]
If app.py doesn't have an explicit routes list and uses a different shape, follow that shape.
Any, no dict.get, no getattr on typed shapes.Depends(TC.auth.get_claims) / TC.optional_auth.get_claims — never roll your own JWT parsing.fastloom.i18n.base.CustomI18NException subclasses or raise the built-in DoesNotExist, OnlyOwnerAllowed, etc.schemas/. No business logic there.model_validator, BeforeValidator, AliasChoices upstream.After writing files:
poetry run ruff check . or whatever is configured).launch and curl <prefix>/<resource>s.npx claudepluginhub aradng/fastloom --plugin fastloom-sdkCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.