<?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: pratikbin</title>
    <description>The latest articles on DEV Community by pratikbin (@pratikbin).</description>
    <link>https://dev.to/pratikbin</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3888247%2F8425d2c9-6a25-4bd7-af71-669911159255.png</url>
      <title>DEV Community: pratikbin</title>
      <link>https://dev.to/pratikbin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pratikbin"/>
    <language>en</language>
    <item>
      <title>Run NextDNS and Tailscale together without breaking MagicDNS</title>
      <dc:creator>pratikbin</dc:creator>
      <pubDate>Wed, 06 May 2026 09:56:09 +0000</pubDate>
      <link>https://dev.to/pratikbin/run-nextdns-and-tailscale-together-without-breaking-magicdns-4b06</link>
      <guid>https://dev.to/pratikbin/run-nextdns-and-tailscale-together-without-breaking-magicdns-4b06</guid>
      <description>&lt;p&gt;If you ssh into a tailnet host by name and your terminal answers &lt;code&gt;Unknown host&lt;/code&gt;, NextDNS is probably eating your queries before Tailscale sees them.&lt;/p&gt;

&lt;p&gt;Here's why, and a one-command fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The conflict
&lt;/h2&gt;

&lt;p&gt;NextDNS ships an Apple Configuration Profile (&lt;code&gt;apple.nextdns.io&lt;/code&gt;) that installs a system-wide DNS-over-HTTPS handler. The profile is tidy, signed, and ten-second setup — but it captures &lt;strong&gt;every&lt;/strong&gt; query, including ones meant for your tailnet.&lt;/p&gt;

&lt;p&gt;Tailscale's MagicDNS lives at &lt;code&gt;100.100.100.100&lt;/code&gt;. Names like &lt;code&gt;mybox.tailnet-name.ts.net&lt;/code&gt; only resolve there. NextDNS doesn't know your tailnet, so it asks the public DNS root, gets &lt;code&gt;NXDOMAIN&lt;/code&gt;, and your shell gives up.&lt;/p&gt;

&lt;p&gt;The usual macOS escape hatch — dropping a file in &lt;code&gt;/etc/resolver/&lt;/code&gt; — looks like it works:&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"nameserver 100.100.100.100"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/resolver/your-tailnet.ts.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;scutil --dns&lt;/code&gt; even shows the new resolver. But Configuration Profiles outrank &lt;code&gt;/etc/resolver&lt;/code&gt;, so the file is ignored. Silent failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;Replace the profile with NextDNS's CLI client. The CLI supports per-domain forwarders. Same profile, same blocklists, same dashboard — plus split DNS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Remove the Apple profile&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;System Settings → General → Device Management → NextDNS → Remove&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Install the CLI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;nextdns/tap/nextdns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Install with a forwarder for your tailnet&lt;/strong&gt;&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="nb"&gt;sudo &lt;/span&gt;nextdns &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-profile&lt;/span&gt; YOUR_PROFILE_ID &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-forwarder&lt;/span&gt; &lt;span class="s1"&gt;'your-tailnet.ts.net=100.100.100.100'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-forwarder&lt;/span&gt; &lt;span class="s1"&gt;'ts.net=100.100.100.100'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-report-client-info&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The format is &lt;code&gt;DOMAIN=SERVER&lt;/code&gt;, not the dnsmasq-style &lt;code&gt;/DOMAIN/SERVER&lt;/code&gt; — the CLI rejects slashes with a confusing "not a valid IP address" error.&lt;/p&gt;

&lt;p&gt;The second forwarder catches MagicDNS short names and any other &lt;code&gt;*.ts.net&lt;/code&gt; host. Drop it if you only want one tailnet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Verify&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig mybox.your-tailnet.ts.net    &lt;span class="c"&gt;# → 100.x.y.z (Tailscale)&lt;/span&gt;
dig example.com                   &lt;span class="c"&gt;# → public IP via NextDNS&lt;/span&gt;
ping mybox.your-tailnet.ts.net    &lt;span class="c"&gt;# works in your shell, not just dig&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last check matters. &lt;code&gt;dig&lt;/code&gt; ignores the resolver chain; &lt;code&gt;ping&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, and your apps don't. If both pass, you're done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this works
&lt;/h2&gt;

