<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Steve Davis</title>
    <description>The latest articles on DEV Community by Steve Davis (@iamstevedavis).</description>
    <link>https://dev.to/iamstevedavis</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%2F3787035%2Fa2eacfcd-d867-4524-a34a-02bd75ecdb24.jpeg</url>
      <title>DEV Community: Steve Davis</title>
      <link>https://dev.to/iamstevedavis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iamstevedavis"/>
    <language>en</language>
    <item>
      <title>Building a Self-Hosted AI Developer Assistant with OpenClaw</title>
      <dc:creator>Steve Davis</dc:creator>
      <pubDate>Wed, 11 Mar 2026 23:59:40 +0000</pubDate>
      <link>https://dev.to/iamstevedavis/building-a-self-hosted-ai-developer-assistant-with-openclaw-3kj7</link>
      <guid>https://dev.to/iamstevedavis/building-a-self-hosted-ai-developer-assistant-with-openclaw-3kj7</guid>
      <description>&lt;h1&gt;
  
  
  Building a Self-Hosted AI Developer Assistant with OpenClaw
&lt;/h1&gt;

&lt;p&gt;I wanted an assistant that could do real engineering work, not just answer prompts. So I turned a VPS into a self-hosted AI operator that can open GitHub issues, implement fixes, push branches, open PRs, write docs, and even generate blog drafts like this one.&lt;/p&gt;

&lt;p&gt;This post walks through how I set up OpenClaw, why I routed coding work through Edith, and what actually worked (and what broke) once the system started doing real tasks.&lt;/p&gt;




&lt;h2&gt;
  
  
  What OpenClaw actually is
&lt;/h2&gt;

&lt;p&gt;OpenClaw is a hostable agent runtime. Think of it as an orchestration layer between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;messaging channels (Signal, Discord, etc.)&lt;/li&gt;
&lt;li&gt;tools (shell, git, browser, APIs)&lt;/li&gt;
&lt;li&gt;memory/context&lt;/li&gt;
&lt;li&gt;specialized workers (subagents / coding agents)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s not “just a chatbot.” It’s a controllable runtime that can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;parse instructions from chat&lt;/li&gt;
&lt;li&gt;call tools with guardrails&lt;/li&gt;
&lt;li&gt;run code tasks in isolated worker sessions&lt;/li&gt;
&lt;li&gt;produce artifacts (commits, PRs, docs, drafts)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In practice, OpenClaw gives you a policy-aware control plane for AI actions. You can keep high-trust actions internal, require confirmation for risky external writes, and still move quickly on repetitive engineering work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I wanted a self-hosted agent
&lt;/h2&gt;

&lt;p&gt;I wanted three things cloud copilots don’t really give me:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control over execution&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I choose where commands run, where secrets live, and which repos the agent can touch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Composable automation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I wanted one assistant that can coordinate issues, PRs, docs, and content—not five disconnected tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Predictable ops + lower marginal cost&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A VPS + containers + my own workflow is easier to reason about than constantly changing SaaS limits.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also: I don’t want to copy/paste the same “please create branch, implement, test, open PR” instructions every day.&lt;/p&gt;




&lt;h2&gt;
  
  
  My architecture
&lt;/h2&gt;

