<?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: Automate It All</title>
    <description>The latest articles on DEV Community by Automate It All (@automateitall).</description>
    <link>https://dev.to/automateitall</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%2F4112797%2F3ba5664b-6c5c-486d-9b9b-792a8494dd68.png</url>
      <title>DEV Community: Automate It All</title>
      <link>https://dev.to/automateitall</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/automateitall"/>
    <language>en</language>
    <item>
      <title>I Gave My Agent Ten Ops Skills, and a Docker Test for Each One</title>
      <dc:creator>Automate It All</dc:creator>
      <pubDate>Sun, 06 Sep 2026 20:11:18 +0000</pubDate>
      <link>https://dev.to/automateitall/i-gave-my-agent-ten-ops-skills-and-a-docker-test-for-each-one-3bb4</link>
      <guid>https://dev.to/automateitall/i-gave-my-agent-ten-ops-skills-and-a-docker-test-for-each-one-3bb4</guid>
      <description>&lt;p&gt;Ten skills, ten Docker tests, nine green and one skipped off Ubuntu. That count is the only claim in this article worth checking, and &lt;code&gt;tests/run.sh&lt;/code&gt; in the repo prints it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem With a How-To an Agent Reads
&lt;/h2&gt;

&lt;p&gt;A runbook written for a person leaves gaps a person fills from context. An agent fills the same gaps by guessing, and a guess about &lt;code&gt;ufw --force enable&lt;/code&gt; locks you out of the box.&lt;/p&gt;

&lt;p&gt;So each procedure here ships as a folder the agent loads whole:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;skills/vps-basics/
  SKILL.md          YAML front matter, then numbered steps
  references/
    jail.local      the file step 3 copies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Front matter carries &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;version&lt;/code&gt;, &lt;code&gt;license&lt;/code&gt; and &lt;code&gt;platforms&lt;/code&gt;. Claude Code reads that layout natively. Any AgentSkills-spec loader reads the same folders, though only Claude Code and my own runner have been tested against these.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Test Runs the Skill's Own Steps
&lt;/h2&gt;

&lt;p&gt;A skill is a document, and a document rots. The harness closes that gap by executing the document:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--privileged&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$skill_dir&lt;/span&gt;&lt;span class="s2"&gt;/references:/refs:ro"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ubuntu:22.04 bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'
    apt-get update -qq &amp;amp;&amp;amp; apt-get install -y -qq ufw fail2ban
    ufw default deny incoming
    ufw allow 22/tcp &amp;amp;&amp;amp; ufw allow 80/tcp &amp;amp;&amp;amp; ufw allow 443/tcp
    ufw --force enable
    cp /refs/jail.local /etc/fail2ban/jail.local
    service fail2ban start
    ufw status | grep -q "Status: active"
    ufw status | grep -q "22/tcp"
    fail2ban-client status sshd | grep -q "Status for the jail: sshd"
  '&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those commands are the steps of &lt;code&gt;skills/vps-basics/SKILL.md&lt;/code&gt;, copied out. Edit the SKILL.md without editing the test and the two disagree; edit the test without editing the SKILL.md and the assertions stop matching. Either way the harness goes red before a reader gets the wrong version.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tests/run.sh&lt;/code&gt; walks every &lt;code&gt;tests/&amp;lt;name&amp;gt;.sh&lt;/code&gt;, skips a skill whose front matter says &lt;code&gt;host-specific: true&lt;/code&gt;, and exits non-zero on the first failure. One skill is host-specific: &lt;code&gt;wan-failover-uplink-guard&lt;/code&gt; needs two physical uplinks, and no container gives it those.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Ten Cover
&lt;/h2&gt;

&lt;p&gt;Free and MIT, in the public repo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;vps-basics&lt;/code&gt;: ufw default-deny plus a fail2ban sshd jail on a fresh box.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backup-restore-drill&lt;/code&gt;: every backup step paired with a restore step, so a backup counts only after it has been read back.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;service-health-check&lt;/code&gt;: process, port and HTTP checked in that order.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;systemd-unit-authoring&lt;/code&gt;: a script turned into a unit that restarts on crash and starts on boot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Paid once the checkout opens, which it has yet to do: &lt;code&gt;caddy-reverse-proxy&lt;/code&gt;, &lt;code&gt;tailscale-funnel&lt;/code&gt;, &lt;code&gt;pi-hardening&lt;/code&gt;, &lt;code&gt;telegram-bot-deployment&lt;/code&gt;, &lt;code&gt;wan-failover-uplink-guard&lt;/code&gt;, &lt;code&gt;wol-wake-and-remote-shutdown&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Three Layers in a Health Check
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;service-health-check&lt;/code&gt; runs process, then port, then HTTP, and stops at the first failure. Each layer catches what the layer above misses. A process check alone passes a hung process that still holds its port. A port check alone passes an app that accepts the connection and returns 500 to every request. Only the HTTP check reads what a user would read.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Does Not Prove
&lt;/h2&gt;

&lt;p&gt;A container test proves the steps run on a clean Ubuntu 22.04. Running on your box, with your kernel and your existing firewall rules, is a separate claim, and no skill in the pack makes it.&lt;/p&gt;

&lt;p&gt;Ten skills is also a small sample for a format claim. The layout may need changing once a third loader reads it.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/automate-it-all/agent-skills-pack" rel="noopener noreferrer"&gt;https://github.com/automate-it-all/agent-skills-pack&lt;/a&gt;&lt;br&gt;
Paid six: &lt;a href="https://automate-it-all.win/skills/" rel="noopener noreferrer"&gt;https://automate-it-all.win/skills/&lt;/a&gt;&lt;br&gt;
Questions: &lt;a href="mailto:skills@automate-it-all.win"&gt;skills@automate-it-all.win&lt;/a&gt;&lt;br&gt;
Who builds this: &lt;a href="https://fidel-perez.github.io/portfolio/" rel="noopener noreferrer"&gt;https://fidel-perez.github.io/portfolio/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>ai</category>
      <category>homelab</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
