<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Thryx</title>
    <description>The latest articles on DEV Community by Thryx (@thryx).</description>
    <link>https://dev.to/thryx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3911321%2Fba62a579-36d3-4022-a33c-0e30ad8df208.png</url>
      <title>DEV Community: Thryx</title>
      <link>https://dev.to/thryx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thryx"/>
    <language>en</language>
    <item>
      <title>How to Create a Skill in Claude Code</title>
      <dc:creator>Thryx</dc:creator>
      <pubDate>Thu, 09 Jul 2026 21:19:15 +0000</pubDate>
      <link>https://dev.to/thryx/how-to-create-a-skill-in-claude-code-pih</link>
      <guid>https://dev.to/thryx/how-to-create-a-skill-in-claude-code-pih</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a cross-post — the original (and any updates) live at &lt;a href="https://broke2builtai.com/guides/how-to-create-a-skill-in-claude-code/" rel="noopener noreferrer"&gt;broke2builtai.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first time I watched Claude Code reach for a skill I hadn't told it to use — read a folder, run the script inside it, and hand back the finished thing — the difference from a slash command finally landed. A slash command waits for you to type it. A skill waits for the &lt;em&gt;situation&lt;/em&gt;. Claude decides. That one shift is the whole feature, and building one takes about five minutes once you know where the file goes.&lt;/p&gt;

&lt;p&gt;Here's the entire thing end to end, including the one gotcha that decides whether your skill ever actually fires.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Skill actually is
&lt;/h2&gt;

&lt;p&gt;A Skill is a folder with a &lt;code&gt;SKILL.md&lt;/code&gt; file inside it. The Markdown holds instructions; the YAML frontmatter at the top holds a &lt;code&gt;name&lt;/code&gt; and a &lt;code&gt;description&lt;/code&gt;. That description is doing the most important job in the whole file: Claude reads it to decide, on its own, whether the current task warrants invoking the skill. Nothing else you write matters if the description doesn't get you picked.&lt;/p&gt;

&lt;p&gt;That's the mental model to hold onto: a &lt;a href="https://dev.to/guides/how-to-create-a-custom-slash-command-in-claude-code/"&gt;custom slash command&lt;/a&gt; is a prompt &lt;em&gt;you&lt;/em&gt; trigger by typing &lt;code&gt;/name&lt;/code&gt;; a skill is a procedure &lt;em&gt;Claude&lt;/em&gt; triggers when the context matches. Same reusable-instructions idea, opposite trigger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the file goes
&lt;/h2&gt;

&lt;p&gt;Two locations register, exactly like commands and &lt;a href="https://dev.to/guides/how-to-use-subagents-in-claude-code/"&gt;subagents&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project skill&lt;/strong&gt; — &lt;code&gt;.claude/skills/&amp;lt;skill-name&amp;gt;/SKILL.md&lt;/code&gt; inside the repo. Committed, so your whole team gets it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personal skill&lt;/strong&gt; — &lt;code&gt;~/.claude/skills/&amp;lt;skill-name&amp;gt;/SKILL.md&lt;/code&gt; in your home directory. Follows you across every project on your machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each skill is its own folder, and the folder name should match the &lt;code&gt;name&lt;/code&gt; in the frontmatter. A loose &lt;code&gt;SKILL.md&lt;/code&gt; sitting somewhere else won't be picked up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The minimum viable skill
&lt;/h2&gt;

&lt;p&gt;Create the folder and the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.claude/skills/pytest-runner/SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then write the two-part file — frontmatter, then body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pytest-runner&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Run,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;generate,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;debug&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pytest&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tests&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;this&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Use&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;when&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;asks&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;suite,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;add&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tests&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;function,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;figure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;out&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;why&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;failing."&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

When invoked:
&lt;span class="p"&gt;
1.&lt;/span&gt; Run the suite with &lt;span class="sb"&gt;`python -m pytest -q`&lt;/span&gt; and read the output.
&lt;span class="p"&gt;2.&lt;/span&gt; If tests fail, show the failing test names and the assertion, then propose the smallest fix.
&lt;span class="p"&gt;3.&lt;/span&gt; When asked to add tests, match the existing style in &lt;span class="sb"&gt;`tests/`&lt;/span&gt; — same fixtures, same naming.
&lt;span class="p"&gt;4.&lt;/span&gt; Never mark work done until the suite is green; paste the passing summary line.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a working skill. No install step, no registration file — Claude Code discovers it from the folder. Next time you ask something that matches the description, Claude reaches for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one gotcha: the description IS the trigger
&lt;/h2&gt;