&lt;p&gt;Here’s the shape that worked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VPS&lt;/strong&gt; running Dockerized workloads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenClaw&lt;/strong&gt; as the agent runtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nginx Proxy Manager&lt;/strong&gt; for ingress/TLS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub auth + repo clones&lt;/strong&gt; on host&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill modules&lt;/strong&gt; for repeatable tasks (e.g., DEV draft creation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagents&lt;/strong&gt; for longer coding jobs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edith&lt;/strong&gt; as the coding-task routing setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Edith fits in
&lt;/h3&gt;

&lt;p&gt;Friday is my main agent and orchestrator. When I give a non-trivial coding task, Friday delegates it to Edith as the coding worker, then Edith reports back to Friday with results.&lt;/p&gt;

&lt;p&gt;That separation matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Friday stays responsive in the main conversation&lt;/li&gt;
&lt;li&gt;coding jobs run in focused worker context via Edith&lt;/li&gt;
&lt;li&gt;long jobs complete asynchronously&lt;/li&gt;
&lt;li&gt;failures are isolated and easy to report&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short: Friday orchestrates, Edith executes coding tasks, and Friday delivers the final outcome back to me.&lt;/p&gt;

&lt;h3&gt;
  
  
  A simplified flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;I send a request in chat (e.g., “fix oldest open issue in repo X”).&lt;/li&gt;
&lt;li&gt;OpenClaw reads policy/skills and validates tool path.&lt;/li&gt;
&lt;li&gt;Task is delegated through Edith to a coding worker.&lt;/li&gt;
&lt;li&gt;Worker explores code, edits files, runs checks.&lt;/li&gt;
&lt;li&gt;Worker pushes branch + opens PR.&lt;/li&gt;
&lt;li&gt;Assistant reports back with links and test output.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Automating PRs + issues
&lt;/h2&gt;

&lt;p&gt;This is where the setup started paying for itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create GitHub issues from backlog notes
&lt;/h3&gt;

&lt;p&gt;Instead of manually drafting issue bodies, I feed rough notes and constraints. The assistant turns them into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clear problem statements&lt;/li&gt;
&lt;li&gt;acceptance criteria&lt;/li&gt;
&lt;li&gt;implementation hints&lt;/li&gt;
&lt;li&gt;priority labels / metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That keeps issue quality high and reduces “what does done mean?” ambiguity before code starts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement issue, branch, test, open PR
&lt;/h3&gt;

&lt;p&gt;For implementation flows, I use a consistent contract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;find target issue&lt;/li&gt;
&lt;li&gt;restate requirements&lt;/li&gt;
&lt;li&gt;create branch (&lt;code&gt;issue-&amp;lt;id&amp;gt;-&amp;lt;slug&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;implement minimal targeted fix/feature&lt;/li&gt;
&lt;li&gt;add/update tests&lt;/li&gt;
&lt;li&gt;run lint/test/typecheck/build&lt;/li&gt;
&lt;li&gt;commit with standardized message&lt;/li&gt;
&lt;li&gt;push + open PR with &lt;code&gt;Closes #&amp;lt;id&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The big win is consistency. Same structure every time means less review overhead and fewer missing steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate docs while context is fresh
&lt;/h3&gt;

&lt;p&gt;After implementation, I often have the agent update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;README sections&lt;/li&gt;
&lt;li&gt;operator notes&lt;/li&gt;
&lt;li&gt;migration/setup steps&lt;/li&gt;
&lt;li&gt;changelog snippets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the assistant just touched the code, it usually documents changes more accurately than delayed manual docs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate draft blog posts from shipped work
&lt;/h3&gt;

&lt;p&gt;I also reuse this pipeline for writing. The assistant can create DEV.to drafts from completed features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;summarize what changed&lt;/li&gt;
&lt;li&gt;explain architecture decisions&lt;/li&gt;
&lt;li&gt;include command snippets&lt;/li&gt;
&lt;li&gt;leave post unpublished for review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That removes the “I should write about this later” graveyard of ideas.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Guardrails are not optional
&lt;/h3&gt;

&lt;p&gt;Give the agent broad read access, but put friction on destructive/external writes unless explicitly requested. “Fast + safe” beats “fully autonomous.”&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Small, deterministic tasks outperform vague prompts
&lt;/h3&gt;

&lt;p&gt;“Fix issue #24 with acceptance criteria + tests + PR format” works better than “improve this codebase.”&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Subagents are worth it for context isolation
&lt;/h3&gt;

&lt;p&gt;Long coding tasks in a dedicated worker produce better outcomes than cramming everything into the primary chat thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  4) Standardized PR templates reduce cleanup
&lt;/h3&gt;

&lt;p&gt;When every PR includes summary, test notes, and closing keywords, reviews go faster and project history stays clean.&lt;/p&gt;

&lt;h3&gt;
  
  
  5) Self-hosted doesn’t mean zero maintenance
&lt;/h3&gt;

&lt;p&gt;You’re now running an automation platform. Monitor logs, rotate keys, and keep dependencies patched.&lt;/p&gt;

&lt;h3&gt;
  
  
  6) Treat “AI ops” like real ops
&lt;/h3&gt;

&lt;p&gt;Track checks, document runbooks, and design for failure modes. If a workflow is important, make it observable.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I used OpenClaw + containerized infrastructure on a VPS to build a practical AI developer assistant that can create issues, ship PRs, write docs, generate blog drafts, and manage repos. Routing coding jobs through Edith gave me cleaner isolation, better reliability, and a workflow I can actually trust.&lt;/p&gt;

&lt;p&gt;If you want to build one, start with strict guardrails and one repeatable automation path, then expand from there.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Automated DEV.to Drafts from a VPS with OpenClaw</title>
      <dc:creator>Steve Davis</dc:creator>
      <pubDate>Mon, 23 Feb 2026 22:43:25 +0000</pubDate>
      <link>https://dev.to/iamstevedavis/i-automated-devto-drafts-from-a-vps-with-openclaw-l77</link>
      <guid>https://dev.to/iamstevedavis/i-automated-devto-drafts-from-a-vps-with-openclaw-l77</guid>
      <description>&lt;h1&gt;
  
  
  I Automated DEV.to Drafts from a VPS with OpenClaw
