<?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: TECHDEV</title>
    <description>The latest articles on DEV Community by TECHDEV (@techdevfun).</description>
    <link>https://dev.to/techdevfun</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4188359%2Fe5cd62cb-6e0b-44dd-b1d7-3934d6cf3ef0.webp</url>
      <title>DEV Community: TECHDEV</title>
      <link>https://dev.to/techdevfun</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/techdevfun"/>
    <language>en</language>
    <item>
      <title>I installed a bunch of agent skills. Then I wrote a tool to audit them.</title>
      <dc:creator>TECHDEV</dc:creator>
      <pubDate>Sat, 17 Oct 2026 10:02:54 +0000</pubDate>
      <link>https://dev.to/techdevfun/i-installed-a-bunch-of-agent-skills-then-i-wrote-a-tool-to-audit-them-4e2h</link>
      <guid>https://dev.to/techdevfun/i-installed-a-bunch-of-agent-skills-then-i-wrote-a-tool-to-audit-them-4e2h</guid>
      <description>&lt;p&gt;Every week a new agent skills pack shows up on GitHub Trending. I installed a few. Then a few more. Then I copied skills from three different packs into one folder.&lt;/p&gt;

&lt;p&gt;That is when things got weird.&lt;/p&gt;

&lt;p&gt;Two skills had the same name. The agent picked one at random. Two more had almost identical descriptions, so both triggered on the same prompt. One skill had no description at all, so the agent never picked it. I had no idea until I started reading every SKILL.md by hand.&lt;/p&gt;

&lt;p&gt;So I built a tiny tool to do that reading for me: &lt;strong&gt;skill-audit&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;One command audits a whole skills folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;skill-audit check &lt;span class="nt"&gt;--path&lt;/span&gt; ~/.claude/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It checks for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate names&lt;/strong&gt; — two skills declaring the same &lt;code&gt;name&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invalid names&lt;/strong&gt; — anything that is not kebab-case&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing name / description&lt;/strong&gt; — the description is how the agent decides when to trigger a skill&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing frontmatter&lt;/strong&gt; — a SKILL.md with no &lt;code&gt;---&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate / overlapping descriptions&lt;/strong&gt; — identical text, or &amp;gt;=70% token overlap, so two skills fight over the same prompt&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description too short / too long&lt;/strong&gt; — under 20 chars, or over 1024&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thin body&lt;/strong&gt; — a header, not a skill&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing SKILL.md&lt;/strong&gt; — a folder agents will never discover&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No version&lt;/strong&gt; — so you can tell whether you have the latest&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exit code &lt;code&gt;0&lt;/code&gt; means no errors. Warnings never fail the run on their own, so you can use it in CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ skill-audit check --path examples/messy
[ERROR] duplicate-name: Duplicate skill name 'dup-skill'
[ERROR] invalid-name: 'Bad Name' must be kebab-case
[ERROR] missing-description: no-desc has no 'description'
[ERROR] missing-description: (unnamed) has no 'description'
[ERROR] missing-name: no-frontmatter/SKILL.md has no 'name'
[WARN ] frontmatter-parse: no-frontmatter/SKILL.md missing frontmatter block
[WARN ] no-version: (unnamed) has no 'version' in frontmatter
Summary: 5 error(s), 2 warning(s), 5 skill(s).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/techdevfun/skill-audit.git
&lt;span class="nb"&gt;cd &lt;/span&gt;skill-audit
&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src python &lt;span class="nt"&gt;-m&lt;/span&gt; skill_audit check &lt;span class="nt"&gt;--path&lt;/span&gt; examples/good
&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src python &lt;span class="nt"&gt;-m&lt;/span&gt; skill_audit check &lt;span class="nt"&gt;--path&lt;/span&gt; examples/messy &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero dependencies, Python 3.9+ stdlib only. Tests + CI included.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/techdevfun/skill-audit" rel="noopener noreferrer"&gt;https://github.com/techdevfun/skill-audit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Existing skill packs add more skills. This one tells you whether the ones you already have are healthy. If you maintain a pack, running this in CI catches the duplicate-name / missing-description breakage before your users do.&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>cli</category>
      <category>devops</category>
    </item>
    <item>
      <title>Your .env file is lying to you. I built a tiny tool to catch it.</title>
      <dc:creator>TECHDEV</dc:creator>
      <pubDate>Fri, 16 Oct 2026 08:44:22 +0000</pubDate>
      <link>https://dev.to/techdevfun/your-env-file-is-lying-to-you-i-built-a-tiny-tool-to-catch-it-1mcg</link>
      <guid>https://dev.to/techdevfun/your-env-file-is-lying-to-you-i-built-a-tiny-tool-to-catch-it-1mcg</guid>
      <description>&lt;h1&gt;
  
  
  Your .env file is lying to you. I built a tiny tool to catch it.
&lt;/h1&gt;

&lt;p&gt;Every new AI tool wants another API key. So my &lt;code&gt;.env&lt;/code&gt; file kept growing — and one day I realized I no longer trusted it.&lt;/p&gt;

&lt;p&gt;A teammate cloned the repo, followed &lt;code&gt;.env.example&lt;/code&gt;, and the app crashed. A key that was in &lt;code&gt;.env&lt;/code&gt; had never been added to the example. An old key that nobody used anymore was still there. And somewhere in the middle sat &lt;code&gt;STRIPE_KEY=changeme&lt;/code&gt;, which had been there long enough that nobody noticed.&lt;/p&gt;

