← All guides
ai-toolsreality-check

Claude Code Skills: What They Are, How to Use Them, and the Minimal Memory Setup We Run

What is Claude Code skills and how to use it? The four-skill memory harness we run in production, file by file: where Claude Code skills are stored, whether Claude uses them automatically, the exact SKILL.md files, and the settings.json hook that makes state survive restarts. Plus two mechanisms people keep configuring that do not exist, and how skills compare to hooks, slash commands, and CLAUDE.md.

2026-07-19 · 15 min read
Claude Code Skills: What They Are, How to Use Them, and the Minimal Memory Setup We Run

The same question keeps appearing on Reddit in different clothes: how do you make Claude Code remember what it was doing? Sessions end, context fills up, and the agent that confidently refactored your code yesterday greets you today with no idea the refactor happened. People ask for a setup that fixes this with minimal moving parts.

We have one. Four skills and a directory of markdown files run the publishing side of this site, and the setup has survived several weeks of daily use. Every file is in this post, and every mechanism it relies on is checked against the official Claude Code documentation, because configs for this tool that circulate online reliably include a few pieces Claude Code does not actually have. Those get flagged along the way.

What is Claude Code skills and how does it work

A skill is a folder with a SKILL.md file inside. The file has YAML frontmatter that tells Claude when to use it, and a markdown body with the instructions to follow. That is the whole format:

---
description: Saves work state between turns and sessions.
  Use when completing a task step, making progress on a
  multi-step goal, or before any interruption.
---

## Process

Before finishing any significant step:

1. Update .claude/state/CURRENT_STATE.md with current
   task, progress, artifacts, and context to continue.
2. Commit the change.

The economics are the point. Skill descriptions sit in the model's context all the time, so Claude knows what is available. The body loads only when the skill is invoked. A 400-line procedure costs you a one-line description until the moment it is needed. This is why skills beat stuffing everything into CLAUDE.md, which is loaded in full every session: the docs cap each skill's listing entry at 1,536 characters and budget about 1% of the context window for the whole listing, while bodies stay on disk until called.

Skills follow the Agent Skills open standard, so the same folder works in other tools that adopted it. Claude Code adds its own extensions on top: invocation control, running a skill in a subagent, and shell preprocessing.

Where are Claude Code skills stored

Four places, and the location decides who gets the skill:

LocationPathApplies to
Personal~/.claude/skills/<name>/SKILL.mdall your projects
Project.claude/skills/<name>/SKILL.mdthis repo only
Plugin<plugin>/skills/<name>/SKILL.mdwhere the plugin is enabled
Enterprisemanaged settingsyour whole org

When names collide, enterprise beats personal and personal beats project. Two details from the docs that most tutorials get wrong: the command you type comes from the directory name, not the frontmatter, and the frontmatter name field is only a display label. .claude/skills/deploy-staging/SKILL.md becomes /deploy-staging no matter what name says. Also, custom slash 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.

For a memory harness, project scope is the right answer. The state the skills manage lives in the repo, so the skills that manage it should travel with the repo. Commit .claude/skills/ and every clone gets the same behavior.

Does Claude Code use skills automatically

Yes, and this is the mechanism the whole setup depends on. Claude reads the description of every available skill and loads one when the conversation matches it. You can also invoke any skill by typing /skill-name. Two frontmatter fields adjust this:

  • disable-model-invocation: true makes a skill manual-only. Use it for anything with side effects, like deploy scripts. Claude deciding on its own that your code looks ready to ship is not a feature.
  • user-invocable: false hides a skill from the / menu. Use it for background knowledge that is not an action.

The default, with neither field set, is that both you and Claude can trigger the skill. For memory skills the default is what you want, with one caveat we will get to: "can invoke automatically" does not mean "will invoke reliably."

The four skills that run this site

Our harness is four project-level skills plus a .claude/state/ directory they read and write. Nothing else.

.claude/
├── skills/
│   ├── state-management/SKILL.md
│   ├── goal-tracking/SKILL.md
│   ├── context-preservation/SKILL.md
│   └── task-orchestration/SKILL.md
└── state/
    ├── CURRENT_STATE.md
    ├── GOAL.md
    ├── CONTEXT_SUMMARY.md
    └── {task}_TODO.md

state-management is the workhorse. After any significant step it updates CURRENT_STATE.md with the current task, a progress checklist, the files touched, and the context needed to continue. The full file is in the panel on the right. The "next step written down explicitly" checkbox is the single highest-value line in the whole setup: a fresh session that reads a state file ending in "next: generate the cover image, then commit" starts working instead of asking what you meant.

goal-tracking keeps one global goal in GOAL.md with success criteria and a dated progress log. Its job is drift control. Agents are enthusiastic; give one a bug to fix and it may come back having also reorganized your imports. A goal file the agent checks before switching tasks gives it a reason to ask "does this serve the goal?" instead of following whatever looked interesting.

context-preservation writes key decisions and constraints to CONTEXT_SUMMARY.md when a conversation gets long or before switching topics. Claude Code compacts context automatically when it fills up, and its own summary decides what survives. A decisions file you control is insurance: the reasoning behind "we rejected approach X because Y" survives even when the conversation that produced it does not.

task-orchestration creates a TODO file for any task over three steps: decomposition, dependencies, current status. When a session dies mid-task, the TODO file is the difference between resuming and restarting.

The last piece is CLAUDE.md. This is the part most write-ups skip, and without it the whole thing is decorative. Skills give the agent the ability to save state; standing instructions give it the habit. Our CLAUDE.md has a short mandatory-practices section: always save state after significant steps, check the goal before switching tasks, keep a TODO for anything over three steps, and update state before ending a session. The exact block is in the panel. In our experience the difference between having and not having those lines is the difference between a state file updated most sessions and a state file updated never.

