AI-Assisted Development¶
QuoinAPI ships with a first-class Claude Code setup. This guide covers everything that was configured — skills, hooks, plugins, and MCP servers — so you can take full advantage of it and extend it as the project evolves.
Overview¶
The setup is layered: Claude Code reads conventions from CLAUDE.md on every
turn, loads on-demand workflow skills when they match your request, fires
hooks automatically to enforce quality and safety, and connects to live
documentation via an MCP server.
CLAUDE.md ← always-on conventions (60 lines)
.claude/skills/ ← workflow skills, loaded when triggered
.claude/hooks/ ← enforcement scripts
.claude/settings.json ← hook wiring + enabled plugins
.mcp.json ← MCP server config (committed, team-wide)
prek.toml ← git-level quality gates
First-time setup¶
just setup handles everything:
The pre-push hook runs the full pytest suite. PostgreSQL must be running
when you push (just db). Use git push --no-verify in emergencies only.
The Claude Code plugins, skills, and MCP server activate automatically the
first time you open the project in a Claude Code session. You will be prompted
to approve the context7 MCP server on first use.
Skills¶
Skills are packaged workflows that Claude invokes automatically when your
request matches, or that you can trigger explicitly with /skill-name.
All project skills live in .claude/skills/.
quoin-new-module¶
Triggers on: "add a product module", "scaffold an orders feature", "create a new resource for X"
Walks through the full DDD module scaffold: just new <module> →
models → schemas → repository → service → routes → exceptions → review
auto-registered router → generate and review migration → write tests →
just check.
quoin-add-endpoint¶
Triggers on: "add an endpoint to the user module", "add a GET /users/by-email route", "expose a search endpoint on products", "add a deactivate action to users"
The single-endpoint counterpart to quoin-new-module: adds one route plus
its plumbing to a module that already exists, working up the layers
schema → repository → service → route against the app/modules/user/
reference. Covers the route-ordering gotcha (declare /count before
/{user_id}), the response_model vs return-type convention, reusing the
module's get_<module>_service dependency, and the required auth/domain-error
test cases. For a brand-new module use quoin-new-module; for a schema change
behind the endpoint use quoin-db-migration first.
quoin-db-migration¶
Triggers on: "add a column", "add a field to", "make X nullable", "change the type of", "add an index on"
Covers the schema-change loop with a built-in migration review checklist: NOT NULL backfills, type narrowing risk, enum change gaps, downgrade reversibility, and common autogenerate blind spots.
quoin-auth-route¶
Triggers on: "protect this endpoint", "add RBAC", "require the X role", "make this admin-only", "who is the caller"
DDD scope syntax (domain.action), require_roles() wiring, the auth
test triple (happy path / 403 / 401), and api.superuser bypass rules.
quoin-write-tests¶
Triggers on: "write tests for", "add a test", "test this endpoint", "I need coverage for"
Project fixture map (client, read_client, admin_client, db_session,
caller_read, caller_admin), SAVEPOINT isolation behaviour, adding
domain-specific callers for new modules, and common test anti-patterns to
avoid.
quoin-coverage¶
Triggers on: "make coverage 100%", "fill the coverage gaps", "cover the
missing lines", "get this to 100%", or pasting a pytest --cov report
The gap-closing counterpart to quoin-write-tests: read the Missing column,
classify each gap (error path / partial branch / dead code / defensive guard),
write targeted tests with the existing fixtures, and loop on just test until
the target is met. Prefers real tests over # pragma: no cover.
quoin-pre-pr¶
Triggers on: "create a PR", "open a pull request", "I'm done with this feature", "ready to merge", "ship this"
Three-step pre-PR checklist: run just check (format, lint, typecheck, tests
at 100% coverage) → update CHANGELOG.md [Unreleased] with a concise entry →
run just docb to verify the docs build and commit the synced files → create
the PR.
quoin-deps-upgrade¶
Triggers on: "upgrade the dependencies", "update deps", "bump the GitHub Actions", "upgrade to Python 3.x", "is there a newer version of X"
The version-upgrade ritual for both Python deps and GitHub Actions:
uv lock --upgrade respecting exclude-newer, checking upstream release notes
for pinning changes, sweeping docs/.env/Dockerfile/copier.yml for stale
version strings, and verifying with just check.
quoin-docs-audit¶
Triggers on: "review the docs for accuracy", "check docs against the code", "audit docs/ for stale info", "do the guides match the implementation"
A periodic docs↔code drift sweep over docs/guides/ and README.md: settings
table vs config.py, endpoint lists vs routers, just recipes vs justfile,
stale version strings, and broken file references — finishing with just docb.
Reports findings before fixing, since a mismatch sometimes means the code
regressed, not the doc.
quoin-release¶
Triggers on: "cut a release", "bump the version", "tag the release", "prepare the changelog"
Five-step release ritual: curate [Unreleased] → just bump part="..." →
promote changelog heading → commit and merge to main → just tag. Covers
changelog section ordering, tag-from-main-only rule, and what to do if the
GitHub Actions release workflow fails.
Hooks¶
Stop hook — quality gate (automatic)¶
Configured in .claude/settings.json. Fires at the end of every Claude turn
where the working tree is dirty.
Runs just format && just lint && just typecheck. If any step fails, the
turn is blocked and Claude sees the output — it must fix the issue before
responding. Turns with no code changes (Q&A, doc reads) are skipped.
Tests are deliberately excluded here — too slow per turn. Tests are gated at push time instead (see below).
Stop hook — config-drift warning (automatic)¶
Script at .claude/hooks/config-drift.sh. Also fires at the end of a dirty
turn. If app/core/config.py changed but neither .env.example nor
docs/guides/configuration.md did, it emits a non-blocking reminder to
keep the settings surface and its docs in sync. It never blocks the turn —
not every config edit adds or renames a setting — so treat it as advisory.
Stop hook — migration reminder (automatic)¶
Script at .claude/hooks/migration-reminder.sh. Also fires at the end of a
dirty turn. If a app/modules/*/models.py changed but no new script was added
under alembic/versions/, it emits a non-blocking reminder to run
just migrate-gen. Like the config-drift hook it is advisory — some
models.py edits (a docstring, a non-mapped attribute) need no migration.
PostToolUse hook — auto-format Python (automatic)¶
Configured in .claude/settings.json. Fires after any
Edit / Write / MultiEdit tool call.
When the edited file is a .py file, it runs ruff format on just that
file, so formatting stays clean mid-turn instead of accumulating drift until
the Stop hook runs at the end. It never blocks — it only reformats — and is a
no-op for non-Python files.
PreToolUse hook — block sensitive files (automatic)¶
Script at .claude/hooks/block-sensitive.sh. Fires before any
Edit / Write / MultiEdit tool call.
Refuses edits to:
| File pattern | Reason |
|---|---|
.env, .env.* (except .env.example) |
Credential leak risk |
uv.lock |
Must change via uv add / uv remove / uv sync |
alembic/versions/*.py |
Applied migrations must not be rewritten |
copier.yml, copier.yaml |
Copier template config — edit deliberately |
*.jinja |
Copier template files — break consumers if changed |
prek git hooks (automatic on commit / push)¶
Configured in prek.toml, installed by just setup.
| Event | What runs |
|---|---|
git commit |
ruff format, ruff check --fix, ty check |
git push |
full pytest suite (requires Postgres running) |
Plugins¶
Enabled in .claude/settings.json. Activate on session start.
commit-commands¶
Provides a commit skill that structures git commits following the
project's Conventional Commits convention. Claude uses it automatically
when asked to commit.
pr-review-toolkit¶
Invoke: /review-pr (or /review-pr <aspect> to target one lens)
Six specialized agents run in parallel against the current branch diff:
| Agent | Focuses on |
|---|---|
code-reviewer |
Project guidelines, CLAUDE.md conventions |
comment-analyzer |
Code comment quality |
pr-test-analyzer |
Test coverage gaps |
silent-failure-hunter |
Swallowed exceptions, bare except, missing error propagation |
type-design-analyzer |
Type correctness and design |
code-simplifier |
Clarity and maintainability |
The silent-failure-hunter is particularly relevant here: the project's
exception contract (always raise domain exceptions, never swallow errors)
is exactly what it checks.
security-guidance¶
Automatic — no invocation needed. A PreToolUse hook that scans file
edits for security patterns (command injection, XSS, hardcoded secrets,
unsafe deserialization) and injects a contextual warning into Claude's
context when a risk is detected.
claude-md-management¶
Two tools:
/revise-claude-md — run at the end of a productive session. Reviews
the conversation, extracts codebase learnings, and proposes targeted
updates to CLAUDE.md.
claude-md-improver skill — triggered by "audit CLAUDE.md",
"check project memory". Scans all CLAUDE.md files, scores quality, and
proposes improvements.
claude-code-setup¶
Provides the claude-automation-recommender skill, which analyses the
codebase and suggests new Claude Code automations (hooks, skills, MCP
servers, plugins). Use it periodically or after adding a new major
dependency.
Subagents¶
Project-local agents live in .claude/agents/. They run with their own
context and a restricted toolset, separate from the pr-review-toolkit
plugin agents above.
migration-reviewer¶
Invoke: "review this migration", "is this migration safe", or run it after
just migrate-gen and before just migrate-up.
Audits the newest autogenerated Alembic script against the project's
schema-change checklist — autogen faithfulness, unrelated drift, NOT NULL
backfills, type narrowing, enum ops, downgrade() reversibility, and
server-vs-Python defaults — and returns an APPROVE / CHANGES NEEDED /
DO NOT APPLY verdict. It mirrors the quoin-db-migration skill's checklist
so the riskiest class of change gets a second pass before it lands.
MCP servers¶
Configured in .mcp.json (committed — the whole team gets them).
context7¶
Fetches live SDK documentation at query time. Eliminates the "Claude wrote SQLAlchemy 1.4 syntax" class of failure for libraries with breaking API changes in Claude's training window.
Active for: FastAPI, SQLModel, SQLAlchemy 2.x async, Alembic, Pydantic v2, OpenTelemetry, structlog. No explicit invocation needed — Claude fetches docs automatically when working with these libraries.
postgres (read-only)¶
Runs @modelcontextprotocol/server-postgres via npx, which executes every
query inside a READ ONLY transaction — so Claude can introspect the live
schema (tables, columns, indexes, constraints) before editing a model or
reviewing a migration, but cannot mutate data. Connects to the local dev
DB by default (postgresql://postgres:postgres@localhost:5432/app_db);
override with the QUOIN_MCP_DATABASE_URI environment variable. Never point
it at production. Requires the dev DB running (just db).
Chosen over
crystaldba/postgres-mcp(uvx) because that package'spglastdependency has no Python 3.14 wheel and fails to build in this repo's toolchain. The npx reference server is build-free and read-only.
Extending the setup¶
- New skill: create
.claude/skills/<name>/SKILL.md. Follow the existing skills as a template. Trigger description is the most important part — be specific about what phrases should invoke it. - New hook: add a script to
.claude/hooks/and wire it in.claude/settings.json. Pipe-test before committing. - New subagent: create
.claude/agents/<name>.mdwith adescription(when to invoke) and a restrictedtoolslist. - New plugin: add to
enabledPluginsin.claude/settings.json. - New MCP server: add to
.mcp.json. Commit so the team gets it.
For broader automation ideas, run the claude-automation-recommender
skill (say "recommend Claude automations for this project").