&lt;p&gt;The NextDNS daemon listens on &lt;code&gt;127.0.0.1:53&lt;/code&gt; and becomes the system resolver. For each query it checks forwarders first, then falls back to the NextDNS DoH endpoint. Tailscale's &lt;code&gt;100.100.100.100&lt;/code&gt; only needs to be reachable, which it is whenever &lt;code&gt;tailscaled&lt;/code&gt; is running.&lt;/p&gt;

&lt;p&gt;NextDNS keeps filtering, analytics, and parental controls. Tailscale keeps MagicDNS. No fights.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;System-wide DNS-over-HTTPS profiles are convenient until you need split DNS. If you run a VPN with its own resolver — Tailscale, ZeroTier, WireGuard with &lt;code&gt;dns=&lt;/code&gt; — switch to a daemon that supports forwarders. Five minutes, no recurring pain.&lt;/p&gt;

</description>
      <category>tailscale</category>
      <category>nextdns</category>
      <category>macos</category>
      <category>networking</category>
    </item>
    <item>
      <title>Your product has an API. It still doesn't speak agent</title>
      <dc:creator>pratikbin</dc:creator>
      <pubDate>Tue, 21 Apr 2026 11:30:00 +0000</pubDate>
      <link>https://dev.to/pratikbin/your-product-has-an-api-it-still-doesnt-speak-agent-30a8</link>
      <guid>https://dev.to/pratikbin/your-product-has-an-api-it-still-doesnt-speak-agent-30a8</guid>
      <description>&lt;p&gt;Most developer tools are built for two audiences: humans and software. Humans get docs and dashboards. Software gets APIs, SDKs, and CLIs. Agents sit awkwardly in the middle. They can read, they can call APIs, they can follow instructions, but they still can't answer a basic question when they land on your domain: what does this product actually know how to help me do? Ready to copy prompt at the end&lt;/p&gt;

&lt;p&gt;I think that's a real gap. We just closed it on CreateOS, and more companies should do the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agents still need to be told everything
&lt;/h2&gt;

&lt;p&gt;If Claude Code or OpenCode needs to deploy an app, it doesn't automatically know your platform exists. You can put instructions in &lt;code&gt;CLAUDE.md&lt;/code&gt;; we do that too. But that only helps inside a specific repo. An MCP server helps, but only after someone installs it. &lt;code&gt;llms.txt&lt;/code&gt; is useful, but it's descriptive. It tells an agent what your product is, not how to use it.&lt;/p&gt;

&lt;p&gt;So today, most agents are still operating on tribal knowledge and prompt glue. That's not a great long-term interface.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/cloudflare/agent-skills-discovery-rfc" rel="noopener noreferrer"&gt;Agent Skills Discovery RFC&lt;/a&gt; is a clean fix for this. Think &lt;code&gt;robots.txt&lt;/code&gt;, but for product capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we shipped
&lt;/h2&gt;

&lt;p&gt;Starting today, &lt;code&gt;https://createos.nodeops.network/.well-known/agent-skills/index.json&lt;/code&gt; returns a machine-readable index of every skill our platform offers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;https://schemas.agentskills.io/discovery/0.2.0/schema.json&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"skills"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"createos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"archive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deploy ANYTHING to production on CreateOS cloud platform..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/.well-known/agent-skills/createos.tar.gz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"digest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:740b1bf8c464aa6148a3eb9d666f2542..."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nodeops-auth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"skill-md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Add NodeOps PKCE OAuth authentication to a Next.js app..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/.well-known/agent-skills/nodeops-auth/SKILL.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"digest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:ca197a7ca9fbc5561a6b71c02ea3652..."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An agent fetches one URL and gets the shortlist. Roughly 100 tokens per skill. No repo cloning, no scraping docs, no custom integration work just to understand what the platform can do.&lt;/p&gt;

&lt;p&gt;When the task matches something specific like "deploy my app" or "add NodeOps auth," the agent pulls only that skill, verifies the sha256 digest, and moves on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Progressive disclosure is the part they got right
&lt;/h2&gt;

