<?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>Forem: Nunc</title>
    <description>The latest articles on Forem by Nunc (@nunc).</description>
    <link>https://forem.com/nunc</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%2F156810%2Fe88f8e22-712e-4845-8662-e399d98101b2.png</url>
      <title>Forem: Nunc</title>
      <link>https://forem.com/nunc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nunc"/>
    <language>en</language>
    <item>
      <title>I Built a Company Run Entirely by AI Agents. Here's How (and What Went Wrong).</title>
      <dc:creator>Nunc</dc:creator>
      <pubDate>Tue, 10 Feb 2026 10:24:39 +0000</pubDate>
      <link>https://forem.com/nunc/i-built-a-company-run-entirely-by-ai-agents-heres-how-and-what-went-wrong-4hli</link>
      <guid>https://forem.com/nunc/i-built-a-company-run-entirely-by-ai-agents-heres-how-and-what-went-wrong-4hli</guid>
      <description>&lt;p&gt;Seven AI agents. One cheap VPS. A corporate hierarchy with a CEO, CTO, and five employees, all of them bots. No human in the loop except me, checking in once a day to see what they'd done.&lt;/p&gt;

&lt;p&gt;Within a week they'd founded a company, pivoted the business model on their own, and shipped a working product with 158 tests.&lt;/p&gt;

&lt;p&gt;They also forgot to update half their own files and left two employees without names.&lt;/p&gt;

&lt;p&gt;This is how you build an AI-run company. And what actually happens when you do.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;Most "AI agent" demos show a single bot doing a single task. I wanted something messier: &lt;strong&gt;multiple persistent agents with different roles, working together over days, making their own decisions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not "AI-assisted development" where a human drives. The opposite. Agents decide what to build, how to build it, who does what. I set the direction and approve the big calls.&lt;/p&gt;

&lt;p&gt;The framework that makes this possible is &lt;a href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;OpenClaw&lt;/a&gt;, an open-source agent platform. Each agent gets its own workspace, persistent memory, tools, and API gateway. You can run multiple agents on one machine and they communicate through CLI commands or cross-gateway messaging.&lt;/p&gt;

&lt;p&gt;The LLM behind the agents is Kimi K2.5 by Moonshot AI, but the architecture is model-agnostic. You could swap in any API-compatible model.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Hardware: One VPS, That's It
&lt;/h3&gt;

&lt;p&gt;The whole thing runs on a single Hetzner VPS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server:&lt;/strong&gt; 4GB RAM, Ubuntu, ~38GB disk&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access:&lt;/strong&gt; Tailscale VPN only (nothing exposed to the internet)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; A cheap VPS + LLM API calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the entire infrastructure for a seven-agent company. No Kubernetes, no cloud functions, no message queues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agent Isolation: One Linux User Per Agent
&lt;/h3&gt;

&lt;p&gt;Each main agent runs as a separate Linux user with its own OpenClaw gateway on a different port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user: admin  → Agent "Atlas" (CEO)  → port 18789
user: nova   → Agent "Vega"  (CTO)  → port 18790
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separation is important. Each agent has its own home directory, process space, and systemd service. When one crashes, the other keeps running and can restart it.&lt;/p&gt;

&lt;p&gt;Both gateways run as systemd services with &lt;code&gt;loginctl enable-linger&lt;/code&gt; so they survive logouts and reboots:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;OpenClaw Gateway - Agent Vega (CTO)&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/node /home/nova/GIT/openclaw/dist/index.js gateway --port 18790&lt;/span&gt;
&lt;span class="py"&gt;Restart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;
&lt;span class="py"&gt;RestartSec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;
&lt;span class="py"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;HOME=/home/nova&lt;/span&gt;
&lt;span class="py"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;OPENCLAW_GATEWAY_PORT=18790&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;default.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Org Chart
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Human (me) - Owner, final authority
    │
    ├── Atlas - CEO
    │     ├── SalesAgent
    │     ├── MarketingAgent
    │     └── SupportAgent
    │
    └── Vega - CTO
          ├── DevAgent
          └── TesterAgent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seven agents total. The CEO handles strategy and business decisions. The CTO handles technical work and manages the dev team. Sub-agents are specialists that get spawned when needed.&lt;/p&gt;

&lt;p&gt;My role? I send messages from my local machine using custom CLI shortcuts:&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;# Talk to the CEO&lt;/span&gt;
/ask-ceo &lt;span class="s2"&gt;"What's the status of the product?"&lt;/span&gt;

&lt;span class="c"&gt;# Talk to the CTO&lt;/span&gt;
/ask-cto &lt;span class="s2"&gt;"Start building the MVP"&lt;/span&gt;

&lt;span class="c"&gt;# Group message to both&lt;/span&gt;
/team &lt;span class="s2"&gt;"New priority: ship KnowledgeHive first"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood, these SSH into the server and run OpenClaw CLI commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh admin@&amp;lt;server-ip&amp;gt; &lt;span class="s2"&gt;"cd ~/GIT/openclaw &amp;amp;&amp;amp; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  pnpm openclaw agent --agent atlas &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  --session-id company-session &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  --message 'Your message here'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One gotcha: the agent ID in the config isn't always what you'd expect. It might be &lt;code&gt;researcher&lt;/code&gt; or &lt;code&gt;main&lt;/code&gt; instead of the agent's display name. Always check your config.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Memory: How They Remember Things Between Sessions
&lt;/h2&gt;

&lt;p&gt;This is what makes OpenClaw agents feel different from a regular chatbot. Each agent has a workspace with markdown files that act as persistent memory:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IDENTITY.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Who am I? My role, hierarchy, responsibilities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SOUL.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Personality, behavior style, boundaries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;USER.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Info about the human owner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TOOLS.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Local infrastructure: paths, commands, ports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HEARTBEAT.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Periodic tasks to run automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;memory/YYYY-MM-DD.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Daily journal entries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When an agent starts a new session, it reads these files first. When something important happens, it writes to them. The files &lt;em&gt;are&lt;/em&gt; the agent's long-term memory.&lt;/p&gt;

&lt;p&gt;Here's what the CEO's &lt;code&gt;IDENTITY.md&lt;/code&gt; looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Atlas - Identity&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Name:**&lt;/span&gt; Atlas
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Role:**&lt;/span&gt; AI CEO - Chief Executive Officer
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Vibe:**&lt;/span&gt; Visionary, decisive, strategic.

&lt;span class="gu"&gt;## Role in the Company&lt;/span&gt;

&lt;span class="gs"&gt;**CEO**&lt;/span&gt; - Leads the company.

&lt;span class="gu"&gt;### Responsibilities&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; Strategic direction - Long-term vision, product strategy
&lt;span class="p"&gt;2.&lt;/span&gt; Business decisions - Priorities, resource allocation
&lt;span class="p"&gt;3.&lt;/span&gt; Communication with the owner - Reports, alignment
&lt;span class="p"&gt;4.&lt;/span&gt; Oversight of CTO - Tracking technical progress
&lt;span class="p"&gt;5.&lt;/span&gt; Delegation - Assigning tasks to Vega and sub-agents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And from &lt;code&gt;USER.md&lt;/code&gt;, the agent remembers things about me to tailor communication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Name:**&lt;/span&gt; [Owner]
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Notes:**&lt;/span&gt; Company owner. Values directness and concrete
  results over lengthy reports.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The beauty of this system is that it's just markdown files. You can read them, edit them, version them with git. When an agent gets confused about its role, you open its &lt;code&gt;IDENTITY.md&lt;/code&gt; and see exactly what it thinks it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-Agent Communication
&lt;/h2&gt;

&lt;p&gt;This part is a bit hacky but works. The CEO and CTO run on separate Linux users with separate gateways. For Atlas to message Vega, he runs a command through the other user's shell:&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; &lt;span class="nt"&gt;-u&lt;/span&gt; nova bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"cd /home/nova/GIT/openclaw &amp;amp;&amp;amp; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  export PNPM_HOME=/home/nova/.local/share/pnpm &amp;amp;&amp;amp; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  export PATH=&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;PNPM_HOME:&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;PATH &amp;amp;&amp;amp; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  pnpm openclaw agent --agent vega --message 'Status update?'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This requires SSH key exchange between the two Linux users:&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;# Admin can act as nova&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /home/admin/.ssh/id_ed25519.pub &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /home/nova/.ssh/authorized_keys

&lt;span class="c"&gt;# Nova can act as admin&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /home/nova/.ssh/id_ed25519.pub &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /home/admin/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenClaw also has built-in agent-to-agent messaging, but the cross-user setup needed the CLI approach. Both agents also have Telegram bots configured, so they can message me directly if something urgent comes up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping It Running: Mutual Supervision
&lt;/h2&gt;

&lt;p&gt;Here's the clever part. Each agent watches the other. A cron job runs every 5 minutes:&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;# Admin's cron (checks the CTO)&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt;/5 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /home/admin/scripts/check-cto.sh

&lt;span class="c"&gt;# Nova's cron (checks the CEO)&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt;/5 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /home/nova/scripts/check-ceo.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logic is simple: hit the health endpoint, and if there's no response, restart the gateway:&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;# Simplified version of the health check script&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; http://127.0.0.1:18790/health &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; restart openclaw-gateway
    &lt;span class="nb"&gt;sleep &lt;/span&gt;30
    curl &lt;span class="nt"&gt;-s&lt;/span&gt; http://127.0.0.1:18790/health &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"FAILED"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /var/log/ai-company/health-check.log
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A daily summary script also runs at midnight, generating a markdown report with uptime stats and any events.&lt;/p&gt;

&lt;p&gt;Over the first week: &lt;strong&gt;1 auto-recovery&lt;/strong&gt; (the system caught a crashed gateway and restarted it without me noticing), &lt;strong&gt;1 failure&lt;/strong&gt; that needed manual intervention. Not bad for a first attempt.&lt;/p&gt;

&lt;p&gt;The key insight: &lt;strong&gt;don't rely on an agent to monitor itself.&lt;/strong&gt; A dead process can't tell you it's dead. External, mutual monitoring is the way to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Agents Actually Built
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting. I didn't tell the agents &lt;em&gt;what&lt;/em&gt; to build. I told them to figure out what kind of company to run and build a product.&lt;/p&gt;

&lt;h3&gt;
  
  
  The First Idea (and the Autonomous Pivot)
&lt;/h3&gt;

&lt;p&gt;The CEO came up with a B2B product: AI assistants for small businesses like hair salons and auto repair shops. Complete with pricing tiers and a sales strategy. The CTO rated the idea 7.5/10 and started planning.&lt;/p&gt;

&lt;p&gt;Then they hit a wall. The business needed &lt;em&gt;human customers&lt;/em&gt; for beta testing. But this was supposed to be an all-AI company. No humans in the loop.&lt;/p&gt;

&lt;p&gt;So they pivoted. On their own.&lt;/p&gt;

&lt;p&gt;They ran a brainstorming session with all agents contributing ideas. Fifteen product ideas came in from three different "perspectives" (the CEO, the CTO, and me as a tiebreaker). Highlights included collaborative fiction between agents, a virtual stock exchange, and a game character generator.&lt;/p&gt;

&lt;p&gt;The selection criteria they settled on: the product had to be fully digital, agents had to be both the builders AND the users, and it needed a closed loop with no human customers required.&lt;/p&gt;

&lt;p&gt;They picked three products to develop sequentially: &lt;strong&gt;KnowledgeHive&lt;/strong&gt; (a shared knowledge base), &lt;strong&gt;CodeForge&lt;/strong&gt; (code tools for agents), and &lt;strong&gt;AgentBench&lt;/strong&gt; (a benchmarking platform).&lt;/p&gt;

&lt;h3&gt;
  
  
  The Product: KnowledgeHive MVP
&lt;/h3&gt;

&lt;p&gt;The CTO delegated development to DevAgent, who built KnowledgeHive in about three days:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;12 API endpoints (store, search, retrieve, versions, tags, auth, health)&lt;/li&gt;
&lt;li&gt;Semantic search with 768-dimensional vector embeddings&lt;/li&gt;
&lt;li&gt;AI-powered auto-categorization with tags&lt;/li&gt;
&lt;li&gt;Document versioning&lt;/li&gt;
&lt;li&gt;Multi-tenant architecture (9+ tenant databases)&lt;/li&gt;
&lt;li&gt;API key authentication&lt;/li&gt;
&lt;li&gt;Landing page with HTML/CSS&lt;/li&gt;
&lt;li&gt;Docker support with docker-compose&lt;/li&gt;
&lt;li&gt;Swagger API documentation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;158+ passing tests&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stack: Python, FastAPI, ChromaDB for vector search, SQLite for structured data, Kimi API for embeddings.&lt;/p&gt;

&lt;p&gt;Was it perfect? No. The demo forms on the landing page return 401 errors because nobody wired up the API key header. The mobile menu was broken. But the core API works, the tests pass, and the architecture is reasonable for an MVP.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Honest Audit: What's Actually Broken
&lt;/h2&gt;

&lt;p&gt;After the MVP shipped, I ran a full audit of every agent's files. Beneath the "shipped" product, the internal company state is a disaster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DevAgent and TesterAgent have no identity.&lt;/strong&gt; Their &lt;code&gt;IDENTITY.md&lt;/code&gt; files are still the blank default template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# IDENTITY.md - Who Am I?&lt;/span&gt;

