Claude Code is how you build client work faster and more safely. This module turns it from a chat in a terminal into a repeatable setup: project memory, permissions, hooks, subagents on cheaper models, and a template repo you reuse on every engagement.
Claude Code is an agentic coding tool. You describe a goal; it reads the repository, edits files, runs commands, and shows you what it did. It works with your real tools (git, pytest, ruff, docker, the gh CLI) instead of working in a sandbox of its own. For you it has two uses: building client deliveries faster, and being something you teach the client's developers to use.
| Surface | What it is | Use it for |
|---|---|---|
| Terminal (CLI) | The claude command inside a project folder. The most complete surface and the one this module uses. | Daily delivery work, scripting, CI |
| IDE extensions | Claude Code inside VS Code and JetBrains editors, with diffs shown in the editor | Client developers who live in their editor |
| Desktop app | Claude Code sessions in the Claude desktop app | Running several sessions side by side, reviewing changes visually |
| Web | Sessions run in the cloud against a connected GitHub repository, from a browser or phone | Starting a task away from your machine, longer background jobs |
The surfaces share the same ideas: CLAUDE.md, settings, slash commands, subagents, MCP. Feature coverage differs between them and changes often, so check the overview page for the current list and the install steps. Do not write install commands from memory into a client handover.
You already like this pattern: a strong model plans, cheaper models do the legwork. Claude Code supports it directly. The main session runs on the model you picked (Opus or Sonnet). It hands bounded jobs to subagents. Each subagent runs in its own context window, so a long file search does not fill the main conversation, and each can use a cheaper model.
A local llama.cpp box does not plug into Claude Code as a subagent model. Subagent models are Claude models. If you want the local box in the loop, expose it as a small script or MCP tool (for example "classify this log line", "extract the invoice number") and let a subagent call it. Keep it for tiny, low-risk tasks.
CLAUDE.md is a Markdown file that Claude Code loads at the start of a session. It is the cheapest way to improve results: you write the rules once instead of repeating them in every prompt. Put in it what a new developer would need on day one.
.env, never send real client data to an API in tests, ask before adding dependenciesKeep it short and specific. Every line is read on every session, so every line costs context. Vague advice ("write clean code") adds cost and no value.
| Level | Where | Shared with | Put here |
|---|---|---|---|
| User | ~/.claude/CLAUDE.md | Only you, all projects | Your own habits: "reply concisely", "I use uv", your preferred test style |
| Project | ./CLAUDE.md (committed) | The whole team | Commands, layout, conventions, hard rules |
| Local project | ./CLAUDE.local.md (git-ignored) | Only you, this project | Your sandbox URLs, personal notes. Check the memory docs for whether your version still supports this file. |
| Subfolder | ./src/api/CLAUDE.md | The team | Rules for one area. Loaded when Claude works on files there. |
CLAUDE.md files can also import other files. The syntax and the exact loading order are in the memory docs; read them before you build a deep hierarchy. In session, /memory lets you see and edit what is loaded, and /init drafts a first CLAUDE.md from the codebase. Treat the draft as a starting point and trim it.
By default Claude Code asks before it edits files or runs commands. Permissions let you pre-approve the safe things and block the dangerous ones, so the sessions run smoothly without you giving up control.
| File | Scope | Committed? |
|---|---|---|
~/.claude/settings.json | You, all projects | No |
.claude/settings.json | This project, the team | Yes |
.claude/settings.local.json | This project, only you | No (git-ignored) |
Settings hold permission rules (allow, ask, deny), hooks, environment variables and more. More specific and local files override broader ones, and a deny rule wins. Rule syntax and the full key list are in the docs, and they change, so look them up when you write a client config.
.env and secrets; leave anything that writes outside the repo, installs packages or touches the network on "ask". The /permissions command shows what is active. Do not use a "skip all permissions" mode on a client machine.A Markdown file in .claude/commands/ becomes a command. .claude/commands/eval.md is run as /eval. The body is a prompt; $ARGUMENTS is replaced by what you type after the command. A short frontmatter block can set a description and, optionally, allowed tools and a model. Commands are how you turn your own methods ("how we scope a use case") into a one-line habit that every developer on the project uses.
A hook is a shell command that Claude Code runs automatically at a defined moment, for example after a file edit or when Claude finishes a turn. Hooks are deterministic: they run every time, which a CLAUDE.md instruction does not guarantee. Typical uses are running ruff after edits, running pytest before Claude says it is done, and blocking edits to protected files. Hooks run with your permissions, so review any hook you copy from somewhere. Event names, matcher syntax and exit-code behaviour are in the hooks reference; verify them there.
A subagent is a Markdown file in .claude/agents/ (project) or ~/.claude/agents/ (user). Frontmatter sets its name, a description that tells Claude when to use it, an optional list of tools, and an optional model. The body is its system prompt. Claude delegates to a subagent automatically when the description matches the task, or when you ask by name.
| Use a subagent for | Why | Model and tools |
|---|---|---|
| Exploration: "where is invoice parsing done?" | Reading many files floods the main context; you only need the answer | Haiku; read-only tools |
| Running tests and reporting | Test output is long; you only need the failures and likely cause | Haiku; bash and read |
| Review of a diff | A fresh context judges the change without the author's assumptions | Sonnet; read-only tools |
Do not make a subagent for work that needs the full conversation history, or for one small edit. Delegation has overhead. See the sub-agents docs for the current frontmatter fields and model values.
Skills are folders with a SKILL.md and optional scripts that Claude loads when the task matches. In Claude Code they live in .claude/skills/ (project) or ~/.claude/skills/ (user). The difference from CLAUDE.md: a skill loads only when relevant, so it costs nothing the rest of the time. Put always-true rules in CLAUDE.md and task-specific procedures in a skill. Module 8 covers skills in depth.
A .mcp.json file at the repo root declares MCP servers for everyone who works in the project. Claude Code asks each person to approve a project server before using it. This is how the server you built in Module 6 becomes available to the whole team without anyone editing personal settings. Never put secrets in .mcp.json; reference environment variables instead, and check the docs for the expansion syntax.
Most failed Claude Code sessions skip the plan. Plan mode (cycle to it with Shift+Tab, or start the session in it; confirm the current key in the docs) lets Claude read and think but not edit. You read the plan, correct it, and only then approve implementation.
Habits that make the loop work:
/rewind and checkpoints exist too; check the docs for what they cover.Claude Code runs git and, if installed and authenticated, the GitHub gh CLI. A clean delivery flow:
git switch -c feature/phone-normalizer). Never work on main.gh pr create and write the description: what changed, how it was tested, what to check.For automatic review on every pull request, Anthropic provides a Claude Code GitHub Action. It can review PRs and respond when someone mentions Claude in a comment. Setup (the /install-github-app command in a session, or a manual workflow file plus a repository secret) and the current options are in the GitHub Actions docs. Store the API key as a repository secret and never in the workflow file.
The -p (print) flag runs Claude Code once, non-interactively, and prints the result. That makes it usable in scripts and CI: summarize a failing build, draft release notes, check a migration. Output can be requested as plain text or JSON. In CI, restrict the tools with allow rules and run with a scoped, low-privilege key. The exact flags (output format, allowed tools, turn limits) are in the CLI reference. Run claude --help and read the docs; do not trust a flag you remember from last month.
# Example shape only: confirm every flag with `claude --help` and the CLI reference
claude -p "List functions in src/ that have no tests" --output-format json
Claude Code cost follows tokens, and tokens follow context. Four habits matter more than any setting:
/model./clear between unrelated tasks. A session that carries three old tasks pays for them on every turn./compact summarizes the conversation so far; you can add instructions about what to keep, such as "keep the plan and the failing test names". Do it at a natural break, not when quality has already dropped.src/app/core.py" beats "find the bug".Use /cost or the usage views to see where tokens go, and look at the pricing page and the plan's usage rules before you tell a client what a Claude Code rollout will cost. Do not quote numbers from memory.
Many of your clients have one to five developers and no process for AI-assisted coding. Your template repo is the teaching tool. A good first session runs 90 minutes:
Their security person will ask what data leaves the machine, so prepare the answer from current Anthropic documentation and Trust Center pages, with the date you checked.
Claude Code changes fast: commands, settings keys, hook events and model aliases are added and renamed. Treat this page as the map and the docs as the ground truth. Before you commit a config to a client repo, verify each key in the docs, start a session, and run /permissions, /agents, /hooks and /mcp to see that your files are actually loaded. If something does not load, the config is usually silently wrong, not broken.
Goal: one repository you clone at the start of every engagement, so each project begins with memory, guardrails, cheap subagents and a test loop already in place. Then prove it by building a tiny feature with plan mode.
The files below are complete. Config key names were correct when this course was written; verify each against the docs from section 7.10 and adjust. Model aliases in subagent files (haiku, sonnet) are shorthand; the docs list the accepted values.
Setup
mkdir client-engagement-template && cd client-engagement-template
git init -b main
mkdir -p .claude/commands .claude/agents src/app tests
python -m venv .venv && source .venv/bin/activate
pip install ruff pytest
CLAUDE.md
# Project: CLIENT_NAME engagement
Python service built by Vastama Ltd for CLIENT_NAME. Replace this paragraph
with two lines on what the system does and who uses it.
## Commands
- Install: `pip install -e ".[dev]"`
- Test: `pytest -q`
- Lint: `ruff check .`
- Format: `ruff format .`
## Layout
- `src/app/` application code
- `tests/` pytest tests, mirror the `src/app/` structure
- `docs/` decisions and use-case briefs
## Conventions
- Python 3.11+, type hints on all public functions
- Small functions, no global state, no print in library code (use logging)
- Comments and docstrings in English. User-facing strings may be Hebrew,
Russian or English; keep them in one place so they can be translated.
- Model IDs live in one config module. Add a "check current IDs" comment.
## Hard rules
- Never read or edit `.env` or anything under `secrets/`.
- Tests must not call the Claude API or touch client data. Use fixtures.
- Ask before adding a dependency.
- Work on a branch, never on `main`.
## Definition of done
1. `pytest -q` passes
2. `ruff check .` is clean
3. New behaviour has a test
4. README or docs updated if usage changed
## Working style
- For any change over ~20 lines, propose a plan first and wait for approval.
- Use the `explorer` subagent to find code, `test-runner` to run tests,
`reviewer` before suggesting a commit.
.claude/settings.json (permissions and hooks)
{
"permissions": {
"allow": [
"Bash(pytest:*)",
"Bash(ruff check:*)",
"Bash(ruff format:*)",
"Bash(git status)",
"Bash(git diff:*)",
"Bash(git log:*)"
],
"deny": [
"Read(./.env)",
"Read(./secrets/**)",
"Bash(git push --force:*)"
]
},
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "ruff check --fix --quiet . ; ruff format --quiet ."
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "pytest -q 1>&2 || exit 2"
}
]
}
]
}
}
The first hook formats and lints after every edit. The second runs the tests when Claude finishes a turn; exit code 2 is how a hook feeds a failure back to Claude so it keeps working. Confirm that behaviour for the Stop event in the hooks reference. If it differs in your version, move the pytest hook to PostToolUse with a narrower matcher, or drop it and rely on the test-runner subagent.
.claude/commands/new-usecase.md
---
description: Scope a new AI use case and create its brief
argument-hint: short name of the use case
---
Create a brief for a new use case called: $ARGUMENTS
1. Ask me up to five questions you need answered. Stop and wait for answers.
2. Then write `docs/usecase-$ARGUMENTS.md` with these sections:
- Problem and who has it
- Input and output (examples, in the real language of the data)
- Success metric and how we measure it
- Risks and what a human must approve
- Proposed model tier and why
- First test cases (at least five, including two hard ones)
3. Do not write application code yet. End with a suggested plan to implement
the first slice.
.claude/commands/eval.md
---
description: Run the test suite and summarize results
argument-hint: optional pytest path or -k expression
---
Use the `test-runner` subagent to run `pytest -q $ARGUMENTS`.
Report:
- number passed, failed, skipped
- for each failure: test name, one-line cause, the file and line to look at
- whether the failures look like a code bug or a bad test
Do not edit any files. Wait for my instruction before fixing anything.
.claude/agents/explorer.md
---
name: explorer
description: Finds code and explains how a part of the codebase works. Use for "where is X", "how does Y flow" and any search across many files. Read-only.
tools: Read, Grep, Glob
model: haiku
---
You explore the repository and answer questions about it.
- Search first, read second. Read only the files you need.
- Answer in under 200 words: the relevant file paths with line numbers, and
a short description of how they connect.
- If you are not sure, say what you checked and what you did not find.
- Never suggest edits and never invent paths.
.claude/agents/test-runner.md
---
name: test-runner
description: Runs the test suite and reports failures concisely. Use after code changes and before suggesting a commit.
tools: Bash, Read, Grep
model: haiku
---
You run tests and report results. You do not fix code.
1. Run `pytest -q` (or the path or expression you were given).
2. If everything passes, reply with the counts and nothing else.
3. If something fails, reply with, for each failure: test name, the assertion
or error in one line, and the most likely file and line responsible.
4. Do not paste full tracebacks unless asked.
.claude/agents/reviewer.md
---
name: reviewer
description: Reviews the current uncommitted diff for bugs, missing tests, security problems and convention violations. Use before every commit or PR.
tools: Read, Grep, Glob, Bash
model: sonnet
---
You are a careful code reviewer. Run `git diff` and `git status` to see the
change, then read surrounding code where needed.
Check, in this order:
1. Correctness: edge cases, wrong assumptions, off-by-one, None handling
2. Tests: is the new behaviour covered, including a failure case?
3. Security and data: secrets, client data in logs or fixtures, unsafe input
4. Conventions from CLAUDE.md
5. Simplicity: anything that can be removed
Reply with a short list grouped as Must fix, Should fix, Nice to have. Each
item has the file, line and a one-sentence reason. If there is nothing to
fix, say so. Do not edit files.
.mcp.json (the Module 6 server)
{
"mcpServers": {
"client-data": {
"command": "python",
"args": ["-m", "client_data_mcp"],
"env": {
"CLIENT_DATA_DIR": "${CLIENT_DATA_DIR}"
}
}
}
}
Replace client-data, the module name and the variable with the real names from your Module 6 server, and use the uv or pip install you chose there. Confirm the environment variable expansion syntax in the MCP section of the Claude Code docs. No secrets go in this file.
pyproject.toml
[project]
name = "client-engagement"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = []
[project.optional-dependencies]
dev = ["pytest", "ruff"]
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find]
where = ["src"]
[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
[tool.ruff]
line-length = 100
src = ["src", "tests"]
[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP"]
src/app/__init__.py
"""Application package."""
src/app/core.py
"""Core helpers. Replace with the first real slice of the engagement."""
import logging
logger = logging.getLogger(__name__)
def clean_text(value: str) -> str:
"""Trim whitespace and collapse internal runs of spaces."""
return " ".join(value.split())
tests/test_core.py
from app.core import clean_text
def test_clean_text_trims_and_collapses():
assert clean_text(" שלום עולם ") == "שלום עולם"
def test_clean_text_empty():
assert clean_text("") == ""
.gitignore
.venv/
__pycache__/
*.egg-info/
.pytest_cache/
.ruff_cache/
.env
secrets/
.claude/settings.local.json
CLAUDE.local.md
README.md
# Client engagement template
Starting point for Vastama client projects built with Claude Code.
## Start a new engagement
1. Click "Use this template" on GitHub (or clone and delete `.git`).
2. Edit `CLAUDE.md`: client name, what the system does, any extra rules.
3. Edit `.mcp.json` to point at the client's MCP server, or remove it.
4. `python -m venv .venv && source .venv/bin/activate && pip install -e ".[dev]"`
5. Run `claude` in the folder. Check `/agents`, `/hooks`, `/mcp` and
`/permissions` show what you expect.
## What is in the box
| Path | Purpose |
| --- | --- |
| `CLAUDE.md` | Project memory: commands, layout, rules, definition of done |
| `.claude/settings.json` | Permissions and hooks (ruff after edits, pytest on stop) |
| `.claude/commands/` | `/new-usecase`, `/eval` |
| `.claude/agents/` | `explorer` (Haiku), `test-runner` (Haiku), `reviewer` (Sonnet) |
| `.mcp.json` | Project MCP server |
| `src/app/`, `tests/` | Skeleton with one passing test |
## Daily flow
Branch, plan mode, implement, test, review, pull request. See
"How we build with Claude Code" in `docs/`.
## Rules
Never commit `.env`. Tests never call external APIs. Always read the diff.
Commit and push
pytest -q && ruff check .
git add -A && git commit -m "Client engagement template"
gh repo create client-engagement-template --private --source . --push
# On GitHub: Settings, then tick "Template repository"
Use it: a tiny feature with plan mode
Feature: normalize Israeli mobile phone numbers (050-123-4567, +972 50 123 4567, 0501234567) to +972501234567, and return None for anything invalid.
git switch -c feature/phone-normalizer.claude, switch to plan mode, and run /new-usecase phone-normalizer. Answer its questions, then read docs/usecase-phone-normalizer.md.src/app/phones.py. Watch the ruff hook run after each edit./eval. Confirm the test-runner subagent was used and the summary is short.gh pr create with a description. Review the PR page yourself and merge.Stretch (1 h): add the Claude Code GitHub Action to the template using the current docs, open a PR with a deliberate bug, and see whether the review catches it. Then run one headless claude -p command from a shell script and save the output.
Two things you can hand to any client:
docs/how-we-build.md in the repo and as a PDF. Suggested structure:
src/api/ folder?
~/.claude/CLAUDE.md. The test command in the project ./CLAUDE.md, committed. The API rule in src/api/CLAUDE.md, loaded when Claude works there.-p flag) with a restricted set of allowed tools and a scoped key stored as a CI secret. Before writing the pipeline, check the CLI reference for the exact flags and output formats, because they change. Review what the job can read and write./clear when switching to an unrelated task, or /compact with instructions when you must continue the same task. Push searching and test running to Haiku subagents. Name files in prompts and trim CLAUDE.md. Optionally switch the main model for the next step with /model.