Configuring Skills with Frontmatter

In the previous lesson, you learned how to create Skills and package them into Plugins. You built a basic Skill with a name and description, and you learned about frontmatter configuration. Now we'll explore the full range of frontmatter options that give you precise control over how your Skills behave.

Think of frontmatter as a control panel for your Skill — like the settings on your phone for a specific app. Some settings control when the app sends you notifications (when the Skill activates), others control how the app describes itself to the system (how Claude discovers it), and some affect whether the app appears on your home screen (how the Skill shows up in menus). Each field in that YAML section between the --- markers is like flipping one of these switches. Understanding these options lets you design Skills that work exactly the way you need them to.

This lesson focuses on the most important frontmatter fields and how to combine them effectively. By the end, you'll know how to write configurations that make your Skills reliable, discoverable, and context-appropriate.

The Description Field: Helping Claude Choose

Let's start with the description field, which you've already used. This field serves a specific purpose: it helps Claude decide whether your Skill is relevant to the current request. When you ask Claude to do something, Claude reviews all available Skill descriptions and determines which ones might help. A well-written description increases the likelihood that Claude will load your Skill automatically when appropriate.

Here's the explain-code Skill with a clear description:

The description Explains code with visual diagrams and analogies. Use when explaining how code works tells Claude two things: what the Skill does (explains code with diagrams and analogies) and when to use it (when explaining how code works). This clarity helps Claude match your request to the right Skill.

If you ask Can you explain how this sorting algorithm works? Claude will likely load this Skill automatically because explain and how this works match the description's language. The description acts like keywords that Claude uses for matching, though it's more sophisticated than simple keyword matching.

The description is technically optional. If you omit it, Claude uses the first paragraph of your Skill's Markdown content as the description. However, writing an explicit description gives you better control over how Claude interprets your Skill's purpose. A good description is concise, action-oriented, and mentions the situations where the Skill applies.

You don't need to overthink this. Write a sentence or two that answers and That's usually sufficient for Claude to make good decisions about when to load your Skill.

Controlling Who Can Invoke a Skill

The disable-model-invocation flag prevents Claude from automatically loading a Skill, requiring you to explicitly invoke it by typing /skill-name. It's essential for Skills that perform actions with consequences, like committing code or deploying applications.

Here's the commit Skill that requires manual invocation:

Even though this Skill has a description, Claude won't use it automatically because of disable-model-invocation: true. You must explicitly type /commit to activate it. Think of this like a two-person rule at a nuclear facility — even if the system knows launching is appropriate, both operators must turn their keys simultaneously. This prevents Claude from creating commits during casual conversation about version control. You're the second key.

The deploy Skill follows the same pattern:

Deployment affects your production environment, so it absolutely requires explicit invocation. Without disable-model-invocation: true, Claude might decide to deploy your app just because you mentioned testing is complete. That's not a risk worth taking.

There's another invocation control option: user-invocable: false. This works in the opposite direction. It hides the Skill from you but allows Claude to use it automatically. You might wonder why you'd ever want this.

Restricting Available Tools with Allowed-Tools

Claude has several tools available: Read for viewing file contents, Write for creating files, Edit for modifying files, Bash for running shell commands, Grep for searching text, and Glob for finding files. By default, all tools are available. The allowed-tools field restricts which tools Claude can actually use while the Skill is active — this is an enforced limitation.

Here's a Skill that restricts Claude to read-only operations:

When you invoke /code-reviewer, Claude can only use Read, Grep, and Glob. The Write, Edit, and Bash tools are locked out — they're physically unavailable while this Skill is active. Think of it like child safety locks on cabinets. When engaged, certain cabinets simply won't open. The restriction is absolute.

Dynamic Context with !`command`

Sometimes your Skills need current information — the git branch, today's date, environment variables, or command output. The !`command` syntax runs a shell command when the Skill loads and injects its output into your Skill content.

Here's a Skill that uses the current git branch:

When you invoke /create-pr, the !`git branch --show-current` runs and Claude sees the actual branch name like feature/add-login instead of the command.

You can use any shell command that produces text output:

The command runs when the Skill loads, not when you create the file. Each time you invoke the Skill, the command runs again with fresh output. If a command fails, the !`command` notation remains unchanged, making debugging easier.

Arguments with $ARGUMENTS

While !`command` injects dynamic context from your system, $ARGUMENTS lets you pass specific information when you invoke a Skill. This makes Skills reusable like function parameters.

Here's a simple example:

You invoke this with /analyze-file src/auth.js. The src/auth.js replaces $ARGUMENTS in the Skill content. You can use $ARGUMENTS multiple times in a Skill — all occurrences get replaced with the same text.

Arguments are optional. If you invoke without arguments, $ARGUMENTS becomes empty. If you invoke a Skill with arguments but the Skill doesn't include $ARGUMENTS, Claude Code appends ARGUMENTS: <your input> to the end of the Skill content so Claude still sees what you typed.

For more precise control, you can access individual arguments by position using $ARGUMENTS[N] or the shorter $N notation:

Running /migrate-component SearchBar React Vue replaces with , with , and with .

Choosing the Right Configuration

Now that you understand the individual frontmatter fields, let's talk about when to use each configuration. The decision comes down to what your Skill does and who should control when it runs.

For Skills that read and analyze without making changes, use the defaults or explicitly set allowed-tools to read-only operations. You don't need disable-model-invocation — Claude can safely load these Skills automatically. A code review Skill, a documentation search Skill, or an analysis Skill should use allowed-tools: [Read, Grep, Glob] to ensure they can't accidentally modify anything.

For Skills that modify code, commit changes, or deploy applications, always set disable-model-invocation: true. These actions have consequences. You want explicit control over when they happen. The description still helps you remember what the Skill does, but Claude won't load it unless you invoke it with /skill-name. This is the most important safety mechanism available. These Skills often benefit from $ARGUMENTS to specify targets and !`command` to include current state.

For Skills that represent background knowledge rather than executable actions, use user-invocable: false. This keeps them out of your menu while making them available for Claude to reference. Think of these as reference documents disguised as Skills. They inform Claude's responses without being commands you'd trigger.

For Skills where tool usage needs to be restricted, use allowed-tools. This creates an enforced barrier preventing specific tools from being used. A read-only analysis Skill should restrict to [Read, Grep, Glob]. A scaffolding Skill might allow but not or .

Summary and Practice Preview

You've learned how frontmatter fields control Skill behavior. The description field helps Claude decide when to load your Skill automatically by providing context about what the Skill does and when it applies. Setting disable-model-invocation: true requires explicit invocation with /skill-name, preventing Claude from using the Skill automatically — this is the primary safety mechanism for Skills with side effects like commits or deployments. Setting user-invocable: false hides the Skill from your menu while allowing Claude to use it, useful for background knowledge. The allowed-tools field restricts which tools Claude can actually use while the Skill is active, creating an enforced safety barrier for read-only or limited-capability Skills.

Beyond static configuration, !`command` notation injects dynamic content by running shell commands when the Skill loads, and $ARGUMENTS lets you pass specific values when invoking a Skill, making Skills flexible and reusable. You can use positional arguments with $ARGUMENTS[N] or $N for more precise control.

In the practice exercises, you'll create Skills with different configurations and see how they behave. You'll build Skills that require manual invocation and Skills that serve as background knowledge. This hands-on practice will help you internalize when to use each frontmatter field, with emphasis on disable-model-invocation: true as the reliable safety mechanism for protecting against unintended side effects.

The next lesson introduces Plugins, where you'll learn to package related Skills together and share them across projects.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal