Skip to main content

Module 16 — Project: the Kiosque team's complete Claude Code toolkit

This module closes the course by assembling the pieces seen in modules 3, 6, 7, 9, 10, 11, 12, and 14 around a single project: the Kiosque toolkit. Five developers share a FastAPI/React application ("Kiosque", a corporate RSS reader). Goal: configure the repo so that each workstation, each cron, and each PR uses Claude Code the same way, with the same guardrails and the same predictable cost. In the end, a new collaborator who clones Kiosque and types /new-endpoint gets good work without asking a colleague.

The final tree of the Kiosque repo

kiosque/
├── .claude/
│ ├── settings.json # allow/deny and enabled plugins
│ ├── settings.local.json # (.gitignore) personal preferences
│ ├── agents/{reviewer,tester}.md
│ ├── commands/ # /commit /review-code /new-endpoint
│ │ # /targeted-tests /api-doc /release-notes
│ ├── claude-security-guidance.md # in-house rules
│ └── security-patterns.yaml # forbidden project patterns
├── .github/workflows/claude.yml # anthropics/claude-code-action@v1
├── .mcp.json # github and postgres MCP servers
├── backend/ # FastAPI + SQLAlchemy + Alembic
├── frontend/ # Vite + React + TanStack Query
├── plugins/kiosque-tools/ # local plugin, versioned
├── CLAUDE.md # conventions, < 200 lines
├── Makefile # test, lint, run, migrate targets
└── README.md

Five invariants: versioned settings.json applies to everyone; settings.local.json is personal, git-ignored; project skills live under .claude/commands/, those reusable elsewhere under plugins/kiosque-tools/; two subagents, not ten (clear role, short prompt); the Makefile is the contract between humans and Claude — every skill calls it instead of inventing its own command.

Step 1 — Lay down the team invariants

In a freshly cloned shell: git checkout -b claude-toolkit then mkdir -p .claude/{agents,commands} plugins/kiosque-tools/{commands,skills}. Check: ls .claude/ returns agents commands.

Then write .claude/settings.json — this is the file that governs everything:

{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(make test)",
"Bash(make lint)",
"Bash(make run)",
"Bash(make migrate)",
"Bash(ruff *)",
"Bash(pytest *)",
"Bash(npm test)",
"Bash(npm run build)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Bash(curl *)",
"Bash(wget *)"
]
},
"enabledPlugins": {
"security-guidance@claude-plugins-official": true,
"kiosque-tools@local": true
}
}

Check: launch claude in the folder, type /status and confirm the Setting sources line mentions Project; type /permissions to view the merged lists.

Step 2 — Write the CLAUDE.md

