---
title: "06 — Skills — Teaching the Loop Repeatable Workflows On Demand"
uid: skills
tags: ["skill-md", "roadmap:claude-code", "automation", "workflows", "skills", "claude-code"]
excerpt: "A skill is a folder of expert knowledge Claude loads only when the task matches its description — lazy loading so it never bloats context by default."
date: 2026-08-13T03:28:22+0000
source: https://www.aveshina.my.id/en/blog/skills
---

"Just saved prompts" was my read on skills, and it missed the loading mechanism that makes them work. The distinction that stuck: **a skill is a folder of expert knowledge and repeatable workflow that Claude loads dynamically into context only when the task requires it — not a script that always runs.** [1] The whole point is lazy loading: the skill sits dormant until its description matches what I'm doing, and only then does it enter the context window.

The framing that clicked is the contrast with CLAUDE.md. The memory file loads at _every_ launch, so it has to stay short. A skill loads _on demand_, so it can be deep — a full deployment runbook, a security-audit procedure, a multi-step content workflow — without taxing sessions that don't need it [1][2]. That separation is what makes the system scale: persistent rules in the memory file, deep procedural knowledge in skills, and never the two bloating each other.

## The anatomy of a skill

Mechanically, a skill is a folder inside .claude/skills/ anchored by a SKILL.md file [1]. The file has two parts:

- **YAML frontmatter** — at minimum a unique name and a detailed description. This frontmatter is what Claude reads to decide whether the skill is relevant; the description is the semantic trigger.
- **A body of specific instructions** — the actual workflow: which tools to call, in what order, against what inputs.

