Lesson 3 of 7
A CLAUDE.md for an ABAP repository
11 min
Listen to this lesson
Every Claude Code session starts with an empty context. It doesn't know that Contoso's views start with ZI_CMC_, that ZCMC_CLOUD is ABAP for Cloud Development, or that a change isn't done until ATC is clean. CLAUDE.md is the file that tells it. Claude Code reads it at the start of every session, from the working directory and every directory above it, and concatenates what it finds; subdirectory files load when Claude works there. Anthropic recommends keeping each file under about 200 lines, because longer files cost context and reduce adherence.
Two facts shape everything in this lesson. First, Anthropic states that Claude treats CLAUDE.md as context, not enforced configuration; a rule there is a strong request, not a control. Second, specific, checkable rules are followed far more reliably than general advice. "Run ATC with variant ZCMC_CLOUD_DEV and report priority 1 and 2 findings" works; "write good code" does nothing.
AGENTS.md and CLAUDE.md together
Contoso already has an AGENTS.md, written from SAP's template for the ADT MCP server (see sap-aid-202), so that GitHub Copilot and other agents get the same rules. Claude Code can read AGENTS.md, but by default only when no CLAUDE.md exists in the working directory or above it. Contoso wants both: shared rules for every agent and a few Claude-specific ones. So the repository's CLAUDE.md starts with an import, @AGENTS.md. Imports are expanded at launch, resolve relative to the importing file and can nest up to four hops. Claude Code never reads an imported AGENTS.md twice.
Contoso's CLAUDE.md
Why each section is there
| Section | What it prevents | What backs it up (enforcement) |
|---|---|---|
| System and scope | Work in the wrong system or package; surprise transports | No CMQ/CMP destinations; ADT access restrictions; S_TRANSPRT without release; deny rule on transport creation |
| Naming | Objects nobody can find or that break ATC naming checks | ATC naming checks; review |
| Clean core | Invented APIs; unreleased SAP objects; table access around the BO | ABAP Cloud syntax check (unreleased use is an error in ZCMC_CLOUD); ATC; review |
| Definition of done | "Done" without activation, tests or ATC | Stop hook evidence gate (lesson 4); rerun in ADT before release |
| How to work | Large unreviewed edits; loops; tampered tests; prompt injection | Manual mode prompts; ask rules on edits; diff review |
Each CLAUDE.md rule maps to a control that holds if Claude ignores the rule.
Clean core rules that an agent can follow
"Use released APIs only" is the right rule and the hardest one for a model, because its training data is full of classic ABAP: function modules, direct table reads, CALL TRANSACTION. Make the rule operational. In ZCMC_CLOUD the language version enforces it for you: using an unreleased object is a syntax error, so activation fails and Claude sees why. In classic packages such as ZCMC_SD the same code compiles, so the rule needs teeth elsewhere: Contoso's ATC variant ZCMC_CLASSIC_DEV, the monthly ZCMC_CLEAN_CORE classification run, and a reviewer who asks where each SAP object came from. Tell the agent what to do when no released API exists: stop and say so. An agent told never to fail will invent something.
Path-scoped rules for abapGit files
On Route B, Claude edits serialized files. Rules that matter only for some files can live in .claude/rules/ with a paths list in YAML frontmatter, for example src/**/*.clas.testclasses.abap for test-class rules (RISK LEVEL HARMLESS, DURATION SHORT, test doubles instead of database reads). They load when Claude uses Read, Write or Edit on a matching file. They don't load when Claude reads source through abap_read_file, because no local file matches. Keep every rule the MCP route needs in CLAUDE.md itself.
| Rule in CLAUDE.md | Where it is enforced instead |
|---|---|
| Never touch CMQ or CMP | No destinations on the laptop; agent users exist in CMD only |
| Only package ZCMC_CORE_AGREEMENT | ADT MCP access restrictions; S_DEVELOP in ZCMC_AGENT_DEV |
| Never release or create requests | S_TRANSPRT without activity 43; deny rule on abap_transport_create_request |
| Never request ATC exemptions | Deny rule on abap_atc_exemption_request; no approver role |
| Run ATC and ABAP Unit before done | Stop hook evidence gate; reviewer reruns in ADT |
What would you do?
After two months, Contoso's CLAUDE.md has grown to 600 lines: the team pasted in SAP's Clean ABAP style guide, every RAP how-to they found and a list of past incidents. Developers report that Claude now ignores rules it used to follow, such as running ATC. What should Kenji do?
- CLAUDE.md loads into every session; keep it under about 200 lines of specific, checkable rules.
- Import a shared AGENTS.md with @AGENTS.md so every agent gets the same ABAP rules.
- Cover scope, naming, clean core, the definition of done and how to work; tell the agent to stop rather than invent an API.
- Path-scoped rules help on abapGit files but don't load for MCP reads.
- Every important rule needs a control behind it: SAP authorization, access restriction, permission rule or hook.
Check your understanding · not graded
Lesson check
1. Contoso's repository has both AGENTS.md and CLAUDE.md. By default, what does Claude Code load?
2. Why does Contoso's CLAUDE.md tell the agent to stop when no released API fits?
3. A path-scoped rule for src/**/*.clas.testclasses.abap exists in .claude/rules/. When does it NOT load?
4. Which statement about CLAUDE.md is accurate according to Anthropic's documentation?