<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Claude on</title><link>https://mcculley.tech/tags/claude/</link><description>Recent content in Claude on</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Mon, 13 Apr 2026 00:00:00 -0500</lastBuildDate><atom:link href="https://mcculley.tech/tags/claude/index.xml" rel="self" type="application/rss+xml"/><item><title>claude skills vs. claude.md</title><link>https://mcculley.tech/posts/claude-skills-vs-claude-md/</link><pubDate>Mon, 13 Apr 2026 00:00:00 -0500</pubDate><guid>https://mcculley.tech/posts/claude-skills-vs-claude-md/</guid><description>&lt;p&gt;In one of my &lt;a href="https://mcculley.tech/posts/using-ai-to-manage-my-nix-configs/"&gt;previous blog posts&lt;/a&gt;, I discussed using the &lt;code&gt;CLAUDE.md&lt;/code&gt; file in order to have AI create services for my NixOS configuration in a more deterministic manner. And while that did work, it&amp;rsquo;s technically not best practice. I needed to migrate away from the &lt;code&gt;CLAUDE.md&lt;/code&gt; file into a skill that can be invoked either automatically or manually through a slash command, which was designed for repeatable processes.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;CLAUDE.md&lt;/code&gt; file is more for naming schemes, architectural decisions and verification tasks than repeatable processes. And while you can use it to document and inform the model of repeatable processes, it&amp;rsquo;s better to leave those as skills files (or commands for simpler tasks, but that term is more legacy these days).&lt;/p&gt;</description><content>&lt;p&gt;In one of my &lt;a href="https://mcculley.tech/posts/using-ai-to-manage-my-nix-configs/"&gt;previous blog posts&lt;/a&gt;, I discussed using the &lt;code&gt;CLAUDE.md&lt;/code&gt; file in order to have AI create services for my NixOS configuration in a more deterministic manner. And while that did work, it&amp;rsquo;s technically not best practice. I needed to migrate away from the &lt;code&gt;CLAUDE.md&lt;/code&gt; file into a skill that can be invoked either automatically or manually through a slash command, which was designed for repeatable processes.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;CLAUDE.md&lt;/code&gt; file is more for naming schemes, architectural decisions and verification tasks than repeatable processes. And while you can use it to document and inform the model of repeatable processes, it&amp;rsquo;s better to leave those as skills files (or commands for simpler tasks, but that term is more legacy these days).&lt;/p&gt;
&lt;p&gt;The good news is that the migration from the &lt;code&gt;CLAUDE.md&lt;/code&gt; to skills is super easy. You can just tell Claude to translate certain sections of the &lt;code&gt;CLAUDE.md&lt;/code&gt; into skills files and place them in the appropriate section of your repository, which is the &lt;code&gt;.claude/skills/&amp;lt;SKILL-NAME&amp;gt;/SKILL.md&lt;/code&gt; directory in your repo. Below is an example of one I pulled out of &lt;a href="https://github.com/mcculleytech/nixos-config"&gt;my nixos-config repo&amp;rsquo;s&lt;/a&gt; &lt;code&gt;CLAUDE.md&lt;/code&gt; — this one is a repeatable process for wiring a new service into Prometheus and Grafana, invoked as &lt;code&gt;/add-monitoring &amp;lt;service&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;SKILL.md (click to expand)&lt;/summary&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;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Add Prometheus monitoring and a Grafana dashboard for a service. The service to add monitoring for is: $ARGUMENTS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;If no service name was provided in $ARGUMENTS, ask the user which service needs monitoring before proceeding.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## Step 1: Identify the Service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Confirm the service name and which host it runs on. Read the service&amp;#39;s &lt;span style="color:#e6db74"&gt;`.nix`&lt;/span&gt; file to understand its current configuration.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## Step 2: Determine the Monitoring Path
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Choose one of the two paths:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;**Path A — Service has a built-in Prometheus metrics endpoint**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(Examples: Traefik exposes metrics on port 8080, Blocky on port 4000)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;1.&lt;/span&gt; Enable the metrics endpoint within the service&amp;#39;s own config if not already enabled.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;2.&lt;/span&gt; Ensure the metrics port is open in &lt;span style="color:#e6db74"&gt;`networking.firewall.allowedTCPPorts`&lt;/span&gt; in the service&amp;#39;s &lt;span style="color:#e6db74"&gt;`.nix`&lt;/span&gt; file.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;3.&lt;/span&gt; Skip to Step 3.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;**Path B — Service needs a dedicated NixOS exporter**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(Examples: PostgreSQL → &lt;span style="color:#e6db74"&gt;`services.prometheus.exporters.postgres`&lt;/span&gt;, nginx → &lt;span style="color:#e6db74"&gt;`services.prometheus.exporters.nginx`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;1.&lt;/span&gt; Check available exporters at &lt;span style="color:#e6db74"&gt;`https://search.nixos.org/options?channel=25.11&amp;amp;query=services.prometheus.exporters`&lt;/span&gt; to find the right one.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;2.&lt;/span&gt; Enable the exporter in the service&amp;#39;s &lt;span style="color:#e6db74"&gt;`.nix`&lt;/span&gt; file:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ``&lt;span style="color:#e6db74"&gt;`nix
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; services.prometheus.exporters.&amp;lt;name&amp;gt; = {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; enable = true;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; port = &amp;lt;exporter-port&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; networking.firewall.allowedTCPPorts = [ &amp;lt;exporter-port&amp;gt; ];
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; `&lt;/span&gt;`&lt;span style="color:#e6db74"&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;3. Note the exporter port for Step 3.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;## Step 3: Add a scrapeConfigs Entry
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Edit `&lt;/span&gt;hosts/common/optional/roles/server/prometheus.nix&lt;span style="color:#e6db74"&gt;` and add a new entry to the `&lt;/span&gt;scrapeConfigs&lt;span style="color:#e6db74"&gt;` list.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Follow the existing pattern exactly — IPs must come from `&lt;/span&gt;hosts = config.lab.hosts&lt;span style="color:#e6db74"&gt;` (never hardcoded):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;`&lt;span style="color:#e6db74"&gt;`nix
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; job_name = &amp;#34;&amp;lt;service-name&amp;gt;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; static_configs = [
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; targets = [ &amp;#34;${hosts.&amp;lt;hostname&amp;gt;.ip}:&amp;lt;port&amp;gt;&amp;#34; ];
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ];
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;`&lt;span style="color:#e6db74"&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;## Step 4: Grafana Dashboard
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Search `&lt;/span&gt;https://grafana.com/grafana/dashboards/&lt;span style="color:#e6db74"&gt;` for a community dashboard matching the service.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- If a good match is found: report the dashboard ID and name to the user, and remind them to import it in the Grafana UI on **atreides** (Dashboards → Import → enter ID).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- If no match is found: note that no community dashboard was found; the user can build a custom one.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Key existing dashboard IDs for reference: `&lt;/span&gt;1860&lt;span style="color:#e6db74"&gt;` (Node Exporter Full), `&lt;/span&gt;17346&lt;span style="color:#e6db74"&gt;` (Traefik), `&lt;/span&gt;13768` (Blocky).
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;Now those instructions only enter context when I actually invoke the command — instead of bloating every session in that repo.&lt;/p&gt;
&lt;p&gt;One of the cooler things that you can do with the skills files is you can also have user-based skills instead of repository-based skills - user skills are located at &lt;code&gt;~/.claude/skills/&amp;lt;SKILL-NAME&amp;gt;/SKILL.md&lt;/code&gt;. These are skills that you could use across machines, across repositories, wherever you have a Claude Code Terminal Session open. They&amp;rsquo;re kind of like dot files but for agent skills. They even work in the webui or the desktop application (depending on what exactly you need them to do).&lt;/p&gt;
&lt;p&gt;This solves the same issue that I had in my other post by providing a more deterministic way of making the AI behave, but it also leaves the &lt;code&gt;CLAUDE.md&lt;/code&gt; file less cluttered. If your &lt;code&gt;CLAUDE.md&lt;/code&gt; file gets too large you start to eat away at your context window and get diminishing results.&lt;/p&gt;
&lt;p&gt;For more details on skills, check the &lt;a href="https://docs.anthropic.com/en/docs/claude-code/skills"&gt;official Claude Code skills documentation&lt;/a&gt;.&lt;/p&gt;</content></item></channel></rss>