C1 — Write a Real CLAUDE.md

Summary — what this page covers Point Claude Code at the C0 starter, run a quick gap analysis, then write a real CLAUDE.md — the project briefing Claude loads on every session. This is your first Day 1 lab: you configure Claude to understand BookTracker before you change a single line of code.

Time: ~30 minutes · Format: hands-on, solo · You start from: checkpoint/c0-base · You end at: checkpoint/c1-claude-md

C0 left you with a starter you can build, run, and read — and a notepad of rough edges. In C1 you turn that understanding into a map Claude can use. A good CLAUDE.md is facts and soft conventions, not a wall of rules: it describes the project, the stack, the commands, the architecture, and the handful of conventions that keep the code healthy. No production code changes in this lab — the only file you commit is CLAUDE.md.


1. Prerequisites

This is a Day 1 (Claude Code) lab, so beyond the C0 tooling you need:

Tool Why Check
Claude Code CLI runs the agent against your repo claude --version
A paid Claude plan required to use Claude Code sign in when prompted

Day 1 uses Claude Code with a paid Claude plan. (Day 2's labs use the Anthropic API and a separate API key — you don't need that here.)


2. Continue from your C0 work

If you already have your my-booktracker branch from C0, just keep using it. Otherwise start a fresh working branch from the C0 checkpoint:

# only if you don't already have a working branch
git switch -c lab checkpoint/c0-base

Everything in this lab runs from the solution folder, where Claude Code should be launched so it picks up the right project root:

cd src/BookTracker
claude

3. Run a gap analysis with Claude Code

Before you write anything, let Claude read the starter and tell you what's wrong with it. From inside the claude session, ask for a structured review — for example:

Review this BookTracker starter. List the risks, gaps, and inconsistencies you find
(security, validation, error handling, observability, what leaks across the API boundary,
and test coverage). Group them and keep it short — don't fix anything yet.

Compare Claude's findings against the notes you took in C0. You should see the deliberate gaps surface: a string-built SQL query in the search repository, a POST /books that doesn't validate input, an endpoint returning an EF entity instead of a DTO, and thin-to-nonexistent observability. Don't fix any of these now — each one becomes a convention you write in the next step.


4. Scaffold and trim a CLAUDE.md

Let Claude scaffold the file, then trim it to a map, not a junk drawer. From the session:

/init

/init writes a first-draft CLAUDE.md by reading the repo. Now edit it down — keep it well under ~200 lines. Remember: CLAUDE.md is loaded on every session, so every line is paid for on every turn. Earn each one. Your file must include:

  1. A project description — what BookTracker is.
  2. The stack — .NET 10 / ASP.NET Core 10 Minimal API, EF Core 10, SQLite, xUnit.
  3. The four commands — build, test, run, plus EF migrations:

    dotnet build                                   # build the solution
    dotnet test                                    # run the xUnit tests
    dotnet run --project BookTracker.Api           # run the API (http://localhost:5255)
    
    # migrations (EF Core CLI; run from src/BookTracker)
    dotnet ef migrations add <Name> --project BookTracker.Data --startup-project BookTracker.Api
    dotnet ef database update      --project BookTracker.Data --startup-project BookTracker.Api
  4. Architecture + the deliberate dependency direction — Core ← Data ← Api ← Tests:

    BookTracker.Core   ← BookTracker.Data   ← BookTracker.Api   ← BookTracker.Tests
  5. At least five conventions — each one should counter a gap you found in step 3:
    • Return DTOs, never EF entities across the API boundary (DTOs live in BookTracker.Core/Dtos).
    • Validate inputs at the endpoint before they reach the data layer.
    • Keep endpoints thin — business logic belongs in Core services.
    • Parameterized queries / EF LINQ only — never build SQL by string concatenation.
    • Async all the way — use the async EF APIs and thread CancellationToken through.
    • Schema changes go through EF Core migrations in BookTracker.Data.

Facts and soft conventions only. CLAUDE.md is not the place for hard, deterministic guardrails like "never run rm -rf" or "never commit secrets." Prompt text can't reliably enforce anything — those become a PreToolUse hook + permissions in C2. Keep this file descriptive: say what the conventions are, not that they're enforced.

For reference, here's the shape of a good result (this is the C1 answer key — write your own, don't paste this):

# BookTracker

ASP.NET Core 10 Minimal API for tracking books and reading progress, backed by EF Core 10.

## Stack
- C# / .NET 10 · ASP.NET Core 10 Minimal API (no controllers)
- EF Core 10 · SQLite (dev) · xUnit for tests

## Commands
... (the four commands above)

## Architecture
Four projects with a deliberate dependency direction: Core ← Data ← Api ← Tests.
- BookTracker.Core — entities, DTOs, service interfaces, domain logic. Depends on nothing.
- BookTracker.Data — EF Core DbContext, migrations, seed, implementations. → Core.
- BookTracker.Api — Minimal API endpoints, DI, mapping. → Core, Data.
- BookTracker.Tests — xUnit. → all of the above.

## Conventions
- Return DTOs, never EF entities; validate at the endpoint; keep endpoints thin;
  parameterized/LINQ only; async + CancellationToken; migrations in BookTracker.Data.

## Notes
- The starter has intentional gaps — find and fix them, don't copy them.

5. Confirm Claude loads it

CLAUDE.md is only useful if it's actually in context. From the session, check the loaded memory:

/memory

CLAUDE.md should appear in the list of loaded memory files. (It's also picked up automatically on startup whenever you launch claude from src/BookTracker.)


6. Verify nothing broke and commit

You changed no code, so the solution must still be green. From src/BookTracker:

dotnet build BookTracker.sln
dotnet test BookTracker.sln

Both should pass exactly as they did in C0. Then commit your one deliverable:

git add CLAUDE.md
git commit -m "Add project CLAUDE.md"

Want the full reference? The matching checkpoint tag checkpoint/c1-claude-md is the answer key — diff your file against it rather than copying it in.


Checkpoint — you're done when:

  • You ran a gap analysis with Claude Code and recognized the planted C0 gaps.

  • CLAUDE.md exists, is < ~200 lines, and includes the project description, the stack, the four commands (build/test/run + EF migrations), the architecture with the Core ← Data ← Api ← Tests dependency direction, and ≥5 conventions.

  • The file contains no hard-prohibition / guardrail language (those are C2's job).

  • /memory lists CLAUDE.md as loaded.

  • The four commands in the file actually work from src/BookTracker.

  • dotnet build and dotnet test are still green (no code changed).


What's next

Lab 2 (C1 → C2): you'll turn these conventions into a committed .claude/ steering kit — moving the path-scoped rules out of CLAUDE.md into .claude/rules/*.md and adding the first deterministic guardrails (a PreToolUse hook + permissions) that prompt text can't enforce.