← Back to the list

Claude Code Skills Primer — Build Your Own Commands with SKILL.md

claude-codeindie-dev

An overview of Claude Code "skills." A skill is a folder with instructions in a SKILL.md, and it becomes a homemade command callable as /skill-name. The older "custom slash commands" (.claude/commands/*.md) were merged into skills (the old format still works).

What is a skill?

  • Write instructions in a SKILL.md and it can be invoked by you as /name or loaded automatically by Claude when a related task comes up
  • The difference from CLAUDE.md is load timing. CLAUDE.md enters the context in full every session, while a skill keeps only its description resident and loads its body on use. Long procedures are cheaper as skills
  • Rule of thumb: "facts and conventions" go in CLAUDE.md, "procedures and checklists" go in skills. Pasting the same instructions into chat twice is the signal to make a skill

Where skills live

Scope Path Applies to
Personal ~/.claude/skills/NAME/SKILL.md All of your projects
Project .claude/skills/NAME/SKILL.md That repository only (commit it to share)
Plugin PLUGIN/skills/NAME/SKILL.md Wherever the plugin is enabled
  • On name collisions, personal beats project. Bundled skills (/code-review etc.) can also be overridden by a same-named skill of yours
  • In a monorepo, subdirectory .claude/skills/ folders are auto-discovered too (they get directory-qualified names like apps/web:deploy)
  • Adding or editing files takes effect immediately, no session restart

Writing SKILL.md

---
name: deploy
description: Deploy the app to production. Use when asked to deploy or release
disable-model-invocation: true
---

Deployment steps:

1. Run the tests
2. Build
3. Push to the deployment target

All frontmatter is optional (though you should write description — Claude uses it to decide on automatic invocation). The main fields:

Field Role
description What the skill does + when to use it. Input for auto-invocation decisions
disable-model-invocation: true Forbids automatic invocation by Claude. Only you can call it (essential for side-effecting things like deploy/commit)
user-invocable: false Hidden from the / menu. Background knowledge only Claude uses
argument-hint Argument hint shown during completion (e.g. [PR number])
allowed-tools Tools that run without approval while this skill executes (e.g. Bash(git add *))
context: fork Run as a subagent in a separate context
model / effort Override the model / thinking depth only while this skill runs
paths Auto-invoke only when files matching the glob are touched

Who can invoke what

Setting You Claude Use case
Default General procedures and knowledge
disable-model-invocation: true × Side-effecting operations like /commit /deploy
user-invocable: false × Background knowledge, e.g. legacy-spec notes

Arguments and dynamic context

  • $ARGUMENTS = all invocation arguments. $0 $1 reference them individually; with arguments: [issue, branch] in frontmatter you get named ones like $issue
  • Writing !`command` in the body means the command runs before Claude reads the skill and its output replaces the placeholder — dynamic context injection
    • Example: embed !`git diff HEAD` and the skill always starts with the latest diff already in its body
  • ${CLAUDE_SKILL_DIR} references the skill's own directory, ${CLAUDE_PROJECT_DIR} the project root

Companion files

A skill is a folder, so files other than SKILL.md can live there too.

my-skill/
├── SKILL.md        ← the core (required; keep under ~500 lines)
├── reference.md    ← detailed material (read only when needed)
└── scripts/
    └── helper.js   ← a script Claude executes

Reference them from SKILL.md ("see reference.md for details") and Claude reads them only when necessary. The thinner the main body, the better the token efficiency.

Real examples from this repo

This monorepo keeps the following under .claude/skills/, all operated as "invoked by me" (the disable-model-invocation style):

  • /commit — commit message conventions (Conventional Commits + Japanese summaries) and the push procedure
  • /blog-article — the procedure for generating app-introduction articles in 6 languages (screenshot commands included)
  • /x-announce — demo GIF capture and post drafting for X announcements (with a character-count script bundled)

Turning "the procedure I explained every time" into a skill reduces the request to a single /blog-article. Bundling scripts is the killer feature: fixed processing like GIF encoding and character-count validation is frozen into .js files inside the skill.

Summary

  • A skill = a homemade command that exists by placing a SKILL.md. Its body loads only on use, so it is cheaper than CLAUDE.md
  • Side-effecting procedures get disable-model-invocation: true to stay you-only
  • The practical power moves: !`command` dynamic injection and bundled helper scripts
  • Details in the official docs