Cheap Until Called

A close read of Claude Code Skills — reusable instructions whose descriptions stay lightweight, while their full content loads only when invoked.

You  invoke with /name Claude  invokes by matching intent 13 sections
01Why it exists

The CLAUDE.md Problem

CLAUDE.md enters the session context whether the current task needs it or not. A skill keeps its full instructions deferred until invocation.

CLAUDE.md — remains in the session context deployment checklist, API conventions, style guide… turn 1 turn 2 turn 3 the same instructions occupy context, even when unrelated a skill — full content deferred small metadata footprint description listed at startup* full body, on trigger turn where it's actually relevant
Move reusable procedures into skills; keep always-relevant project facts in CLAUDE.md. *Manual-only skills hide their description until you invoke them.
02Anatomy

One Folder, One Required File

A skill is a directory. SKILL.md is the only file it needs — frontmatter on top, instructions below, extra files alongside.

my-skill/
my-skill/
├── SKILL.md        # required — overview + nav
├── reference.md    # read only when needed
├── examples.md     # read only when needed
└── scripts/
    └── helper.py   # usually executed for output
SKILL.md
---
name: commit
description: Stage and commit changes.
  Use when the user asks to commit.
allowed-tools: Bash(git add *)
---

# instructions, third person,
# under 500 lines
1. Review the diff
2. Stage relevant files
3. Write a commit message
All frontmatter fields are optional. description is recommended; without it, Claude Code uses the first markdown paragraph. A script can also be read explicitly when its implementation matters.
03The core mechanic

Three Levels of Loading

This is the whole point of a skill: content arrives in layers, and each layer only loads when the one before it justified it.

LevelWhenCostContent
1 · ListingAt startup, when model-invocablesmall, variabledescription + optional when_to_use
2 · InstructionsWhen the skill is invokedfull rendered bodyThe rendered SKILL.md content enters as one message
3 · ResourcesOnly when Claude reads or runs themdeferred until accessReferences, examples, assets, and script output
The 5,000-token figure is a post-compaction retention limit, not an invocation limit. Keep SKILL.md concise; the documentation recommends fewer than 500 lines.
04The matching signal

What Claude Actually Reads

For model-invocable skills, Claude sees the listing text — description plus optional when_to_use — before it sees the body.

weak

"Handles PDFs"

Says what, not when. Claude has no signal for which requests should trigger it.

strong

"Extract text and tables from PDFs, fill forms, merge documents. Use when working with PDFs or the user mentions PDF extraction."

Key use case first, then explicit trigger language — both the what and the when.

The combined description + when_to_use text is truncated at 1,536 characters in the skill listing — front-load the part that actually distinguishes this skill from the others in context.
05Invocation

Two Ways In, One Load

By default both paths are open at once — you can always type the name, and Claude can always decide the description matches.

You type /skill-name explicit, deliberate Claude matches description autonomous, contextual Rendered SKILL.md enters as one message Claude proceeds with the task
Arguments work through $ARGUMENTS, positional $0/$1, or named placeholders declared by arguments. Up to six inline skills can stack; expansion stops at the first token that is not an inline user-invocable skill.
06Gating a skill

Not Every Skill Wants Both Doors Open

Two booleans narrow the default "either of us can trigger this" down to exactly one side.

FrontmatterYou invokeClaude invokesUse it for
(default)yesyesMost skills — let either side reach for it
disable-model-invocation: trueyesnoSide-effecting actions — /deploy, /commit. You decide the timing, not "the code looks ready."
user-invocable: falsenoyesBackground knowledge with nothing for a person to run — legacy-system-context
disable-model-invocation: true also removes the description from Claude's startup context. Combining it with user-invocable: false leaves no normal invocation path.
07Scoping

Four Primary Locations, One Resolution Order

Location defines scope. Name collisions are resolved across levels; plugins remain namespaced alongside local skills.

enterprise

Managed settings

Every user in the org. Overrides everything else with the same name.

personal

~/.claude/skills/

All of your projects. Overrides a project skill of the same name.

project

.claude/skills/

The project and parent directories to the repo root; nested variants appear on demand.

plugin

plugin/skills/

Namespaced plugin:skill — never conflicts, loads alongside.

A skill also beats a same-named .claude/commands/ file, and any local skill beats one synced from your claude.ai account. Nested apps/web/.claude/skills/ skills load only once Claude touches a file in that subdirectory, and surface under a directory-qualified name if they clash with the root.
08Permissions

A Grant for This Turn, Not This Session

allowed-tools and disallowed-tools both apply only for the turn that invokes the skill — then they clear.

allowed-tools — pre-approve
---
name: commit
disable-model-invocation: true
allowed-tools: Bash(git add *)
  Bash(git commit *)
---
disallowed-tools — remove
---
name: background-loop
disallowed-tools: AskUserQuestion
---
# keeps an autonomous skill from
# ever stopping to ask a person
allowed-tools pre-approves listed tools but does not restrict unlisted ones. disallowed-tools removes listed tools for the turn. Neither replaces deny rules, sandboxing, or deterministic hooks. Review repository skills: checked-in grants apply even before workspace trust.
09Lifecycle

Invoked Once, Retained Across Turns

Rendered skill content remains in the conversation. Claude Code does not automatically re-read the file on each later turn.

skill loads, turn 3 rendered content persists across later turns context fills → auto-compaction summarizes the conversation most recent skill: first 5,000 tokens kept next most recent: kept if budget allows older skills: can drop entirely
After compaction, the latest invocation of each skill can be reattached: first 5,000 tokens each, within a shared 25,000-token budget, newest first. Identical reinvocation adds only a short note; changed arguments or dynamic output append a fresh rendered copy.
10Dynamic injection

Grounding a Skill in Live Data

A line starting with ! runs before Claude ever sees the skill — its output replaces the placeholder, the command itself never does.

SKILL.md
---
description: Summarize uncommitted
  changes and flag risks.
---

## Current changes
!`git diff HEAD`

## Instructions
Summarize in 2-3 bullets, then
list risks …
what Claude receives
# the actual diff text,
# already inlined —
# not the git command

diff --git a/app.py b/app.py
+  def validate(x):
+      return x is not None
…
A failed or non-approved command aborts the whole invocation; Claude never sees the skill content. Commands use the shell tool's timeout and never pause for permission. Locally synced claude.ai skills do not execute these commands on your machine.
11context: fork

Fork the Task, Not the Conversation

With context: fork, the skill body becomes the subagent's task. The parent conversation history is not passed into that isolated context.

Inline skill shares your conversation, no isolation context: fork isolated subagent; background by default* agent: Explore / Plan /general-purpose / custom background: falsewaits in this turn instead
CLAUDE.md normally still loads; Explore and Plan are exceptions. *CLI non-interactive mode, the Agent SDK, disabled background tasks, scheduled tasks, and overlapping same-skill runs wait in the foreground. Background forks use fewer tools and sit outside /rewind checkpoints.
12The model

Described Cheaply, Loaded Precisely

Metadata small listing, when visible Instructions full rendered body, on invocation Resources deferred until read or run

A skill is a bet that most turns will not need its full procedure: expose a precise matching signal, load instructions only on invocation, and defer supporting resources until the task actually needs them.

01 / 13
use ← → or click the edges to navigate