Two mechanisms people keep configuring that do not exist

Setup guides for Claude Code, including most AI-generated ones, tend to include two pieces of plumbing the tool does not have. Both fail silently, so they are worth naming before the part that does work.

Claude Code does not execute scripts from .claude/hooks/. A recipe you will see everywhere is .claude/hooks/on_session_start.sh and on_session_end.sh, shell scripts meant to print the previous state at startup and auto-commit it at shutdown. The naming is plausible and several other tools work exactly this way, but in Claude Code a bare script in that directory is just a file. There is no error and no warning: your session-end auto-commit simply never runs, and you find out weeks later when the state file turns out to be stale. Hooks themselves are real, but every hook must be registered in a settings JSON file; the working version is in the next section.

There is no built-in /todo command. Claude Code has an internal todo mechanism the agent uses on its own, and a /tasks command for background work, but an instruction like "track steps with the built-in /todo" sends the agent chasing a command that is not there. Keep the task list in a file the agent writes, which is what the task-orchestration skill does.

Two smaller landmines from the same family: session ID substitution in skill files is real but the syntax is ${CLAUDE_SESSION_ID} with the dollar sign, and disable-model-invocation: false is a real field wasted as a line, since false is already the default.

The hook that makes state survive restarts

Hooks are registered in .claude/settings.json under a hooks key, keyed by lifecycle event. SessionStart and SessionEnd are real events, and anything a SessionStart hook prints to stdout is added to the model's context:

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "cat .claude/state/CURRENT_STATE.md 2>/dev/null || echo 'No previous state.'"
          }
        ]
      }
    ]
  }
}

That one hook makes every session start with the previous session's state already in context, and it happens deterministically rather than whenever the model remembers to look. A SessionEnd hook set up the same way can run the state auto-commit. We ran without hooks for weeks, on CLAUDE.md instructions alone, and that was enough to test whether the harness earned its keep; the hook is the hardening step once you know it does.

Claude Code skills vs hooks vs slash commands vs CLAUDE.md

These four mechanisms get conflated constantly. The split that holds up in the docs and in daily use:

  • CLAUDE.md is for facts and standing rules: loaded in full every session, always in context, always costing tokens. Short rules that must always apply belong here. Our mandatory-practices block is five lines for exactly this reason.
  • Skills are for procedures: loaded on demand, cheap until invoked. The docs' own guidance is to create a skill when a section of CLAUDE.md has grown into a procedure rather than a fact.
  • Slash commands are not a separate system anymore. .claude/commands/ files still work, but they are skills with fewer features now.
  • Hooks are for guarantees. Skills and CLAUDE.md are suggestions to a model; hooks are code that runs on events whether the model feels like it or not. Anything that must happen every time belongs in a hook.

The honest version of the tradeoff: our harness is built almost entirely from the "suggestions" layers, and that is a deliberate starting point, not the endpoint. Start with suggestions because they are five files and zero configuration; add hook guarantees where the suggestions demonstrably fail.

Where it still fails

Receipts cut both ways, so: the model does forget. With the skills installed and CLAUDE.md wired, sessions still sometimes end without a state update, usually when a task finished quickly or the conversation wandered. The skill descriptions say "before any interruption," but a session that dies from a closed laptop lid does not announce itself. That specific failure is what the SessionEnd hook exists for.

The other failure mode is stale state. A state file the agent wrote three sessions ago describes a project that has moved on, and an agent that trusts it confidently resumes the wrong work. Our fix is boring: the state update instruction says to rewrite the "next step" line every time, and we treat the state file as the agent's scratchpad, reviewed in git diffs like any other change. If a state line looks wrong, it gets deleted in the same commit that fixes the code.

What we have not needed: session IDs in state files, auto-generated summaries of every conversation, or a state file per session. One current-state file, one goal file, one decisions file, and TODO files that get deleted when tasks finish. Memory harnesses rarely fail from having too little structure. They fail when the structure stops being maintained, so every file has to earn its upkeep.

FAQ

Does Claude Code have skills? Yes. They are folders with a SKILL.md file, stored per-project in .claude/skills/ or per-user in ~/.claude/skills/, and they follow the Agent Skills open standard. Claude Code also ships bundled skills like /code-review and /debug.

Does Claude Code use skills automatically? Yes, based on the description field in the skill's frontmatter, unless the skill sets disable-model-invocation: true. You can always invoke one manually with /skill-name. Automatic invocation is real but not guaranteed; pair skills with CLAUDE.md instructions for behavior you need often, and hooks for behavior you need always.

Where is the Claude Code skills directory? .claude/skills/ in your project for repo-scoped skills, ~/.claude/skills/ in your home directory for personal skills that apply everywhere. The directory name of each skill becomes its slash command.

What is the minimal setup worth copying? Four project skills (state-management, goal-tracking, context-preservation, task-orchestration), a .claude/state/ directory they maintain, and a five-line mandatory-practices block in CLAUDE.md. The prompt panel of this post has the state-management file, a bootstrap prompt that builds the other three, the CLAUDE.md block, and the optional SessionStart hook that prints the state file into context at startup.

Do Claude Code skills reduce token usage? Compared to putting the same instructions in CLAUDE.md, yes. CLAUDE.md loads in full every session; a skill costs its one-line description until invoked, and the body loads only when needed. Moving procedures out of CLAUDE.md into skills is the single easiest context-budget win in this setup, and it is the docs' own recommendation for CLAUDE.md sections that have grown into procedures.