&lt;p&gt;Formatters and linters check whether your &lt;code&gt;.env&lt;/code&gt; file &lt;em&gt;looks&lt;/em&gt; right. None of them told me whether my env setup was &lt;em&gt;actually&lt;/em&gt; correct. So I built a small tool that does exactly that: &lt;strong&gt;env-doctor&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it checks
&lt;/h2&gt;

&lt;p&gt;One stdlib-only Python CLI. No dependencies, no network, no telemetry.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; env_doctor check &lt;span class="nt"&gt;--env&lt;/span&gt; .env &lt;span class="nt"&gt;--example&lt;/span&gt; .env.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;What it finds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Drift&lt;/td&gt;
&lt;td&gt;Keys in &lt;code&gt;.env.example&lt;/code&gt; missing in &lt;code&gt;.env&lt;/code&gt;, and vice versa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicates&lt;/td&gt;
&lt;td&gt;Same key defined twice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Placeholders&lt;/td&gt;
&lt;td&gt;Empty values, &lt;code&gt;changeme&lt;/code&gt;, &lt;code&gt;your-api-key&lt;/code&gt;, &lt;code&gt;TODO&lt;/code&gt;, &lt;code&gt;xxx&lt;/code&gt;, ...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Risky secrets&lt;/td&gt;
&lt;td&gt;Known prefixes (&lt;code&gt;ghp_&lt;/code&gt;, &lt;code&gt;sk-&lt;/code&gt;, &lt;code&gt;AKIA&lt;/code&gt;, ...) or long high-entropy values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unused vars&lt;/td&gt;
&lt;td&gt;Keys not referenced in scanned code (&lt;code&gt;--scan .&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invalid lines&lt;/td&gt;
&lt;td&gt;Lines without &lt;code&gt;=&lt;/code&gt;, invalid key names&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Exit code &lt;code&gt;0&lt;/code&gt; means no errors, &lt;code&gt;1&lt;/code&gt; means errors found. Warnings never fail the run on their own, so you can use it in CI without false failures from heuristics.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python -m env_doctor check --env examples/drift/.env --example examples/drift/.env.example
[ERROR] duplicate-key: Duplicate key 'DATABASE_URL' (line 3)
[ERROR] missing-in-env: 'NEW_API_URL' is in .env.example but missing in .env
[WARN ] placeholder-value: 'STRIPE_KEY' still looks like a placeholder value
[WARN ] missing-in-example: 'OLD_FLAG' is in .env but missing in .env.example
Summary: 2 error(s), 2 warning(s), 3 key(s).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;drift/&lt;/code&gt; example ships in the repo, broken on purpose, so you can see the output immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it in 3 steps
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Clone&lt;/span&gt;
git clone https://github.com/techdevfun/env-doctor.git
&lt;span class="nb"&gt;cd &lt;/span&gt;env-doctor

&lt;span class="c"&gt;# 2. No dependencies to install (Python 3.9+ stdlib only).&lt;/span&gt;
&lt;span class="c"&gt;#    Optional: install the `env-doctor` command&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# 3. Run it&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; env_doctor check &lt;span class="nt"&gt;--env&lt;/span&gt; .env &lt;span class="nt"&gt;--example&lt;/span&gt; .env.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few more ways to use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clean setup — should pass&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; env_doctor check &lt;span class="nt"&gt;--env&lt;/span&gt; examples/basic/.env &lt;span class="nt"&gt;--example&lt;/span&gt; examples/basic/.env.example

&lt;span class="c"&gt;# JSON output for CI / scripts&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; env_doctor check &lt;span class="nt"&gt;--env&lt;/span&gt; examples/drift/.env &lt;span class="nt"&gt;--example&lt;/span&gt; examples/drift/.env.example &lt;span class="nt"&gt;--format&lt;/span&gt; json

&lt;span class="c"&gt;# Also flag vars not referenced in code&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; env_doctor check &lt;span class="nt"&gt;--env&lt;/span&gt; .env &lt;span class="nt"&gt;--example&lt;/span&gt; .env.example &lt;span class="nt"&gt;--scan&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in CI, it's one step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&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;Audit .env drift&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python -m env_doctor check --env .env --example .env.example --format text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repo runs the same check in &lt;code&gt;.github/workflows/ci.yml&lt;/code&gt; on Python 3.9, 3.11, and 3.12.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;On the roadmap: &lt;code&gt;--fix&lt;/code&gt; to auto-add missing keys to &lt;code&gt;.env.example&lt;/code&gt; as empty placeholders, &lt;code&gt;--strict&lt;/code&gt; to turn selected warnings into errors, support for &lt;code&gt;.env.local&lt;/code&gt; / &lt;code&gt;.env.production&lt;/code&gt; layering checks, and SARIF output for GitHub code scanning.&lt;/p&gt;

&lt;p&gt;If you try it and it misses a case your project hits, open an issue — that's the feedback that shapes what gets built next.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/techdevfun/env-doctor" rel="noopener noreferrer"&gt;https://github.com/techdevfun/env-doctor&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>dotenv</category>
      <category>cli</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
