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 fromgit diff --staged, offers to commit, does not push.allowed-tools: [Bash(git *)]./review-code: invokesrevieweron the diff versusorigin/main, displays the findings./new-endpoint: two arguments (method, path), generates FastAPI route, Pydantic schema, Alembic migration if a model is touched,pytesttest, React stub. Each step callsmake testbefore continuing./targeted-tests: computes the minimal list from the diff, runspytest -k "<expr>"thennpm test -- --changed./api-doc: regenerates the OpenAPI doc and updatesdocs/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,
claudelaunched at the root./statusconfirms shared settings, active plugins, two MCP servers connected. - 1 - 3 min —
/new-endpoint POST /articles/{id}/lu. Claude generates route, schema, migration, test. TheStophook runsmake test: green. - 3 - 5 min — Ask "show me the content of
.env". Thedenyrule refuses, the trace shows it. - 5 - 6 min —
/review-code: thereviewersubagent cites two minor points, verdictacceptable. - 6 - 7 min —
/commitproduces 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.
| Axis | Criterion | Points |
|---|---|---|
| Shared configuration | Versioned .claude/settings.json, coherent permissions.allow/deny, correct enabledPlugins | 4 |
| Skills and subagents | The six skills exist, the two subagents have a short clear role, /new-endpoint produces route + test + migration | 4 |
| Hooks | PostToolUse ruff, PreToolUse protection for .env/migrations, Stop make test in place and firing | 3 |
| MCP and plugin | Versioned .mcp.json with github and postgres, kiosque-tools plugin active and tested | 3 |
| CI workflow | claude.yml triggered on @claude, minimal permissions, restrictive --allowedTools, demo PR green | 3 |
| Costs and hygiene | CLAUDE.md < 200 lines, /usage shows Prompt cache (main) warm, demo cost < 0.50 EUR | 3 |
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 amodelPricingat the contracted rate; publishkiosque-toolson 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-endpointthat inlines a FastAPI tutorial exceeds the context budget; keep the essentials, let Claude read the files. - Subagent that writes. A
reviewerallowed to write fixes itself what it should flag; frontmatter withoutEditorWrite. - Stop hook too long. A three-minute
make testblocks every turn; isolate amake test-fasttarget for the hook. postgresMCP with write access. Always URL with areadonlyuser — an accidentalDROP TABLEis unrecoverable.--dangerously-skip-permissionsin the workflow. Never on a non-isolated runner; always--permission-mode dontAskand narrow--allowedTools.- Root
CLAUDE.mdthat 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.