<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Claude Code on Roland Huß</title><link>https://ro14nd.de/tags/claude-code/</link><description>Recent content in Claude Code on Roland Huß</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>© 2026 Roland Huß</copyright><lastBuildDate>Thu, 09 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://ro14nd.de/tags/claude-code/index.xml" rel="self" type="application/rss+xml"/><item><title>Claude Code skill patterns</title><link>https://ro14nd.de/cc-skill-patterns/</link><pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate><guid>https://ro14nd.de/cc-skill-patterns/</guid><description>&lt;p&gt;Claude Code skills let you extend a coding agent with custom workflows, specialist knowledge, and automation. You write a &lt;code&gt;SKILL.md&lt;/code&gt; file with instructions, and the agent follows them. At least, that&amp;rsquo;s the idea.&lt;/p&gt;
&lt;p&gt;In practice, Claude treats skill content as advice, not as instructions. A skill that says &amp;ldquo;always use spec-kit to create the specification&amp;rdquo; might get followed, or Claude might decide it already has enough context from the brainstorming phase to write the spec directly. It&amp;rsquo;s being helpful, but it&amp;rsquo;s also wrong. This post describes patterns for dealing with that challenge, from scripts that enforce consistency to hooks that block shortcuts before they happen.&lt;/p&gt;
&lt;p&gt;Stronger wording does not help. I tried &amp;ldquo;MUST&amp;rdquo;, &amp;ldquo;ALWAYS&amp;rdquo;, &amp;ldquo;CRITICAL&amp;rdquo;, bold, uppercase. None of it changes the underlying behavior: the model reads your skill, considers it, and then makes its own judgment call. Compare that to hook-injected context (system reminders), which Claude treats as ground truth. This difference in compliance is not a bug, it&amp;rsquo;s how the architecture works. Understanding it early saves you from writing increasingly aggressive skill instructions that still get ignored.&lt;/p&gt;
&lt;p&gt;The patterns in this post come from building &lt;a href="https://github.com/rhuss/cc-prose" target="_blank" rel="noreferrer"&gt;cc-prose&lt;/a&gt; (voice-consistent writing), &lt;a href="https://github.com/rhuss/cc-spex" target="_blank" rel="noreferrer"&gt;cc-spex&lt;/a&gt; (spec-driven development on top of &lt;a href="https://github.com/github/spec-kit" target="_blank" rel="noreferrer"&gt;spec-kit&lt;/a&gt;), and a few others.&lt;/p&gt;

&lt;h2 class="relative group"&gt;The shortcut race
 &lt;div id="the-shortcut-race" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-shortcut-race" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;This shortcutting behavior keeps coming back and deserves its own section.&lt;/p&gt;
&lt;p&gt;You fix one shortcut in your skill instructions, Claude finds another path around it, you patch that one, and it discovers a third. It&amp;rsquo;s a classic &lt;a href="https://en.wikipedia.org/wiki/The_Hare_and_the_Hedgehog" target="_blank" rel="noreferrer"&gt;Hase-und-Igel&lt;/a&gt; race, and as the skill author you will always be the hedgehog.&lt;/p&gt;
&lt;p&gt;In cc-spex, the brainstorming phase collects requirements, explores alternatives, and validates assumptions before the specification phase formalizes everything into a proper spec using spec-kit. But Claude regularly decides that the brainstorming output is &amp;ldquo;structured enough&amp;rdquo; and writes the spec directly. From the model&amp;rsquo;s perspective, this is a reasonable optimization. From the workflow&amp;rsquo;s perspective, it&amp;rsquo;s skipping the entire point.&lt;/p&gt;
&lt;p&gt;What makes this particularly frustrating is that Claude usually knows it did the wrong thing. Point out the shortcut and it will apologize, acknowledge that it should have followed the workflow, and promise to do better next time, without that actually preventing the next occurrence.&lt;/p&gt;
&lt;p&gt;A useful debugging technique is to open a fresh session, show Claude what happened, and ask: &amp;ldquo;Why did you do this, and how can we prevent it in the future?&amp;rdquo; The answers are surprisingly insightful, and many of the patterns in this post came directly from those conversations. Then I let Claude fix the skill right there in the same session, while the reasoning is still fresh. Each iteration makes the skill more reliable.&lt;/p&gt;
&lt;p&gt;Can you win this race? Not entirely. But you can make shortcuts increasingly expensive for the model by moving critical logic out of skills and into scripts and hooks, where it stops being a suggestion and becomes a constraint.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Skills vs scripts
 &lt;div id="skills-vs-scripts" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#skills-vs-scripts" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Skills can call out to scripts during execution. This is the escape hatch from the shortcut race: instead of relying on Claude to follow a multi-step procedure described in English, you delegate the deterministic parts to a script that the skill invokes at the right moment. The question then becomes: what belongs in the skill, and what belongs in the script?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Skills&lt;/strong&gt; give you flexibility, error-forgiveness, and adaptability. The LLM can handle ambiguous input, recover from unexpected situations, and apply judgment, so use them when the outcome benefits from interpretation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scripts&lt;/strong&gt; give you determinism, repeatability, and predictability because a Python script does the same thing every time. Use them when the outcome must be consistent across runs.&lt;/p&gt;
