Decision tree
flowchart TD
Q["I want Claude to know or do something"] --> A{"Is it a fact about<br/>the project that is<br/>always relevant?"}
A -->|"Yes"| CM["<b>CLAUDE.md</b><br/>build commands, layout, gotchas"]
A -->|"No"| B{"Does it only apply to<br/>certain file types<br/>or directories?"}
B -->|"Yes"| RU["<b>.claude/rules/ with paths:</b><br/>per-language style guides"]
B -->|"No"| C{"Is it a procedure<br/>I invoke deliberately?"}
C -->|"Yes"| SK["<b>Skill</b><br/>/api-review, /release-notes"]
C -->|"No"| D{"Would doing it flood<br/>my context, or does it<br/>need restricted tools?"}
D -->|"Yes"| SA["<b>Subagent</b><br/>log triage, test analysis, read-only review"]
D -->|"No"| E{"Is it about tone or<br/>response shape on<br/>every turn?"}
E -->|"Yes"| OS["<b>Output style</b>"]
E -->|"No"| F{"Must it happen<br/>100% of the time?"}
F -->|"Yes"| HO["<b>Hook</b>"]
F -->|"No"| G{"Is it an environment<br/>variable or a<br/>structured setting?"}
G -->|"Yes"| SE["<b>settings.json</b>"]
G -->|"No"| CM2["<b>CLAUDE.md</b><br/>and accept occasional misses"]
CM --> SHARE{"Does a second repo<br/>need this too?"}
RU --> SHARE
SK --> SHARE
SA --> SHARE
HO --> SHARE
SHARE -->|"Yes"| PL["Package it as a <b>plugin</b>"]
Comparison matrix
| CLAUDE.md | Rule | Skill | Subagent | Output style | Hook | Setting | |
|---|---|---|---|---|---|---|---|
| Format | Markdown | Markdown + frontmatter | Dir + SKILL.md | Markdown + frontmatter | Markdown + frontmatter | Shell command | JSON |
| Always in context | Yes | Only if no paths: |
Description only | No | Yes (system prompt) | No | n/a |
| Own context window | No | No | No | Yes | No | n/a | n/a |
| Replaces system prompt | No | No | No | Yes | Partially | No | No |
| Can restrict tools | No | No | Per-turn only | Yes, hard | No | Yes, blocks | Yes |
| Own model | No | No | Yes | Yes | No | n/a | Yes |
| User-invocable | No | No | /name |
@name |
Via /config |
No | No |
| Deterministic | No | No | No | No | No | Yes | Yes |
| Conflict model | Additive | Additive | Shadow | Shadow | Override | Additive | Override |
The same instruction, placed five ways
It helps to see one requirement travel down the tree. Take: “error responses must use the standard envelope.”
| Placed as | What you get | What it costs |
|---|---|---|
A line in CLAUDE.md |
Claude usually complies. No enforcement, no feedback when it doesn’t | Paid on every turn of every session, including CSS work |
.claude/rules/api.md with paths: ["**/handlers/**"] |
Same compliance, but only present when editing handlers | Nearly zero when irrelevant |
A /api-review skill |
A deliberate review pass with a checklist and the diff already inlined | One description line |
A security-reviewer subagent |
A separate read-only pass that cannot “fix” things by rewriting them | Zero in your context; a second model call |
A PreToolUse hook running a linter rule |
Genuinely cannot merge a violation | A script to maintain, and a false positive risk |
None of these is the single right answer. The realistic setup uses three of them: the rule so Claude writes it correctly, the skill so you can audit deliberately, and the linter hook so the rare miss cannot ship.
Common mis-placements
| You wrote | It belongs in | Why |
|---|---|---|
A 200-line Java style guide in CLAUDE.md |
.claude/rules/java.md with paths: |
It loads during your TypeScript sessions and dilutes everything else |
“Never edit generated/” in CLAUDE.md |
permissions.deny |
Prose is a request; the edit will eventually happen |
“Always run the formatter” in CLAUDE.md |
PostToolUse hook |
Deterministic, and removes it from your prompts entirely |
A release checklist in CLAUDE.md |
A skill | You invoke it a few times a month, not every turn |
| “Be concise” repeated in every prompt | An output style | It is a system-prompt concern, not a project fact |
| “Read these 40 log files and summarise” typed inline | A subagent | The 40 files stay out of your window |
The same .claude/ tree copy-pasted into a second repo |
A plugin | The copies will drift within a quarter |
A rule of thumb for the ambiguous cases
When two mechanisms both seem defensible, pick by asking what happens when the instruction is ignored:
- Nothing much → prose. CLAUDE.md or a rule.
- You would want to catch it in review → a skill, so the check is repeatable.
- It must never reach the branch → a hook or a permission.
- The check itself is expensive to perform → a subagent, so the cost lands outside your context window.