&lt;/h1&gt;

&lt;p&gt;Most writing workflows die in the gap between “good idea” and “I’ll write that later.” I wanted a system where I could drop a rough idea from my phone and get a polished DEV draft waiting for review. Running OpenClaw on a VPS made that possible without keeping my laptop online.&lt;/p&gt;




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

&lt;p&gt;If you publish technical posts regularly, consistency is harder than inspiration. Ideas appear in bursts, but formatting, structuring, and posting can be slow. An always-on VPS turns that friction into an automated pipeline: capture an idea, generate a draft, and store it safely as unpublished for final human approval.&lt;/p&gt;




&lt;h2&gt;
  
  
  The idea in one minute
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Build a small custom skill (&lt;code&gt;devto-draft&lt;/code&gt;) that turns rough prompts into DEV-ready Markdown.&lt;/li&gt;
&lt;li&gt;Post via the DEV API with &lt;code&gt;published: false&lt;/code&gt; so nothing goes live by accident.&lt;/li&gt;
&lt;li&gt;Return the draft URL immediately so editing and approval stay in your control.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step-by-step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Create a skill for one specific outcome
&lt;/h3&gt;

&lt;p&gt;General prompts produce inconsistent structure. A dedicated skill lets you enforce a predictable post shape: hook, rationale, steps, pitfalls, TL;DR, and next steps.&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;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.openclaw/workspace/skills/devto-draft/&lt;span class="o"&gt;{&lt;/span&gt;templates,tools&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep your &lt;code&gt;SKILL.md&lt;/code&gt; strict about output and execution contract (write markdown to &lt;code&gt;/tmp/devto_post.md&lt;/code&gt;, then call your uploader script).&lt;/p&gt;




&lt;h3&gt;
  
  
  2) Add a tiny uploader script for DEV drafts
&lt;/h3&gt;

&lt;p&gt;Use a local Python script to call &lt;code&gt;https://dev.to/api/articles&lt;/code&gt; with your API key and hard-code draft behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 tools/devto_create_draft.py &lt;span class="s2"&gt;"My Title"&lt;/span&gt; &lt;span class="s2"&gt;"openclaw,automation,devops"&lt;/span&gt; /tmp/devto_post.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the payload, force:&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;"published"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That one flag is the safety rail that keeps automation useful instead of risky.&lt;/p&gt;




&lt;h3&gt;
  
  
  3) Keep secrets and runtime stable on the VPS
&lt;/h3&gt;

&lt;p&gt;Your script should read &lt;code&gt;DEVTO_API_KEY&lt;/code&gt; from env and optionally fall back to &lt;code&gt;~/.secrets/devto.env&lt;/code&gt;. A VPS is ideal here because you get one stable runtime, one skill path, and one place to debug.&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;# ~/.secrets/devto.env&lt;/span&gt;
&lt;span class="nv"&gt;DEVTO_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use a local venv in the skill folder so dependency changes are controlled and reproducible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common pitfalls
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pitfall:&lt;/strong&gt; Script path mismatches between skill docs and real files&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Use absolute paths derived from the skill base directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pitfall:&lt;/strong&gt; Missing API key at runtime&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Check env first, then load &lt;code&gt;~/.secrets/devto.env&lt;/code&gt; as fallback.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pitfall:&lt;/strong&gt; Automation accidentally publishes&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Hard-code &lt;code&gt;published: false&lt;/code&gt; in the uploader and never expose a “publish now” default.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A practical example
&lt;/h2&gt;

&lt;p&gt;My day-to-day prompt can be short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use devto-draft: write a DEV post draft about automating DEV drafts from a VPS with OpenClaw.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The skill handles structure and tone, writes &lt;code&gt;/tmp/devto_post.md&lt;/code&gt;, calls the uploader, and returns JSON like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1234567&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://dev.to/yourname/your-slug"&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;Now I review, tweak voice and details, then publish manually when ready.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A VPS makes OpenClaw-based writing automation always available.&lt;/li&gt;
&lt;li&gt;A focused skill beats ad-hoc prompting for consistent draft quality.&lt;/li&gt;
&lt;li&gt;Draft-only posting (&lt;code&gt;published: false&lt;/code&gt;) gives you speed without losing editorial control.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add a “house style” reference file for your voice.&lt;/li&gt;
&lt;li&gt;Add optional variants (short, standard, deep-dive).&lt;/li&gt;
&lt;li&gt;Add a final pre-publish checklist (facts, links, code validity, claims).&lt;/li&gt;
&lt;li&gt;If you run this setup, share what part saved you the most time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dead internet theory is real.&lt;/p&gt;

</description>
      <category>openclaw</category>
      <category>automation</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