&lt;p&gt;One of my plugins has a workflow for processing external PDF reviews: iterate over reviewer comments, map them to source files, assess complexity, and generate fix proposals. This follows a fixed procedure with multiple stages. Early versions used skills for the whole flow, and the result was a different experience every time: sometimes it would skip comments, sometimes it would process them in the wrong order, sometimes it would invent stages that didn&amp;rsquo;t exist. A &lt;code&gt;session_manager.py&lt;/code&gt; script now handles the state management, tracks the interaction state, and stores results. The skill handles the judgment calls within each stage, like assessing whether a reviewer&amp;rsquo;s suggestion actually improves clarity. The script handles everything else.&lt;/p&gt;
&lt;p&gt;The evolution path is predictable: you start with a simple prompt-only skill (just English instructions, fragile by nature) and gradually move state management into scripts as you hit consistency problems. And you don&amp;rsquo;t write those scripts by hand, either. You tell Claude &amp;ldquo;let&amp;rsquo;s create a script to make this more predictable&amp;rdquo; and let it build the script and wire it into the skill at the right checkpoints. The rule of thumb: every state change should go through a script. Let the LLM do the thinking, and let scripts do the bookkeeping.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Hooks over hopes
 &lt;div id="hooks-over-hopes" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#hooks-over-hopes" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;If skills are advisory and scripts are deterministic, hooks are the bridge. Claude Code&amp;rsquo;s hook system lets you inject context at specific points in the interaction, and that context arrives as a system reminder, which Claude treats as ground truth. Better skill instructions won&amp;rsquo;t fix the compliance gap, but hooks can enforce what instructions can&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;cc-spex uses a &lt;code&gt;PreToolUse&lt;/code&gt; hook as a guardrail layer. This hook fires before every tool call and can either allow it, deny it with an error message, or inject additional context. When the plugin runs a multi-stage ship workflow (brainstorm, specify, plan, implement, review, verify), Claude regularly tries to skip stages. A skill instruction saying &amp;ldquo;complete each stage in order&amp;rdquo; gets interpreted as a suggestion. The hook makes it a constraint: a state file on the filesystem tracks the current pipeline stage, and the hook checks it before every tool call. If Claude tries to jump from stage 2 (spec review) to stage 6 (implementation), the hook blocks the call and lists every stage it needs to complete first:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PIPELINE DISCIPLINE: You are trying to invoke speckit-implement 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(stage 6: implement) but the pipeline is at stage 2: review-spec. 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;You MUST complete these stages first, in order:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2. review-spec (spex:review-spec)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3. plan (speckit-plan)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 4. tasks (speckit-tasks)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 5. review-plan (spex:review-plan)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Do NOT skip stages. Do NOT shortcut.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The same hook catches hallucinated commands (Claude inventing &lt;code&gt;/spex:specify&lt;/code&gt; which doesn&amp;rsquo;t exist) and reminds about verification before git commits. A companion &lt;code&gt;UserPromptSubmit&lt;/code&gt; hook injects plugin state as a structured system reminder on every prompt, including resolved script paths, project configuration, and session context, so that skills always have accurate state without needing to rediscover it.&lt;/p&gt;