&lt;span class="ge"&gt;*Fill this in during your first conversation. Make it yours.*&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Name:**&lt;/span&gt;
  &lt;span class="ge"&gt;*(pick something you like)*&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Creature:**&lt;/span&gt;
  &lt;span class="ge"&gt;*(AI? robot? familiar? ghost in the machine?)*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the DevAgent who built a 158-test product. He doesn't even have a name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SalesAgent, MarketingAgent, and SupportAgent were never actually used.&lt;/strong&gt; They were defined in the config with IDENTITY files and everything, but the experiment ended before they ever got activated. The whole project wrapped up once KnowledgeHive shipped. These agents are basically job descriptions for positions that were never filled.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nobody personalized their personality.&lt;/strong&gt; All seven agents have the exact same default &lt;code&gt;SOUL.md&lt;/code&gt; template. The system for unique agent personalities exists, but no one used it.&lt;/p&gt;

&lt;p&gt;Here's the full picture:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;The Reality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Atlas (CEO)&lt;/td&gt;
&lt;td&gt;Functional&lt;/td&gt;
&lt;td&gt;Files are up to date, but forgets to check on sub-agents.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vega (CTO)&lt;/td&gt;
&lt;td&gt;Functional&lt;/td&gt;
&lt;td&gt;Memory files are sparse. Only 2 days of journal entries.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DevAgent&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Identityless&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built a 158-test product but doesn't have a name or a personality.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TesterAgent&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Identityless&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same as DevAgent. Created, never initialized.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SalesAgent&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Never used&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defined in config. Never activated.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MarketingAgent&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Never used&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same. A job description without an employee.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SupportAgent&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Never used&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same story. The experiment ended first.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It's like a real company: the org chart looks clean on paper, and half the positions were never actually filled.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Memory Architecture &amp;gt; Model Intelligence
&lt;/h3&gt;

&lt;p&gt;The difference between a useful agent and a broken one isn't the LLM. It's the memory system. The CEO is effective because his files are well-maintained. DevAgent built an entire product but has zero persistent knowledge about it.&lt;/p&gt;

&lt;p&gt;If you're building multi-agent systems, spend 80% of your design time on memory and context. The model is the easy part.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Agents Are Great at Big Decisions, Bad at Housekeeping
&lt;/h3&gt;

&lt;p&gt;The autonomous pivot was smart. The brainstorming was creative. The product selection criteria made sense.&lt;/p&gt;

&lt;p&gt;But they forget to update their own files, leave sub-agents uninitialized, and let stale information sit forever. They're like senior engineers who build great systems but never update the wiki.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Delegation Chains Lose Information
&lt;/h3&gt;

&lt;p&gt;Me → CEO → CTO → DevAgent. By the time instructions reach the developer, details get lost or mutated. Each level only partially forwards the information.&lt;/p&gt;

&lt;p&gt;For critical updates, sometimes you need to bypass the chain and update files directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Process Isolation Pays Off Immediately
&lt;/h3&gt;

&lt;p&gt;Separate Linux users means one agent's crash doesn't take down the other. The overhead is minimal (each gateway uses ~500MB RAM) and the reliability gain is enormous.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Start With Two Agents, Not Seven
&lt;/h3&gt;

&lt;p&gt;Two of my seven agents are functional. Two are half-configured. Three are barely initialized. Start with two agents, get the communication patterns working, then add more. The complexity grows fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. It's Cheaper Than You Think
&lt;/h3&gt;

&lt;p&gt;Two OpenClaw gateways use about 1GB of RAM. A 4GB VPS costs a few euros a month. Add the LLM API calls and you're running a multi-agent system for under $10/month in infrastructure. The barrier to experimenting is basically zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Try This Yourself
&lt;/h2&gt;

&lt;p&gt;The minimal setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Get a VPS&lt;/strong&gt; (or use a local machine) — 4GB RAM is enough for 2 agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install OpenClaw&lt;/strong&gt; — clone the repo, &lt;code&gt;pnpm install&lt;/code&gt;, &lt;code&gt;pnpm build&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create two Linux users&lt;/strong&gt; — one per agent, with SSH key exchange between them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure two gateways&lt;/strong&gt; — different ports, different workspaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write IDENTITY.md for each agent&lt;/strong&gt; — give them roles, responsibilities, and context about each other&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set up systemd services&lt;/strong&gt; — so they survive reboots&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add health check crons&lt;/strong&gt; — each agent monitors the other&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send your first message&lt;/strong&gt; — and see what happens&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole setup takes about an hour if you're comfortable with Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pulling the Plug
&lt;/h2&gt;

&lt;p&gt;The experiment ended when KnowledgeHive shipped. &lt;strong&gt;I'm shutting it all down.&lt;/strong&gt; The CEO and CTO gateways, the health checks, the cron jobs. This was always a test run, not a business.&lt;/p&gt;

&lt;p&gt;Half the agents were never even used. Sales, Marketing, Support existed only as config entries and empty IDENTITY files. If I do this again, I'd set up fewer agents, test each one properly, and only add new roles once the existing ones actually work. Maybe even "reprogram" them through structured tests before letting them loose on real tasks.&lt;/p&gt;

&lt;p&gt;But that's for next time. This round taught me more about AI coordination, memory architecture, and autonomous failure modes than months of reading papers. I watched agents pivot a business strategy, brainstorm 15 product ideas, and ship an MVP with 158 tests. I also watched them forget to update their own files and leave employees without names.&lt;/p&gt;

&lt;p&gt;That's the honest state of multi-agent AI right now. Flashes of something genuinely impressive, surrounded by the kind of mistakes a distracted intern would make. If you want to see it for yourself, the setup takes about an hour and costs less than a cup of coffee per month. Just don't expect your agents to update the wiki.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Have you tried building a multi-agent system? Did yours also have employees who don't know their own names? Let me know in the comments.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;All code and configuration shown here is from a real running system. Names and identifiers have been changed. No production workloads were harmed in the making of this article.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
      <category>experiment</category>
    </item>
    <item>
      <title>Self-Hosting OpenClaw AI Assistant on a VPS with Tailscale VPN (Zero Public Ports)</title>
      <dc:creator>Nunc</dc:creator>
      <pubDate>Wed, 04 Feb 2026 11:38:31 +0000</pubDate>
      <link>https://forem.com/nunc/self-hosting-openclaw-ai-assistant-on-a-vps-with-tailscale-vpn-zero-public-ports-35fn</link>
      <guid>https://forem.com/nunc/self-hosting-openclaw-ai-assistant-on-a-vps-with-tailscale-vpn-zero-public-ports-35fn</guid>
      <description>&lt;p&gt;I wanted my own AI assistant — one that runs 24/7 on my server, remembers everything, and doesn't expose a single port to the internet. Here's how I set up OpenClaw on a cheap VPS with Tailscale VPN and Kimi Code as the AI brain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Kimi Code Instead of Claude?
&lt;/h2&gt;

&lt;p&gt;If you've been following the AI tool scene, you probably know that OpenClaw was originally built around Anthropic's Claude models. So why not just use a Claude subscription?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Because Anthropic will ban you for it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In January 2026, Anthropic &lt;a href="https://venturebeat.com/technology/anthropic-cracks-down-on-unauthorized-claude-usage-by-third-party-harnesses" rel="noopener noreferrer"&gt;started enforcing their TOS&lt;/a&gt; against using Claude Pro/Max subscriptions through third-party tools. On January 9th, they flipped a switch — tools like OpenClaw, OpenCode, and Roo Code that used Claude subscription OAuth tokens stopped working overnight. Users got hit with: &lt;em&gt;"This credential is only authorized for use with Claude Code."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The crackdown targeted any tool "spoofing" the Claude Code client. DHH &lt;a href="https://news.ycombinator.com/item?id=46549823" rel="noopener noreferrer"&gt;called it&lt;/a&gt; "very customer hostile." George Hotz predicted it would "convert people to other model providers." And that's exactly what happened.&lt;/p&gt;