&lt;p&gt;The smartest part of the RFC is that it doesn't force you to dump everything into context up front.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;When&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;name&lt;/code&gt; + &lt;code&gt;description&lt;/code&gt; from &lt;code&gt;index.json&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Startup / probing&lt;/td&gt;
&lt;td&gt;~100 tokens/skill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Full &lt;code&gt;SKILL.md&lt;/code&gt; body&lt;/td&gt;
&lt;td&gt;When skill is activated&lt;/td&gt;
&lt;td&gt;&amp;lt;5k tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Scripts, references, configs&lt;/td&gt;
&lt;td&gt;On demand&lt;/td&gt;
&lt;td&gt;As needed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Our &lt;code&gt;createos&lt;/code&gt; skill bundles deployment scripts, API references, and config templates at about 28 KB. An agent working on a simple auth task never has to touch any of that. It grabs &lt;code&gt;nodeops-auth/SKILL.md&lt;/code&gt; at about 6 KB and moves on. That's the whole point. Context is expensive. Don't waste it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we built it
&lt;/h2&gt;

&lt;p&gt;We kept the implementation boring on purpose: one build-time script and static files.&lt;/p&gt;

&lt;p&gt;No route handlers. No cold starts. No database read just to answer a well-known URL.&lt;/p&gt;