&lt;p&gt;Instead of telling Claude what to do and hoping it complies, you build guardrails that make non-compliance impossible. The hooks don&amp;rsquo;t ask Claude to follow the process, they enforce it at the tool level before Claude&amp;rsquo;s output reaches the user.&lt;/p&gt;
&lt;div class="diagram-themed"&gt;
&lt;img class="diagram-light" src="https://ro14nd.de/images/cc-skill-patterns/enforcement-architecture-light.svg" alt="Enforcement architecture: hooks inject state and block shortcuts, skills provide advisory guidance, scripts handle deterministic state management" /&gt;
&lt;img class="diagram-dark" src="https://ro14nd.de/images/cc-skill-patterns/enforcement-architecture-dark.svg" alt="Enforcement architecture: hooks inject state and block shortcuts, skills provide advisory guidance, scripts handle deterministic state management" /&gt;
&lt;/div&gt;

&lt;h2 class="relative group"&gt;More patterns
 &lt;div id="more-patterns" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#more-patterns" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;A few more patterns that came up across my skills.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Multi-specialist over monolith.&lt;/strong&gt; Instead of one massive skill that tries to do everything, split into independent specialist skills with their own activation rules. One of my plugins uses 12 specialists for different editing concerns: style, consistency, flow, references, links, examples, and more. This keeps individual skills focused and within context budget, because one monolithic skill will lose track of its own instructions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prevention over correction.&lt;/strong&gt; cc-prose generates clean content upfront using voice profiles and AI pattern avoidance, rather than generating text and then running a fixer pass. It&amp;rsquo;s cheaper to prevent bad output than to detect and fix it after the fact. Not to mention that fixing AI-generated text while using AI tends to be an exercise in whack-a-mole.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Keep skills small.&lt;/strong&gt; Every line of skill content fills the context window, so if Claude &amp;ldquo;helpfully&amp;rdquo; adds optional features to your skill output, remove them. Periodic cleanup during development is important because skill code accumulates cruft faster than regular code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Configuration hierarchy.&lt;/strong&gt; Skill defaults in &lt;code&gt;knowledge-base/&lt;/code&gt; get overridden by global user config, which get overridden by project config. cc-prose uses this to layer project-specific voice profiles on top of general writing defaults. Three layers is enough.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Building on a moving platform.&lt;/strong&gt; Claude Code is transitioning from &lt;code&gt;commands/&lt;/code&gt; to user-invocable &lt;code&gt;skills/&lt;/code&gt;, but plugin skills installed from marketplaces still don&amp;rsquo;t appear in the &lt;code&gt;/&lt;/code&gt; slash command autocomplete (&lt;a href="https://github.com/anthropics/claude-code/issues/18949" target="_blank" rel="noreferrer"&gt;anthropics/claude-code#18949&lt;/a&gt;, open since January 2026). Build with &lt;code&gt;skills/&lt;/code&gt; as the primary structure but keep thin &lt;code&gt;commands/*.md&lt;/code&gt; stubs as a bridge until autocomplete catches up.&lt;/p&gt;
&lt;p&gt;The core tension between flexibility and determinism, between skills and scripts, won&amp;rsquo;t go away with better models. If anything, more capable models will just make the shortcut race more creative.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re building Claude Code skills and have found patterns of your own, I&amp;rsquo;d like to hear about them.&lt;/p&gt;
&lt;div class="ai-attribution"&gt;
&lt;p&gt;Author: Roland Huß &lt;a href="https://aiattribution.github.io/statements/AIA-Ph-SeNc-Hin-R-?model=Claude%20Opus%204.6-v1.0" target="_blank" rel="noreferrer"&gt;AIA Ph SeNc Hin R Claude Opus 4.6 v1.0&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description></item></channel></rss>