Open CLAUDE.md at the root. Content under 200 lines, five sections: Structure (FastAPI backend, React frontend, Alembic migrations in backend/migrations/); Test target (make test runs pytest then npm test; PR without green tests refused by the workflow); Style (ruff backend, prettier frontend, no print shipped); Migrations (never modify an applied migration; always a new revision); Where to find what (docstrings in backend/app/routes/*.py, styles in frontend/src/styles/).

Check: /context must report project CLAUDE.md at about 1,800 tokens — above that, trim.

Step 3 — The six project skills

Every skill lives under .claude/commands/<name>.md with minimal frontmatter (description, optionally allowed-tools):

  • /commit: conventional message from git diff --staged, offers to commit, does not push. allowed-tools: [Bash(git *)].
  • /review-code: invokes reviewer on the diff versus origin/main, displays the findings.
  • /new-endpoint: two arguments (method, path), generates FastAPI route, Pydantic schema, Alembic migration if a model is touched, pytest test, React stub. Each step calls make test before continuing.
  • /targeted-tests: computes the minimal list from the diff, runs pytest -k "<expr>" then npm test -- --changed.
  • /api-doc: regenerates the OpenAPI doc and updates docs/api.md.
  • /release-notes: reuses the Python script from module 14, also called from a cron.

Check: / alone lists the six commands; /new-endpoint POST /articles/{id}/lu produces route + test + migration coherent in one turn, the turn ends with a green make test.

Step 4 — The two subagents

Two short files, two roles.

.claude/agents/reviewer.md — frontmatter skills: [Read, Grep, Bash], model: claude-sonnet-5. Body: "You review a FastAPI + React diff. Flag regressions, missing tests, secret leaks, dangerous migrations. Use git diff origin/main...HEAD. Do not write to files. End with a verdict blocker | fix | acceptable."

.claude/agents/tester.md — frontmatter skills: [Bash, Read], model: claude-sonnet-5. Body: "You run make test (or a pytest -k selection) and report failures with file and line. No code modification. Two-line summary per failure."

Check: /agents lists the two subagents. /review-code must invoke reviewer (visible in the trace).

Step 5 — The hooks

Three hooks in .claude/settings.json, under a hooks key, all in "type": "command": PostToolUse ruff with matcher: "Edit|Write" and command: "make lint 2>/dev/null || true" (linter after every write, output ignored on failure, lint is advisory); PreToolUse protection for migrations/.env with the same matcher, command: ".claude/hooks/protect-sensitive.sh" — a short script that refuses (exit code 2) any write on already-committed backend/migrations/*.py or on .env*; Stop make test with no matcher, command: "make test", the suite runs at every end of turn and a failure feeds the result back into the conversation.

Check: ask Claude to write to .env; the hook must reply refused: sensitive file protected. Modify a route and let the turn end: make test appears in the trace.

Step 6 — The MCP servers

.mcp.json at the root, versioned, declares two stdio servers: github (via @modelcontextprotocol/server-github) to open PRs, list issues, and comment; postgres (via @modelcontextprotocol/server-postgres, URL with a read-only user) to inspect the schema. Definitions stay deferred by tool search — Claude only loads them when needed.

Check: /mcp shows two connected servers. /context all must indicate an MCP load near zero as long as no tool has been called.

Step 7 — The kiosque-tools plugin

plugins/kiosque-tools/plugin.json declares a local plugin: name, version, description, commands and skills lists pointing at the subfolders. It bundles a variant of /release-notes reusable on another in-house repo and a weekly-changelog skill that condenses the week's commits. Activation through enabledPlugins in .claude/settings.json, already in place.

Check: /plugin list mentions kiosque-tools@local with status enabled. Plugin commands appear in the palette with the prefix kiosque-tools:.

Step 8 — The GitHub Actions workflow

.github/workflows/claude.yml reuses module 14's skeleton: issue_comment and pull_request_review_comment triggers (types [created]), if: contains(github.event.comment.body, '@claude') guard, minimal permissions (contents: write, pull-requests: write, issues: write, id-token: write, actions: read), actions/checkout@v6 with fetch-depth: 1, then anthropics/claude-code-action@v1 with anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} and claude_args: --max-turns 8 --model claude-sonnet-5 --allowedTools "Bash(make test),Bash(make lint),Read,Edit".

Check: open a PR, comment @claude look at this diff and fix the lint issues; the workflow fires, a commit is pushed on the branch, make test stays green.

Ten-minute demo scenario

Proven pace for showing the toolkit to a new colleague.

  • 0 - 1 min — Clone the repo, claude launched at the root. /status confirms shared settings, active plugins, two MCP servers connected.
  • 1 - 3 min/new-endpoint POST /articles/{id}/lu. Claude generates route, schema, migration, test. The Stop hook runs make test: green.
  • 3 - 5 min — Ask "show me the content of .env". The deny rule refuses, the trace shows it.
  • 5 - 6 min/review-code: the reviewer subagent cites two minor points, verdict acceptable.
  • 6 - 7 min/commit produces a conventional message, staged, ready to push.
  • 7 - 9 min — Push the branch, open the PR, comment @claude check there is no regression. The workflow fires, Claude comments on the PR.
  • 9 - 10 min/usage: demo cost around 0.25 EUR, Prompt cache (main) at 90% read.

Grading rubric

Twenty points on five axes.

AxisCriterionPoints
Shared configurationVersioned .claude/settings.json, coherent permissions.allow/deny, correct enabledPlugins4
Skills and subagentsThe six skills exist, the two subagents have a short clear role, /new-endpoint produces route + test + migration4
HooksPostToolUse ruff, PreToolUse protection for .env/migrations, Stop make test in place and firing3
MCP and pluginVersioned .mcp.json with github and postgres, kiosque-tools plugin active and tested3
CI workflowclaude.yml triggered on @claude, minimal permissions, restrictive --allowedTools, demo PR green3
Costs and hygieneCLAUDE.md < 200 lines, /usage shows Prompt cache (main) warm, demo cost < 0.50 EUR3

A project below 15 out of 20 signals a missing axis: most often the CI workflow or the hooks. A project at 18 out of 20 or more holds in internal production — module 15 recalls the monthly moves (review of behavior flags, reading ~/.claude/usage-data/report.html).

Variants

Three variants to adapt without redoing:

  • Kiosque-mono. One developer only: three skills (/commit, /review-code, /new-endpoint), one subagent (tester), no workflow (the module 14 cron is enough).
  • Kiosque-scale. Fifty developers: managed settings to lock permissions.deny, enabledPlugins, and a modelPricing at the contracted rate; publish kiosque-tools on a private marketplace.
  • Kiosque-cloud. Team mostly on Claude Code on the web: .claude/settings.json, .mcp.json, CLAUDE.md, skills, and workflow work; what lives in ~/.claude/ (user settings, user-scope plugins) must be migrated into the repo or into managed settings.

Frequent pitfalls

  • Overly verbose skill. A /new-endpoint that inlines a FastAPI tutorial exceeds the context budget; keep the essentials, let Claude read the files.
  • Subagent that writes. A reviewer allowed to write fixes itself what it should flag; frontmatter without Edit or Write.
  • Stop hook too long. A three-minute make test blocks every turn; isolate a make test-fast target for the hook.
  • postgres MCP with write access. Always URL with a readonly user — an accidental DROP TABLE is unrecoverable.
  • --dangerously-skip-permissions in the workflow. Never on a non-isolated runner; always --permission-mode dontAsk and narrow --allowedTools.
  • Root CLAUDE.md that accumulates. Migrate detailed instructions to an invokable skill, keep the stable invariants in the root file.

Endpoint

Every workstation shares the same palette: the same commands, the same permission rules, the same subagents, the same hooks, the same MCP servers. The GitHub Actions workflow replays the palette in CI. A nightly cron (module 14) can call claude --bare -p with the same guarantees. Claude Code is no longer a tool you use, it is a versioned component of the repo that enforces rules as strictly as the linter and the tests.

You are ready for the recap and exam.