Claude Code

Turn prompts you repeat into your own Claude Code commands

A skill is a small Markdown file that becomes a /command of your own. Write one for the checklist you keep pasting, include current data such as your git diff, and choose whether Claude may use it on its own.

Checked against the official documentation on

On this page11 sections
  1. 01Skills and custom commands are the same thing now
  2. 02Where skills live
  3. 03Your first skill
  4. 04Let Claude find it on its own
  5. 05Decide who may run it
  6. 06Pass arguments
  7. 07Feed a skill the output of commands
  8. 08Skills from someone else's repository
  9. 09Keep skills short
  10. 10When a skill does not show up
  11. 11Sources

If you keep typing the same instructions ("summarize my changes and flag anything risky", "commit this with a proper message", "check the disk and memory"), you can turn each one into a command of your own. Type /summarize-changes and Claude gets the full instructions, with the data it needs already filled in.

In Claude Code these are called skills. This guide shows how to write one, how to pass it arguments and the output of commands, how to decide who may run it, and the safety points to check before you use skills from someone else's repository.

Skills and custom commands are the same thing now

Older guides talk about custom commands in .claude/commands/. Those 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. Your old command files keep working.

Skills add a few things on top: a folder for extra files, settings that control whether Claude may run the skill on its own, and the ability for Claude to pick a skill up automatically when it fits what you asked.

Where skills live

Each skill is a folder with a SKILL.md file inside. Where you put the folder decides where the skill works:

  • ~/.claude/skills/<name>/SKILL.md: a personal skill, in every project on your machine.
  • .claude/skills/<name>/SKILL.md in a project: in that project only. Commit it and everyone working on the project gets it.

The folder name becomes the command. .claude/skills/summarize-changes/SKILL.md gives you /summarize-changes. If a personal skill and a project skill have the same name, the personal one runs.

Your first skill

This skill summarizes your uncommitted changes and points out anything risky. It is adapted from the example in the official documentation.

  1. Create the folder

    Shell · your user
    mkdir -p .claude/skills/summarize-changes
  2. Write SKILL.md

    .claude/skills/summarize-changes/SKILL.md
    ---
    description: Summarizes uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff.
    ---
    
    ## Current changes
    
    !`git diff HEAD`
    
    ## Instructions
    
    Summarize the changes above in two or three bullet points, then list any risks you notice, such as hardcoded passwords, changed limits or missing error handling. If the diff is empty, say there are no uncommitted changes.
  3. Run it

    Claude Code
    /summarize-changes

The file has two parts:

  • The frontmatter, between the --- lines. Here it holds only the description, which tells Claude what the skill is for and when to use it.
  • The body, the instructions Claude follows when the skill runs.

The line !`git diff HEAD` is not an instruction for Claude. Claude Code runs the command first and puts its output in that spot, so Claude receives your actual diff, not a request to go and get it.

In our test, a change that raised a limit from 10 to 1000 and added a password to a PHP file came back as two bullet points, followed by risks that included "Hardcoded password" and "Limit raised 100×".

Let Claude find it on its own

You don't have to type the command. Claude sees each skill's description, and when your request fits one, it loads the skill itself. In our test, the plain question below was enough: Claude called the summarize-changes skill without being told to.

Claude Code
What did I change?

That makes the description the most important line in the file. Say what the skill does first, then the requests it should answer, in the words people actually use: "Use when the user asks what changed, wants a commit message, or asks to review their diff."

Decide who may run it

Some skills should never run unless you ask. You don't want Claude deciding on its own that now is a good time to deploy. Two frontmatter settings control this:

  • disable-model-invocation: true: only you can run it, by typing the command. Claude does not even see it in its list. Use it for anything with side effects: commits, deploys, sending messages.
  • user-invocable: false: only Claude can use it. It disappears from the / menu. Use it for background knowledge, such as how an old system works, which is not a command anyone would type.

We tested the first one with a manual-only server report. Asked in plain words for "a short health report for this server using the server-report skill", Claude did not use the skill and ran its own commands instead. Typing /server-report ran the skill.

Pass arguments

Whatever you type after the command reaches the skill as $ARGUMENTS. This /commit skill uses it for the commit message:

.claude/skills/commit/SKILL.md
---
description: Stage all changes and commit them with the given message
disable-model-invocation: true
argument-hint: [commit message]
allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)
---

Stage all changes with `git add -A` and commit them with this message: $ARGUMENTS

If no message was given, write a one-line message from the diff. Then show the result of `git status --short`.
Claude Code
/commit Raise limit to 1000
  • argument-hint is the hint shown while you type the command.
  • To take arguments one by one, use $0, $1 and so on: /deploy staging v2 makes $0 equal staging and $1 equal v2. Wrap a value in quotes to keep several words together.
  • allowed-tools lets the skill run those commands without asking you. Our test commit went through with no permission prompt. The approval lasts only for that turn: it ends when you send your next message.

Claude still uses its judgment inside a skill. On our first try, the change included a password written into the code, and instead of committing, Claude stopped and asked whether to remove it first.

Feed a skill the output of commands

The !`command` lines are what make skills useful for server work. This one collects the numbers for a quick health report:

.claude/skills/server-report/SKILL.md
---
description: Short health report for this server (disk, memory, load)
disable-model-invocation: true
allowed-tools: Bash(systemctl --failed *)
---

## Disk
!`df -h /`

## Memory
!`free -h`

## Load
!`uptime`

## Failed services
!`systemctl --failed --no-legend`

## Instructions

Write a five-line health report from the numbers above. Say plainly if disk use is over 80 percent or if memory is nearly full.

These commands never stop to ask for permission. Claude Code checks each one against your permission rules first:

  • Read-only commands that Claude Code recognizes run as they are. In our test, df, free and uptime needed nothing.
  • Any other command that your rules don't allow stops the whole skill before it reaches Claude.

Without the allowed-tools line, systemctl --failed stopped the skill with:

Output

Shell command permission check failed for pattern "!`systemctl --failed --no-legend`": This command requires approval

The allowed-tools line in the file above fixes it, by approving systemctl --failed commands for this skill only.

Warning

In a claude -p run, that failure is easy to miss: the run ended with no output and exit status 0, and the error only showed up in the detailed JSON output. If a skill in a script returns nothing, check its !`command` lines first.

A command that exits with an error also stops the skill. If a command is expected to exit with a non-zero code, for example a check script that reports problems that way, end the line with || true.

Skills from someone else's repository

Three points from the documentation are worth knowing before you work in a repository you did not write:

  • A project skill's allowed-tools applies even if you never trusted the folder, including in claude -p runs. That is different from allow rules in .claude/settings.json, which wait for the trust dialog. We saw it in our test: the folder had never been trusted, and /commit still ran git add and git commit without a prompt. A skill can approve broad access for itself. Read the allowed-tools lines in the repository's .claude/skills/ before you run Claude Code there.
  • The !`command` lines run on your machine when the skill runs. They still pass the permission check, but allowed-tools can approve them.
  • You can switch off those command lines entirely with "disableSkillShellExecution": true in your settings. Each command is then replaced with a note instead of being run.

Keep skills short

  • A skill's full text loads only when it runs. Until then, only its description takes up space, so a long skill costs almost nothing while it sits unused.
  • Once it runs, its text stays in the conversation. Every line costs tokens on every later turn, so write what to do, not why.
  • The documentation suggests keeping SKILL.md under 500 lines. Put long reference material in other files in the same folder, and say in SKILL.md which file holds what, so Claude reads them only when needed.

When a skill does not show up

  • Check the path. It must be .claude/skills/<name>/SKILL.md, with SKILL.md in capitals.
  • Check the first line. The frontmatter is read only if the opening --- is the very first line of the file.
  • Check the field names. They must match exactly, hyphens included. Claude Code ignores a field it does not recognize without any error.
  • If Claude never picks it up on its own, rewrite the description with the words you actually use when you ask, or just type the command.
  • If it runs too often, make the description narrower, or add disable-model-invocation: true.

Sources

Checked on

Claude Code 2.1.280 on AlmaLinux 9.8. All three skills were tested in a throwaway git project with claude -p: direct invocation, automatic invocation from a plain question, the manual-only setting, arguments, allowed-tools, the permission check on !`command` lines, and allowed-tools in a folder that had never been trusted. The messages above were copied from those runs.