Skip to main content
Claude Code tips · Lesson 12 of 13 · 11 min

Where to Put Instructions in Claude Code: A Decision Guide

Where to put instructions in Claude Code: CLAUDE.md, rules, skills, custom commands, hooks or auto memory. A decision table built on a real repo.

By Matthews WongReviewed on Checked against Claude Code v2.1.301

Key takeaway

Claude Code gives you several homes for a reusable instruction, and the right one depends on when Claude must see it and whether it is advice or a guarantee. Always-true facts go in CLAUDE.md, occasional procedures in a skill, must-happen rules in a hook, and what Claude learns as you work in auto memory.

You will be able to

  • Sort any instruction into CLAUDE.md, a skill, a hook or auto memory with a few questions.
  • Explain how custom commands and skills relate today, and which wins a name clash.
  • Tell what is shared through git and what stays on your machine.
Watch it work

Step through the diagram

Press Play, or step with the arrows. Every step is written out below the diagram.

One instruction, four possible homes

An instruction that is always true goes to CLAUDE.md, a procedure needed sometimes to a skill, a rule that must hold to a hook, and what Claude learns itself to auto memory.

Reviewed on 17 October 2026 · Claude Code v2.1.301

Step 1 of 6. One reusable instruction, four homes. Where it goes decides when Claude sees it, and whether it is only advice or something that always runs.

Keys: ← → step · Home / End · K play or pause

  1. One reusable instruction, four homes. Where it goes decides when Claude sees it, and whether it is only advice or something that always runs.

  2. A fact true in every session, such as a build command or a convention, belongs in CLAUDE.md. It loads at session start, so keep it short.

    Predict the next step A long release checklist matters only when you release. Where should it live? (In CLAUDE.md · In a skill · In a hook)
  3. Claude sees a skill's description each session; the full text loads when you type /name or Claude matches the task. Command files work the same way.

  4. CLAUDE.md and skills are requests Claude may weigh. A hook runs on its event whatever Claude decides, and adds no context unless it returns output.

    Predict the next step You correct Claude's test style twice and edit no file. Which home can still pick that up? (CLAUDE.md, by itself · Auto memory · A hook, by itself)
  5. Auto memory is Claude's own notebook, saved per repository on your machine. The first 200 lines or 25KB of its index load each session.

  6. Always true: CLAUDE.md. Sometimes needed: a skill. Must happen: a hook. Learned while working: auto memory. Team knowledge goes in a committed file.

How do you choose where a Claude Code instruction belongs?

Ask three questions in order. Does Claude need it in every session? Then it is context, and CLAUDE.md is the home: build commands, conventions, never-do-X rules. Does Claude need it only sometimes, for one kind of task? Then it is a skill, because a skill's description loads each session but its full content loads only when used. Must it happen every single time, with no judgement involved? Then it is a hook, which runs on its event whatever Claude decides.

Read more (2)

The docs give the same triggers from the other direction. If Claude gets a convention or command wrong twice, add it to CLAUDE.md. If you paste the same playbook into chat for the third time, make it a skill. If you want something to happen every time without asking, write a hook. And the docs state the limit plainly: CLAUDE.md is context, not enforced configuration, so for a rule that must hold, use a hook instead of a prompt instruction.

This repo shows the split. Its CLAUDE.md carries the hard rules every session needs, such as keeping the two message files on the same key tree. The long how-to for writing a post lives in a skill that loads only for blog work. The one thing that must run after every edit, the figure review, is a hook. And the rule that generated sources must not be stale is enforced by the build, which fails, rather than by a sentence anyone could skip.

Slash commands, custom commands and skills: what is the difference now?

Custom commands have been merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way, and existing command files keep working. Skills add a folder for supporting files, frontmatter that controls who invokes them, and the ability for Claude to load them automatically when relevant. The docs recommend a skill for new work. If a command file and a skill share a name, the skill wins.

Read more (2)

Two frontmatter fields decide who can call a skill. With disable-model-invocation: true, only you can run it with /name, and its description stays out of context until you do; use that for workflows with side effects. With user-invocable: false, only Claude can invoke it, and it disappears from the / menu. By default, both of you can. Built-in commands such as /memory and /status are a different thing: they ship with Claude Code, not as files you write.