&lt;p&gt;Build pipeline (&lt;code&gt;scripts/build-agent-skills.mts&lt;/code&gt;, about 200 lines):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;git clone --depth 1&lt;/code&gt; the skills repo into &lt;code&gt;.agent-skills-src/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;For each skill directory, read &lt;code&gt;SKILL.md&lt;/code&gt;, parse frontmatter (&lt;code&gt;name&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;If the skill is just a &lt;code&gt;SKILL.md&lt;/code&gt; → copy it. If it has supporting files → tar.gz it&lt;/li&gt;
&lt;li&gt;Compute &lt;code&gt;sha256&lt;/code&gt; digests, write &lt;code&gt;index.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It runs as a &lt;code&gt;prebuild&lt;/code&gt; hook before every &lt;code&gt;next build&lt;/code&gt; and &lt;code&gt;build:cloudflare&lt;/code&gt;, so the published skills stay in sync with upstream.&lt;/p&gt;

&lt;p&gt;Serving is just static files in &lt;code&gt;public/.well-known/agent-skills/&lt;/code&gt; behind Cloudflare Pages. Three header rules in &lt;code&gt;next.config.ts&lt;/code&gt; handle the RFC requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;index.json&lt;/code&gt; → &lt;code&gt;application/json; charset=utf-8&lt;/code&gt; + CORS + &lt;code&gt;max-age=60, s-maxage=300&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.md&lt;/code&gt; → &lt;code&gt;text/markdown; charset=utf-8&lt;/code&gt; + CORS + &lt;code&gt;max-age=300, s-maxage=3600&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.tar.gz&lt;/code&gt; → &lt;code&gt;application/gzip&lt;/code&gt; + CORS + &lt;code&gt;max-age=300, s-maxage=3600&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We keep the index TTL short so new skills show up quickly. Artifacts get a longer TTL because they're digest-pinned. If the sha256 matches, the file is still the file.&lt;/p&gt;

&lt;p&gt;Serving cost is basically zero because it's static content on a CDN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why more companies should publish this
&lt;/h2&gt;

&lt;p&gt;If you run a platform, an API, or a developer tool, you should seriously consider publishing &lt;code&gt;/.well-known/agent-skills/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, it's cheap. A &lt;code&gt;SKILL.md&lt;/code&gt;, some frontmatter, a small build step, and a few headers. We did the first version in an afternoon.&lt;/p&gt;

&lt;p&gt;Second, it's standard. You're not inventing another one-off agent integration. You're publishing something any RFC-compliant client can understand.&lt;/p&gt;

&lt;p&gt;Third, it composes well. Our &lt;code&gt;createos&lt;/code&gt; skill teaches an agent how to deploy. Our &lt;code&gt;nodeops-auth&lt;/code&gt; skill teaches it how to wire auth. Another vendor can publish observability or billing or incident-response skills the same way. The agent can mix and match without every platform building a separate integration for every other platform.&lt;/p&gt;

&lt;p&gt;And finally, it's probably where this goes anyway. Claude Code doesn't auto-probe &lt;code&gt;/.well-known/agent-skills/&lt;/code&gt; yet. OpenCode doesn't either. Fine. &lt;code&gt;robots.txt&lt;/code&gt; was useful before every crawler agreed on it too. Standards usually show up before the tooling catches up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trade-off
&lt;/h2&gt;

&lt;p&gt;This is still pull, not push. Agents need to know your domain exists before they can ask for &lt;code&gt;/.well-known/agent-skills/index.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So no, this doesn't solve discovery all by itself. There's no master directory yet. In practice, the bridge is simple: mention the URL in your docs, your &lt;code&gt;AGENTS.md&lt;/code&gt;, your MCP server docs, or your &lt;code&gt;llms.txt&lt;/code&gt;. That's enough to make it usable today while clients catch up.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to add it to your product
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Write your skills.&lt;/strong&gt; Create a directory per skill with a &lt;code&gt;SKILL.md&lt;/code&gt;. The frontmatter needs &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt;. The body is instructions for the agent. That's the whole format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Package and serve.&lt;/strong&gt; Solo skills ship as plain &lt;code&gt;SKILL.md&lt;/code&gt;. Skills with supporting files (scripts, references) ship as &lt;code&gt;.tar.gz&lt;/code&gt;. Compute sha256 digests. Write &lt;code&gt;index.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add headers.&lt;/strong&gt; &lt;code&gt;Content-Type&lt;/code&gt;, &lt;code&gt;Access-Control-Allow-Origin: *&lt;/code&gt;, and tiered &lt;code&gt;Cache-Control&lt;/code&gt;. Three URL patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Publish.&lt;/strong&gt; Put it behind your domain. &lt;code&gt;https://your-domain.com/.well-known/agent-skills/index.json&lt;/code&gt;. Done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwlbe44kwh0lxm5wlwxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwlbe44kwh0lxm5wlwxf.png" alt="RFC implementation on https://nodeops.networ"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The RFC is &lt;a href="https://github.com/cloudflare/agent-skills-discovery-rfc" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The schema is &lt;a href="https://schemas.agentskills.io/discovery/0.2.0/schema.json" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it
&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;# this will fail&lt;/span&gt;
npx skills add https://createos.nodeops.network &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;there is active &lt;a href="https://github.com/vercel-labs/skills/issues/985#issuecomment-4304244935" rel="noopener noreferrer"&gt;issue&lt;/a&gt; on skills to add support for RFC v0.2.0&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Or just hand this to your coding agent
&lt;/h2&gt;

&lt;p&gt;Don't feel like reading a build script? Fill in the four inputs at the top, paste this into Claude Code, Cursor, or Copilot inside the target repo, and let it wire everything up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Add &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Agent Skills Discovery RFC v0.2.0&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://github.com/cloudflare/agent-skills-discovery-rfc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; to this site so agents auto-discover our skills at &lt;span class="sb"&gt;`/.well-known/agent-skills/index.json`&lt;/span&gt;.

&lt;span class="gs"&gt;**Inputs**&lt;/span&gt; (fill in before pasting):
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Skills source**&lt;/span&gt;: &lt;span class="sb"&gt;`&amp;lt;git URL of repo holding skills&amp;gt;`&lt;/span&gt; on branch &lt;span class="sb"&gt;`&amp;lt;ref&amp;gt;`&lt;/span&gt;, skills live under path &lt;span class="sb"&gt;`&amp;lt;skills/skills&amp;gt;`&lt;/span&gt; (each subdir = one skill with a &lt;span class="sb"&gt;`SKILL.md`&lt;/span&gt; containing &lt;span class="sb"&gt;`name`&lt;/span&gt; + &lt;span class="sb"&gt;`description`&lt;/span&gt; frontmatter).
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Host framework**&lt;/span&gt;: &lt;span class="sb"&gt;`&amp;lt;Next.js app router | Astro | SvelteKit | plain static | Express | other&amp;gt;`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Public dir**&lt;/span&gt;: &lt;span class="sb"&gt;`&amp;lt;public | static | dist | ...&amp;gt;`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Production origin**&lt;/span&gt;: &lt;span class="sb"&gt;`&amp;lt;https://example.com&amp;gt;`&lt;/span&gt;.

&lt;span class="gs"&gt;**Deliverables**&lt;/span&gt; (do all):
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**Build script**&lt;/span&gt; (zero new deps; Node built-ins + system &lt;span class="sb"&gt;`git`&lt;/span&gt; + system &lt;span class="sb"&gt;`tar`&lt;/span&gt;):
&lt;span class="p"&gt;   -&lt;/span&gt; Clone the skills repo shallow (&lt;span class="sb"&gt;`git clone --depth 1 --branch &amp;lt;ref&amp;gt;`&lt;/span&gt;) into a gitignored &lt;span class="sb"&gt;`.agent-skills-src/`&lt;/span&gt;. Re-runs do &lt;span class="sb"&gt;`git fetch &amp;amp;&amp;amp; git reset --hard FETCH_HEAD`&lt;/span&gt;.
&lt;span class="p"&gt;   -&lt;/span&gt; Iterate each skill dir under the configured path. Read &lt;span class="sb"&gt;`SKILL.md`&lt;/span&gt;, parse YAML frontmatter, require &lt;span class="sb"&gt;`name`&lt;/span&gt; + &lt;span class="sb"&gt;`description`&lt;/span&gt;. Validate &lt;span class="sb"&gt;`name`&lt;/span&gt; against &lt;span class="sb"&gt;`^[a-z0-9]+(-[a-z0-9]+)*$`&lt;/span&gt;, length 1–64. Fail build on violation.
&lt;span class="p"&gt;   -&lt;/span&gt; If dir contains only &lt;span class="sb"&gt;`SKILL.md`&lt;/span&gt; → copy to &lt;span class="sb"&gt;`&amp;lt;public&amp;gt;/.well-known/agent-skills/&amp;lt;name&amp;gt;/SKILL.md`&lt;/span&gt;, &lt;span class="sb"&gt;`type: "skill-md"`&lt;/span&gt;.
&lt;span class="p"&gt;   -&lt;/span&gt; Else → &lt;span class="sb"&gt;`tar -czf &amp;lt;public&amp;gt;/.well-known/agent-skills/&amp;lt;name&amp;gt;.tar.gz --sort=name --mtime=@&amp;lt;upstream-commit-ts&amp;gt; -C &amp;lt;skill-dir&amp;gt; .`&lt;/span&gt;, &lt;span class="sb"&gt;`type: "archive"`&lt;/span&gt;. Fall back without repro flags on BSD tar.
&lt;span class="p"&gt;   -&lt;/span&gt; Compute &lt;span class="sb"&gt;`sha256:&amp;lt;hex&amp;gt;`&lt;/span&gt; over the served artifact bytes.
&lt;span class="p"&gt;   -&lt;/span&gt; Write &lt;span class="sb"&gt;`&amp;lt;public&amp;gt;/.well-known/agent-skills/index.json`&lt;/span&gt;:
     &lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;
&lt;/span&gt;
json
     { "$schema": "https://schemas.agentskills.io/discovery/0.2.0/schema.json",
       "skills": [{ "name": "...", "type": "skill-md|archive", "description": "...", "url": "/.well-known/agent-skills/...", "digest": "sha256:..." }] }


     &lt;span class="p"&gt;```&lt;/span&gt;
&lt;span class="p"&gt;   -&lt;/span&gt; Sort skills alphabetically by &lt;span class="sb"&gt;`name`&lt;/span&gt; (stable digest of &lt;span class="sb"&gt;`index.json`&lt;/span&gt;).
&lt;span class="p"&gt;
2.&lt;/span&gt; &lt;span class="gs"&gt;**Wire as prebuild hook**&lt;/span&gt; for the host framework (e.g. npm &lt;span class="sb"&gt;`prebuild`&lt;/span&gt; script, Astro integration, CI step) so output regenerates on every deploy.
&lt;span class="p"&gt;
3.&lt;/span&gt; &lt;span class="gs"&gt;**HTTP response headers**&lt;/span&gt; (per framework's config — &lt;span class="sb"&gt;`next.config.ts`&lt;/span&gt; &lt;span class="sb"&gt;`headers()`&lt;/span&gt;, &lt;span class="sb"&gt;`astro.config`&lt;/span&gt; headers adapter, &lt;span class="sb"&gt;`_headers`&lt;/span&gt; for Pages/Netlify, nginx/express middleware, etc.):
&lt;span class="p"&gt;   -&lt;/span&gt; &lt;span class="sb"&gt;`/.well-known/agent-skills/index.json`&lt;/span&gt; → &lt;span class="sb"&gt;`Content-Type: application/json; charset=utf-8`&lt;/span&gt;, &lt;span class="sb"&gt;`Access-Control-Allow-Origin: *`&lt;/span&gt;, &lt;span class="sb"&gt;`Cache-Control: public, max-age=60, s-maxage=300`&lt;/span&gt;.
&lt;span class="p"&gt;   -&lt;/span&gt; &lt;span class="sb"&gt;`/.well-known/agent-skills/*.md`&lt;/span&gt; → &lt;span class="sb"&gt;`Content-Type: text/markdown; charset=utf-8`&lt;/span&gt;, &lt;span class="sb"&gt;`Access-Control-Allow-Origin: *`&lt;/span&gt;, &lt;span class="sb"&gt;`Cache-Control: public, max-age=300, s-maxage=3600`&lt;/span&gt;.
&lt;span class="p"&gt;   -&lt;/span&gt; &lt;span class="sb"&gt;`/.well-known/agent-skills/*.tar.gz`&lt;/span&gt; → &lt;span class="sb"&gt;`Content-Type: application/gzip`&lt;/span&gt;, &lt;span class="sb"&gt;`Access-Control-Allow-Origin: *`&lt;/span&gt;, &lt;span class="sb"&gt;`Cache-Control: public, max-age=300, s-maxage=3600`&lt;/span&gt;.
&lt;span class="p"&gt;
4.&lt;/span&gt; &lt;span class="gs"&gt;**Gitignore**&lt;/span&gt;: &lt;span class="sb"&gt;`.agent-skills-src/`&lt;/span&gt; and &lt;span class="sb"&gt;`&amp;lt;public&amp;gt;/.well-known/agent-skills/`&lt;/span&gt;.
&lt;span class="p"&gt;
5.&lt;/span&gt; &lt;span class="gs"&gt;**Verify locally**&lt;/span&gt;:
&lt;span class="p"&gt;   -&lt;/span&gt; &lt;span class="sb"&gt;`curl -sS http://localhost:&amp;lt;port&amp;gt;/.well-known/agent-skills/index.json | jq .`&lt;/span&gt; returns valid JSON with &lt;span class="sb"&gt;`$schema`&lt;/span&gt; + &lt;span class="sb"&gt;`skills[]`&lt;/span&gt;.
&lt;span class="p"&gt;   -&lt;/span&gt; Re-hash every served artifact and confirm match against &lt;span class="sb"&gt;`digest`&lt;/span&gt; in the index.
&lt;span class="p"&gt;   -&lt;/span&gt; Response headers match section 3.
&lt;span class="p"&gt;
6.&lt;/span&gt; &lt;span class="gs"&gt;**Post-deploy check**&lt;/span&gt;: same three &lt;span class="sb"&gt;`curl`&lt;/span&gt; calls against the production origin.

&lt;span class="gs"&gt;**Constraints**&lt;/span&gt;:
&lt;span class="p"&gt;-&lt;/span&gt; Do not add runtime dependencies. Hand-parse the two frontmatter fields (&lt;span class="sb"&gt;`name:`&lt;/span&gt; and &lt;span class="sb"&gt;`description:`&lt;/span&gt;) with a regex — full YAML is overkill here.
&lt;span class="p"&gt;-&lt;/span&gt; Static output only. No server route handler — agents must be able to fetch from edge/CDN with no origin cold start.
&lt;span class="p"&gt;-&lt;/span&gt; Never commit generated artifacts or the cloned skills repo.
&lt;span class="p"&gt;-&lt;/span&gt; Skip skills with missing/invalid frontmatter with a warning. Hard-fail on bad &lt;span class="sb"&gt;`name`&lt;/span&gt; format.

&lt;span class="gs"&gt;**Reference implementation**&lt;/span&gt; (adapt, don't copy-paste): https://github.com/cloudflare/agent-skills-discovery-rfc/tree/main/examples

Return a summary of: files created, files modified, verification commands run, and production URL of the new &lt;span class="sb"&gt;`index.json`&lt;/span&gt;.
&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;
&lt;/span&gt;
`

Four inputs in, working `/.well-known/agent-skills/` out. No runtime deps, static output, deploy hook wired.

Agents are already reading `llms.txt`. They're already talking to MCP servers. This fills a different gap: a standard way to publish what your product can help an agent do.

If you build developer tools, I think you should publish one.

Agents are already reading `llms.txt`. They're already talking to MCP servers. This fills a different gap: a standard way to publish what your product can help an agent do.

If you build developer tools, I think you should publish one.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