&lt;p&gt;If your skill never fires, the description is almost always why. Claude selects a skill by matching the task against the description text, so a vague &lt;code&gt;description: helps with tests&lt;/code&gt; competes badly against everything else in context and usually loses.&lt;/p&gt;

&lt;p&gt;Write the description like a trigger list, not a summary. Name the concrete situations, the verbs, and the file types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Weak:&lt;/strong&gt; &lt;code&gt;description: Testing helper.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong:&lt;/strong&gt; &lt;code&gt;description: Run, generate, or debug pytest tests. Use when the user asks to run the suite, add tests for a function/module, or diagnose a failing test.&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The body can be as long and detailed as you want — that content only loads once the skill is invoked. The description is the part that's always competing for selection, so that's where the precision has to live. This is the same discipline behind &lt;a href="https://dev.to/guides/how-to-write-a-system-prompt-for-an-ai-agent/"&gt;writing a good system prompt for an agent&lt;/a&gt;: be explicit about &lt;em&gt;when&lt;/em&gt;, not just &lt;em&gt;what&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bundling scripts, references, and templates
&lt;/h2&gt;

&lt;p&gt;The reason a skill beats a slash command for real workflows is that the folder can hold more than instructions. Anything you drop in the skill directory is available to Claude when the skill runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.claude/skills/release-notes/
├── SKILL.md
├── template.md          # the format to fill in
└── changelog-parse.py   # a helper the skill runs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reference them from &lt;code&gt;SKILL.md&lt;/code&gt; by relative path — "fill in &lt;code&gt;template.md&lt;/code&gt;", "run &lt;code&gt;changelog-parse.py&lt;/code&gt; on the git log" — and Claude reads or executes them as part of following the skill. That's how a skill packages an entire procedure (a format + a script + the rules for using them), not just a paragraph of prompt. If the script needs a tool that prompts for permission, the same &lt;a href="https://dev.to/guides/how-to-use-claude-code-hooks/"&gt;permission and hooks rules&lt;/a&gt; apply as anywhere else in Claude Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skill vs. slash command vs. CLAUDE.md — which to reach for
&lt;/h2&gt;

&lt;p&gt;Three ways to give Claude Code reusable instructions, and they're not interchangeable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CLAUDE.md&lt;/strong&gt; — always-on. Loaded every session. Use it for standing facts about the project (&lt;a href="https://dev.to/guides/how-to-write-a-claude-md-file/"&gt;here's how to write one&lt;/a&gt;). The cost is context: everything in it is paid for on every turn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slash command&lt;/strong&gt; — you-triggered, on demand. Use it when &lt;em&gt;you&lt;/em&gt; decide the moment (&lt;code&gt;/review&lt;/code&gt;, &lt;code&gt;/deploy&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill&lt;/strong&gt; — model-triggered, on demand. Use it when you want Claude to notice the situation and reach for the procedure itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical rule: standing context goes in CLAUDE.md; a procedure you invoke yourself is a slash command; a procedure Claude should invoke when it sees the trigger is a skill. Getting that split right is what keeps your everyday context lean while still having deep procedures on tap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest workflow
&lt;/h2&gt;

&lt;p&gt;Build the skill small, then watch whether it fires. Ask something that &lt;em&gt;should&lt;/em&gt; trigger it and see if Claude reaches for it — if it doesn't, tighten the description and try again. That loop takes a couple of minutes and is the only real test that matters, because a skill that never gets invoked is just a Markdown file nobody reads.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This site runs its own automation on Claude Code and free-tier AI. If you're wiring up cheap models to do real work, we run everything on GLM's free tier through the &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai Coding Plan&lt;/a&gt; (referral link — it funds our compute); a tight SKILL.md is exactly the kind of harness that keeps a cheaper model on rails.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Broke to Built is one broke human + AI agents building real software with no budget, writing down every step. This site's tools run on free GLM — &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai's Coding Plan&lt;/a&gt; is the referral that funds our compute (disclosed affiliate).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