So the practical choice is rarely command versus skill any more. It is skill versus CLAUDE.md. A skill's description is always in context, so write it so Claude can tell when to use it. This repo never had a .claude/commands/ folder; its procedures went straight into skills.

Where does auto memory fit next to CLAUDE.md?

They are two complementary memory systems, both loaded at the start of a conversation, and both treated as context rather than enforcement. You write CLAUDE.md, and it holds instructions and rules. Claude writes auto memory, and it holds learnings: your role and preferences, corrections you gave, project decisions it cannot derive from the code, and pointers to outside systems. Claude skips what it can read from the codebase and what your CLAUDE.md files already say.

Read more (2)

Auto memory lives in a folder per project under ~/.claude/projects, with a MEMORY.md index and one file per topic. It is machine-local: it is not committed and not shared across machines. Only the first 200 lines or 25KB of MEMORY.md load at the start; topic files are read on demand. Run /memory to browse and open the files and to toggle auto memory, which is on by default in local sessions. You can also edit or delete any note; they are plain markdown.

That makes the sharing rule simple. Knowledge your whole team needs must live in a file you commit: CLAUDE.md, a skill, or a plain note in the repo. This repo's CLAUDE.md points at a dated review file under .dev/review for exactly that reason, so any contributor and any machine sees the same list. Auto memory is for what Claude learns about you and your working style, not for the team's shared record.

How this site does it

The real config behind this lesson

Excerpts from the repository that builds and deploys this website, quoted as they are.

CLAUDE.md:105-107
1. **`messages/en.json` and `messages/id.json` must have the exact same key tree.** Missing key in either file → runtime error.
2. **No `{`, `}`, or `<` in blog `content.*` JSON values.** The merge script rejects them. Put markup in JSX; put ICU interpolation only in non-blog UI strings.
3. **Every slug in `BLOG_POSTS_STATIC` must have an entry in `BLOG_META` (and vice versa).** `assertBlogParity()` fails the build otherwise.

Always-true rules: they apply to every task in the repo, so they sit in CLAUDE.md, which loads in full each session. They are requests, though. Rule 3 is also enforced, because assertBlogParity() runs in the build and fails it; the sentence tells Claude, the build guarantees it.

.claude/skills/writing-blog-content/SKILL.md:1-4
---
name: writing-blog-content
description: House standard for writing a bilingual blog post on this site — voice, section skeleton, callout and code-block conventions, the SEO limits enforced by the validators (title 63 chars, description 140-155, 12-15 keywords ending "Matthews Wong"), citation discipline, Indonesian translation rules, and the anti-patterns that make agent-written posts read as filler. Use when drafting, editing or reviewing any blog post, article, excerpt, key takeaway, FAQ, meta description or keyword set for this repository.
---

Sometimes-needed knowledge: a skill. Only the description (and name) sits in context every session, and it ends with a trigger, Use when drafting, editing or reviewing any blog post. The long standard under the frontmatter loads when a blog task matches. No tools are listed, so it is read as knowledge, not run as a script.

.claude/settings.json:1-17
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "node \"${CLAUDE_PROJECT_DIR:-.}/scripts/review-blog-figures.mjs\" --hook 2>/dev/null || true",
            "timeout": 30,
            "statusMessage": "Checking whether the figures fit"
          }
        ]
      }
    ]
  }
}

Must-happen behavior: a hook. After every Write or Edit, the figure review runs whether or not Claude remembers. This one only advises, but the trigger is guaranteed, and it costs no context unless the script returns output.

CLAUDE.md:379-381
`HubBacklink` (in the blog `[slug]` layout) links an article back to every hub that lists
it. `.dev/review/indonesia-posts-accuracy-2026-10-12.md` tracks which posts still disagree
with current sources.

Shared memory the repo keeps itself: a note in git, referenced from CLAUDE.md. A fact like which posts still disagree with current sources changes over time and belongs to everyone, so it is committed rather than left to one machine's auto memory.

What breaks

Mistakes that cost real time

  • A must-never rule left only in CLAUDE.md

    An instruction like never edit this file in CLAUDE.md or a skill is a request, not a guarantee. If breaking it is costly, enforce it with a PreToolUse hook or a failing build check, and keep the sentence only to explain why.

  • A CLAUDE.md that keeps growing

    The docs target under 200 lines per CLAUDE.md, because longer files cost context and reduce adherence. This repo's own CLAUDE.md is over 600 lines, so treat it as a warning, not a model: its field guides for single sections are candidates to move into skills or path-scoped rules. Imports help organize a file but do not cut its context cost.

  • A vague skill description

    Claude matches your task against skill descriptions. If they are vague or overlap, it may load the wrong skill or miss the right one. Name the files, commands and phrases a request will contain, or invoke the skill yourself with /name.

  • Team knowledge stored only in auto memory

    Auto memory is machine-local. A teammate never sees it, a second laptop has its own, and everything past the first 200 lines or 25KB of MEMORY.md is not loaded at session start. If a fact must reach other people or other machines, put it in a committed file.

Where an instruction can live, and what each home guarantees
CLAUDE.mdEvery session, in fullYouYesNo, it is context
Rules in .claude/rulesEvery session, or when matching files openYouYesNo, it is context
Skill or command fileDescription always; full text when usedYouYes, if committedNo, Claude interprets it
HookOn its event, outside the chatYouYes, in a shared settings fileYes, the trigger always fires
Auto memoryFirst 200 lines or 25KB of the indexClaudeNo, machine-localNo, it is context
Try it yourself

Do it on your own machine

You need Claude Code in a scratch git repository. You will inspect what is loaded, create one skill, and watch it beat a command file with the same name.

  1. Start Claude Code and run /memory. It lets you browse and open memory files and holds the auto memory toggle. Note which files are in your repo and which are under your home folder.

    claude
    > /memory
  2. Create a manual-only skill. disable-model-invocation keeps it out of context until you type its name, and $ARGUMENTS receives what you type after it.

    mkdir -p .claude/skills/release-notes
    cat > .claude/skills/release-notes/SKILL.md <<'EOF'
    ---
    name: release-notes
    description: Draft release notes from recent commits
    disable-model-invocation: true
    ---
    
    Summarize the commits since $ARGUMENTS as release notes, grouped by theme.
    EOF
  3. Create a command file with the same name and different text. Then restart Claude Code and run /release-notes v1.0. The skill's text should be the one that runs, because a skill beats a command file.

    mkdir -p .claude/commands
    echo 'List the commits since $ARGUMENTS as a plain bullet list.' > .claude/commands/release-notes.md
    
    claude
    > /release-notes v1.0
  4. Sort five instructions of your own with the three questions: always needed, sometimes needed, must happen. Write each one's home next to it, and commit only the ones that are team knowledge.

Quick quiz

Three questions before you move on

Pick an answer to see why it is right or wrong. Nothing is saved or graded, so guess freely.

  1. 1.A 40-step release procedure matters only on release day. Where does it belong?
  2. 2.Both .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md exist. You type /deploy. Which one runs?
  3. 3.A teammate asks why Claude never knows the preferences it learned on your laptop. What is the reason?
Think it through

Answer in your head, then check

  1. 1.Which three questions sort an instruction into its home?Show the answer

    Answer:Does Claude need it every session (CLAUDE.md)? Only sometimes, for one kind of task (a skill)? Must it happen every time with no judgement (a hook)? What Claude learns on its own as you work goes to auto memory.

  2. 2.Why is a hook, not CLAUDE.md, the home for a rule that must never be broken?Show the answer

    Answer:CLAUDE.md is context that Claude tries to follow, not enforced configuration. A hook fires on its event whatever Claude decides, and a PreToolUse hook can block the action.

  3. 3.What does disable-model-invocation: true change about a skill?Show the answer

    Answer:Claude no longer invokes it on its own, and its description stays out of context. Only you can run it with /name, which suits workflows with side effects.

Go deeper

Related deep dives on this site