IDInternals Decoded
Claude Code, Mastered
PlaybooksIntermediate10 min readMay 2026

Skills and Slash Commands: Teach It Your Workflows

Turn repeated instructions into reusable skills your whole team can invoke.

Part 3 of 10Claude Code, MasteredView series →

Skills and slash commands in Claude Code are file-based workflows stored in .claude/commands/ and .claude/skills/. A single Markdown file becomes a reusable /command. The runtime loads instructions on demand, using progressive disclosure to keep context small and token costs low. The same mechanism powers both manual shortcuts and automatic, multi-step procedures.

Unlike Slack slash commands that call an external server, Claude Code commands are interpreted entirely within the LLM (large language model) runtime. The file system is the API (application programming interface). That means you version-control workflows alongside code, and the model itself decides when to load a skill’s full instructions. The result is a declarative control plane that scales from a one-line prompt to a whole team’s playbook.

How does Claude Code turn a Markdown file into a slash command?

The simplest form is a legacy custom command. You create a Markdown file in .claude/commands/ and the filename becomes the command name. The file’s body is a prompt template. When you type /deploy-staging, Claude Code reads that file, substitutes any $ARGUMENTS placeholder with whatever you typed after the command, and injects the rendered text into the conversation as a single message.

Think of it like a macro in an editor, but the macro is executed by the AI. The file system acts as the registry. Claude Code scans .claude/commands/ and ~/.claude/commands/ at startup and builds an internal list of available commands. The first line or frontmatter description appears in the auto-complete menu.

The execution pipeline has four stages. First, the input is parsed into a command name and an argument string. Second, the runtime resolves the name to a file path, using a precedence order (project commands override personal ones). Third, the file is read and placeholders like $ARGUMENTS are replaced with the actual arguments. Fourth, the resulting prompt is injected into the context. From the model’s perspective, it looks like you just pasted a detailed instruction block.

For your side project, you might have a file .claude/commands/lint.md that contains “Run the linter on $ARGUMENTS and fix all auto-fixable issues.” Typing /lint src/ would turn that into a concrete task. The model then uses its tools to execute the linter and apply fixes. The command itself is stateless; it’s just a prompt shortcut.

Skills build on this same foundation but add auto-invocation and multi-file packaging. We’ll see how next.

What makes a skill different from a custom command?

A skill is a directory with a SKILL.md file at its core. The directory name becomes both the skill name and the slash command (/skill-name). The SKILL.md file uses YAML frontmatter to declare metadata: a description, when the skill should be triggered, which tools it may use, and an optional argument schema. The body contains the step-by-step instructions. source

The big leap is automatic invocation. Custom commands only fire when you type them. Skills can also fire when the model detects that the current task matches the skill’s description. If your SKILL.md frontmatter says “Use this skill whenever the user asks to deploy to staging,” Claude will notice that pattern and load the skill on its own. source

Custom Commands vs Skills
Custom Commands
  • Triggered only by slash command
  • Single .md file
  • No bundled resources
Skills
  • Triggered manually or automatically
  • Directory with SKILL.md
  • Can include scripts, references, assets
Skills extend commands with auto-invocation and bundled resources.

Skills can also bundle extra resources. You can add a scripts/ folder with executable code, a references/ folder with guidelines, and an assets/ folder with templates. The model is instructed in SKILL.md when to open those files. This turns a skill into a self-contained workflow package, not just a prompt. source

For your web app, a deploy skill might live at .claude/skills/deploy/SKILL.md. The frontmatter describes that it handles deployment to staging and production. The body lists the steps: run tests, build the container, push to registry, apply Terraform. A scripts/ folder could hold a smoke-test runner. A references/ folder could contain environment-specific configs. The model loads only what it needs when it needs it.

This leads directly to the design principle that makes skills practical for large workflows: progressive disclosure.

Why does Claude Code use progressive disclosure for skills?

Every token you put into context costs money and latency. If a skill’s full instructions, examples, and reference documents were loaded into every session, you would burn through your context budget before any real work began. Progressive disclosure solves this by loading only the metadata upfront, the body on invocation, and linked resources only when the model decides they are necessary. source

The frontmatter of SKILL.md is small. It contains a name, a description, and trigger hints. This metadata is loaded into the system prompt for all sessions in scope. That gives Claude a global index of available workflows without inflating the context. When a skill is invoked (manually or automatically), the full body of SKILL.md is read and injected. That body can be long and detailed, but you pay for it only during actual use. source

Even then, the references, scripts, and assets inside the skill directory are not loaded automatically. The instructions in SKILL.md tell the model when to open them. For example, a deploy skill might say “If the target is production, open references/production-config.md.” That file is read only when the condition is met. This three-level disclosure (metadata, body, on-demand resources) keeps the average token cost far lower than a flat prompt would. source

In your side project, imagine a code-review skill that references a 50-page style guide. Without progressive disclosure, every /review command would load the entire guide. With a skill, the guide sits in references/ and the model opens it only when it encounters a styling question. The result is a workflow that stays cheap even when the underlying knowledge base is huge.

Context savings with progressive disclosure
50,000
Tokens if full guide loaded
200
Tokens with frontmatter only
Illustrative token counts for a code-review skill with a 50-page style guide.

Skills also integrate with external tools, and progressive disclosure applies there too. The tool permissions are declared in the frontmatter, but the actual tool calls happen only when the skill is active. That’s our next topic.

How do skills integrate with tools and MCP?