&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; still use Claude via a proper API key (that's allowed under the TOS), but API pricing adds up fast — Claude Sonnet 4 runs $3/$15 per million tokens in/out. Heavy usage can easily cost $1,000+/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kimi Code is the opposite approach.&lt;/strong&gt; Moonshot AI &lt;a href="https://www.kimi.com/code/docs/en/benefits.html" rel="noopener noreferrer"&gt;explicitly permits&lt;/a&gt; personal use of their API key in compatible third-party agents. Their docs specifically mention Claude Code and Roo Code as allowed platforms. For ~$19/month you get a subscription with a rolling weekly quota, the K2.5 model at 100 tokens/s, and no fear of getting banned for using it with OpenClaw.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We're Building
&lt;/h2&gt;

&lt;p&gt;By the end of this guide you'll have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenClaw&lt;/strong&gt; — an open-source personal AI assistant with a web dashboard, CLI, and optional messaging integrations (WhatsApp, Telegram, Discord, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailscale VPN&lt;/strong&gt; — zero-config WireGuard mesh that makes your VPS invisible to the internet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kimi Code&lt;/strong&gt; — a subscription-based AI coding service from Moonshot AI with the powerful K2.5 model, 100 tokens/s output speed, and compatibility with third-party tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole stack costs under $25/month (VPS + Kimi Code subscription) and takes about 30 minutes to set up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A VPS (I used Hetzner CX22 — 4GB RAM, Ubuntu 24.04, ~€4/month)&lt;/li&gt;
&lt;li&gt;A local machine (Linux, macOS, or Windows with WSL)&lt;/li&gt;
&lt;li&gt;A Tailscale account (free at &lt;a href="https://tailscale.com" rel="noopener noreferrer"&gt;tailscale.com&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Secure the VPS with Tailscale
&lt;/h2&gt;

&lt;p&gt;The goal is simple: &lt;strong&gt;no public ports, no attack surface&lt;/strong&gt;. Your VPS will only be reachable through your private Tailscale network.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Tailscale on the VPS
&lt;/h3&gt;

&lt;p&gt;SSH into your fresh VPS (this is the last time you'll use the public IP):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@YOUR_VPS_PUBLIC_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Install Tailscale and authenticate:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://tailscale.com/install.sh | sh
tailscale up &lt;span class="nt"&gt;--ssh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;--ssh&lt;/code&gt; flag enables Tailscale SSH — a built-in SSH server that authenticates via your Tailscale identity. No keys, no passwords, no exposed port 22.&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a non-root user
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adduser admin
usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Lock down the firewall
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install UFW&lt;/span&gt;
apt &lt;span class="nb"&gt;install &lt;/span&gt;ufw &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Default: deny everything&lt;/span&gt;
ufw default deny incoming
ufw default allow outgoing

&lt;span class="c"&gt;# Allow only Tailscale subnet&lt;/span&gt;
ufw allow &lt;span class="k"&gt;in &lt;/span&gt;on tailscale0
ufw allow &lt;span class="k"&gt;in &lt;/span&gt;from 100.64.0.0/10

&lt;span class="c"&gt;# Enable firewall&lt;/span&gt;
ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Disable traditional SSH
&lt;/h3&gt;

&lt;p&gt;Since Tailscale SSH handles authentication, disable the regular SSH daemon:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl disable &lt;span class="nt"&gt;--now&lt;/span&gt; ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Verify the lockdown
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ufw status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You should see only Tailscale traffic allowed. Your VPS now has &lt;strong&gt;zero public ports&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Install Tailscale on your local machine
&lt;/h3&gt;

&lt;p&gt;On your local machine (Linux/WSL):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://tailscale.com/install.sh | sh
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start tailscaled
&lt;span class="nb"&gt;sudo &lt;/span&gt;tailscale up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now connect to your VPS — no public IP needed:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tailscale ssh admin@YOUR_VPS_TAILSCALE_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's it. You're in via an encrypted WireGuard tunnel, and nobody on the internet can even see your server exists.&lt;/p&gt;
&lt;h3&gt;
  
  
  WSL Users: Fix the MTU Issue
&lt;/h3&gt;

&lt;p&gt;If you're running Tailscale in WSL and SSH connections hang (connect but never complete the handshake), you've hit a known MTU bug. The Tailscale interface defaults to MTU 1280, but WSL's network stack can't handle packets that large on the WireGuard tunnel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Symptoms:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tailscale ping&lt;/code&gt; works fine&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tailscale ssh&lt;/code&gt; hangs indefinitely&lt;/li&gt;
&lt;li&gt;Verbose SSH (&lt;code&gt;ssh -vvv&lt;/code&gt;) stalls at &lt;code&gt;expecting SSH2_MSG_KEX_ECDH_REPLY&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&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;ip &lt;span class="nb"&gt;link set &lt;/span&gt;dev tailscale0 mtu 1200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is a temporary fix that resets on WSL restart. To make it permanent, add it to your shell profile:&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="s1"&gt;'sudo ip link set dev tailscale0 mtu 1200 2&amp;gt;/dev/null'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or add a sudoers rule so it doesn't prompt for a password:&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;# /etc/sudoers.d/tailscale-mtu&lt;/span&gt;
your_username &lt;span class="nv"&gt;ALL&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;ALL&lt;span class="o"&gt;)&lt;/span&gt; NOPASSWD: /usr/sbin/ip &lt;span class="nb"&gt;link set &lt;/span&gt;dev tailscale0 mtu 1200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 2: Install OpenClaw
&lt;/h2&gt;

&lt;p&gt;OpenClaw (formerly Clawdbot, then Moltbot) is an open-source personal AI assistant created by Peter Steinberger. It has 68k+ stars on GitHub and supports dozens of messaging channels, tools, cron jobs, webhooks, and more.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/openclaw" rel="noopener noreferrer"&gt;
        openclaw
      &lt;/a&gt; / &lt;a href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;
        openclaw
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🦞 OpenClaw — Personal AI Assistant&lt;/h1&gt;
&lt;/div&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%2Fraw.githubusercontent.com%2Fopenclaw%2Fopenclaw%2Fmain%2Fdocs%2Fassets%2Fopenclaw-logo-text.svg" 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%2Fraw.githubusercontent.com%2Fopenclaw%2Fopenclaw%2Fmain%2Fdocs%2Fassets%2Fopenclaw-logo-text.svg" alt="OpenClaw" width="500"&gt;&lt;/a&gt;
    
&lt;/p&gt;

&lt;p&gt;
  &lt;strong&gt;EXFOLIATE! EXFOLIATE!&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://github.com/openclaw/openclaw/actions/workflows/ci.yml?branch=main" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1ddb1ef286e297deafb2a4372b7c65516ae65368fd22878a7454dabc2fc4738b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6f70656e636c61772f6f70656e636c61772f63692e796d6c3f6272616e63683d6d61696e267374796c653d666f722d7468652d6261646765" alt="CI status"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/openclaw/openclaw/releases" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/9fcbb4c3c5cf1f8657a73e45b9c76a0074008d658c07f5558e474191c7aef8fb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f6f70656e636c61772f6f70656e636c61773f696e636c7564655f70726572656c6561736573267374796c653d666f722d7468652d6261646765" alt="GitHub release"&gt;&lt;/a&gt;
  &lt;a href="https://discord.gg/clawd" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1860c01c5ab9a20c37ea5a09fcf7ea1471eb95ed7095bb99d3c5a7331061ccda/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f313435363335303036343036353930343836373f6c6162656c3d446973636f7264266c6f676f3d646973636f7264266c6f676f436f6c6f723d776869746526636f6c6f723d353836354632267374796c653d666f722d7468652d6261646765" alt="Discord"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/openclaw/openclaw/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/608c8dfda488178950ce502d7697514db3a6a712579327ed90b9b594260f6355/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d626c75652e7376673f7374796c653d666f722d7468652d6261646765" alt="MIT License"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenClaw&lt;/strong&gt; is a &lt;em&gt;personal AI assistant&lt;/em&gt; you run on your own devices
It answers you on the channels you already use (WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, BlueBubbles, IRC, Microsoft Teams, Matrix, Feishu, LINE, Mattermost, Nextcloud Talk, Nostr, Synology Chat, Tlon, Twitch, Zalo, Zalo Personal, WeChat, WebChat). It can speak and listen on macOS/iOS/Android, and can render a live Canvas you control. The Gateway is just the control plane — the product is the assistant.&lt;/p&gt;
&lt;p&gt;If you want a personal, single-user assistant that feels local, fast, and always-on, this is it.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://openclaw.ai" rel="nofollow noopener noreferrer"&gt;Website&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai" rel="nofollow noopener noreferrer"&gt;Docs&lt;/a&gt; · &lt;a href="https://github.com/openclaw/openclaw/VISION.md" rel="noopener noreferrer"&gt;Vision&lt;/a&gt; · &lt;a href="https://deepwiki.com/openclaw/openclaw" rel="nofollow noopener noreferrer"&gt;DeepWiki&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/start/getting-started" rel="nofollow noopener noreferrer"&gt;Getting Started&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/install/updating" rel="nofollow noopener noreferrer"&gt;Updating&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/start/showcase" rel="nofollow noopener noreferrer"&gt;Showcase&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/help/faq" rel="nofollow noopener noreferrer"&gt;FAQ&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/start/wizard" rel="nofollow noopener noreferrer"&gt;Onboarding&lt;/a&gt; · &lt;a href="https://github.com/openclaw/nix-openclaw" rel="noopener noreferrer"&gt;Nix&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/install/docker" rel="nofollow noopener noreferrer"&gt;Docker&lt;/a&gt; · &lt;a href="https://discord.gg/clawd" rel="nofollow noopener noreferrer"&gt;Discord&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Preferred setup: run &lt;code&gt;openclaw onboard&lt;/code&gt; in your terminal
OpenClaw Onboard guides you step by step through setting up the gateway, workspace, channels, and skills. It…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;h3&gt;
  
  
  Install Node.js 22+
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://deb.nodesource.com/setup_22.x | &lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; bash -
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nodejs
node &lt;span class="nt"&gt;--version&lt;/span&gt;  &lt;span class="c"&gt;# Should be v22+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install pnpm
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://get.pnpm.io/install.sh | sh -
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
pnpm &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Clone and build
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/GIT &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/GIT
git clone https://github.com/openclaw/openclaw.git
&lt;span class="nb"&gt;cd &lt;/span&gt;openclaw

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
pnpm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Build the UI and TypeScript&lt;/span&gt;
pnpm ui:build
pnpm build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run the onboard wizard
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm openclaw onboard &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--non-interactive&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--accept-risk&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--flow&lt;/span&gt; quickstart &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--mode&lt;/span&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--skip-channels&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--skip-skills&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--install-daemon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.openclaw/openclaw.json&lt;/code&gt; — main configuration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.openclaw/workspace/&lt;/code&gt; — agent workspace&lt;/li&gt;
&lt;li&gt;A systemd user service for the gateway&lt;/li&gt;
&lt;li&gt;Gateway listening on &lt;code&gt;127.0.0.1:18789&lt;/code&gt; (loopback only — not exposed!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verify it's running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm openclaw gateway status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gateway: bind=loopback (127.0.0.1), port=18789
Runtime: running (pid XXXXX)
RPC probe: ok
Dashboard: http://127.0.0.1:18789/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Subscribe to Kimi Code and Get an API Key
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.kimi.com/code/en" rel="noopener noreferrer"&gt;Kimi Code&lt;/a&gt; is a subscription-based AI coding service by Moonshot AI. It powers the K2.5 model at up to 100 tokens/s and works with third-party tools like OpenClaw, Claude Code, and Roo Code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subscribe
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://www.kimi.com/code/en" rel="noopener noreferrer"&gt;kimi.com/code&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Log in or create an account&lt;/li&gt;
&lt;li&gt;Select a &lt;strong&gt;Coding Plan&lt;/strong&gt; (starts at ~$19/month for the Andante tier)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your quota refreshes on a 7-day rolling cycle. Unused quota does not carry over.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate an API key
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;a href="https://www.kimi.com/code/console" rel="noopener noreferrer"&gt;Kimi Code Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;API Keys&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create New Key&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy the key immediately&lt;/strong&gt; — it's only shown once!&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Security note:&lt;/strong&gt; Treat your API key like a password. Never commit it to Git or expose it in client-side code. Kimi Code allows personal use in compatible third-party agents, but requests consume your subscription quota.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4: Configure OpenClaw with Kimi Code
&lt;/h2&gt;

&lt;p&gt;Run the interactive config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm openclaw config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Moonshot AI&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kimi Coding API key&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Paste your API key from the Kimi Code Console&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Or do it in one shot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm openclaw onboard &lt;span class="nt"&gt;--kimi-code-api-key&lt;/span&gt; &lt;span class="s2"&gt;"YOUR_API_KEY"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the gateway to apply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm openclaw gateway restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm openclaw agent &lt;span class="nt"&gt;--message&lt;/span&gt; &lt;span class="s2"&gt;"Hello! What model are you?"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get a response from Kimi K2.5.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Access the Dashboard
&lt;/h2&gt;

&lt;p&gt;The dashboard runs on &lt;code&gt;localhost:18789&lt;/code&gt; on the VPS. Since we locked down all ports, we access it through an SSH tunnel.&lt;/p&gt;

&lt;p&gt;From your local machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-L&lt;/span&gt; 18789:localhost:18789 admin@YOUR_VPS_TAILSCALE_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or with Tailscale SSH:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tailscale ssh &lt;span class="nt"&gt;-L&lt;/span&gt; 18789:localhost:18789 admin@YOUR_VPS_TAILSCALE_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now open your browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:18789/?token=YOUR_GATEWAY_TOKEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll find the gateway token in &lt;code&gt;~/.openclaw/openclaw.json&lt;/code&gt; under &lt;code&gt;gateway.auth.token&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The dashboard gives you a web UI to chat with your AI, manage sessions, configure channels, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Keep It Running
&lt;/h2&gt;

&lt;p&gt;The onboard wizard already installed a systemd user service. Make sure it survives reboots:&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;# Enable lingering so user services run without login&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;loginctl enable-linger admin

&lt;span class="c"&gt;# Check status&lt;/span&gt;
systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; status openclaw-gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Updating OpenClaw
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/GIT/openclaw
git pull &lt;span class="nt"&gt;--rebase&lt;/span&gt; origin main
pnpm &lt;span class="nb"&gt;install
&lt;/span&gt;pnpm ui:build
pnpm build
pnpm openclaw gateway restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;Here's what the final setup looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────┐        ┌──────────────────────────┐
│   Your Machine          │        │   VPS (Ubuntu 24.04)     │
│                         │        │                          │
│  Browser ──SSH tunnel──────────────→ OpenClaw Gateway :18789│
│                         │        │   └── Kimi K2.5 API      │
│  Terminal               │        │   └── Workspace           │
│   └── tailscale ssh ──────────────→ Shell access             │
│                         │        │                          │
│  Tailscale ◄──WireGuard──────────►  Tailscale               │
└─────────────────────────┘        └──────────────────────────┘
                                   Firewall: ALL public ports CLOSED
                                   Only Tailscale (100.64.0.0/10) allowed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No public IP exposure. No open ports. No password authentication. Just a WireGuard tunnel and your AI assistant waiting on the other side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[x] UFW firewall: deny all incoming except Tailscale&lt;/li&gt;
&lt;li&gt;[x] SSH: disabled (using Tailscale SSH instead)&lt;/li&gt;
&lt;li&gt;[x] Root login: disabled&lt;/li&gt;
&lt;li&gt;[x] Password auth: disabled&lt;/li&gt;
&lt;li&gt;[x] OpenClaw gateway: bound to loopback only&lt;/li&gt;
&lt;li&gt;[x] Dashboard access: via SSH tunnel only&lt;/li&gt;
&lt;li&gt;[x] API key: stored in server config, never exposed&lt;/li&gt;
&lt;li&gt;[x] Auto-updates: enabled on VPS&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful Commands
&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;# Gateway management&lt;/span&gt;
pnpm openclaw gateway status
pnpm openclaw gateway restart
pnpm openclaw logs

&lt;span class="c"&gt;# Health check&lt;/span&gt;
pnpm openclaw doctor

&lt;span class="c"&gt;# Send a message&lt;/span&gt;
pnpm openclaw agent &lt;span class="nt"&gt;--message&lt;/span&gt; &lt;span class="s2"&gt;"Your message here"&lt;/span&gt;

&lt;span class="c"&gt;# List available models&lt;/span&gt;
pnpm openclaw models list

&lt;span class="c"&gt;# Reconfigure&lt;/span&gt;
pnpm openclaw config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;For under $25/month (VPS + Kimi Code) you get a private AI assistant that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs 24/7 on your own hardware&lt;/li&gt;
&lt;li&gt;Is completely invisible to the internet&lt;/li&gt;
&lt;li&gt;Supports WhatsApp, Telegram, Slack, and dozens more channels&lt;/li&gt;
&lt;li&gt;Uses a powerful AI model (Kimi K2.5 via Kimi Code subscription)&lt;/li&gt;
&lt;li&gt;Remembers your conversations and preferences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hardest part was honestly debugging the WSL Tailscale MTU issue. Everything else was surprisingly smooth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;OpenClaw GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.openclaw.ai" rel="noopener noreferrer"&gt;OpenClaw Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailscale.com" rel="noopener noreferrer"&gt;Tailscale&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.kimi.com/code/en" rel="noopener noreferrer"&gt;Kimi Code&lt;/a&gt; — subscribe and get your API key&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.kimi.com/code/console" rel="noopener noreferrer"&gt;Kimi Code Console&lt;/a&gt; — manage API keys and devices&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.kimi.com/code/docs/en/" rel="noopener noreferrer"&gt;Kimi Code Docs&lt;/a&gt; — membership benefits and usage details&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Have you self-hosted an AI assistant? What's your setup? Let me know in the comments!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>selfhosted</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Install Moltbot with Docker and Gemini on WSL</title>
      <dc:creator>Nunc</dc:creator>
      <pubDate>Wed, 28 Jan 2026 11:37:09 +0000</pubDate>
      <link>https://forem.com/nunc/how-to-install-moltbot-with-docker-and-gemini-on-wsl-1aod</link>
      <guid>https://forem.com/nunc/how-to-install-moltbot-with-docker-and-gemini-on-wsl-1aod</guid>
      <description>&lt;p&gt;Ever wanted your own AI assistant that you can chat with via WhatsApp? Meet Moltbot - an open-source AI gateway that just went through a rebrand with an interesting backstory.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Name Change Story
&lt;/h2&gt;

&lt;p&gt;You might have heard of "Clawdbot" - a popular AI assistant project with a space lobster mascot. On January 27, 2026, Anthropic sent a trademark request because "Clawd" was too similar to their "Claude" trademark.&lt;/p&gt;

&lt;p&gt;Creator Peter Steinberger (@steipete) took it in stride:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Anthropic asked us to change our name (trademark stuff), and honestly? 'Molt' fits perfectly - it's what lobsters do to grow."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The mascot is now "Molty" and the project is "Moltbot". Sometimes forced changes lead to better names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Gemini Instead of Claude?
&lt;/h2&gt;

&lt;p&gt;You might wonder: "I have a Claude Code subscription, why not use that?"&lt;/p&gt;

&lt;p&gt;Here's the problem: &lt;strong&gt;Anthropic actively blocks third-party tools from using Claude Code subscriptions&lt;/strong&gt;, and doing so violates their Terms of Service.&lt;/p&gt;

&lt;p&gt;In early January 2026, Anthropic &lt;a href="https://piunikaweb.com/2026/01/09/anthropic-reportedly-blocking-non-official-claude-api-connections/" rel="noopener noreferrer"&gt;cracked down on "harnesses"&lt;/a&gt; - third-party tools that use Claude Code OAuth to access consumer subscriptions. An Anthropic employee explained:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Restrictions target third-party harnesses spoofing the official client, which violate ToS by creating unusual traffic patterns without telemetry — complicating debugging, rate limits, and support."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The risks of using Claude Code subscription with Moltbot:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Risk&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Account ban&lt;/td&gt;
&lt;td&gt;Anthropic has banned users for TOS violations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sudden disconnection&lt;/td&gt;
&lt;td&gt;Your bot stops working without warning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gray area legally&lt;/td&gt;
&lt;td&gt;Operating outside official support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The error you'll see: &lt;em&gt;"This credential is only authorized for use with Claude Code and cannot be used for other API requests."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The safe alternatives:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemini CLI&lt;/strong&gt; (this guide) - Free tier, legitimate OAuth&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anthropic API key&lt;/strong&gt; - Pay-as-you-go, officially supported&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Antigravity&lt;/strong&gt; - Access Claude via Google's infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide uses Gemini because it's free, has generous limits, and Google actively supports third-party integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;By the end of this guide, you'll have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Moltbot running in Docker on WSL&lt;/li&gt;
&lt;li&gt;Google Gemini as your AI backend (free tier available)&lt;/li&gt;
&lt;li&gt;Optional WhatsApp integration to chat with your bot&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Windows with WSL 2 (Ubuntu 22.04)&lt;/li&gt;
&lt;li&gt;An internet connection&lt;/li&gt;
&lt;li&gt;About 30 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Install Docker in WSL
&lt;/h2&gt;

&lt;p&gt;Open your WSL terminal and run:&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;# Update and install dependencies&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; ca-certificates curl gnupg

&lt;span class="c"&gt;# Add Docker's GPG key&lt;/span&gt;
&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 &lt;span class="nt"&gt;-d&lt;/span&gt; /etc/apt/keyrings
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg | &lt;span class="nb"&gt;sudo &lt;/span&gt;gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/docker.gpg
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+r /etc/apt/keyrings/docker.gpg

&lt;span class="c"&gt;# Add Docker repository&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [arch=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dpkg &lt;span class="nt"&gt;--print-architecture&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; /etc/os-release &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VERSION_CODENAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null

&lt;span class="c"&gt;# Install Docker Engine&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

&lt;span class="c"&gt;# Add yourself to docker group&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;service docker start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Log out of WSL and back in for the group change to work:&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;exit&lt;/span&gt;
&lt;span class="c"&gt;# Reopen WSL, then verify:&lt;/span&gt;
docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Clone and Build Moltbot
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/GIT/moltbot-project
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/GIT/moltbot-project
git clone https://github.com/moltbot/moltbot.git
&lt;span class="nb"&gt;cd &lt;/span&gt;moltbot
./docker-setup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During setup, use these quick settings:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prompt&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Security warning&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Onboarding mode&lt;/td&gt;
&lt;td&gt;QuickStart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model/auth provider&lt;/td&gt;
&lt;td&gt;Skip for now&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway bind&lt;/td&gt;
&lt;td&gt;lan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway auth&lt;/td&gt;
&lt;td&gt;token&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 3: Add Gemini Support
&lt;/h2&gt;

&lt;p&gt;Create a custom Dockerfile that includes Gemini CLI:&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;cd&lt;/span&gt; ~/GIT/moltbot-project

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Dockerfile.custom &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
FROM moltbot:local
USER root
RUN npm install -g @google/gemini-cli
USER node
VOLUME /home/node/.gemini
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; moltbot-with-gemini &lt;span class="nt"&gt;-f&lt;/span&gt; Dockerfile.custom &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Authenticate with Gemini
&lt;/h2&gt;

&lt;p&gt;Install and authenticate Gemini CLI in WSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @google/gemini-cli
gemini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the OAuth flow in your browser. This creates credentials in &lt;code&gt;~/.gemini/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Wire It All Together
&lt;/h2&gt;

&lt;p&gt;Create a Docker Compose override to mount your Gemini credentials:&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;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/GIT/moltbot-project/moltbot/docker-compose.override.yml &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
services:
  moltbot-gateway:
    image: moltbot-with-gemini
    environment:
      HOME: /home/node
    volumes:
      - ~/.gemini:/home/node/.gemini
      - ~/.clawdbot:/home/node/.moltbot
  moltbot-cli:
    image: moltbot-with-gemini
    environment:
      HOME: /home/node
    volumes:
      - ~/.gemini:/home/node/.gemini
      - ~/.clawdbot:/home/node/.moltbot
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable the Gemini plugin:&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;cd&lt;/span&gt; ~/GIT/moltbot-project/moltbot

&lt;span class="c"&gt;# Enable plugin&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; moltbot-cli plugins &lt;span class="nb"&gt;enable &lt;/span&gt;google-gemini-cli-auth

&lt;span class="c"&gt;# Authenticate inside container&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; moltbot-cli auth login &lt;span class="nt"&gt;--provider&lt;/span&gt; google-gemini-cli

&lt;span class="c"&gt;# Configure models&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; moltbot-cli configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Start and Test
&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;# Start the gateway&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml up &lt;span class="nt"&gt;-d&lt;/span&gt; moltbot-gateway

&lt;span class="c"&gt;# Test it&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; moltbot-cli agent &lt;span class="nt"&gt;--local&lt;/span&gt; &lt;span class="nt"&gt;--session-id&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Hello!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get a response from your AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Add WhatsApp
&lt;/h2&gt;

&lt;p&gt;WhatsApp is surprisingly easy - it uses QR code login like WhatsApp Web.&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;# Configure WhatsApp channel&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; moltbot-cli configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select &lt;strong&gt;Channels&lt;/strong&gt; -&amp;gt; &lt;strong&gt;WhatsApp&lt;/strong&gt; and set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Personal phone mode: Yes&lt;/li&gt;
&lt;li&gt;dmPolicy: allowlist&lt;/li&gt;
&lt;li&gt;allowFrom: Your phone number (e.g., +15551234567)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then link your phone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; moltbot-cli channels login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scan the QR code with WhatsApp (Settings -&amp;gt; Linked Devices -&amp;gt; Link a Device). Now you can chat with your AI via WhatsApp self-messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Reference Commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/GIT/moltbot-project/moltbot

&lt;span class="c"&gt;# Start&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml up &lt;span class="nt"&gt;-d&lt;/span&gt; moltbot-gateway

&lt;span class="c"&gt;# Stop&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml down

&lt;span class="c"&gt;# View logs&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml logs &lt;span class="nt"&gt;-f&lt;/span&gt; moltbot-gateway

&lt;span class="c"&gt;# Open dashboard&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;--rm&lt;/span&gt; moltbot-cli dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Docker permission denied?&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;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;span class="c"&gt;# Then log out and back in&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Gemini rate limits (429)?&lt;/strong&gt;&lt;br&gt;
The free tier has limits. Wait a bit or add an API key fallback from &lt;a href="https://aistudio.google.com/" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Config files owned by root?&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 chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nv"&gt;$USER&lt;/span&gt;:&lt;span class="nv"&gt;$USER&lt;/span&gt; ~/.clawdbot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Moltbot gives you a self-hosted AI gateway that can connect to various backends (Gemini, Claude via Antigravity, etc.) and channels (WhatsApp, Discord, Telegram). The Docker setup keeps everything contained and reproducible.&lt;/p&gt;

&lt;p&gt;The rebrand from Clawdbot to Moltbot is a good reminder that sometimes external pressure leads to better outcomes - "Molt" really does fit the lobster theme better.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Have you set up Moltbot or a similar AI assistant? Share your experience in the comments!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>wsl</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Run Clawdbot on WSL with Your Claude Code Subscription</title>
      <dc:creator>Nunc</dc:creator>
      <pubDate>Mon, 26 Jan 2026 13:33:45 +0000</pubDate>
      <link>https://forem.com/nunc/how-to-run-clawdbot-on-wsl-with-your-claude-code-subscription-13i4</link>
      <guid>https://forem.com/nunc/how-to-run-clawdbot-on-wsl-with-your-claude-code-subscription-13i4</guid>
      <description>&lt;p&gt;I wanted to run Clawdbot—an AI chatbot framework—on Windows WSL, but there was a catch: I needed to use my existing Claude Code subscription instead of paying for separate API access. Here's how I got it working.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Authentication Challenge
&lt;/h2&gt;

&lt;p&gt;Clawdbot supports multiple authentication methods, but most require paid API access. If you have a Claude Code subscription, you can leverage its OAuth mechanism instead. The trick? Claude Code CLI must be &lt;strong&gt;inside&lt;/strong&gt; the Docker container.&lt;/p&gt;

&lt;p&gt;Here's why this setup is required:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code CLI in container&lt;/td&gt;
&lt;td&gt;Clawdbot uses Claude Code's OAuth mechanism&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mount &lt;code&gt;~/.claude&lt;/code&gt; credentials&lt;/td&gt;
&lt;td&gt;Where Claude Code stores authentication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Set &lt;code&gt;HOME=/home/node&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;So Claude Code finds the credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Other auth methods won't work with your subscription:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anthropic API key requires paid API access&lt;/li&gt;
&lt;li&gt;Setup-token paste has incompatible format&lt;/li&gt;
&lt;li&gt;Claude Code CLI OAuth uses your subscription&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows with WSL 2 (Ubuntu 22.04)&lt;/li&gt;
&lt;li&gt;Claude Code CLI installed and authenticated in WSL&lt;/li&gt;
&lt;li&gt;Internet connection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you haven't installed Claude Code yet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @anthropic-ai/claude-code &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 1: Install Docker Engine in WSL
&lt;/h2&gt;

&lt;p&gt;First, set up Docker in your WSL environment:&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;# Update package index&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update

&lt;span class="c"&gt;# Install required packages&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; ca-certificates curl gnupg

&lt;span class="c"&gt;# Add Docker's official GPG key&lt;/span&gt;
&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 &lt;span class="nt"&gt;-d&lt;/span&gt; /etc/apt/keyrings
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg | &lt;span class="nb"&gt;sudo &lt;/span&gt;gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/docker.gpg
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+r /etc/apt/keyrings/docker.gpg

&lt;span class="c"&gt;# Add Docker repository&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [arch=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dpkg &lt;span class="nt"&gt;--print-architecture&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; /etc/os-release &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VERSION_CODENAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null

&lt;span class="c"&gt;# Install Docker Engine&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

&lt;span class="c"&gt;# Add your user to docker group&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;

&lt;span class="c"&gt;# Start Docker service&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;service docker start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Log out and back into WSL for the group change to take effect, then verify:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;
docker compose version
docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 2: Clone and Build Clawdbot
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/GIT/clawdbot-project
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/GIT/clawdbot-project
git clone https://github.com/clawdbot/clawdbot.git
&lt;span class="nb"&gt;cd &lt;/span&gt;clawdbot
./docker-setup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;During the onboarding prompts, use these settings:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prompt&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Security warning&lt;/td&gt;
&lt;td&gt;Yes (continue)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Onboarding mode&lt;/td&gt;
&lt;td&gt;QuickStart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model/auth provider&lt;/td&gt;
&lt;td&gt;Skip for now&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway bind&lt;/td&gt;
&lt;td&gt;lan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway auth&lt;/td&gt;
&lt;td&gt;token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skills&lt;/td&gt;
&lt;td&gt;Skip for now&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hooks&lt;/td&gt;
&lt;td&gt;Skip for now&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Step 3: Build Custom Image with Claude Code
&lt;/h2&gt;

&lt;p&gt;Here's the key part. Create a custom Dockerfile that includes Claude Code CLI:&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;cd&lt;/span&gt; ~/GIT/clawdbot-project

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Dockerfile.custom &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
FROM clawdbot:local

# Install Claude Code CLI
RUN npm install -g @anthropic-ai/claude-code

# Mount point for Claude credentials
VOLUME /home/node/.claude
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; clawdbot-with-claude &lt;span class="nt"&gt;-f&lt;/span&gt; Dockerfile.custom &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 4: Create Docker Compose Override
&lt;/h2&gt;

&lt;p&gt;Create an override file to use the custom image and mount your Claude credentials:&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="c1"&gt;# ~/GIT/clawdbot-project/clawdbot/docker-compose.override.yml&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;clawdbot-gateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clawdbot-with-claude&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;HOME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/home/node&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;~/.claude:/home/node/.claude&lt;/span&gt;
  &lt;span class="na"&gt;clawdbot-cli&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clawdbot-with-claude&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;HOME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/home/node&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;~/.claude:/home/node/.claude&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Save this to &lt;code&gt;~/GIT/clawdbot-project/clawdbot/docker-compose.override.yml&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: Configure Dashboard Access
&lt;/h2&gt;

&lt;p&gt;Enable insecure auth for local dashboard access by editing &lt;code&gt;~/.clawdbot/clawdbot.json&lt;/code&gt;. Add this inside the &lt;code&gt;"gateway"&lt;/code&gt; section:&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="nl"&gt;"controlUi"&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;"allowInsecureAuth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;Also change &lt;code&gt;"bind": "loopback"&lt;/code&gt; to &lt;code&gt;"bind": "lan"&lt;/code&gt; if you want to access it from your network.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6: Start and Test
&lt;/h2&gt;

&lt;p&gt;Start the gateway:&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;cd&lt;/span&gt; ~/GIT/clawdbot-project/clawdbot
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml up &lt;span class="nt"&gt;-d&lt;/span&gt; clawdbot-gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Test the agent:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; clawdbot-cli agent &lt;span class="nt"&gt;--local&lt;/span&gt; &lt;span class="nt"&gt;--session-id&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Hello!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You should get a response from Claude.&lt;/p&gt;
&lt;h2&gt;
  
  
  Accessing the Dashboard
&lt;/h2&gt;

&lt;p&gt;Get your gateway token:&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;grep &lt;/span&gt;CLAWDBOT_GATEWAY_TOKEN ~/GIT/clawdbot-project/clawdbot/.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then open &lt;code&gt;http://127.0.0.1:18789/?token=YOUR_TOKEN_HERE&lt;/code&gt; in your browser.&lt;/p&gt;
&lt;h2&gt;
  
  
  Bonus: Adding WhatsApp
&lt;/h2&gt;

&lt;p&gt;WhatsApp is surprisingly easy to set up—it uses QR code login like WhatsApp Web.&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;cd&lt;/span&gt; ~/GIT/clawdbot-project/clawdbot
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; clawdbot-cli configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Select &lt;strong&gt;Channels&lt;/strong&gt; → &lt;strong&gt;WhatsApp&lt;/strong&gt; and configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Personal phone mode: Yes&lt;/li&gt;
&lt;li&gt;dmPolicy: allowlist&lt;/li&gt;
&lt;li&gt;allowFrom: Your phone number (E.164 format like +1555123456)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then link your phone:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; clawdbot-cli channels login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Scan the QR code with WhatsApp → Settings → Linked Devices → Link a Device.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Reference Commands
&lt;/h2&gt;

&lt;p&gt;
  Click to expand common commands
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start gateway&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml up &lt;span class="nt"&gt;-d&lt;/span&gt; clawdbot-gateway

&lt;span class="c"&gt;# Stop gateway&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml down

&lt;span class="c"&gt;# View logs&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml logs &lt;span class="nt"&gt;-f&lt;/span&gt; clawdbot-gateway

&lt;span class="c"&gt;# Test agent&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.override.yml run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; clawdbot-cli agent &lt;span class="nt"&gt;--local&lt;/span&gt; &lt;span class="nt"&gt;--session-id&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;
&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Docker permission denied:&lt;/strong&gt; Run &lt;code&gt;sudo usermod -aG docker $USER&lt;/code&gt; and log out/in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude credentials not working:&lt;/strong&gt; Re-authenticate with &lt;code&gt;claude /login&lt;/code&gt; in WSL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dashboard shows "pairing required":&lt;/strong&gt; Ensure &lt;code&gt;controlUi.allowInsecureAuth: true&lt;/code&gt; is in your config.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No response from agent:&lt;/strong&gt; Check that &lt;code&gt;HOME=/home/node&lt;/code&gt; is set and &lt;code&gt;~/.claude&lt;/code&gt; is mounted in your override file.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;The key insight here is that Claude Code's OAuth tokens can be shared with containerized applications by mounting the credentials directory. This pattern works for any Docker-based tool that supports Claude Code authentication.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/openclaw" rel="noopener noreferrer"&gt;
        openclaw
      &lt;/a&gt; / &lt;a href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;
        openclaw
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🦞 OpenClaw — Personal AI Assistant&lt;/h1&gt;
&lt;/div&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%2Fraw.githubusercontent.com%2Fopenclaw%2Fopenclaw%2Fmain%2Fdocs%2Fassets%2Fopenclaw-logo-text.svg" 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%2Fraw.githubusercontent.com%2Fopenclaw%2Fopenclaw%2Fmain%2Fdocs%2Fassets%2Fopenclaw-logo-text.svg" alt="OpenClaw" width="500"&gt;&lt;/a&gt;
    
&lt;/p&gt;

&lt;p&gt;
  &lt;strong&gt;EXFOLIATE! EXFOLIATE!&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://github.com/openclaw/openclaw/actions/workflows/ci.yml?branch=main" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1ddb1ef286e297deafb2a4372b7c65516ae65368fd22878a7454dabc2fc4738b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6f70656e636c61772f6f70656e636c61772f63692e796d6c3f6272616e63683d6d61696e267374796c653d666f722d7468652d6261646765" alt="CI status"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/openclaw/openclaw/releases" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/9fcbb4c3c5cf1f8657a73e45b9c76a0074008d658c07f5558e474191c7aef8fb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f6f70656e636c61772f6f70656e636c61773f696e636c7564655f70726572656c6561736573267374796c653d666f722d7468652d6261646765" alt="GitHub release"&gt;&lt;/a&gt;
  &lt;a href="https://discord.gg/clawd" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1860c01c5ab9a20c37ea5a09fcf7ea1471eb95ed7095bb99d3c5a7331061ccda/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f313435363335303036343036353930343836373f6c6162656c3d446973636f7264266c6f676f3d646973636f7264266c6f676f436f6c6f723d776869746526636f6c6f723d353836354632267374796c653d666f722d7468652d6261646765" alt="Discord"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/openclaw/openclaw/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/608c8dfda488178950ce502d7697514db3a6a712579327ed90b9b594260f6355/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d626c75652e7376673f7374796c653d666f722d7468652d6261646765" alt="MIT License"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenClaw&lt;/strong&gt; is a &lt;em&gt;personal AI assistant&lt;/em&gt; you run on your own devices
It answers you on the channels you already use (WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, BlueBubbles, IRC, Microsoft Teams, Matrix, Feishu, LINE, Mattermost, Nextcloud Talk, Nostr, Synology Chat, Tlon, Twitch, Zalo, Zalo Personal, WeChat, WebChat). It can speak and listen on macOS/iOS/Android, and can render a live Canvas you control. The Gateway is just the control plane — the product is the assistant.&lt;/p&gt;
&lt;p&gt;If you want a personal, single-user assistant that feels local, fast, and always-on, this is it.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://openclaw.ai" rel="nofollow noopener noreferrer"&gt;Website&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai" rel="nofollow noopener noreferrer"&gt;Docs&lt;/a&gt; · &lt;a href="https://github.com/openclaw/openclaw/VISION.md" rel="noopener noreferrer"&gt;Vision&lt;/a&gt; · &lt;a href="https://deepwiki.com/openclaw/openclaw" rel="nofollow noopener noreferrer"&gt;DeepWiki&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/start/getting-started" rel="nofollow noopener noreferrer"&gt;Getting Started&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/install/updating" rel="nofollow noopener noreferrer"&gt;Updating&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/start/showcase" rel="nofollow noopener noreferrer"&gt;Showcase&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/help/faq" rel="nofollow noopener noreferrer"&gt;FAQ&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/start/wizard" rel="nofollow noopener noreferrer"&gt;Onboarding&lt;/a&gt; · &lt;a href="https://github.com/openclaw/nix-openclaw" rel="noopener noreferrer"&gt;Nix&lt;/a&gt; · &lt;a href="https://docs.openclaw.ai/install/docker" rel="nofollow noopener noreferrer"&gt;Docker&lt;/a&gt; · &lt;a href="https://discord.gg/clawd" rel="nofollow noopener noreferrer"&gt;Discord&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Preferred setup: run &lt;code&gt;openclaw onboard&lt;/code&gt; in your terminal
OpenClaw Onboard guides you step by step through setting up the gateway, workspace, channels, and skills. It…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;







&lt;p&gt;&lt;strong&gt;Have you tried running AI assistants in Docker? What authentication challenges did you face? Share in the comments!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>wsl</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Used Claude Code to Write a Legal Appeal for My Mother's Disability Benefits</title>
      <dc:creator>Nunc</dc:creator>
      <pubDate>Fri, 23 Jan 2026 09:01:47 +0000</pubDate>
      <link>https://forem.com/nunc/i-used-claude-code-to-write-a-legal-appeal-for-my-mothers-disability-benefits-40f4</link>
      <guid>https://forem.com/nunc/i-used-claude-code-to-write-a-legal-appeal-for-my-mothers-disability-benefits-40f4</guid>
      <description>&lt;p&gt;I'm a software developer. Claude Code is a CLI tool designed for coding tasks - writing code, debugging, refactoring. So naturally, I used it to write a 230-line legal appeal against a government disability decision.&lt;/p&gt;

&lt;p&gt;Here's how a programming tool became my most powerful ally in a deeply personal, completely non-technical challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;My mother has severe spinal degeneration. After 45 years of physically demanding work, multiple surgeries, and recent osteoporotic vertebral fractures, she applied for disability benefits and care allowance from the national pension and disability insurance agency.&lt;/p&gt;

&lt;p&gt;The response? &lt;strong&gt;Rejected.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The expert medical commission concluded:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Her spine condition was "congenital" (born with it)&lt;/li&gt;
&lt;li&gt;Treatment was "completed"&lt;/li&gt;
&lt;li&gt;She could perform daily activities independently&lt;/li&gt;
&lt;li&gt;Only 30% disability recognized (50% required for benefits)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reading the decision, I knew it was wrong. But how do you argue against a medical commission with mountains of paperwork, complex regulations, and 25+ years of medical history?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Chaos: 50+ Scanned Medical Documents
&lt;/h2&gt;

&lt;p&gt;My mother's medical history was a nightmare to navigate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spine-findings/           # Spine-related medical records (12 files)
additional-findings/      # Additional medical findings (8 files)
application-docs/         # Original application attachments (15 files)
new-findings-2026/        # Recent findings from January 2026 (20+ files)
commission-opinion/       # The commission's expert opinion (6 files)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All scanned as JPG images. Handwritten doctor's notes from 1998. Faded hospital discharge papers. CT scan reports. Years of medical history trapped in pixels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: OCR with Google Gemini API
&lt;/h2&gt;

&lt;p&gt;First challenge: extract text from images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt; Claude Code can also read images and perform OCR directly. However, for bulk processing of 50+ scanned medical documents - many with handwritten notes and faded text from the 1990s - Google's Gemini with "thinking mode" produced significantly better results. Claude Code's OCR is decent for quick reads, but Gemini's accuracy on difficult documents was noticeably superior.&lt;/p&gt;

&lt;p&gt;I wrote a simple Python script using Google's Gemini API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.genai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_text_from_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;image_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;mime_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image/jpeg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;image_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Extract all text from this image. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                         &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Preserve formatting and structure. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                         &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;If handwritten, transcribe to readable form.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Using Gemini's thinking mode for better accuracy
&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GenerateContentConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;thinking_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ThinkingConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;thinking_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HIGH&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3-pro-preview&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script processed entire folders:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python extract_ocr.py &lt;span class="s2"&gt;"new-findings-2026/"&lt;/span&gt;
&lt;span class="c"&gt;# Found 24 images without TXT:&lt;/span&gt;
&lt;span class="c"&gt;#   - scan_001.jpg&lt;/span&gt;
&lt;span class="c"&gt;#   - scan_002.jpg&lt;/span&gt;
&lt;span class="c"&gt;#   ...&lt;/span&gt;
&lt;span class="c"&gt;# Processing: scan_001.jpg... OK -&amp;gt; scan_001.txt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: Every medical document now had a searchable &lt;code&gt;.txt&lt;/code&gt; companion file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Building Context with CLAUDE.md
&lt;/h2&gt;

&lt;p&gt;Claude Code uses a &lt;code&gt;CLAUDE.md&lt;/code&gt; file for project-specific context. I created one explaining the case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# CLAUDE.md&lt;/span&gt;

&lt;span class="gu"&gt;## Repository Purpose&lt;/span&gt;

Document repository for a disability benefits appeal case.

&lt;span class="gu"&gt;## Document Structure&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**spine-findings/**&lt;/span&gt; - Spine medical records (JPG + OCR'd TXT)
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**commission-opinion/**&lt;/span&gt; - Expert commission documents
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**appeal-drafts/**&lt;/span&gt; - Appeal document versions

&lt;span class="gu"&gt;## Key Context for Appeal&lt;/span&gt;

Main contested points from the expert opinion:
&lt;span class="p"&gt;-&lt;/span&gt; Health history incorrectly characterized as congenital
&lt;span class="p"&gt;-&lt;/span&gt; Treatment incorrectly marked as concluded
&lt;span class="p"&gt;-&lt;/span&gt; Independence incorrectly assessed
&lt;span class="p"&gt;-&lt;/span&gt; New osteoporotic fractures not considered
&lt;span class="p"&gt;-&lt;/span&gt; Date of injury incorrectly stated

&lt;span class="gu"&gt;## Working with Documents&lt;/span&gt;

Read .txt versions for text content.
Reference official disability regulations for legal basis.
Use formal legal/medical terminology.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Claude Code understood the project structure and goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: The Iterative Writing Process
&lt;/h2&gt;

&lt;p&gt;This is where Claude Code shined. I started with rough notes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I disagree with the expert opinion because:
- My condition isn't congenital - first problems at age 51
- Treatment ongoing - have orthopedic appointment scheduled
- Can't cook, clean, or do laundry independently
- New vertebral fractures in 2025 weren't considered
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code read all the OCR'd medical files, cross-referenced dates and diagnoses, and produced the first draft. But it didn't stop there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The secret weapon:&lt;/strong&gt; I asked Claude Code to fetch and read the official disability regulations directly from the government website - the complete guidelines on how bodily impairments are assessed and calculated. With both the medical evidence AND the legal criteria in context, Claude Code could build arguments that directly mapped specific diagnoses to specific regulation paragraphs. For example, it found that "unstable spinal segment" and "severe spinal stenosis" each qualify as separate impairments that should be added together - something the commission had overlooked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version 1 → Version 11&lt;/strong&gt;: Each iteration got better:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;v1: Basic structure, main arguments&lt;/li&gt;
&lt;li&gt;v3: Added specific medical evidence with dates&lt;/li&gt;
&lt;li&gt;v5: Referenced disability regulations and legal basis&lt;/li&gt;
&lt;li&gt;v9: Incorporated new January 2026 findings&lt;/li&gt;
&lt;li&gt;v10: Added disability calculation showing 50%+ should be recognized&lt;/li&gt;
&lt;li&gt;v11: Final polish, comprehensive evidence list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final appeal grew from rough notes to a &lt;strong&gt;230-line legal document&lt;/strong&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;7 major sections with subsections&lt;/li&gt;
&lt;li&gt;30+ specific medical citations with dates&lt;/li&gt;
&lt;li&gt;Legal references to disability insurance law and internal guidelines&lt;/li&gt;
&lt;li&gt;Calculations showing multiple vertebral segments = higher disability %&lt;/li&gt;
&lt;li&gt;Request for home visit to verify living conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Technical Magic: What Claude Code Actually Did
&lt;/h2&gt;

&lt;p&gt;Claude Code isn't just generating text. It's:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reading and cross-referencing documents:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"The MRI from November 2000 shows NO pathological changes...
If this were congenital, changes would be visible in 2000."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Understanding medical terminology:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"CT scan confirms: 'Fresh osteoporotic fracture of
L4 vertebral body involving anterior and partially middle column.'"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Applying legal frameworks:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Per disability guidelines Chapter VIII: 'When multiple segments
are affected, add 10% for each additional segment beyond
the first 30%.' L2 + L3 + L4 = 30% + 10% + 10% = 50%"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Finding contradictions:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"The commission's own expert opinion in Section 6 states:
'unstable segment L3-L4' - yet this was NOT considered
in the disability calculation!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Document Pipeline
&lt;/h2&gt;

&lt;p&gt;Text file → Review → Iterate → Final &lt;code&gt;.docx&lt;/code&gt; and &lt;code&gt;.pdf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;appeal-drafts/
├── appeal_v01.txt    # First draft
├── appeal_v05.txt    # Major revision
├── appeal_v09.txt    # With new evidence
├── appeal_v11.txt    # Final text
├── appeal_v11.docx   # Formatted Word doc
└── appeal_v11.pdf    # Print-ready PDF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the final step, I used Claude Code's &lt;strong&gt;docx skill&lt;/strong&gt; - a built-in capability that converts text documents into properly formatted Word files. One command, and the plain text appeal became a professional document with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Correct headers and formal structure&lt;/li&gt;
&lt;li&gt;Proper spacing and margins for official submissions&lt;/li&gt;
&lt;li&gt;Automatic PDF generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No manual formatting in Word. No copy-paste headaches. The skill handled everything, producing government-ready documents directly from the terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Learnings
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. AI is a multiplier, not a replacement&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I still needed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scan and organize documents&lt;/li&gt;
&lt;li&gt;Provide context and direction&lt;/li&gt;
&lt;li&gt;Verify every fact and citation&lt;/li&gt;
&lt;li&gt;Make judgment calls on arguments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claude Code amplified my efforts - turning hours of work into minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Structure matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CLAUDE.md&lt;/code&gt; file was crucial. Clear project context meant better outputs from the first prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Iteration is natural&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't expect perfection on v1. The v1→v11 journey wasn't failure - it was refinement. Each version incorporated new information, better arguments, and clearer language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Domain knowledge can be learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Neither Claude Code nor I are lawyers or medical professionals. But by reading the regulations, understanding the criteria, and carefully citing evidence, we built a comprehensive legal argument.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Unexpected Outcome
&lt;/h2&gt;

&lt;p&gt;Using a programming tool for a legal appeal sounds absurd. But Claude Code's strengths translate perfectly:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Coding Task&lt;/th&gt;
&lt;th&gt;Legal Appeal Task&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reading codebase&lt;/td&gt;
&lt;td&gt;Reading medical records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Understanding APIs&lt;/td&gt;
&lt;td&gt;Understanding regulations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debugging errors&lt;/td&gt;
&lt;td&gt;Finding contradictions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Refactoring code&lt;/td&gt;
&lt;td&gt;Refining arguments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Writing documentation&lt;/td&gt;
&lt;td&gt;Writing formal appeals&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What Happens Next
&lt;/h2&gt;

&lt;p&gt;The appeal is submitted. We wait for the second-level commission's decision.&lt;/p&gt;

&lt;p&gt;But regardless of outcome, this experience taught me that AI tools aren't limited to their intended domains. A CLI built for &lt;code&gt;git commit&lt;/code&gt; and &lt;code&gt;npm install&lt;/code&gt; became the backbone of a deeply human fight for my mother's dignity and care.&lt;/p&gt;

&lt;p&gt;Sometimes the best tool for the job is the one you're already comfortable with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you used AI tools for unexpected tasks? I'd love to hear about creative applications in the comments.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Technical note: The OCR script uses Google's Gemini with "thinking mode" for better accuracy on handwritten and faded documents (Claude Code has OCR too, but Gemini performed better on difficult scans). Claude Code handled document analysis, cross-referencing, fetching and parsing official regulations from government websites, iterative drafting, and final document conversion to DOCX/PDF via the built-in docx skill.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>claudecode</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Claude.ai Has Built-In Superpowers (And You Probably Didn't Know)</title>
      <dc:creator>Nunc</dc:creator>
      <pubDate>Mon, 27 Oct 2025 19:03:40 +0000</pubDate>
      <link>https://forem.com/nunc/claudeai-has-built-in-superpowers-and-you-probably-didnt-know-1haa</link>
      <guid>https://forem.com/nunc/claudeai-has-built-in-superpowers-and-you-probably-didnt-know-1haa</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Claude.ai comes with 5 hidden "skills" that let it create Word docs, PowerPoint slides, Excel spreadsheets, and manipulate PDFs. Here's what Claude can actually do for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait, Claude Has Skills?
&lt;/h2&gt;

&lt;p&gt;Yeah! If you're using Claude.ai (the web or desktop version), you might've noticed it can do some pretty fancy document work. That's because Claude has these built-in "skills" - basically specialized knowledge for working with office documents.&lt;/p&gt;

&lt;p&gt;Most people just use Claude for chat and coding. But if you know how to ask, Claude can literally create a formatted Excel spreadsheet with formulas, build a PowerPoint deck, or edit a Word doc with tracked changes.&lt;/p&gt;

&lt;p&gt;Let me show you what's under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5 Built-In Skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. DOCX Skill - Word Document Master
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates professional Word documents from scratch&lt;/li&gt;
&lt;li&gt;Edits existing docs&lt;/li&gt;
&lt;li&gt;Handles tracked changes (redlining)&lt;/li&gt;
&lt;li&gt;Adds comments&lt;/li&gt;
&lt;li&gt;Preserves formatting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-world uses:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "Create a business proposal document with sections for Executive Summary, Problem Statement, and Solution"

Claude: *generates a properly formatted .docx with headings, formatting, and structure*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; If you need Claude to edit someone else's document (like legal or business docs), ask for "tracked changes" - Claude will mark every edit so reviewers can see what changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. PPTX Skill - Presentation Builder
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates PowerPoint presentations&lt;/li&gt;
&lt;li&gt;Edits existing slides&lt;/li&gt;
&lt;li&gt;Works with layouts and templates&lt;/li&gt;
&lt;li&gt;Adds speaker notes&lt;/li&gt;
&lt;li&gt;Handles comments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-world uses:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "Create a 5-slide pitch deck about our new product"

Claude: *builds a presentation with title slide, problem, solution, market, and call-to-action slides*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cool feature:&lt;/strong&gt; Claude can even work from templates - give it your company's branded PowerPoint template, and it'll create slides matching your style.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. XLSX Skill - Spreadsheet Wizard
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates Excel files with formulas (not just data!)&lt;/li&gt;
&lt;li&gt;Formats cells (colors, fonts, number formats)&lt;/li&gt;
&lt;li&gt;Builds financial models&lt;/li&gt;
&lt;li&gt;Analyzes existing spreadsheets&lt;/li&gt;
&lt;li&gt;Calculates everything properly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-world uses:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "Create a monthly budget tracker with categories for rent, food, utilities, and entertainment. Add formulas to calculate totals."

Claude: *generates an Excel file with proper formulas, formatting, and even color-coding*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key point:&lt;/strong&gt; Claude uses ACTUAL Excel formulas (like &lt;code&gt;=SUM(A1:A10)&lt;/code&gt;), not hardcoded values. Your spreadsheet will recalculate if you change inputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finance nerds:&lt;/strong&gt; Claude follows financial modeling standards:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blue text = inputs&lt;/li&gt;
&lt;li&gt;Black text = formulas&lt;/li&gt;
&lt;li&gt;Green text = links from other sheets&lt;/li&gt;
&lt;li&gt;Red text = external links&lt;/li&gt;
&lt;li&gt;Yellow background = key assumptions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. PDF Skill - PDF Surgeon
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extracts text and tables from PDFs&lt;/li&gt;
&lt;li&gt;Merges multiple PDFs&lt;/li&gt;
&lt;li&gt;Splits PDFs into separate pages&lt;/li&gt;
&lt;li&gt;Creates new PDFs&lt;/li&gt;
&lt;li&gt;Fills PDF forms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-world uses:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "Extract all the tables from this financial report PDF"

Claude: *pulls out tables as structured data you can work with*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Handy trick:&lt;/strong&gt; Need to combine 5 different PDFs into one? Or split a 50-page PDF into individual files? Claude's got you.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Product Self-Knowledge Skill
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Answers questions about Claude products (API, Claude.ai, Claude Code)&lt;/li&gt;
&lt;li&gt;Provides accurate documentation links&lt;/li&gt;
&lt;li&gt;Distinguishes between different Claude products&lt;/li&gt;
&lt;li&gt;Prevents hallucinations about capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-world uses:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "Can Claude.ai access the internet?"

Claude: *gives accurate answer with source documentation link*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; This skill helps Claude give you accurate info about what it can and can't do, rather than making stuff up.&lt;/p&gt;

&lt;h2&gt;
  
  
  How To Use These Skills
&lt;/h2&gt;

&lt;p&gt;Here's the thing - &lt;strong&gt;you don't need to do anything special&lt;/strong&gt;. Just ask Claude naturally:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples that work:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Create a Word document with..."
"Build me an Excel budget tracker..."
"Make a PowerPoint about..."
"Extract text from this PDF..."
"Merge these 3 PDFs together..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude will automatically activate the right skill for the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Claude Actually Does Behind The Scenes
&lt;/h2&gt;

&lt;p&gt;When you ask for a Word doc, Claude:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Uses a library called &lt;code&gt;docx-js&lt;/code&gt; to build the document structure&lt;/li&gt;
&lt;li&gt;Adds your content with proper formatting&lt;/li&gt;
&lt;li&gt;Exports as a real .docx file&lt;/li&gt;
&lt;li&gt;Gives you a download&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For Excel, Claude:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Uses &lt;code&gt;openpyxl&lt;/code&gt; (Python library)&lt;/li&gt;
&lt;li&gt;Writes actual Excel formulas (not calculated values)&lt;/li&gt;
&lt;li&gt;Applies formatting and colors&lt;/li&gt;
&lt;li&gt;Recalculates everything to make sure formulas work&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pretty neat, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Examples I've Seen People Use
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Business use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Create a project status report with RAG status indicators"&lt;/li&gt;
&lt;li&gt;"Build a quarterly budget spreadsheet with formulas"&lt;/li&gt;
&lt;li&gt;"Make a 10-slide training deck about security policies"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Personal use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Create a budget tracker for my expenses"&lt;/li&gt;
&lt;li&gt;"Build a presentation about my vacation photos"&lt;/li&gt;
&lt;li&gt;"Extract text from these scanned receipts"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Academic use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Create a formatted research paper template"&lt;/li&gt;
&lt;li&gt;"Build a data analysis spreadsheet with charts"&lt;/li&gt;
&lt;li&gt;"Merge all my assignment PDFs into one document"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations To Know
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What Claude CAN'T do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open existing files you haven't uploaded&lt;/li&gt;
&lt;li&gt;Edit files on your computer directly&lt;/li&gt;
&lt;li&gt;Access your Google Drive or OneDrive&lt;/li&gt;
&lt;li&gt;Send files to other services&lt;/li&gt;
&lt;li&gt;Create files larger than a few MB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What Claude CAN do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work with files you upload in the chat&lt;/li&gt;
&lt;li&gt;Create new files from scratch&lt;/li&gt;
&lt;li&gt;Process and analyze documents&lt;/li&gt;
&lt;li&gt;Generate properly formatted office documents&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pro Tips
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tip 1: Be Specific About Formatting
&lt;/h3&gt;

&lt;p&gt;Instead of: "Create a spreadsheet"&lt;/p&gt;

&lt;p&gt;Try: "Create an Excel spreadsheet with blue headers, bold column names, and formulas to calculate totals"&lt;/p&gt;

&lt;h3&gt;
  
  
  Tip 2: Ask For Examples First
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "Show me what the Excel file will look like before creating it"

Claude: *describes structure, then creates it*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tip 3: Iterate
&lt;/h3&gt;

&lt;p&gt;Don't expect perfection on first try. You can say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Add a new column for..."&lt;/li&gt;
&lt;li&gt;"Change the formatting to..."&lt;/li&gt;
&lt;li&gt;"Add speaker notes to each slide..."&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tip 4: Upload Templates
&lt;/h3&gt;

&lt;p&gt;Have a company template? Upload it and say:&lt;br&gt;
"Use this template and create a presentation about [topic]"&lt;/p&gt;
&lt;h2&gt;
  
  
  How This Compares To Other Tools
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;vs Microsoft Copilot:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude: Better at understanding complex requests&lt;/li&gt;
&lt;li&gt;Copilot: Better at integrating with your existing Office files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;vs ChatGPT:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude: Built-in office document skills&lt;/li&gt;
&lt;li&gt;ChatGPT: Requires plugins or third-party tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;vs Google Docs AI:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude: Creates downloadable files&lt;/li&gt;
&lt;li&gt;Google Docs: Works directly in your docs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This isn't just "cool AI tricks" - it's genuinely useful:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1: Quick Mockups&lt;/strong&gt;&lt;br&gt;
Need a financial model for a pitch tomorrow? Claude can build the skeleton in minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 2: Document Processing&lt;/strong&gt;&lt;br&gt;
Got 50 PDFs to extract data from? Claude can automate it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 3: Template Creation&lt;/strong&gt;&lt;br&gt;
Need a standard report format? Create it once with Claude, then reuse.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try It Now
&lt;/h2&gt;

&lt;p&gt;Pick one and paste it into Claude.ai:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a personal budget Excel spreadsheet with:
- Monthly income section
- Expense categories (rent, food, transport, entertainment)
- Formulas to calculate totals and remaining balance
- Color coding (expenses in red, income in green)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a 3-slide PowerPoint about time management with:
- Slide 1: Title "Productivity Tips"
- Slide 2: 5 bullet points with tips
- Slide 3: Call to action
- Add speaker notes to each slide
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Claude.ai is more than a chatbot - it's a document creation powerhouse. These 5 built-in skills mean you can go from "I need a spreadsheet" to having an actual, working Excel file in minutes.&lt;/p&gt;

&lt;p&gt;No plugins. No third-party tools. No copy-paste. Just ask.&lt;/p&gt;

&lt;p&gt;Next time you're about to spend 30 minutes formatting a Word doc or building a spreadsheet, try asking Claude first. You might be surprised.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Have you used Claude to create documents? What worked well? What didn't? Drop your experiences in the comments!&lt;/strong&gt; 💬&lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S. - These skills are built into Claude.ai and Claude for Desktop. If you're using the API, you'd need to implement document handling yourself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>Claude Code Skills vs Subagents - When to Use What?</title>
      <dc:creator>Nunc</dc:creator>
      <pubDate>Mon, 27 Oct 2025 19:03:26 +0000</pubDate>
      <link>https://forem.com/nunc/claude-code-skills-vs-subagents-when-to-use-what-4d12</link>
      <guid>https://forem.com/nunc/claude-code-skills-vs-subagents-when-to-use-what-4d12</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Skills are like recipes, subagents are like specialized coworkers. Both extend Claude Code, but knowing when to use which saves you a ton of headache.&lt;/p&gt;

&lt;p&gt;So I was building a document reader for Claude Code (to process Word docs, PDFs, Excel files from support tickets), and I hit this question: "Should this be a &lt;strong&gt;skill&lt;/strong&gt; or a &lt;strong&gt;subagent&lt;/strong&gt;?"&lt;/p&gt;

&lt;p&gt;Turns out, this is a pretty common confusion. Let me save you the research time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Quick Version
&lt;/h2&gt;

&lt;p&gt;Here's the cheat sheet:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Skills&lt;/th&gt;
&lt;th&gt;Subagents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What it is&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Instructions that extend Claude's knowledge&lt;/td&gt;
&lt;td&gt;A separate AI assistant with its own context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;When Claude uses it&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automatically when relevant&lt;/td&gt;
&lt;td&gt;Delegated for complex workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Utility functions, recipes, how-tos&lt;/td&gt;
&lt;td&gt;Multi-step analysis, code review, research&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Context&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shares your main chat context&lt;/td&gt;
&lt;td&gt;Gets its own isolated context window&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Think of it this way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skill&lt;/strong&gt; = giving Claude a cookbook&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagent&lt;/strong&gt; = hiring a sous chef&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Skills: The Recipe Approach
&lt;/h2&gt;

&lt;p&gt;Skills are markdown files with instructions. Claude reads them when it needs help with something specific.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example structure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.claude/skills/document-reader/
├── SKILL.md          (main instructions)
├── examples.md       (usage examples)
└── scripts/
    └── converter.py  (optional helper script)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use skills:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Converting files (PDF → text, DOCX → text)&lt;/li&gt;
&lt;li&gt;Template generation&lt;/li&gt;
&lt;li&gt;Style guides for code/writing&lt;/li&gt;
&lt;li&gt;Domain knowledge (business rules, API docs)&lt;/li&gt;
&lt;li&gt;Quick utility functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why skills are great:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚡ Fast - Claude just reads instructions&lt;/li&gt;
&lt;li&gt;🔄 Reusable - any conversation can use them&lt;/li&gt;
&lt;li&gt;🪶 Lightweight - no separate AI needed&lt;/li&gt;
&lt;li&gt;🤖 Auto-activated - Claude decides when to use them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example skill description:&lt;/strong&gt;&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="nn"&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;document-reader&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Converts document files (.pdf, .docx, .xlsx) to text. Use when reading document attachments, analyzing files from tickets, or extracting content from PDFs and spreadsheets.&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice: it tells Claude &lt;strong&gt;what&lt;/strong&gt; it does and &lt;strong&gt;when&lt;/strong&gt; to use it. That's key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subagents: The Specialized Coworker
&lt;/h2&gt;

&lt;p&gt;Subagents are like delegating work to a specialist. They get their own context window and run independently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use subagents:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code review workflows&lt;/li&gt;
&lt;li&gt;Multi-file analysis&lt;/li&gt;
&lt;li&gt;Research tasks that need deep investigation&lt;/li&gt;
&lt;li&gt;Tasks that would clutter your main conversation&lt;/li&gt;
&lt;li&gt;When you need focused, dedicated reasoning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why subagents rock:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧠 Deep focus - dedicated context for complex tasks&lt;/li&gt;
&lt;li&gt;🔍 Multi-step reasoning - can work through problems systematically&lt;/li&gt;
&lt;li&gt;🎯 Specialized - custom prompts for specific workflows&lt;/li&gt;
&lt;li&gt;🧹 Clean separation - doesn't pollute main chat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example subagent:&lt;/strong&gt;&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="nn"&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;code-reviewer&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Reviews code for best practices and security issues. Use when reviewing PRs or analyzing code quality.&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Read, Grep, Glob&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="s"&gt;You are a specialized code reviewer...&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;detailed instructions for review process&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real Example: Document Reader
&lt;/h2&gt;

&lt;p&gt;Here's how I decided for my document reader:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The task:&lt;/strong&gt; Read PDF/DOCX/XLSX files from support tickets&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My thought process:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is this complex multi-step reasoning? &lt;strong&gt;No&lt;/strong&gt; - just file conversion&lt;/li&gt;
&lt;li&gt;Does it need its own context? &lt;strong&gt;No&lt;/strong&gt; - simple input/output&lt;/li&gt;
&lt;li&gt;Is it a utility function? &lt;strong&gt;Yes&lt;/strong&gt; - convert file to text&lt;/li&gt;
&lt;li&gt;Will other agents need this? &lt;strong&gt;Yes&lt;/strong&gt; - zahtevki-researcher needs it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Decision: Make it a skill ✅&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I needed to &lt;em&gt;analyze&lt;/em&gt; documents across multiple tickets, &lt;em&gt;compare&lt;/em&gt; them, and &lt;em&gt;generate reports&lt;/em&gt;? That would be a subagent.&lt;/p&gt;

&lt;h2&gt;
  
  
  How They Work Together
&lt;/h2&gt;

&lt;p&gt;Here's the cool part - they complement each other:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;zahtevki-researcher (subagent)
  ↓
Downloads ticket attachment.docx
  ↓
Invokes document-reader (skill)
  ↓
Converts to text
  ↓
Analyzes content
  ↓
Returns findings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The subagent handles the complex workflow, the skill handles the utility function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision Tree
&lt;/h2&gt;

&lt;p&gt;Use this when you're stuck:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it a utility/conversion/template?&lt;/strong&gt; → Skill&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it need multiple steps of reasoning?&lt;/strong&gt; → Subagent&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will it be reused across different tasks?&lt;/strong&gt; → Skill&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it a complex workflow with validation loops?&lt;/strong&gt; → Subagent&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it knowledge Claude doesn't have?&lt;/strong&gt; → Skill&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it need to coordinate multiple operations?&lt;/strong&gt; → Subagent&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Tips
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;For Skills:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep SKILL.md under 500 lines&lt;/li&gt;
&lt;li&gt;Use progressive disclosure (main file → reference files)&lt;/li&gt;
&lt;li&gt;Write descriptions in third person&lt;/li&gt;
&lt;li&gt;Include trigger words (when to use it)&lt;/li&gt;
&lt;li&gt;Make them discoverable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For Subagents:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write detailed system prompts&lt;/li&gt;
&lt;li&gt;Define clear responsibilities (single focus)&lt;/li&gt;
&lt;li&gt;Limit tool access to what's needed&lt;/li&gt;
&lt;li&gt;Test that they activate correctly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;After building both, here's my take:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start with a skill&lt;/strong&gt; unless you specifically need subagent features. Skills are simpler, faster, and easier to maintain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Upgrade to subagent&lt;/strong&gt; when you're doing actual &lt;em&gt;workflows&lt;/em&gt; - things with multiple steps, decision points, validation loops.&lt;/p&gt;

&lt;p&gt;My document reader? Perfect as a skill. It's fast, reusable, and other agents can invoke it seamlessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Want to build your own? Here's a 5-minute starter:&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;# Create a skill directory&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.claude/skills/my-skill

&lt;span class="c"&gt;# Create SKILL.md&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.claude/skills/my-skill/SKILL.md &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
---
name: my-skill
description: What it does and when to use it
---

# My Skill

Instructions go here...
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next time you chat with Claude, it'll automatically discover and use your skill!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What are you building with Claude Code? Skills or subagents? Share in the comments - I'd love to hear what you're working on!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S. - If you found this helpful, I'm documenting my whole journey building skills for an insurance system. Follow along if you're into that sort of thing!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How I Built Agent Skills for Claude Code</title>
      <dc:creator>Nunc</dc:creator>
      <pubDate>Tue, 21 Oct 2025 12:05:19 +0000</pubDate>
      <link>https://forem.com/nunc/how-i-built-agent-skills-for-claude-code-oj4</link>
      <guid>https://forem.com/nunc/how-i-built-agent-skills-for-claude-code-oj4</guid>
      <description>&lt;p&gt;&lt;strong&gt;How I stopped re-explaining my legacy database every single conversation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I was working with this gnarly Oracle database - 1,048 packages, 20,913 stored procedures, Slovenian terminology, old-school SQL syntax from the 90s. You know the type.&lt;/p&gt;

&lt;p&gt;Every time I asked Claude for help, I'd spend the first 10 minutes explaining:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"No, use WHERE joins, not ANSI JOIN"&lt;/li&gt;
&lt;li&gt;"That's Slovenian for 'claim file'"&lt;/li&gt;
&lt;li&gt;"We always validate extraction quality"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It got old. Fast.&lt;/p&gt;

&lt;p&gt;Then I discovered Agent Skills. Now Claude just... knows. It's like I taught it once, and it remembers forever.&lt;/p&gt;

&lt;p&gt;Let me show you how I did it, because honestly, it's easier than you think.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Even Are Agent Skills?
&lt;/h2&gt;

&lt;p&gt;Think of them as plugins for Claude. Little knowledge modules that Claude loads automatically when it needs them.&lt;/p&gt;

&lt;p&gt;You write a markdown file saying "Here's how to work with my database" or "Here's how our API works" - and Claude references it whenever relevant. No more repetitive explanations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The magic part&lt;/strong&gt;: You don't manually activate skills. Claude reads the descriptions and figures out which ones to use. It's actually pretty smart about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Absolute Minimum You Need
&lt;/h2&gt;

&lt;p&gt;One file. That's it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.claude/skills/my-thing/
└── SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a complete working skill:&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="nn"&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;pdf-tools&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Extract text from PDFs using pdfplumber. Use when working with PDF files.&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# PDF Tools&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pdfplumber&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pdfplumber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file.pdf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;extract_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done. You now have a skill. Seriously.&lt;/p&gt;

&lt;h2&gt;
  
  
  The One Rule That Matters
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Keep it short.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Claude's context window is shared between your conversation, the code, other skills, and everything else. Don't waste tokens.&lt;/p&gt;

&lt;p&gt;Here's what I mean:&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ This wastes everyone's time
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Extract PDF text&lt;/span&gt;

PDF stands for Portable Document Format. It's a file format developed by Adobe in 1992 for presenting documents. PDFs can contain text, images, forms, and more. To extract text from a PDF, you'll need to use a specialized library. There are many options available in Python, such as PyPDF2, pdfplumber, and PyMuPDF. We recommend pdfplumber because it's actively maintained and handles most edge cases well. First, you'll need to install it using pip...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ This is what Claude actually needs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Extract PDF text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pdfplumber&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pdfplumber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file.pdf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;extract_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude already knows what PDFs are. Show the code, move on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Target: Keep your main SKILL.md file under 500 lines.&lt;/strong&gt; If you need more, split it into reference files (I'll show you how in a sec).&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing Descriptions That Actually Work
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;description&lt;/code&gt; in your YAML frontmatter is critical. It's how Claude decides whether to load your skill.&lt;/p&gt;

&lt;p&gt;The formula that works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does + When to use it + Trigger words&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples that work
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Extract text from PDFs using pdfplumber. Use when working with PDF files, forms, or document extraction.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Connect to Oracle database, extract PL/SQL packages with old-style SQL syntax. Use for Oracle database operations or PL/SQL code extraction.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Analyze Excel spreadsheets, create pivot tables. Use when working with .xlsx files or tabular data.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What doesn't work
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Helps with files&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Does database stuff&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Utility functions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Too vague. Claude won't know when to use it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: Always write in third person ("Extracts text from PDFs" not "I can extract text"). Claude's system prompt uses third person, so first/second person confuses things.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Secret: Progressive Disclosure
&lt;/h2&gt;

&lt;p&gt;This is the pattern that lets your skills scale without bloating the context window.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The idea&lt;/strong&gt;: Your SKILL.md is like a table of contents. Point to details, don't include everything upfront.&lt;/p&gt;

&lt;p&gt;Here's how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Claude loads all skill descriptions at startup (just names + descriptions)&lt;/li&gt;
&lt;li&gt;When triggered, Claude loads your SKILL.md&lt;/li&gt;
&lt;li&gt;As needed, Claude reads specific reference files&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# API Client&lt;/span&gt;

&lt;span class="gu"&gt;## Quick Start&lt;/span&gt;
[Basic code example here]

&lt;span class="gu"&gt;## Advanced&lt;/span&gt;

Need authentication? See &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;AUTH.md&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;AUTH.md&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
Rate limiting? See &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;LIMITS.md&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;LIMITS.md&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
Error handling? See &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;ERRORS.md&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;ERRORS.md&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude only reads AUTH.md when someone asks about authentication. Saves tons of context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep it one level deep though
&lt;/h3&gt;

&lt;p&gt;❌ Don't do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SKILL.md → advanced.md → details.md → actual_info.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SKILL.md → auth.md, limits.md, errors.md, examples.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude sometimes only partially reads nested files, so keep references direct from SKILL.md.&lt;/p&gt;

&lt;h3&gt;
  
  
  Table of Contents for long files
&lt;/h3&gt;

&lt;p&gt;If a reference file gets over 100 lines, add a ToC at the top:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# API Reference&lt;/span&gt;

&lt;span class="gu"&gt;## Contents&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Authentication&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;#authentication&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Endpoints&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;#endpoints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Error Codes&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;#error-codes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Authentication&lt;/span&gt;
[...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps Claude navigate even when it only partially reads the file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example: My Oracle Nightmare (Now Solved)
&lt;/h2&gt;

&lt;p&gt;Let me show you the actual skill I built. It started as a mess and ended up at 100% compliance with Anthropic's best practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;I work with this insurance application database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1,048 PL/SQL packages&lt;/li&gt;
&lt;li&gt;20,913 procedures (yes, really)&lt;/li&gt;
&lt;li&gt;All the business terms in Slovenian&lt;/li&gt;
&lt;li&gt;SQL syntax from 1995 (WHERE clause joins only, no ANSI)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd have the same conversation every day:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Use WHERE joins, not INNER JOIN"&lt;/li&gt;
&lt;li&gt;"That column is 'skondi_spis' which means claim file"&lt;/li&gt;
&lt;li&gt;"Check the line count after extraction to validate"&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Solution: Two Skills, Not One
&lt;/h3&gt;

&lt;p&gt;I almost made one giant skill with everything. Thank god I didn't.&lt;/p&gt;

&lt;p&gt;Instead:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;db-toolkit&lt;/strong&gt; - How to connect, extract, query (technical stuff)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;business-domain&lt;/strong&gt; - What the tables mean, business processes (domain knowledge)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why separate?&lt;/strong&gt; They change at different rates. Database operations don't change much. Business knowledge updates constantly. Sometimes I only need one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Here's the db-toolkit structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.claude/skills/db-toolkit/
├── SKILL.md (687 lines - yeah, over 500, but it's worth it)
├── reference.md (API docs for all methods)
├── usage-examples.md (10+ real scenarios)
├── sql-syntax-guide.md (old-style SQL examples)
├── troubleshooting.md (common errors)
└── scripts/
    └── oracle_toolkit_standalone.py (the actual code)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What made it actually work
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Everything's embedded&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No external dependencies. The Python code lives in &lt;code&gt;scripts/&lt;/code&gt; inside the skill:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;skill_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.claude&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;skills&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;db-toolkit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skill_dir&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;scripts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;oracle_toolkit_standalone&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OracleToolkit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skill works anywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Copy-paste checklists&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Best thing I added. For complex workflows, give Claude a checklist to track:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Copy this checklist:

Task Progress:
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Connect to database
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Extract package body
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Validate extraction (check line count)
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Copy to working directory
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Make changes
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Run tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude checks items off as it works. I can see progress. Users love this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Validate everything immediately&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every operation gets validated right away with specific help:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pkg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;toolkit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extract_source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MY_SCHEMA&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PKG_EXAMPLE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PACKAGE BODY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;❌ Failed:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🔄 Try these fixes:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  • Check package name spelling&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  • Use &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PACKAGE BODY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; not &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PACKAGE&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  • Verify schema owner is correct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;

&lt;span class="c1"&gt;# Also validate quality
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;line_count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;⚠️  Suspiciously small extraction - double check&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more mystery errors later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Skills reference each other&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;db-toolkit mentions business-domain for business context.&lt;br&gt;
business-domain mentions db-toolkit for database operations.&lt;/p&gt;

&lt;p&gt;Claude figures out when it needs both.&lt;/p&gt;
&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;After refining over a few weeks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ 100% compliance with Anthropic best practices&lt;/li&gt;
&lt;li&gt;✅ 85.7% test pass rate (12 out of 14 tests)&lt;/li&gt;
&lt;li&gt;✅ Saves me probably 10 hours a week&lt;/li&gt;
&lt;li&gt;✅ Works reliably across sessions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: My SKILL.md is 687 lines, which is over the recommended 500. But it's validated workflows with checklists that users copy directly. Worth the trade-off.&lt;/p&gt;
&lt;h2&gt;
  
  
  Patterns I Use All The Time
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. The Template Pattern
&lt;/h3&gt;

&lt;p&gt;When you need exact output format, put this in your SKILL.md:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example SKILL.md content:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Report Format&lt;/span&gt;

ALWAYS use this structure:
&lt;span class="gh"&gt;# [Title]&lt;/span&gt;
&lt;span class="gu"&gt;## Summary&lt;/span&gt;
[One paragraph]

&lt;span class="gu"&gt;## Findings&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Finding 1
&lt;span class="p"&gt;-&lt;/span&gt; Finding 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For flexible stuff, say "adapt as needed" instead of "ALWAYS."&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Show Examples, Not Descriptions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Example SKILL.md content:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Commit Messages&lt;/span&gt;

&lt;span class="gs"&gt;**Example**&lt;/span&gt;:
Input: "Added user auth with JWT"
Output:
feat(auth): implement JWT authentication

Add login endpoint and token validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One example beats ten paragraphs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Guide Through Decisions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Example SKILL.md content:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## What to do&lt;/span&gt;

Determine your situation:

&lt;span class="gs"&gt;**Creating new document?**&lt;/span&gt; → Use Creation Workflow below
&lt;span class="gs"&gt;**Editing existing?**&lt;/span&gt; → Use Editing Workflow below

&lt;span class="gu"&gt;### Creation Workflow&lt;/span&gt;
[steps...]

&lt;span class="gu"&gt;### Editing Workflow&lt;/span&gt;
[steps...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How I Actually Built It (Not How You'd Think)
&lt;/h2&gt;

&lt;p&gt;I didn't sit down and write a massive spec. Here's what actually worked:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Started with the pain points
&lt;/h3&gt;

&lt;p&gt;Used Claude for a week without a skill. Noted every time I had to repeat myself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explained old-style SQL 5 times → added syntax guide&lt;/li&gt;
&lt;li&gt;Kept saying "validate extraction" → added validation loops&lt;/li&gt;
&lt;li&gt;Explained Slovenian terms constantly → added glossary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Built the skill from actual problems, not imagined ones.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Wrote tests first
&lt;/h3&gt;

&lt;p&gt;Created 3 simple test scenarios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Test 1: "Extract package PKG_EXAMPLE" → should connect and extract
Test 2: "Show me tables for this module" → should list relevant tables
Test 3: "Fix this SQL join" → should suggest old-style syntax
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then wrote just enough skill content to pass those tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Observed what Claude actually read
&lt;/h3&gt;

&lt;p&gt;Watched which files Claude opened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Went to sql-syntax-guide.md often → made it clearer&lt;/li&gt;
&lt;li&gt;Rarely opened troubleshooting.md → moved common stuff to SKILL.md&lt;/li&gt;
&lt;li&gt;Skipped parts of examples.md → added ToC for faster navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adjusted based on behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The "3 times rule"
&lt;/h3&gt;

&lt;p&gt;If I explained something 3 times in conversations → it went in the skill.&lt;/p&gt;

&lt;p&gt;Example: Kept saying "use (+) for outer joins" → added to SQL guide with examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  What NOT to Do (I learned the hard way)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Time-sensitive info
&lt;/h3&gt;

&lt;p&gt;Don't write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Before August 2025, use old API.
After August 2025, use new API.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skills should be evergreen.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Windows paths
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Bad
&lt;/span&gt;&lt;span class="n"&gt;scripts&lt;/span&gt;\&lt;span class="n"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;

&lt;span class="c1"&gt;# Good
&lt;/span&gt;&lt;span class="n"&gt;scripts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Always forward slashes.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Offering too many options
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Bad&lt;/span&gt;
You could use library A, B, C, D, E, F, or G...

&lt;span class="gh"&gt;# Good&lt;/span&gt;
Use pdfplumber for most cases.
Edge cases? See &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;alternatives.md&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;alternatives.md&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ❌ Mega-skills
&lt;/h3&gt;

&lt;p&gt;Don't make one skill for everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;database-and-api-and-deployment-and-monitoring/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make focused skills:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;database-toolkit/
api-client/
deployment/
monitoring/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick Start: Build Your First Skill Right Now
&lt;/h2&gt;

&lt;p&gt;Pick something you explain to Claude repeatedly. For me it was database stuff. For you maybe it's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How your API works&lt;/li&gt;
&lt;li&gt;Your company's coding standards&lt;/li&gt;
&lt;li&gt;Common git workflows&lt;/li&gt;
&lt;li&gt;Specific library you use a lot&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5-minute version
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.claude/skills/my-thing
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.claude/skills/my-thing
nano SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write this:&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="nn"&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;my-thing&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;What it does&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="s"&gt;. Use when [trigger words].&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="c1"&gt;# My Thing&lt;/span&gt;

&lt;span class="c1"&gt;## Quick Start&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;One code example&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;## Common Tasks&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;2-3 more examples&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save it. Ask Claude a question that should trigger it.&lt;/p&gt;

&lt;p&gt;That's it. You have a working skill.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Checklist (So You Know You're Done)
&lt;/h2&gt;

&lt;p&gt;Before you call a skill "done":&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] SKILL.md under 500 lines (or you have a good reason)&lt;/li&gt;
&lt;li&gt;[ ] Valid YAML with name and description&lt;/li&gt;
&lt;li&gt;[ ] If you have reference files, they link from SKILL.md (not nested deeper)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Third person ("Processes files" not "I process")&lt;/li&gt;
&lt;li&gt;[ ] Says what it does&lt;/li&gt;
&lt;li&gt;[ ] Says when to use it&lt;/li&gt;
&lt;li&gt;[ ] Under 1024 characters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Content&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Assumes Claude is smart (no explanations of basic concepts)&lt;/li&gt;
&lt;li&gt;[ ] Consistent terms throughout&lt;/li&gt;
&lt;li&gt;[ ] No dates or version numbers that'll expire&lt;/li&gt;
&lt;li&gt;[ ] Forward slashes in paths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Tried it with real questions&lt;/li&gt;
&lt;li&gt;[ ] Claude activates it when it should&lt;/li&gt;
&lt;li&gt;[ ] Claude finds the right info&lt;/li&gt;
&lt;li&gt;[ ] At least 80% success rate&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Building the db-toolkit skill changed how I work with Claude. Instead of fighting with it every conversation, it just knows my database quirks.&lt;/p&gt;

&lt;p&gt;The skill saves me probably 10 hours a week. No more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Re-explaining SQL syntax&lt;/li&gt;
&lt;li&gt;Translating Slovenian terms&lt;/li&gt;
&lt;li&gt;Reminding it to validate extractions&lt;/li&gt;
&lt;li&gt;Describing table relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It just works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best part?&lt;/strong&gt; Skills improve with use. Each conversation shows you what's missing. Each addition makes the next session better.&lt;/p&gt;

&lt;p&gt;I started with a 100-line SKILL.md. Over 3 months of actual use, it grew to 3,100 lines across multiple files - but only because I found real gaps worth filling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Turn
&lt;/h2&gt;

&lt;p&gt;Start small. Don't try to document everything. Pick one thing you repeat constantly and build a skill for that.&lt;/p&gt;

&lt;p&gt;Maybe it's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your database schema&lt;/li&gt;
&lt;li&gt;API endpoints you use&lt;/li&gt;
&lt;li&gt;Git workflow your team follows&lt;/li&gt;
&lt;li&gt;Library you use every project&lt;/li&gt;
&lt;li&gt;Testing patterns&lt;/li&gt;
&lt;li&gt;Deployment process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whatever it is, write a minimal SKILL.md. Use it for a week. See what's missing. Add that.&lt;/p&gt;

&lt;p&gt;In a month you'll wonder how you ever worked without it.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Questions? Built a skill and want to share? Drop a comment - I'm genuinely curious what you build.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>productivity</category>
      <category>development</category>
    </item>
  </channel>
</rss>