The detail that made it click: **Claude never reads the body until the description matches.** The frontmatter is the index; the body is the payload. A poorly-written description means the skill never fires (or fires when it shouldn't); a well-written one means the right deep instructions show up exactly when needed. The roadmap is blunt that the description is the leverage point — it should use specific keywords that help Claude identify when to activate the expert instructions without bloating every conversation [2].

```figure
<svg viewBox="0 0 740 280" xmlns="http://www.w3.org/2000/svg" class="my-6 w-full max-w-2xl" role="img" aria-label="Skill discovery and lazy loading. Three skill folders on the left, each with a YAML frontmatter description tag: deploy, security-audit, create-blog. A task prompt 'deploy the blog' is matched against the descriptions; only the deploy folder lights up and its SKILL.md body flows into the context window on the right. The other two folders stay dim and unloaded.">
  <defs>
    <marker id="sk1" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
      <path d="M0,0 L10,5 L0,10 z" fill="#64748b"/>
    </marker>
  </defs>
  <g font-family="ui-sans-serif, system-ui, sans-serif" text-rendering="geometricPrecision">
    <!-- task -->
    <rect x="270" y="20" width="200" height="34" rx="8" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.5"/>
    <text x="370" y="42" font-size="11" font-family="ui-monospace,monospace" fill="#422006" text-anchor="middle">prompt: "deploy the blog"</text>

    <!-- skills -->
    <rect x="30" y="90" width="170" height="56" rx="8" fill="#dcfce7" stroke="#16a34a" stroke-width="1.8"/>
    <text x="115" y="110" font-size="11" font-weight="700" fill="#052e16" text-anchor="middle">deploy/</text>
    <text x="115" y="126" font-size="9" font-family="ui-monospace,monospace" fill="#052e16" text-anchor="middle">desc: "ship to prod"</text>
    <text x="115" y="139" font-size="9" fill="#16a34a" text-anchor="middle">✓ matches — loads</text>

    <rect x="30" y="160" width="170" height="56" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.2" opacity="0.6"/>
    <text x="115" y="180" font-size="11" font-weight="700" fill="#475569" text-anchor="middle">security-audit/</text>
    <text x="115" y="196" font-size="9" font-family="ui-monospace,monospace" fill="#475569" text-anchor="middle">desc: "scan vulns"</text>
    <text x="115" y="209" font-size="9" fill="#94a3b8" text-anchor="middle">dim — not loaded</text>

    <rect x="30" y="230" width="170" height="40" rx="8" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.2" opacity="0.6"/>
    <text x="115" y="250" font-size="11" font-weight="700" fill="#475569" text-anchor="middle">create-blog/</text>
    <text x="115" y="263" font-size="9" fill="#94a3b8" text-anchor="middle">dim — not loaded</text>

    <!-- context window -->
    <rect x="540" y="90" width="170" height="180" rx="8" fill="#e0e7ff" stroke="#6366f1" stroke-width="1.5"/>
    <text x="625" y="110" font-size="11" font-weight="700" fill="#1e1b4b" text-anchor="middle">context window</text>
    <text x="625" y="126" font-size="9" fill="#475569" text-anchor="middle">only deploy/SKILL.md</text>
    <text x="625" y="142" font-size="9" fill="#475569" text-anchor="middle">body enters here</text>

    <!-- match arrow -->
    <path d="M250,37 C200,60 160,75 120,88" fill="none" stroke="#16a34a" stroke-width="1.5" marker-end="url(#sk1)"/>
    <path d="M200,118 C400,118 480,118 538,140" fill="none" stroke="#16a34a" stroke-width="1.5" marker-end="url(#sk1)"/>
  </g>
</svg>
```

## Creating a custom skill

The recipe from the roadmap is concrete [3]: establish a folder in .claude/skills/ containing a SKILL.md. The frontmatter block holds the unique name and the detailed description (the trigger), and the body holds the logic. Two optional knobs matter:

- **disable-model-invocation: true** — flips the skill from autonomous to manual. With this set, Claude won't auto-load it on a description match; it only runs when I trigger it explicitly via a slash command. This is the right choice for workflows with non-negotiable side effects — a deploy, a destructive migration — where I want determinism, not a model's judgement call [2].
- **Argument placeholders like $ARGUMENTS** — make the skill reusable across different files. A "create-blog" skill can take a topic as an argument instead of being hard-coded.

The body should be a narrow, modular workflow rather than a "Swiss Army Knife" skill. If I have a deployment procedure and a security audit, those are two skills, not one — because their descriptions need to match different tasks precisely. And skills belong in the project's .claude/skills/ so they're version-controlled and shared with the team [2].

## Skill best practices

The roadmap collects the discipline into a short list that matches what I've seen work [2]:

- **Optimize for discoverability.** The description is a semantic trigger — use specific keywords. Vague descriptions mean the skill never fires.
- **Lazy-load.** The whole architecture exists to keep idle skills out of context. Respect it: don't dump every skill into the memory file.
- **Keep skills modular and narrow.** One workflow per skill. A "do everything" skill defeats discovery.
- **Use disable-model-invocation for side effects.** Deploys, migrations, anything destructive — make it manual.
- **Make instructions deterministic.** Provide step-by-step tool sequences so Claude follows the project's golden path for complex tasks, rather than improvising.
- **Version-control them.** .claude/skills/ goes in git so the whole team shares the same workflows.

## How I use this

The habit these notes left me with is a simple test for when something becomes a skill: *do I do this workflow more than twice, and does it have more than three steps?* If yes, it earns a folder. The deploy runbook, the blog-creation procedure, the security scan — each lives in its own skill with a precise description and a deterministic body. Side-effect-heavy ones get disable-model-invocation: true. And I resist the urge to put rules in skills — rules go in CLAUDE.md because they apply to every session; skills are for procedures that apply to specific tasks on demand.

## References

[1] Anthropic, "Extend Claude with skills," Claude Code Docs, 2025. [Online]. Available: [https://code.claude.com/docs/en/skills](https://code.claude.com/docs/en/skills)

[2] Anthropic, "The Complete Guide to Building Skills for Claude," Anthropic Resources, 2025. [Online]. Available: [https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf?hsLang=en](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf?hsLang=en)

[3] Anthropic, "How to create custom Skills," Claude Support, 2025. [Online]. Available: [https://support.claude.com/en/articles/12512198-how-to-create-custom-skills](https://support.claude.com/en/articles/12512198-how-to-create-custom-skills)

```quiz
Q: What is the core difference between CLAUDE.md and a skill?
- CLAUDE.md is for rules; skills are for scripts — otherwise identical
- CLAUDE.md loads at every launch (must stay short); a skill loads on demand (can be deep)
correct: 1
explain: The memory file is persistent and always loaded, so it stays concise. A skill is lazy-loaded only when its description matches, so it can hold deep procedural knowledge without taxing other sessions.

Q: What part of a skill does Claude read to decide whether to load it?
- The entire SKILL.md body
- The YAML frontmatter description (the semantic trigger)
correct: 1
explain: The frontmatter is the index; the body is the payload. Claude matches the task against the description and only reads the body when relevant, keeping idle skills out of context.

Q: What does `disable-model-invocation: true` do?
- Disables the skill entirely
- Forces the skill to run only when manually triggered (via slash command), not auto-loaded on a match
correct: 1
explain: This flag is for workflows with non-negotiable side effects (deploys, migrations). It trades autonomous discovery for determinism — the skill only runs when you explicitly invoke it.

Q: A "do everything" deployment-plus-security-plus-blog skill is a bad idea because…
- it's too long to fit in a file
- it defeats discoverability — one skill should match one workflow so the description triggers precisely
correct: 1
explain: Narrow, modular skills let the description match the right task. A Swiss-Army-Knife skill fires on everything and pulls in irrelevant instructions.

Q: Where should skills live so the whole team shares them?
- in your home directory, outside git
- in the project's .claude/skills/ directory, version-controlled
correct: 1
explain: .claude/skills/ goes in git so every teammate gets the same workflows. Personal one-offs can live globally, but shared procedures belong in the repo.
```