MCP (Model Context Protocol) connects Claude Code to external services like GitHub, Slack, or databases. Skills teach the model how to use those connections in a structured way. You can think of MCP as the raw API and skills as the playbook that orchestrates the calls. source

In the SKILL.md frontmatter, you can list which tools the skill is allowed to use. This might include built-in tools (code execution, file editing) and any MCP servers you have configured. By scoping tool access to a skill, you reduce the risk that the model will call an inappropriate tool during a workflow. For example, a deploy skill might be allowed to run shell commands and call a Terraform MCP server, but not to send Slack messages. source

The scripts/ directory inside a skill lets you bundle executable code. The SKILL.md body can instruct the model to run a Python script to preprocess data, then interpret the output. This shifts deterministic steps out of the model’s reasoning and into explicit code, which is easier to audit and debug. source

For your web app, a pr-review skill could use a GitHub MCP server to fetch the diff and comments. The skill’s scripts/ folder might contain a linter runner. The SKILL.md body would tell the model: “Run scripts/lint.sh on the changed files, then summarize the output and any PR (pull request) discussion.” The model calls the tools, but the skill defines the sequence and the safety rails.

The Agent SDK (software development kit) takes this integration one step further by letting external systems invoke skills programmatically. That’s the final piece of the control plane.

How does the Agent SDK interact with skills and commands?

The Claude Code Agent SDK lets you send slash commands as plain text messages in a session. You can drive a session from a CI pipeline, a monitoring tool, or another AI system. Built-in commands like /compact (summarize history) and /context (show token usage) are available, as are any custom commands and skills you’ve defined. source

When the SDK sends /deploy-staging, the runtime resolves it exactly as if a user typed it. The command’s prompt is injected, and the model acts. Skills invoked this way follow the same progressive disclosure rules. The SDK also supports spawning sub-agents that can run skills in parallel with their own context windows. source

This means your side project’s CI could, after a successful build, use the SDK to tell Claude Code: “Run the /deploy-staging command and report the result.” The model would load the deploy skill, execute the steps, and return a summary. The entire workflow is version-controlled in your repo, not hard-coded in a CI script.

The SDK turns skills into a programmable interface. You get the same file-based workflow definitions, but you can trigger them from anywhere. That’s the full circle: a Markdown file in your project becomes a command you can type, a skill the model can auto-invoke, and an endpoint your automation can call.

Quick Reference

PropertyValue
Legacy command path.claude/commands/<name>.md
Personal command path~/.claude/commands/<name>.md
Skill path.claude/skills/<name>/SKILL.md
Personal skill path~/.claude/skills/<name>/SKILL.md
Required skill fileSKILL.md with YAML frontmatter
Placeholder for arguments$ARGUMENTS
Precedence (high to low)Enterprise → Personal → Project
Auto-invocation triggerModel matches task to skill description
Tool scopingDeclared in SKILL.md frontmatter
SDK command syntaxSend /command as a message

Frequently Asked Questions

Q: How do I create a simple slash command for my project? Create a .claude/commands/ folder, add a Markdown file named after the command (e.g., lint.md), and write the prompt inside. The first line becomes the description. Use $ARGUMENTS to capture what the user types after the command.

Q: Can I use arguments in a skill? Yes. In the SKILL.md frontmatter, you can define an argument schema. The body can then reference those arguments. For simple cases, you can still use $ARGUMENTS as a catch-all placeholder, just like in legacy commands.

Q: What’s the difference between .claude/commands/ and .claude/skills/? Commands are single-file prompt templates. Skills are directories with a SKILL.md file that supports frontmatter, auto-invocation, tool restrictions, and bundled resources. Both create a /name slash command, but skills are the modern, more capable format. source

Q: How do I prevent a skill from triggering automatically? Write a very specific description in the frontmatter. If the description says “Use this skill only when the user explicitly asks to deploy to production,” the model is unlikely to trigger it for a staging deployment. You can also omit a broad trigger description entirely and rely on manual invocation.

Q: Can skills call external APIs? Yes, through MCP servers. You configure an MCP server (e.g., for GitHub or Slack) in Claude Code’s settings, then list that tool in the skill’s frontmatter. The skill’s body instructs the model when and how to use the API. source

Test yourself

Your side project needs a skill that deploys the app to staging, runs smoke tests, and posts a summary to a Slack channel. The smoke tests are in a Python script, and the Slack integration uses an MCP server. How would you structure the skill directory and SKILL.md to keep the workflow efficient and debuggable?

Answer: Create .claude/skills/deploy-staging/SKILL.md. In the frontmatter, set the description to “Deploy the app to staging, run smoke tests, and notify Slack.” List the allowed tools: shell execution, the Slack MCP server, and file reading. In the body, write explicit steps: (1) run scripts/smoke-tests.py and capture the output, (2) if tests pass, execute the deployment command, (3) call the Slack MCP tool to post a summary with the test results and deployment status. Place the smoke-test script in scripts/smoke-tests.py and any staging config in references/staging.env. The model will load the script and config only when the skill is invoked, keeping context low. The step-by-step instructions make the workflow reproducible and easy to audit.

If you want this kind of breakdown every week, how real systems actually work under the hood, subscribe to Internals Decoded at internalsdecoded.com.

Sources

#claude-code-skills#slash-commands
More from the library
The Newsletter

Keep up with AI. One email a week.

One thoughtful email each week. Unsubscribe whenever you like.