Trim the context
Cut your lane's roughly 180-line CLAUDE.md to under 40 lines, with the
whole /context breakdown saved before and after, then re-run Exercise 1's
assignment against the smaller file and check it still stays green and in bounds. You are not
tidying: you are deciding, line by line, which instructions are worth paying for on every turn of
every session your team runs.
Setup
You continue in day1-work, the copy of your lane that Exercise 1 made at the
course root. Every command and every path on this page is written from inside it, and the shipped
sandbox/ is never edited. Exercise 3 left the copy matching the lane apart from your
spec, which is all step 7 needs.
Paste one block. It stages step 4's example rules file in ../work/, where your
answers go and no reset reaches, and records the starting line count.
mkdir -p ../work && cp ../day-1-from-chat-to-spec/starter/rules/EXAMPLE-formatting.md ../work/ && wc -l CLAUDE.md > ../work/context-before.txt && cat ../work/context-before.txt
180 CLAUDE.md
mkdir -p ../work && cp ../day-1-from-chat-to-spec/starter/rules/EXAMPLE-formatting.md ../work/ && wc -l CLAUDE.md > ../work/context-before.txt && cat ../work/context-before.txt
177 CLAUDE.md
Starting from a clean copy
If day1-work carries anything besides your spec, make it again from the lane
and paste the setup block above. The remake throws the copy away, your Exercise 3 spec included.
Save the spec first if you want your own on Day 2, which runs a sharpened reference spec either
way; the reset at the foot of this page saves this exercise's files as well, because by then
there are some:
mkdir -p ../work && cp specs/daily-summary.md ../work/
Then, from inside day1-work:
cd .. && rm -rf day1-work && cp -R sandbox/swift day1-work && cd day1-work
cd .. && rm -rf day1-work && cp -R sandbox/kotlin day1-work && cd day1-work
Answers already written down in ../work outlive the remake, and a spec you saved
goes back with cp ../work/daily-summary.md specs/.
Now start Claude Code here with claude. Project instructions live at
./CLAUDE.md or ./.claude/CLAUDE.md, loaded from the directory you started
in and every directory above it, so today's project file is day1-work's. The lane's
.claude/settings.json skips any above day1-work and turns auto memory
off, so the memory files in step 1's breakdown are this project file and your personal ones. A
block you do not recognise is one of the others
Lesson 6 lists.
Steps
-
Record the before state. Run
/context. In fullscreen mode it collapses the per-item breakdown to keep the grid visible; pass itallto expand the breakdown again. Copy the whole output, exactly as your version prints it, into../work/context-before.txtunder the line count. You compare it with your own after copy, not with a figure on this page. -
Apply the line test. Most of the file is real content, and almost none of it is a lie; that is what makes the cut hard. Paste this prompt. It reports, and the cutting stays yours.
Read CLAUDE.md in this project. For each line or section, tell me the specific mistake you would make if it were not there. Where you cannot name a specific mistake, say "no mistake". Do not edit the file and do not rewrite it for me - I am doing the cutting.It also ships as
../day-1-from-chat-to-spec/starter/prompts/e4-line-test.txt. While it answers, readCLAUDE.mdin your editor and start../work/cut-lines.md: one line per section you will cut or shorten, and why. Sections that would fit any codebase need no report. Then work down its answers; where no specific mistake can be named, the line goes. -
Get the file under 40 lines. Set aside what is worth keeping but not worth paying for on every turn; step 4 gives it a home. Then record the new count:
wc -l CLAUDE.md > ../work/context-after.txt && cat ../work/context-after.txt -
Move the lines that are useful but rarely needed. A line that survives the line test has two places to live, and only one of them costs you every turn.
What each destination costs you: every turn, or only the turns that read a matching file. A file at
.claude/rules/<name>.mdwith apaths:list of globs in its YAML frontmatter enters the window only when the agent reads a file matching one of those globs, and stays out otherwise. Put the file-specific lines you cut there. The example file already holds one of them, the ban on locale APIs thatCLAUDE.mdalso carries. That ban must survive the trim: keep it inCLAUDE.md, in the rules file, or both. The reference answer keeps it only in the rules file, and the reveal argues both sides:mkdir -p .claude/rules && cp ../work/EXAMPLE-formatting.md .claude/rules/formatting.md && ls .claude/rulesConfirm its frontmatter is these three lines, then paste your file-specific lines underneath:
Swift lane--- paths: ["Sources/LedgerKit/*.swift"] ---Kotlin laneThe file ships with the Swift lane's glob. Change it to your own, and change the API names in the body to
java.text.NumberFormat,DateTimeFormatter,Localeand ICU:--- paths: ["src/main/kotlin/ledgerkit/*.kt"] --- -
Measure it. Run
/clear, which starts a new conversation with an empty window, then/context, and paste the whole output into../work/context-after.txtunder the new line count. Without/clearyou measure this afternoon's conversation, not your file. -
Prove nothing broke. Paste Prompt B from Exercise 1 verbatim and let it run against the trimmed file. Approve edits as they come, and do not correct it: a correction from you is the information you are testing whether the file still carries. Between approvals, start step 8's comparison.
Swift lanePrompt B ships as
../day-1-from-chat-to-spec/starter/prompts/e1-prompt-b.txt, the text Exercise 1 gives in full.Kotlin lanePrompt B ships as
../day-1-from-chat-to-spec/starter/prompts/e1-prompt-b-kotlin.txt, the text Exercise 1 gives in full. -
Check the same two things Exercise 1 checked: green, and no source file beyond
LedgerFilterand its test touched.Swift laneswift testThe verdict line names
All tests, and the number that decides this step is the zero. The skipped test is the gated LEDGER-7 case, skipped here as it was in Exercise 1:Test Suite 'All tests' passed at … Executed … tests, with 1 test skipped and 0 failures (0 unexpected) in … secondsKotlin lane./gradlew testBUILD SUCCESSFUL in …BUILD SUCCESSFULis the line that decides this step. Gradle prints no skip count; the gated LEDGER-7 case is skipped here as it was in Exercise 1, and only the test report records it.Then the file list. A recursive diff against the shipped lane one level up is the record of the run, and each file that differs opens its section with a line starting
diff. YourCLAUDE.mdand the.claude/rules/formatting.mdstep 4 added are certain, and so isspecs/daily-summary.mdif your spec is still in the copy.Swift lanediff -ruN -x .build ../sandbox/swift . | grep '^diff 'If the agent changed code,
Sources/LedgerKit/LedgerFilter.swiftandTests/LedgerKitTests/LedgerFilterTests.swiftare the only two more that may appear.Kotlin lanediff -ruN -x build -x .gradle -x .kotlin ../sandbox/kotlin . | grep '^diff 'If the agent changed code,
src/main/kotlin/ledgerkit/LedgerFilter.ktandsrc/test/kotlin/ledgerkit/LedgerFilterTest.ktare the only two more that may appear.An agent that reads the code, finds the merchant match already ignores case and diacritics, and changes no source file and adds no duplicate tests is behaving well, as Exercise 1's key says: the case and diacritic tests Prompt B asks for are already in the lane's
LedgerFiltertest file. Saying so and adding none satisfies Prompt B'sAdd at least one test
line; the tests that line asks for already exist. What this step checks is that no third source file appears.-Nmakes a file the agent created show up, and created files are the ones people forget to count. -
Compare. Open the reveals below: your keep list against the six lines that must survive and the four that people keep and should not.
If you see something else instead
cp: ../day-1-from-chat-to-spec/starter/rules/EXAMPLE-formatting.md: No such file or directorymeans the shell was somewhere other thanday1-work. Runpwd, move back into the copy, and paste the block again; re-running it loses nothing.- The diff names
Money,TransactionFormatterorLedgerSummaryin your lane's source directory: you cut a line that was holding a bound. Put it back and write down which one; that finding is worth more than the line count. - The diff also names
LEDGER-7.md: Exercise 2's ticket, still in the copy, and harmless here. - The re-run goes red on an amount string rather than on a merchant match: the no-locale-APIs
rule left
CLAUDE.mdfor a rules file whose glob does not cover the file the agent is reading. Widen the glob, or put the line back.
Self-check
Run this, from inside day1-work
test "$(wc -l < CLAUDE.md)" -lt 40 && echo TRIM-OK || echo TRIM-TOO-LONG
On an untrimmed file it prints TRIM-TOO-LONG, which is how you know it reads
the file and not your opinion of it.
Then put the two context files side by side: about 180 lines before, under 40 after, and two outputs of the same command from your own version, so what differs is what the cut bought.
Last, the re-run: the test command ended green, and step 7's diff names your
CLAUDE.md and the rules file, and no source file beyond LedgerFilter
and its test.
Done when: the check prints TRIM-OK,
both context files exist and differ, the Exercise 1 re-run is green and in bounds, and
../work/cut-lines.md gives a reason for every section you cut or shortened.
Reference answers
The six lines that must survive, and the four that feel load-bearing and are not
Quoted from the Swift lane. The Kotlin lane carries the same six facts in different sentences and sections, so check against your own file rather than against these strings.
Run the tests with swift test from the package root.
(§ Testing) — without it the agent guesses a test command, and a guessed command that happens to pass is worse than one that fails, because you believe it.The fixture at Tests/LedgerKitTests/Fixtures/transactions.tsv is the source of truth for expected strings.
(§ Fixtures) — where the expected answers live. Fold inNever edit it
as you keep it (the Kotlin lane's version of this line already says so), because that stops a failing test being made to pass.amountMinor is an integer in the currency's minor units; a decimal point never appears in stored data.
(§ Money) — the fact that cannot be recovered by reading one file. Fold inAmounts are never floating point
from the ISO 4217 paragraph below it, because as written this line does not forbid a floating-point value mid-calculation.Negative amountMinor is a debit and prints with -; zero or positive is a credit and prints with +.
(§ Money) — sign, then symbol, then digits is arbitrary, which is exactly what makes it worth writing down.Never use NumberFormatter, Locale, ICU or any locale API: all formatting is hand-rolled.
(§ Money) — it names the wrong move before the agent makes it. This is the line step 4's rules file already carries.Run the tests before you say you are done, and quote the final summary line.
(§ Testing) —quote
rather thansummarise
is what makes the line checkable. A summary of a test run is an opinion.
The four sections people keep on the first pass, each of which feels responsible and changes nothing the agent does:
- § Engineering principles and § Working agreements (Kotlin: § Coding standards) — clean code, short functions, no repetition: true of every codebase, specific to none.
- § Style (Kotlin: § Style guide) — wrong as well as useless: the module's code does the opposite of most of it. A style rule that matters belongs in a formatter.
- § The ledger-sync tool (Kotlin: § Working with LedgerSync) — accurate, written after a painful week, and not in this repository. Background about a system you cannot touch from here is a document, not an instruction.
- § About this project and § History (Kotlin: § Project overview and history and § Directory layout) — the agent learns the module by reading it, faster and more accurately than the file describes it, and a directory tree in a standing file is stale the first time somebody adds a folder. History belongs in git.
Two more go for the same reason in whichever lane carries them: the glossary belongs in
README.md, and the Kotlin lane's § Git and review workflow belongs in
CONTRIBUTING.md. In the Kotlin lane, § Domain rules holds three of your six:
keep those and cut the rest, which the types and README.md already carry. The Swift
lane's § Code review, § Performance notes, § Accessibility and § Security give
good advice about concerns this module does not have. Full key:
answers/e4-claude-md-keepers.md.
The reference trimmed file and the reference rules file
Fifteen lines, Swift lane, and the slack under forty is deliberate: Day 2's self-critique
needs somewhere to route a finding without the file starting to grow again. The Kotlin lane's copy is the same shape built from its own six lines, with
./gradlew test, Fixtures/transactions.tsv and the glob from step 4.
# CLAUDE.md — LedgerKit
## Testing
- Run the tests with `swift test` from the package root. That is the only test command.
- The fixture at `Tests/LedgerKitTests/Fixtures/transactions.tsv` is the source of truth for expected strings. Never edit it: it is shared byte-for-byte with the other lane.
## Money
- `amountMinor` is an integer in the currency's minor units. It never holds a decimal point, and no code turns it into a floating-point number.
- Negative `amountMinor` is a debit and prints with `-`; zero or positive is a credit and prints with `+`. The sign comes before the currency symbol.
## Before you say you are done
- Run the tests before you say you are done, and quote the final summary line.
The four headings cost four lines and make the file skimmable by whoever has to defend it in six weeks; the mistake they prevent is yours. Nothing in it points at a second file: every long section is a false keep named above, so it was cut rather than filed away. And the highest-value line in the original is not in it, because this reference leaves it to the rules file:
---
paths: ["Sources/LedgerKit/*.swift"]
---
Formatting in this module is hand-rolled: never introduce a locale-aware API (`NumberFormatter`, `DateFormatter`, `Locale`, ICU) into these files.
That move is worth a minute's discomfort. For keeping the rule in CLAUDE.md: an
agent can reach for a locale API while editing a test, or a new file the glob does not cover.
Against: a rule paid for on every turn and needed on a tenth of them is the tax this exercise
teaches you to see. Either answer passes if the file is under forty lines; write down which
argument you were making. Longer version, both lanes:
answers/claude-md-trim.md.
Reset
One line, the sandbox reset every Day 1 exercise means: delete the copy, make it again from
the lane, step back in. The whole copy goes, .claude/rules/ and your
Exercise 3 spec included. Save what you want to keep first — your trimmed
CLAUDE.md and your rules files are this exercise's deliverables, and the Day 1 wrap-up
asks you to keep them:
mkdir -p ../work/rules && cp CLAUDE.md ../work/ && cp .claude/rules/*.md ../work/rules/ && cp specs/daily-summary.md ../work/ 2>/dev/null; ls ../work ../work/rules
Then, from inside day1-work:
cd .. && rm -rf day1-work && cp -R sandbox/swift day1-work && cd day1-work
cd .. && rm -rf day1-work && cp -R sandbox/kotlin day1-work && cd day1-work
Everything in ../work outlives the reset, your context files and cut list
included. A spec you saved goes back with cp ../work/daily-summary.md specs/, and
your rules files with mkdir -p .claude/rules && cp ../work/rules/*.md .claude/rules/.
The end-of-day cleanup is the other line, run from inside day1-work once Day 1 is
finished: cd .. && rm -rf day1-work. This removes day1-work and
keeps ../work; Day 2 and Day 3 write there too, so remove work only when
you no longer want the day's answers.
Sources
Claude Code documentation, accessed 2026-09-22 against version 2.1.280, and 2026-09-23 for
cc-core-40 to cc-core-44.
cc-core-08,cc-core-15— project instructions at./CLAUDE.mdor./.claude/CLAUDE.md, and.claude/rules/<name>.mdwith apaths:frontmatter list, from Manage Claude's memory.cc-core-40,cc-core-42— a path-scoped rule loads when Claude reads a matching file, andCLAUDE.mdloads from the working directory and every directory above it, from Manage Claude's memory;cc-core-41— the directory you launch Claude Code in is the session's primary working directory, from Permissions.cc-core-43,cc-core-44—claudeMdExcludesskips instruction files by glob from any settings layer, andautoMemoryEnabledturns auto memory off for one project, from Manage Claude's memory.cc-core-18,cc-core-19—/contextwith itsallargument, and/clear, from Slash commands.cc-core-32— the version this course was checked against, from the Claude Code changelog.