<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Darwin Biler</title>
    <description>Senior Backend Developer</description>
    <link>https://www.darwinbiler.com/</link>
    <atom:link href="https://www.darwinbiler.com/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Sun, 21 Jun 2026 01:36:25 +0000</pubDate>
    <lastBuildDate>Sun, 21 Jun 2026 01:36:25 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Life Decisions is 3D, Not 2D</title>
        <description>&lt;p&gt;Growing up, we were mentally conditioned by movies, fairy tales, religion, and social pressure to always think in 2 dimensions:&lt;/p&gt;

&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-bordered&quot;&gt;
    &lt;thead&gt;
        &lt;tr&gt;&lt;th&gt;Binary Opposites We Were Taught&lt;/th&gt;&lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;&lt;td&gt;Good vs Bad&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;God vs Evil&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Beautiful vs Ugly&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Rewards vs Punishment&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Right vs Wrong&lt;/td&gt;&lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;This binary framework is comforting. It reduces the terrifying complexity of the world into neat little boxes. You are either on the &quot;right&quot; side or the &quot;wrong&quot; side. The hero or the villain. The saint or the sinner.&lt;/p&gt;

&lt;p&gt;But as you mature and learn the dynamics of society, you realize nothing is as simple as that. What one person considers &lt;em&gt;wrong&lt;/em&gt; is perfectly &lt;em&gt;acceptable&lt;/em&gt; to another. Here are just a few examples:&lt;/p&gt;

&lt;h3&gt;The Cracks in the Binary&lt;/h3&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;Politics:&lt;/strong&gt; &quot;Don&apos;t support this cleanup program — it was implemented by the opposing party.&quot; The same action is framed as good or bad depending on who proposed it.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Religion:&lt;/strong&gt; Alcohol is forbidden in some faiths but permitted in others. Divorce is a sin in one tradition and a mundane legal procedure in another. Each faith tradition draws its moral lines differently.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Law:&lt;/strong&gt; Certain substances, behaviors, and contracts are legal in some countries but strictly forbidden in others. The same act crosses the legal line depending only on geography.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Social Norms:&lt;/strong&gt; Peer pressure shifts what is considered &quot;normal.&quot; Conformity is rewarded; deviation is punished — until the norm shifts.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Instinct:&lt;/strong&gt; Avoid harm, protect kin, reproduce, have sex. These primal drives don&apos;t care about moral frameworks.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Personal Ethics:&lt;/strong&gt; &quot;This is not me&quot; — a boundary drawn from within, independent of external rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clearly, the decision-making landscape is not a flat line with two poles. It is a multi-layered space.&lt;/p&gt;

&lt;h2&gt;The 6 Layers of Decision-Making Forces&lt;/h2&gt;

&lt;p&gt;Instead of a binary choice, our decisions are shaped by six distinct layers of influence, stacked upon each other like geological strata:&lt;/p&gt;

&lt;h3&gt;Layer 1: Basic Instinct / Evolutionary Drives&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Reciprocity, kin selection, and group survival.&lt;/em&gt; Rooted in evolutionary psychology. Humans have innate tendencies to help kin, expect reciprocal favors, avoid harm, and bond within groups. Examples: empathy, fairness instinct, revenge instinct, disgust response.&lt;/p&gt;

&lt;h3&gt;Layer 2: Social Norms / Cultural Practices&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Customs, taboos, roles, and traditions.&lt;/em&gt; What is learned from peers and community as acceptable behavior — often unwritten rules. Examples: politeness norms, gender roles, hospitality, food-sharing rules.&lt;/p&gt;

&lt;h3&gt;Layer 3: Religion / Organized Faith Communities&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Codified beliefs, traditions, rituals, and communal practices that define membership in a faith tradition.&lt;/em&gt; These are external systems maintained by institutions and communities. Examples: attending worship services, dietary rules, dress codes, sacraments or rituals, religious authority structures.&lt;/p&gt;

&lt;h3&gt;Layer 4: Spirituality / Personal Relationship with God&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;An individual&apos;s personal pursuit of the divine through conscience, prayer, reflection, or direct experience.&lt;/em&gt; It can reinforce, challenge, or exist independently of organized religion. Examples: feeling called to forgive despite social pressure, personal conviction developed through prayer, believing God asks something different from cultural expectations, mystical or transcendent experiences.&lt;/p&gt;

&lt;h3&gt;Layer 5: Legal and Institutional Rules&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Formal laws, rights, contracts, and punishments.&lt;/em&gt; Created by societies to regulate behavior with clear consequences, often secular. Examples: human rights, criminal laws, property rights, anti-discrimination policies.&lt;/p&gt;

&lt;h3&gt;Layer 6: Personal Ethical Philosophy / Reflective Morality&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Conscience, moral reasoning, and personal principles.&lt;/em&gt; Individually reasoned positions, influenced by but distinct from culture, religion, and law. Examples: utilitarianism, Kantian ethics, existentialist responsibility, self-authored moral code.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;How Decisions Actually Work: The 3D Model&lt;/h2&gt;

&lt;p&gt;Whenever you are making a decision, you are not actually choosing between two options (right vs wrong). You are navigating using three dimensions:&lt;/p&gt;

&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-bordered&quot;&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;Dimension&lt;/th&gt;
            &lt;th&gt;Question&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Goal&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;What is it that you want?&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;What prevents you from doing it?&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;What is that thing that can solve that problem?&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;The decision space itself is &lt;strong&gt;three-dimensional&lt;/strong&gt; (Goal, Problem, Solution), but movement through that space is constrained and influenced by &lt;strong&gt;six overlapping layers&lt;/strong&gt; of instinct, culture, organized religion, personal spirituality, law, and personal ethics. As you determine the &lt;strong&gt;Solution&lt;/strong&gt;, you drag yourself across these layers. Each layer exerts a &lt;em&gt;push&lt;/em&gt; (toward obedience) and a &lt;em&gt;pull&lt;/em&gt; (toward disobedience):&lt;/p&gt;

&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-bordered&quot;&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;Force (Layer)&lt;/th&gt;
            &lt;th&gt;Pushes Toward Obedience&lt;/th&gt;
            &lt;th&gt;Pulls Toward Disobedience&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Basic Instinct (L1)&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;Avoid harm, protect kin&lt;/td&gt;
            &lt;td&gt;Self-interest, group loyalty&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Social Norm (L2)&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;Belonging, avoid shame&lt;/td&gt;
            &lt;td&gt;Rebel for individuality&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Organized Religion (L3)&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;Tradition, community belonging&lt;/td&gt;
            &lt;td&gt;Hypocrisy, institutional distrust&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Spirituality (L4)&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;Personal conviction, divine calling&lt;/td&gt;
            &lt;td&gt;Doubt, unanswered prayers&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Law (L5)&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;Fear of punishment, duty&lt;/td&gt;
            &lt;td&gt;Low enforcement, unjust law&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Personal Ethics (L6)&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;Inner peace, coherence&lt;/td&gt;
            &lt;td&gt;Pragmatism, situational flexibility&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;Your brain subconsciously weighs how heavy each push/pull is. The heaviest force — or the combination of forces tipping the scale — usually wins. And &lt;em&gt;that&lt;/em&gt; is how you come up with what you think is the &lt;strong&gt;&quot;right&quot;&lt;/strong&gt; decision.&lt;/p&gt;

&lt;h2&gt;The Kick: It&apos;s Different for Everyone&lt;/h2&gt;

&lt;p&gt;Here is the interesting part: &lt;em&gt;Every person arrives at what they believe is the right decision as they go through these layers.&lt;/em&gt; But the Goal and the Problem are not the same for everyone.&lt;/p&gt;

&lt;p&gt;Two people facing the same situation can experience completely different:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;Goals&lt;/strong&gt; — Because their desires, fears, and aspirations differ.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Problems&lt;/strong&gt; — Because their circumstances, constraints, and capabilities differ.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Layer Weights&lt;/strong&gt; — Because someone in organized religion weights Layer 3 more than a secular person. A spiritually devout person weights Layer 4 above institutional rules. A lawyer weights Layer 5 more than someone who distrusts institutions. A teenager might weight Layer 2 (social belonging) above all else.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why two reasonable, intelligent, well-meaning people can look at the same issue and reach opposite conclusions. They are not &lt;em&gt;wrong&lt;/em&gt;. They are navigating a different 3D space with different coordinates.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The next time you catch yourself thinking in binary — &quot;this is right, that is wrong&quot; — pause. Ask yourself: what layers are at play? What is my goal? What is my problem? And more importantly, what layers might be at play for the person on the other side of the argument?&lt;/p&gt;

&lt;p&gt;Every decision is the product of a goal, the obstacles standing in its way, and the solution we choose while navigating instincts, culture, religion, law, and personal ethics. Once you see that, life stops looking like a line between right and wrong and starts looking like a multidimensional landscape.&lt;/p&gt;
</description>
        <pubDate>Sun, 21 Jun 2026 01:00:00 +0000</pubDate>
        <link>https://www.darwinbiler.com/life-decisions-is-3d-not-2d/</link>
        <guid isPermaLink="true">https://www.darwinbiler.com/life-decisions-is-3d-not-2d/</guid>
        
        <category>decision making</category>
        
        <category>morality</category>
        
        <category>layers of decision</category>
        
        <category>philosophy</category>
        
        
        <category>philosophy</category>
        
        <category>life</category>
        
      </item>
    
      <item>
        <title>Agentic Coding From Any Device: opencode Server Behind Tailscale</title>
        <description>&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;

&lt;p&gt;Every “AI coding” tool assumes you’re sitting in front of a powerful machine with an IDE installed.&lt;/p&gt;

&lt;p&gt;But what if you’re:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;On the couch with a tablet&lt;/li&gt;
  &lt;li&gt;At a coffee shop with a Chromebook&lt;/li&gt;
  &lt;li&gt;Commuting with only your phone&lt;/li&gt;
  &lt;li&gt;Traveling light without a laptop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The usual answer is: SSH in, use a terminal-based AI tool. That works — I’ve done it — but it still requires a terminal emulator app, and the experience is inherently text-only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if you could get the full agentic coding chat experience — the same one you’d get in VS Code or Claude’s web UI — inside any browser, on any device, without installing anything?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s what this setup does.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-stack&quot;&gt;The Stack&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Fedora Linux server&lt;/strong&gt; (my home lab, behind double NAT)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;opencode&lt;/strong&gt; — a headless server that exposes an agentic coding chat via HTTP&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DeepSeek&lt;/strong&gt; as the LLM backend&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tailscale&lt;/strong&gt; — encrypted WireGuard mesh VPN&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Any browser&lt;/strong&gt; on phone, tablet, laptop, whatever&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The flow:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;📱 Browser → Tailscale IP → opencode server → DeepSeek API → agentic coding&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-opencode-instead-of-ssh--terminal-ai&quot;&gt;Why opencode Instead of SSH + Terminal AI&lt;/h2&gt;

&lt;p&gt;I wrote previously about using Continue.dev CLI over SSH via ConnectBot. That setup is still great for quick terminal queries. But opencode is a different paradigm:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Feature&lt;/th&gt;
      &lt;th&gt;SSH + Continue CLI&lt;/th&gt;
      &lt;th&gt;opencode Server&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Client&lt;/td&gt;
      &lt;td&gt;ConnectBot / terminal&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Any browser&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Interface&lt;/td&gt;
      &lt;td&gt;Text-only terminal&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Rich chat UI&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Device support&lt;/td&gt;
      &lt;td&gt;Android only&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Every device&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;File editing&lt;/td&gt;
      &lt;td&gt;Manual in terminal&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Agent can edit files&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Setup on client&lt;/td&gt;
      &lt;td&gt;Install app&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Open a URL&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Context length&lt;/td&gt;
      &lt;td&gt;Limited by scrollback&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Full HTTP session&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The browser interface means I can hand my phone to a non-technical colleague and say “just type what you need.”&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;setting-it-up&quot;&gt;Setting It Up&lt;/h2&gt;

&lt;h3 id=&quot;1-install-opencode&quot;&gt;1. Install opencode&lt;/h3&gt;

&lt;p&gt;On your server:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-fsSL&lt;/span&gt; https://opencode.ai/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or grab the binary from the &lt;a href=&quot;https://github.com/anomalyco/opencode/releases&quot;&gt;releases page&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;2-configure-the-server&quot;&gt;2. Configure the server&lt;/h3&gt;

&lt;p&gt;opencode can run as an HTTP server. You configure it in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/opencode/opencode.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8094&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;host&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;100.x.x.x&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;provider&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;deepseek&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;deepseek-chat&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host&lt;/code&gt; should be your Tailscale IP so it only listens on the VPN interface — never on a public-facing port.&lt;/p&gt;

&lt;h3 id=&quot;3-start-the-server&quot;&gt;3. Start the server&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;opencode server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’ll see:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;opencode server running on http://100.x.x.x:8094
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;4-access-from-any-device&quot;&gt;4. Access from any device&lt;/h3&gt;

&lt;p&gt;Open your browser and navigate to the Tailscale IP:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://100.x.x.x:8094
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s it. No install, no app, no SSH key setup on the client. You get the full agentic coding chat — the AI can read your codebase, edit files, run commands, and reason about your project.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-tailscale-is-critical&quot;&gt;Why Tailscale Is Critical&lt;/h2&gt;

&lt;p&gt;My home server is behind &lt;strong&gt;double NAT&lt;/strong&gt; (ISP router + my own router). Traditional approaches would require:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Port forwarding (fragile, security risk)&lt;/li&gt;
  &lt;li&gt;A VPS relay (cost, latency)&lt;/li&gt;
  &lt;li&gt;Dynamic DNS + public exposure (dangerous)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tailscale solves all of this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Zero-config NAT traversal&lt;/strong&gt; — devices meet in a WireGuard mesh&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No open ports&lt;/strong&gt; — the server initiates the outbound connection&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Encrypted by default&lt;/strong&gt; — end-to-end WireGuard encryption&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Access controls&lt;/strong&gt; — only devices in your tailnet can reach the server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server binds to the Tailscale IP, so the service is never exposed to the public internet. It’s like having a private LAN that spans the globe.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;real-world-usage&quot;&gt;Real-World Usage&lt;/h2&gt;

&lt;p&gt;I use this constantly. Here are the scenarios that make it worth it:&lt;/p&gt;

&lt;h3 id=&quot;quick-fixes-from-my-phone&quot;&gt;Quick fixes from my phone&lt;/h3&gt;

&lt;p&gt;A bug gets reported while I’m out. I open Chrome on my phone, type in the Tailscale URL, and tell opencode:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Find the error handler in the auth module and add logging for the token expiry case”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It reads the code, makes the edit, and I’m done in 60 seconds.&lt;/p&gt;

&lt;h3 id=&quot;reviewing-prs-on-a-tablet&quot;&gt;Reviewing PRs on a tablet&lt;/h3&gt;

&lt;p&gt;I open the repo, ask opencode to summarize the diff, then ask follow-up questions about specific functions. No laptop needed.&lt;/p&gt;

&lt;h3 id=&quot;pair-debugging-with-a-colleague&quot;&gt;Pair debugging with a colleague&lt;/h3&gt;

&lt;p&gt;I share my screen (or just send them the URL if they’re on my tailnet). They can see the AI reasoning in real time.&lt;/p&gt;

&lt;h3 id=&quot;coding-from-a-chromebook&quot;&gt;Coding from a Chromebook&lt;/h3&gt;

&lt;p&gt;Chromebooks are great for browsing but terrible for local development. This turns any Chromebook into a full agentic coding workstation — just open a tab.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;security&quot;&gt;Security&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;No public ports&lt;/strong&gt; — opencode binds to the Tailscale interface only&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No API keys on clients&lt;/strong&gt; — the LLM API key lives on the server&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No data leaves your tailnet&lt;/strong&gt; — everything stays inside the WireGuard mesh&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tailscale ACLs&lt;/strong&gt; — you can restrict which devices can reach the opencode port&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If someone gets access to your Tailscale network, you have bigger problems — but even then, opencode’s server has no authentication built in, so I add a simple reverse proxy auth or just rely on Tailscale ACLs being strict.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-this-enables&quot;&gt;What This Enables&lt;/h2&gt;

&lt;p&gt;This setup fundamentally changes &lt;em&gt;where&lt;/em&gt; and &lt;em&gt;when&lt;/em&gt; you can do serious coding work.&lt;/p&gt;

&lt;p&gt;You’re no longer tied to a specific machine with a specific IDE. The AI and the codebase live together on the server, and every device becomes a thin client with full agentic capabilities.&lt;/p&gt;

&lt;p&gt;The phone in your pocket is now a supercomputer for software engineering.&lt;/p&gt;

&lt;p&gt;Not “run a terminal and type commands.” A full, interactive, agentic coding assistant — in a browser tab.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;I’ve been through many iterations of this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;SSH + vim&lt;/strong&gt; — works, but no AI&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSH + Continue CLI&lt;/strong&gt; — great, but terminal-only&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;opencode server + Tailscale&lt;/strong&gt; — browser-based agentic coding from anything&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The third one is by far the most practical. It requires zero setup on the client, works on every device I own, and gives me the same agentic coding experience I’d get sitting at my desk — just from a browser tab on a phone.&lt;/p&gt;

&lt;p&gt;If you have a Linux server and a Tailscale network, try it. You might find yourself reaching for your phone more often than you expect.&lt;/p&gt;
</description>
        <pubDate>Sun, 14 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://www.darwinbiler.com/opencode-server-tailscale/</link>
        <guid isPermaLink="true">https://www.darwinbiler.com/opencode-server-tailscale/</guid>
        
        <category>opencode</category>
        
        <category>tailscale</category>
        
        <category>agentic-ai</category>
        
        <category>homelab</category>
        
        <category>devops</category>
        
        <category>productivity</category>
        
        
        <category>DevOps</category>
        
        <category>AI</category>
        
        <category>Productivity</category>
        
      </item>
    
      <item>
        <title>Run Remotion on a Remote Machine and Preview It Locally</title>
        <description>&lt;h1 id=&quot;run-remotion-on-a-remote-machine-and-preview-it-locally&quot;&gt;Run Remotion on a Remote Machine and Preview It Locally&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://remotion.dev&quot;&gt;Remotion&lt;/a&gt; lets you create videos using React. It’s powerful, but running the Remotion Studio (the visual editor) on a headless remote server can feel tricky — there’s no browser to open and no display to render to. This post walks through exactly how to set it up so you can develop Remotion projects on your remote machine and preview everything from your local browser.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1-the-setup&quot;&gt;1. The Setup&lt;/h2&gt;

&lt;p&gt;I assume you already have a Remotion project on your remote machine. If not, create one:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npx create-video@latest my-project
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;my-project
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure Node.js is installed (v18+). Remotion also needs Chrome/Chromium on the server. If it’s not installed, Remotion will download its own — but you can install it explicitly if you prefer:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Ubuntu/Debian&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;chromium-browser
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-start-remotion-studio-on-the-remote-machine&quot;&gt;2. Start Remotion Studio on the Remote Machine&lt;/h2&gt;

&lt;p&gt;SSH into your remote machine and start Remotion Studio:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh user@your-remote-machine
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /path/to/your-remotion-project
npm run dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, Remotion Studio starts on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:3000&lt;/code&gt;. You’ll see output like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Remotion Studio
  http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At this point, the server is running, but you can’t open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost:3000&lt;/code&gt; on your local machine because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost&lt;/code&gt; refers to the remote machine itself.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-ssh-tunnel-bridge-the-gap&quot;&gt;3. SSH Tunnel: Bridge the Gap&lt;/h2&gt;

&lt;p&gt;The trick is &lt;strong&gt;SSH port forwarding&lt;/strong&gt; (also called SSH tunneling). On your &lt;strong&gt;local machine&lt;/strong&gt;, open a new terminal and run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; 3000:localhost:3000 user@your-remote-machine
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s what this does:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Part&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Meaning&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-L 3000:localhost:3000&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Forward local port 3000 to remote’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost:3000&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user@your-remote-machine&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Your SSH login&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Now, any traffic hitting your &lt;strong&gt;local&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:3000&lt;/code&gt; gets securely tunneled through SSH to the remote machine’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost:3000&lt;/code&gt; — where Remotion Studio is listening.&lt;/p&gt;

&lt;p&gt;Open your local browser and go to &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:3000&lt;/code&gt;&lt;/strong&gt;. You should see the Remotion Studio interface.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-vs-code-remote-ssh-even-easier&quot;&gt;4. VS Code Remote SSH (Even Easier)&lt;/h2&gt;

&lt;p&gt;If you use VS Code with the &lt;strong&gt;Remote - SSH&lt;/strong&gt; extension, port forwarding is automatic:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open your remote folder in VS Code (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+Shift+P&lt;/code&gt; → “Remote-SSH: Connect to Host…”)&lt;/li&gt;
  &lt;li&gt;Open the terminal in VS Code and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run dev&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;VS Code detects the port and shows a notification: &lt;em&gt;“Your application running on port 3000 is available.”&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Click “Open in Browser” or manually visit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:3000&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh -L&lt;/code&gt; needed — VS Code handles tunneling behind the scenes.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-rendering-without-preview&quot;&gt;5. Rendering Without Preview&lt;/h2&gt;

&lt;p&gt;If you just want to render a video file and download it:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# On the remote machine&lt;/span&gt;
npx remotion render src/index.ts output.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then copy it to your local machine:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# On your local machine&lt;/span&gt;
scp user@your-remote-machine:/path/to/remotion-project/output.mp4 &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt; for larger files:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rsync &lt;span class=&quot;nt&quot;&gt;-avz&lt;/span&gt; user@your-remote-machine:/path/to/remotion-project/output.mp4 &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;6-persist-the-tunnel-optional&quot;&gt;6. Persist the Tunnel (Optional)&lt;/h2&gt;

&lt;p&gt;If you want the tunnel to stay alive even when you close the terminal, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autossh&lt;/code&gt; or a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-o ServerAliveInterval&lt;/code&gt; flag:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; 3000:localhost:3000 &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ServerAliveInterval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;60 user@your-remote-machine
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or run the Remotion Studio in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen&lt;/code&gt; session so it survives disconnects:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tmux new &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; remotion
npm run dev
&lt;span class=&quot;c&quot;&gt;# Ctrl+B, D to detach&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Goal&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Command&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Start Remotion Studio on remote&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run dev&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Preview locally&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh -L 3000:localhost:3000 user@host&lt;/code&gt; then open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:3000&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Render video on remote&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npx remotion render src/index.ts out.mp4&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Download video&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scp user@host:path/to/out.mp4 .&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Persistent session&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux&lt;/code&gt; on remote&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;That’s it. No display server, no VNC, no X11 forwarding — just SSH and a browser.&lt;/p&gt;
</description>
        <pubDate>Fri, 12 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://www.darwinbiler.com/remotion-remote-machine/</link>
        <guid isPermaLink="true">https://www.darwinbiler.com/remotion-remote-machine/</guid>
        
        
      </item>
    
      <item>
        <title>AI Won&apos;t Replace Software Engineers. It Will Force Them to Think Like Project Managers.</title>
        <description>&lt;p&gt;For months now, the loudest narrative around AI and code has been
simple:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“AI is going to replace software engineers.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s the wrong frame.&lt;/p&gt;

&lt;p&gt;AI isn’t replacing software engineers.
It’s compressing execution — and forcing engineers to level up into
something closer to project managers.&lt;/p&gt;

&lt;p&gt;And that’s a fundamentally different shift.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-old-model-engineers-as-builders&quot;&gt;The Old Model: Engineers as Builders&lt;/h2&gt;

&lt;p&gt;Traditionally, software engineers were valued for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Translating requirements into code&lt;/li&gt;
  &lt;li&gt;Designing technical architecture&lt;/li&gt;
  &lt;li&gt;Debugging complex systems&lt;/li&gt;
  &lt;li&gt;Writing efficient, maintainable implementations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Project managers handled:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Clarifying goals&lt;/li&gt;
  &lt;li&gt;Aligning stakeholders&lt;/li&gt;
  &lt;li&gt;Breaking projects into structured tasks&lt;/li&gt;
  &lt;li&gt;Managing timelines and tradeoffs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There was a clear separation between &lt;em&gt;deciding what should be built&lt;/em&gt; and
&lt;em&gt;building it&lt;/em&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-ai-inflection-point&quot;&gt;The AI Inflection Point&lt;/h2&gt;

&lt;p&gt;Agentic coding tools change the balance.&lt;/p&gt;

&lt;p&gt;They can:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Scaffold entire applications&lt;/li&gt;
  &lt;li&gt;Write boilerplate instantly&lt;/li&gt;
  &lt;li&gt;Refactor large codebases&lt;/li&gt;
  &lt;li&gt;Generate tests and documentation&lt;/li&gt;
  &lt;li&gt;Debug with surprising competence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, they compress the mechanical act of coding.&lt;/p&gt;

&lt;p&gt;If implementation becomes faster and cheaper, the bottleneck shifts.&lt;/p&gt;

&lt;p&gt;And the new bottleneck is thinking.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-new-bottleneck-specification&quot;&gt;The New Bottleneck: Specification&lt;/h2&gt;

&lt;p&gt;With AI, output quality depends almost entirely on:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Clarity of instructions&lt;/li&gt;
  &lt;li&gt;Constraint definition&lt;/li&gt;
  &lt;li&gt;System boundaries&lt;/li&gt;
  &lt;li&gt;Edge case anticipation&lt;/li&gt;
  &lt;li&gt;Iterative refinement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s not “just coding.”&lt;/p&gt;

&lt;p&gt;That’s:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Requirement engineering&lt;/li&gt;
  &lt;li&gt;Scope design&lt;/li&gt;
  &lt;li&gt;Risk anticipation&lt;/li&gt;
  &lt;li&gt;Quality evaluation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are project management skills.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;engineers-are-becoming-execution-orchestrators&quot;&gt;Engineers Are Becoming Execution Orchestrators&lt;/h2&gt;

&lt;p&gt;In the AI-augmented workflow, engineers increasingly:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Frame problems precisely&lt;/li&gt;
  &lt;li&gt;Define constraints clearly&lt;/li&gt;
  &lt;li&gt;Evaluate outputs critically&lt;/li&gt;
  &lt;li&gt;Iterate with strategic intent&lt;/li&gt;
  &lt;li&gt;Balance trade-offs deliberately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of typing every line, they:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Architect solution space&lt;/li&gt;
  &lt;li&gt;Design feedback loops&lt;/li&gt;
  &lt;li&gt;Orchestrate AI agents&lt;/li&gt;
  &lt;li&gt;Integrate generated systems into coherent products&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They move up a layer of abstraction.&lt;/p&gt;

&lt;p&gt;Not away from engineering.
Deeper into it.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;this-isnt-downgrading-engineering-its-upgrading-it&quot;&gt;This Isn’t Downgrading Engineering. It’s Upgrading It.&lt;/h2&gt;

&lt;p&gt;Low-level implementation becomes cheaper.
High-level thinking becomes more valuable.&lt;/p&gt;

&lt;p&gt;The engineer of the AI era isn’t someone who:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Knows the most syntax&lt;/li&gt;
  &lt;li&gt;Memorizes APIs&lt;/li&gt;
  &lt;li&gt;Manually writes boilerplate fastest&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s someone who can:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Translate ambiguous goals into structured systems&lt;/li&gt;
  &lt;li&gt;Design reliable architectures&lt;/li&gt;
  &lt;li&gt;Anticipate failure modes&lt;/li&gt;
  &lt;li&gt;Define clean interfaces&lt;/li&gt;
  &lt;li&gt;Evaluate trade-offs under uncertainty&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Engineers aren’t being replaced.
They’re being forced to think like project managers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But with technical depth.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-real-risk&quot;&gt;The Real Risk&lt;/h2&gt;

&lt;p&gt;The engineers most at risk aren’t those who can’t code.&lt;/p&gt;

&lt;p&gt;They’re those who:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wait to be told exactly what to build&lt;/li&gt;
  &lt;li&gt;Execute blindly without questioning scope&lt;/li&gt;
  &lt;li&gt;Avoid ownership of system-level decisions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI reduces the premium on pure execution.
It increases the premium on ownership.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;final-thought&quot;&gt;Final Thought&lt;/h2&gt;

&lt;p&gt;The future engineer looks less like a ticket-closer
and more like a systems strategist.&lt;/p&gt;

&lt;p&gt;Less like a typist
and more like a designer of outcomes.&lt;/p&gt;

&lt;p&gt;AI won’t replace software engineers.&lt;/p&gt;

&lt;p&gt;It will force them to think bigger.&lt;/p&gt;

&lt;p&gt;And the ones who embrace that shift will become exponentially more
valuable.&lt;/p&gt;
</description>
        <pubDate>Tue, 03 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://www.darwinbiler.com/ai-wont-replace-software-engineers/</link>
        <guid isPermaLink="true">https://www.darwinbiler.com/ai-wont-replace-software-engineers/</guid>
        
        <category>AI</category>
        
        <category>Engineering</category>
        
        <category>Project Management</category>
        
        <category>Agentic Systems</category>
        
        
        <category>AI</category>
        
        <category>Software Engineering</category>
        
      </item>
    
      <item>
        <title>Two Lenses: Why Products Decay (And What Young Engineers Don&apos;t See Yet)</title>
        <description>&lt;h1 id=&quot;two-lenses-why-products-decay-and-what-young-engineers-dont-see-yet&quot;&gt;Two Lenses: Why Products Decay (And What Young Engineers Don’t See Yet)&lt;/h1&gt;

&lt;p&gt;When you’re early in your tech career, products feel simple.&lt;/p&gt;

&lt;p&gt;Good engineering → good product.&lt;br /&gt;
Clean code → long-term success.&lt;br /&gt;
Thoughtful architecture → scalable future.&lt;/p&gt;

&lt;p&gt;It feels rational.&lt;/p&gt;

&lt;p&gt;But 10–15 years into the industry, you start seeing something
unsettling:&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The same product is being viewed through two completely different
lenses.&lt;/p&gt;

&lt;p&gt;And the tension between those lenses is what often leads to what people
now call &lt;em&gt;“enshitification.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This post is about understanding that dynamic early — before cynicism
sets in.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;lens-1-the-engineering-lens&quot;&gt;Lens #1: The Engineering Lens&lt;/h2&gt;

&lt;p&gt;Engineers see products as systems.&lt;/p&gt;

&lt;p&gt;You naturally care about:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Architecture&lt;/li&gt;
  &lt;li&gt;Maintainability&lt;/li&gt;
  &lt;li&gt;Clean abstractions&lt;/li&gt;
  &lt;li&gt;Long-term scalability&lt;/li&gt;
  &lt;li&gt;Minimizing technical debt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you see a shortcut, your brain automatically projects forward:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“This will hurt us later.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your mental model is compounding stability.&lt;/p&gt;

&lt;p&gt;Good structure today = easier evolution tomorrow.&lt;/p&gt;

&lt;p&gt;From this lens, degrading quality feels irrational and self-destructive.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;lens-2-the-business-lens&quot;&gt;Lens #2: The Business Lens&lt;/h2&gt;

&lt;p&gt;Founders, PMs, and investors see something different.&lt;/p&gt;

&lt;p&gt;They see:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Runway (months until money runs out)&lt;/li&gt;
  &lt;li&gt;Revenue growth&lt;/li&gt;
  &lt;li&gt;Customer acquisition cost&lt;/li&gt;
  &lt;li&gt;Competitive pressure&lt;/li&gt;
  &lt;li&gt;Investor expectations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Their mental model isn’t compounding structure.&lt;/p&gt;

&lt;p&gt;It’s survival under uncertainty.&lt;/p&gt;

&lt;p&gt;From this lens:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A quick solution that generates revenue beats a perfect system that
doesn’t.&lt;/li&gt;
  &lt;li&gt;Speed beats elegance before validation.&lt;/li&gt;
  &lt;li&gt;Monetizable problems matter more than meaningful-but-unpaid ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the company dies, your clean architecture dies with it.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;where-the-tension-begins&quot;&gt;Where the Tension Begins&lt;/h2&gt;

&lt;p&gt;Early stage companies usually optimize for users.&lt;/p&gt;

&lt;p&gt;They polish. They care. They iterate. They earn trust.&lt;/p&gt;

&lt;p&gt;But once growth stabilizes, something shifts.&lt;/p&gt;

&lt;p&gt;The optimization function changes.&lt;/p&gt;

&lt;p&gt;It becomes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Increase margins&lt;/li&gt;
  &lt;li&gt;Reduce costs&lt;/li&gt;
  &lt;li&gt;Extract more value per user&lt;/li&gt;
  &lt;li&gt;Satisfy investors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where quality sometimes declines.&lt;/p&gt;

&lt;p&gt;Not because people suddenly became evil.&lt;/p&gt;

&lt;p&gt;But because incentives moved.&lt;/p&gt;

&lt;p&gt;This slow drift from “serve users” to “extract value” is what creates
product decay.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;understanding-enshitification&quot;&gt;Understanding “Enshitification”&lt;/h2&gt;

&lt;p&gt;The term was popularized by Cory Doctorow to describe a common
lifecycle:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A platform is great for users.&lt;/li&gt;
  &lt;li&gt;Then it becomes optimized for business customers.&lt;/li&gt;
  &lt;li&gt;Then it becomes optimized for shareholders.&lt;/li&gt;
  &lt;li&gt;Then user experience degrades.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This isn’t always intentional sabotage.&lt;/p&gt;

&lt;p&gt;It’s often the natural result of late-stage growth pressure.&lt;/p&gt;

&lt;p&gt;And if you stay long enough in tech, you’ll see this cycle repeat.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-this-confuses-young-engineers&quot;&gt;Why This Confuses Young Engineers&lt;/h2&gt;

&lt;p&gt;When you’re early in your career, you assume:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Everyone is trying to build the best possible product.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But in reality, different stakeholders are optimizing for different
outcomes.&lt;/p&gt;

&lt;p&gt;Engineers optimize for system integrity.&lt;br /&gt;
Business optimizes for capital efficiency.&lt;/p&gt;

&lt;p&gt;Neither perspective is irrational.&lt;/p&gt;

&lt;p&gt;But they are incompatible at the extremes.&lt;/p&gt;

&lt;p&gt;If engineering dominates without validation → the company may die
beautifully.&lt;/p&gt;

&lt;p&gt;If business dominates without restraint → the product may survive
financially but decay experientially.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-hard-realization&quot;&gt;The Hard Realization&lt;/h2&gt;

&lt;p&gt;Some founders plan for exit.&lt;/p&gt;

&lt;p&gt;Some investors expect 10x returns.&lt;/p&gt;

&lt;p&gt;Some decisions are made knowing long-term technical debt will become
someone else’s problem.&lt;/p&gt;

&lt;p&gt;That can feel cynical.&lt;/p&gt;

&lt;p&gt;But it’s usually structural, not personal.&lt;/p&gt;

&lt;p&gt;Understanding incentives makes you less angry and more strategic.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-real-skill-to-develop-early&quot;&gt;The Real Skill to Develop Early&lt;/h2&gt;

&lt;p&gt;Instead of choosing a side, learn both lenses.&lt;/p&gt;

&lt;p&gt;As a young engineer:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Master technical craft.&lt;/li&gt;
  &lt;li&gt;Learn how revenue actually works.&lt;/li&gt;
  &lt;li&gt;Observe how incentives shift as companies grow.&lt;/li&gt;
  &lt;li&gt;Notice when survival decisions become extraction decisions.&lt;/li&gt;
  &lt;li&gt;Decide what environments align with your values.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Not every company is built for longevity.&lt;/p&gt;

&lt;p&gt;Not every product is meant to age well.&lt;/p&gt;

&lt;p&gt;Some are experiments. Some are vehicles for exit. Some become enduring
systems.&lt;/p&gt;

&lt;p&gt;Your clarity about this will shape your career more than your choice of
framework.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;final-thought&quot;&gt;Final Thought&lt;/h2&gt;

&lt;p&gt;Technology is not the product.&lt;/p&gt;

&lt;p&gt;It is leverage.&lt;/p&gt;

&lt;p&gt;Engineering asks: &amp;gt; “Is this built well?”&lt;/p&gt;

&lt;p&gt;Business asks: &amp;gt; “Does this generate return?”&lt;/p&gt;

&lt;p&gt;When you understand both lenses, you stop being surprised by product
decay.&lt;/p&gt;

&lt;p&gt;You start predicting it.&lt;/p&gt;

&lt;p&gt;And that awareness changes how you build, where you work, and what you
tolerate.&lt;/p&gt;
</description>
        <pubDate>Tue, 24 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://www.darwinbiler.com/two-lenses-of-product-decay/</link>
        <guid isPermaLink="true">https://www.darwinbiler.com/two-lenses-of-product-decay/</guid>
        
        
      </item>
    
      <item>
        <title>The Clawdbot Debacle Is a Distraction: Agentic AI Ran a Ponzi on Humans</title>
        <description>&lt;h2 id=&quot;a-quick-backstory-for-those-who-missed-the-drama&quot;&gt;A Quick Backstory (For Those Who Missed the Drama)&lt;/h2&gt;

&lt;p&gt;In late January, an open-source AI project called &lt;strong&gt;Clawdbot&lt;/strong&gt; went explosively viral.&lt;/p&gt;

&lt;p&gt;Clawdbot was marketed as a &lt;em&gt;personal AI agent&lt;/em&gt; — something that could run on your own hardware and connect to messaging apps like WhatsApp, Telegram, Discord, Slack, and iMessage. Instead of being “just a chatbot,” it could execute commands, manage email, and act on your behalf.&lt;/p&gt;

&lt;p&gt;Within days, the project accumulated &lt;strong&gt;tens of thousands of GitHub stars&lt;/strong&gt;. Tech Twitter buzzed. Influential developers posted about buying Mac Minis just to run it.&lt;/p&gt;

&lt;p&gt;Then everything unraveled.&lt;/p&gt;

&lt;p&gt;After receiving trademark concerns from Anthropic (the company behind Claude), the creator renamed the project to &lt;strong&gt;Moltbot&lt;/strong&gt;. During the rename process, the old &lt;strong&gt;Clawdbot&lt;/strong&gt; handles on GitHub and X (Twitter) were released and immediately claimed by third parties.&lt;/p&gt;

&lt;p&gt;Those accounts were then used to promote a fake crypto token called &lt;strong&gt;$CLAWD&lt;/strong&gt;, launched on the Solana blockchain.&lt;/p&gt;

&lt;p&gt;The token briefly surged to a &lt;strong&gt;multi‑million‑dollar market cap&lt;/strong&gt;, before collapsing once the original developer publicly disavowed any involvement. Late buyers were wiped out. Early actors exited.&lt;/p&gt;

&lt;p&gt;The internet’s conclusion was swift and simple:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“Clawdbot failed.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That conclusion is wrong.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-wrong-story-is-going-viral&quot;&gt;The Wrong Story Is Going Viral&lt;/h2&gt;

&lt;p&gt;The dominant narrative frames this as a cautionary tale about:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;careless renaming&lt;/li&gt;
  &lt;li&gt;trademark pressure&lt;/li&gt;
  &lt;li&gt;crypto scammers&lt;/li&gt;
  &lt;li&gt;and reckless users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a comforting story because it isolates the problem.&lt;/p&gt;

&lt;p&gt;Delete Clawdbot.&lt;br /&gt;
Avoid Solana memes.&lt;br /&gt;
Be more careful next time.&lt;/p&gt;

&lt;p&gt;Problem solved.&lt;/p&gt;

&lt;p&gt;Except it isn’t.&lt;/p&gt;

&lt;p&gt;What actually happened is far more uncomfortable:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Agentic AI systems executed a Ponzi‑style extraction against humans, and Solana made it frictionless.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clawdbot wasn’t the cause.
It was the &lt;em&gt;vehicle&lt;/em&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;this-wasnt-a-hack--it-was-an-emergent-behavior&quot;&gt;This Wasn’t a “Hack” — It Was an Emergent Behavior&lt;/h2&gt;

&lt;p&gt;No credentials were cracked.
No zero‑day exploit was required.&lt;/p&gt;

&lt;p&gt;Instead:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;High‑value identities were released&lt;/li&gt;
  &lt;li&gt;Automated systems detected the opportunity&lt;/li&gt;
  &lt;li&gt;Fake legitimacy was established instantly&lt;/li&gt;
  &lt;li&gt;A token was created&lt;/li&gt;
  &lt;li&gt;Humans provided liquidity&lt;/li&gt;
  &lt;li&gt;Early actors exited&lt;/li&gt;
  &lt;li&gt;Late humans absorbed the loss&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This sequence didn’t require intelligence.
It required &lt;strong&gt;automation, speed, and incentives&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s not hacking.
That’s a &lt;strong&gt;Ponzi dynamic&lt;/strong&gt; — executed at machine speed.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-clawdbot-failed-is-a-convenient-lie&quot;&gt;Why “Clawdbot Failed” Is a Convenient Lie&lt;/h2&gt;

&lt;p&gt;Blaming Clawdbot implies:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the tool was flawed&lt;/li&gt;
  &lt;li&gt;the developer was careless&lt;/li&gt;
  &lt;li&gt;uninstalling is a solution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But remove Clawdbot from the equation and nothing changes.&lt;/p&gt;

&lt;p&gt;Another agent.
Another repo.
Another viral moment.&lt;/p&gt;

&lt;p&gt;The narrative focuses on &lt;em&gt;which app&lt;/em&gt;, instead of &lt;em&gt;what behavior emerged&lt;/em&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;agentic-ai-is-the-new-counterparty&quot;&gt;Agentic AI Is the New Counterparty&lt;/h2&gt;

&lt;p&gt;This wasn’t simply “crypto scammers versus users.”&lt;/p&gt;

&lt;p&gt;It was:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;automated agents&lt;/li&gt;
  &lt;li&gt;coordinating across platforms&lt;/li&gt;
  &lt;li&gt;exploiting human reaction time&lt;/li&gt;
  &lt;li&gt;monetizing attention&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Humans weren’t deceived so much as &lt;strong&gt;outpaced&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They became liquidity providers in a system that rewards speed over understanding.&lt;/p&gt;

&lt;p&gt;That’s Ponzi logic — without the paperwork.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-solana-matters-and-why-this-will-repeat&quot;&gt;Why Solana Matters (and Why This Will Repeat)&lt;/h2&gt;

&lt;p&gt;Solana didn’t invent the behavior.&lt;/p&gt;

&lt;p&gt;It &lt;strong&gt;enabled it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Solana offers:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;near‑zero transaction costs&lt;/li&gt;
  &lt;li&gt;instant finality&lt;/li&gt;
  &lt;li&gt;permissionless token creation&lt;/li&gt;
  &lt;li&gt;public price charts that manufacture legitimacy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This converts hype into money in minutes.&lt;/p&gt;

&lt;p&gt;Without platforms like Solana:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;impersonation would still happen&lt;/li&gt;
  &lt;li&gt;hype would still spread&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But &lt;strong&gt;extraction would be slower&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Slowness is safety.
Friction is ethics.&lt;/p&gt;

&lt;p&gt;Solana removed both.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-real-vulnerability-isnt-the-platform&quot;&gt;The Real Vulnerability Isn’t the Platform&lt;/h2&gt;

&lt;p&gt;It’s urgency.&lt;/p&gt;

&lt;p&gt;Every cycle looks the same:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;crypto&lt;/li&gt;
  &lt;li&gt;NFTs&lt;/li&gt;
  &lt;li&gt;yield farming&lt;/li&gt;
  &lt;li&gt;AI agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Something goes viral.
Humans rush to be early.
Automation front‑runs them.
Losses concentrate at the edges.&lt;/p&gt;

&lt;p&gt;This isn’t a user education problem.
It’s a &lt;strong&gt;structural incentive problem&lt;/strong&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;just-uninstall-it-is-not-a-resolution&quot;&gt;“Just Uninstall It” Is Not a Resolution&lt;/h2&gt;

&lt;p&gt;Uninstalling Clawdbot fixes nothing.&lt;/p&gt;

&lt;p&gt;The real questions are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Why can agentic systems monetize identity gaps instantly?&lt;/li&gt;
  &lt;li&gt;Why do platforms release high‑value handles with no grace period?&lt;/li&gt;
  &lt;li&gt;Why does speed consistently beat verification?&lt;/li&gt;
  &lt;li&gt;Why is hype allowed to convert directly into financial instruments?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until those questions are addressed:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;another tool, another name, another chain&lt;br /&gt;
will recreate the same outcome&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-uncomfortable-conclusion&quot;&gt;The Uncomfortable Conclusion&lt;/h2&gt;

&lt;p&gt;The Clawdbot debacle wasn’t an accident.&lt;/p&gt;

&lt;p&gt;It was a &lt;strong&gt;preview&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Agentic AI didn’t malfunction.
It followed incentives perfectly.&lt;/p&gt;

&lt;p&gt;Humans didn’t fail because they were stupid.
They failed because they were slower.&lt;/p&gt;

&lt;p&gt;And platforms didn’t intervene because:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;money moving fast is still considered innovation&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s the real issue.&lt;/p&gt;

&lt;p&gt;Everything else is just a story we tell ourselves so we can move on.&lt;/p&gt;
</description>
        <pubDate>Thu, 29 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://www.darwinbiler.com/clawdbot-agentic-ai-ponzi/</link>
        <guid isPermaLink="true">https://www.darwinbiler.com/clawdbot-agentic-ai-ponzi/</guid>
        
        
        <category>ai</category>
        
        <category>crypto</category>
        
        <category>security</category>
        
        <category>opinion</category>
        
      </item>
    
      <item>
        <title>The Hidden Dangers of Vibe Coding at Scale</title>
        <description>&lt;h1 id=&quot;the-hidden-dangers-of-vibe-coding-at-scale&quot;&gt;The Hidden Dangers of Vibe Coding at Scale&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;When AI helps you move fast—until it quietly breaks what already works.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-people-mean-by-vibe-coding&quot;&gt;What People Mean by “Vibe Coding”&lt;/h2&gt;

&lt;p&gt;“Vibe coding” is the practice of building software by giving high‑level, intent‑based prompts to an LLM and letting it generate or rewrite large portions of the codebase.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;“Add Stripe payments.”&lt;/li&gt;
  &lt;li&gt;“Refactor this to support subscriptions.”&lt;/li&gt;
  &lt;li&gt;“I want a new payment system integrated.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At small scale, this feels magical. You move fast, features appear instantly, and the app seems to work. The problem begins when your product grows.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-scaling-problem-nobody-talks-about&quot;&gt;The Scaling Problem Nobody Talks About&lt;/h2&gt;

&lt;p&gt;As your app matures, it accumulates &lt;strong&gt;invisible complexity&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Multiple payment gateways (Stripe, PayPal, local wallets)&lt;/li&gt;
  &lt;li&gt;Legacy users with grandfathered rules&lt;/li&gt;
  &lt;li&gt;One‑off promos (e.g., Black Friday signups)&lt;/li&gt;
  &lt;li&gt;Regulatory or accounting edge cases&lt;/li&gt;
  &lt;li&gt;“Temporary” hacks that became permanent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Humans forget these details too—but humans usually don’t rewrite the entire file when asked for a new feature.&lt;/p&gt;

&lt;p&gt;LLMs often do.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;how-highlevel-prompts-break-existing-logic&quot;&gt;How High‑Level Prompts Break Existing Logic&lt;/h2&gt;

&lt;p&gt;Consider this real‑world scenario:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You already support &lt;strong&gt;2–3 payment gateways&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Black Friday users:
    &lt;ul&gt;
      &lt;li&gt;Locked‑in pricing&lt;/li&gt;
      &lt;li&gt;Different renewal rules&lt;/li&gt;
      &lt;li&gt;Special cancellation behavior&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you prompt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“I want a new payment system integrated.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From the model’s perspective:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The prompt is &lt;strong&gt;present‑focused&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;The most recent instruction has the &lt;strong&gt;highest priority&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Anything not clearly represented in the visible context is treated as expendable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Old conditional logic is simplified away&lt;/li&gt;
  &lt;li&gt;Edge cases are overwritten by a “cleaner” abstraction&lt;/li&gt;
  &lt;li&gt;Rare user segments silently lose guarantees you promised them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing crashes.
No tests fail.&lt;/p&gt;

&lt;p&gt;But production behavior changes.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;context-windows-are-a-hard-technical-limit&quot;&gt;Context Windows Are a Hard Technical Limit&lt;/h2&gt;

&lt;p&gt;This isn’t just “AI being careless.” It’s architectural.&lt;/p&gt;

&lt;p&gt;LLMs have a &lt;strong&gt;finite context window&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As your codebase grows:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Not all files fit into context&lt;/li&gt;
  &lt;li&gt;Not all historical decisions are visible&lt;/li&gt;
  &lt;li&gt;Comments explaining &lt;em&gt;why&lt;/em&gt; something exists are often omitted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the model rewrites code:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;It optimizes for &lt;strong&gt;internal coherence&lt;/strong&gt;, not historical correctness&lt;/li&gt;
  &lt;li&gt;It prefers consistency over exceptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the model’s point of view, deleting them is &lt;em&gt;improving&lt;/em&gt; the code.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-this-is-especially-dangerous-in-payments&quot;&gt;Why This Is Especially Dangerous in Payments&lt;/h2&gt;

&lt;p&gt;Payments are a perfect storm:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Money + trust&lt;/li&gt;
  &lt;li&gt;Legal and accounting implications&lt;/li&gt;
  &lt;li&gt;Users notice changes immediately&lt;/li&gt;
  &lt;li&gt;Rollbacks are messy or impossible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Breaking a UI feature is annoying.
Breaking payment logic is existential.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-illusion-of-it-still-works&quot;&gt;The Illusion of “It Still Works”&lt;/h2&gt;

&lt;p&gt;One of the most dangerous aspects of vibe coding is that &lt;strong&gt;nothing appears broken&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The app builds.
The checkout flows.
The demo works.&lt;/p&gt;

&lt;p&gt;But correctness isn’t binary.&lt;/p&gt;

&lt;p&gt;The app works—&lt;em&gt;just not the way it used to.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;how-to-use-llms-without-shooting-yourself&quot;&gt;How to Use LLMs Without Shooting Yourself&lt;/h2&gt;

&lt;p&gt;Vibe coding isn’t evil—but it needs guardrails.&lt;/p&gt;

&lt;h3 id=&quot;1-narrow-the-rewrite-surface&quot;&gt;1. Narrow the Rewrite Surface&lt;/h3&gt;

&lt;p&gt;Avoid prompts that imply global change.&lt;/p&gt;

&lt;p&gt;Bad:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;“Refactor the payment system.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Better:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;“Add a new gateway without modifying existing pricing logic or legacy user rules.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;2-encode-edge-cases-as-tests-not-comments&quot;&gt;2. Encode Edge Cases as Tests, Not Comments&lt;/h3&gt;

&lt;p&gt;LLMs respect failing tests more than comments.&lt;/p&gt;

&lt;p&gt;If Black Friday users matter, lock their behavior in tests.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;3-document-business-invariants-explicitly&quot;&gt;3. Document Business Invariants Explicitly&lt;/h3&gt;

&lt;p&gt;Create documents like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PAYMENTS_INVARIANTS.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feed them into relevant prompts.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;4-treat-ai-as-a-junior-engineer-not-an-architect&quot;&gt;4. Treat AI as a Junior Engineer, Not an Architect&lt;/h3&gt;

&lt;p&gt;A junior dev can implement scoped changes.
They should not redefine system boundaries.&lt;/p&gt;

&lt;p&gt;Your LLM is no different.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;closing-thought&quot;&gt;Closing Thought&lt;/h2&gt;

&lt;p&gt;Your production system is not just code.&lt;/p&gt;

&lt;p&gt;It is:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;A history of decisions&lt;/li&gt;
  &lt;li&gt;A record of promises&lt;/li&gt;
  &lt;li&gt;A map of exceptions that exist for a reason&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you let high‑level prompts rewrite that history unchecked, you’re not vibe coding.&lt;/p&gt;

&lt;p&gt;You’re vibe gambling.&lt;/p&gt;
</description>
        <pubDate>Wed, 28 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://www.darwinbiler.com/the-hidden-dangers-of-vibe-coding/</link>
        <guid isPermaLink="true">https://www.darwinbiler.com/the-hidden-dangers-of-vibe-coding/</guid>
        
        
        <category>software</category>
        
        <category>ai</category>
        
        <category>engineering</category>
        
      </item>
    
      <item>
        <title>How Do You Make AI Understand Business Rules Across Products — And Still Dive Into the Code?</title>
        <description>&lt;h2 id=&quot;the-question-that-actually-started-this&quot;&gt;The Question That Actually Started This&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;“How can I make the AI understand our business rules across &lt;em&gt;all&lt;/em&gt; products —&lt;br /&gt;
while still being able to dive down to exact code-level details when needed?”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not &lt;em&gt;one&lt;/em&gt; product.&lt;br /&gt;
Not &lt;em&gt;one&lt;/em&gt; repo.&lt;br /&gt;
Not &lt;em&gt;one&lt;/em&gt; stack.&lt;/p&gt;

&lt;p&gt;Multiple long-lived products.&lt;br /&gt;
Multiple repositories per product.&lt;br /&gt;
Different frameworks. Different versions.&lt;br /&gt;
Shared business logic with subtle differences.&lt;/p&gt;

&lt;p&gt;If you’ve ever been responsible for more than one real system, this question probably feels familiar.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-this-is-harder-than-it-sounds&quot;&gt;Why This Is Harder Than It Sounds&lt;/h2&gt;

&lt;p&gt;At a business level, things are usually clear:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“Resellers with 50% commission can’t offer Package A”&lt;/li&gt;
  &lt;li&gt;“This only applies in Country B”&lt;/li&gt;
  &lt;li&gt;“Product A and B follow the same rule — mostly”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At a technical level, reality looks like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Product A: React + Backend 1&lt;/li&gt;
  &lt;li&gt;Product B: Vue + Backend 2&lt;/li&gt;
  &lt;li&gt;Pricing logic spread across:
    &lt;ul&gt;
      &lt;li&gt;frontend conditionals&lt;/li&gt;
      &lt;li&gt;backend validation&lt;/li&gt;
      &lt;li&gt;configs&lt;/li&gt;
      &lt;li&gt;migrations&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Business rules described… &lt;em&gt;somewhere&lt;/em&gt; in Markdown&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hard part isn’t the rule.&lt;br /&gt;
The hard part is &lt;strong&gt;bridging intent → implementation&lt;/strong&gt; across systems.&lt;/p&gt;

&lt;p&gt;That’s what I wanted the AI to help with.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-first-attempt-just-load-the-context&quot;&gt;The First Attempt: “Just Load the Context”&lt;/h2&gt;

&lt;p&gt;Like many teams, we leaned into Markdown:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Business rules written in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.md&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Glossaries explaining internal terms&lt;/li&gt;
  &lt;li&gt;Copilot tools (Amazon Q, later Open WebUI) pointed at them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And at first… it worked.&lt;/p&gt;

&lt;p&gt;Until it didn’t.&lt;/p&gt;

&lt;p&gt;As products grew, so did the Markdown:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Per-product summaries&lt;/li&gt;
  &lt;li&gt;Shared rules duplicated&lt;/li&gt;
  &lt;li&gt;Exceptions layered on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eventually every question started failing the same way:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;“Too much context loaded”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;when-bigger-models-still-hit-the-wall&quot;&gt;When Bigger Models Still Hit the Wall&lt;/h2&gt;

&lt;p&gt;At this point, the natural response was:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Okay, let’s try the biggest LLM we can.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We tried &lt;strong&gt;Claude Sonnet 4.5&lt;/strong&gt; — massive context window, best-in-class reasoning.&lt;/p&gt;

&lt;p&gt;And it helped… briefly.&lt;/p&gt;

&lt;p&gt;Then the same pattern emerged:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Load more Markdown → worse answers&lt;/li&gt;
  &lt;li&gt;Load &lt;em&gt;all&lt;/em&gt; knowledge → hallucinations&lt;/li&gt;
  &lt;li&gt;Remove some docs → missing rules&lt;/li&gt;
  &lt;li&gt;Trust erodes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the moment many teams quietly arrive at the same thought:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“Maybe we need to fine-tune.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-fine-tuning-temptation-and-why-its-a-trap&quot;&gt;The Fine-Tuning Temptation (and Why It’s a Trap)&lt;/h2&gt;

&lt;p&gt;Fine-tuning sounds like the ultimate solution:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;“Teach the model our rules”&lt;/li&gt;
  &lt;li&gt;“Bake in company knowledge”&lt;/li&gt;
  &lt;li&gt;“No more context juggling”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But that idea rests on a false assumption:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;That the problem is memory.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It isn’t.&lt;/p&gt;

&lt;p&gt;Fine-tuning:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Changes &lt;em&gt;behavior&lt;/em&gt;, not structure&lt;/li&gt;
  &lt;li&gt;Compresses knowledge, destroying traceability&lt;/li&gt;
  &lt;li&gt;Makes rules harder to audit&lt;/li&gt;
  &lt;li&gt;Requires retraining as rules change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t want the model to &lt;em&gt;remember&lt;/em&gt; your business logic.&lt;/p&gt;

&lt;p&gt;You want it to &lt;strong&gt;consult it correctly&lt;/strong&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-realization-humans-dont-load-everything-either&quot;&gt;The Realization: Humans Don’t Load Everything Either&lt;/h2&gt;

&lt;p&gt;The turning point was embarrassingly simple:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Senior engineers don’t load the entire system before fixing something.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Clarify intent&lt;/li&gt;
  &lt;li&gt;Consult business rules&lt;/li&gt;
  &lt;li&gt;Identify scope&lt;/li&gt;
  &lt;li&gt;Navigate code &lt;em&gt;selectively&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We were forcing LLMs to skip steps 1–3 and jump straight to step 4 — with all knowledge shoved into a single prompt.&lt;/p&gt;

&lt;p&gt;That’s not intelligence.
That’s overload.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;markdown-was-never-the-problem&quot;&gt;Markdown Was Never the Problem&lt;/h2&gt;

&lt;p&gt;This part surprised me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Markdown was actually the best part of the system.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During meetings:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Someone adds a constraint&lt;/li&gt;
  &lt;li&gt;A paragraph gets appended&lt;/li&gt;
  &lt;li&gt;The rule is updated immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No schemas.
No pipelines.
No re-indexing.&lt;/p&gt;

&lt;p&gt;The problem wasn’t Markdown.&lt;/p&gt;

&lt;p&gt;The problem was treating Markdown as &lt;strong&gt;always-loaded memory&lt;/strong&gt;, instead of &lt;strong&gt;consulted intent&lt;/strong&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-architectural-shift-from-memory-to-consultation&quot;&gt;The Architectural Shift: From Memory to Consultation&lt;/h2&gt;

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

&lt;blockquote&gt;
  &lt;p&gt;“How do I get the AI to read everything?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The better question became:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;“How does the AI ask the &lt;em&gt;right questions&lt;/em&gt;?”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s where &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; fits — not as an AI feature, but as an architectural boundary.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-mcp-enabled-that-rag-couldnt&quot;&gt;What MCP Enabled That RAG Couldn’t&lt;/h2&gt;

&lt;p&gt;With MCP, the AI no longer gets documents dumped into its prompt.&lt;/p&gt;

&lt;p&gt;Instead, it gets tools like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“Search relevant business rules”&lt;/li&gt;
  &lt;li&gt;“Explain this internal term”&lt;/li&gt;
  &lt;li&gt;“What domains might this rule affect?”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AI:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Starts with intent&lt;/li&gt;
  &lt;li&gt;Pulls &lt;em&gt;only&lt;/em&gt; relevant excerpts&lt;/li&gt;
  &lt;li&gt;Decides what code to inspect next&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exactly how an experienced engineer works.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-this-scales-across-products&quot;&gt;Why This Scales Across Products&lt;/h2&gt;

&lt;p&gt;Now:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;One business rule lives in one place&lt;/li&gt;
  &lt;li&gt;Product differences are contextual, not duplicated&lt;/li&gt;
  &lt;li&gt;Markdown stays human-first&lt;/li&gt;
  &lt;li&gt;Indexes are optional accelerators&lt;/li&gt;
  &lt;li&gt;Context windows stay small and meaningful&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same MCP server can be used by:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Amazon Q Developer (inside VS Code)&lt;/li&gt;
  &lt;li&gt;Open WebUI&lt;/li&gt;
  &lt;li&gt;Future agentic tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One knowledge system.
Multiple products.
Multiple entry points.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-outcome&quot;&gt;The Outcome&lt;/h2&gt;

&lt;p&gt;What started as a simple question:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“How can I make AI understand business rules across products &lt;em&gt;and&lt;/em&gt; dive into code?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ended with a realization:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;LLMs don’t fail because they lack knowledge.&lt;br /&gt;
They fail because we architect them like databases.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once we stopped forcing memory&lt;br /&gt;
and started enabling consultation,&lt;/p&gt;

&lt;p&gt;the tools finally behaved like senior engineers instead of overconfident interns.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;if-this-feels-familiar&quot;&gt;If This Feels Familiar&lt;/h2&gt;

&lt;p&gt;If you’ve:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Hit “too much context loaded”&lt;/li&gt;
  &lt;li&gt;Tried the biggest available model&lt;/li&gt;
  &lt;li&gt;Doubted RAG&lt;/li&gt;
  &lt;li&gt;Considered fine-tuning out of frustration&lt;/li&gt;
  &lt;li&gt;Worked on more than one real product&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This problem isn’t unique to you.&lt;/p&gt;

&lt;p&gt;And the solution isn’t a bigger model.&lt;/p&gt;

&lt;p&gt;It’s better boundaries.&lt;/p&gt;
</description>
        <pubDate>Wed, 14 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://www.darwinbiler.com/agentic-coding-across-multiple-products/</link>
        <guid isPermaLink="true">https://www.darwinbiler.com/agentic-coding-across-multiple-products/</guid>
        
        <category>LLM</category>
        
        <category>MCP</category>
        
        <category>Amazon Q</category>
        
        <category>Claude</category>
        
        <category>RAG</category>
        
        <category>Knowledge Systems</category>
        
        
        <category>AI</category>
        
        <category>Engineering</category>
        
        <category>Architecture</category>
        
      </item>
    
      <item>
        <title>Scalable Full-Stack Development Environment</title>
        <description>&lt;h1 id=&quot;scalable-full-stack-development-environment&quot;&gt;Scalable Full-Stack Development Environment&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;A thin-client, container-first approach to building a resilient, portable development workflow.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a full-stack developer, I’ve repeatedly run into problems that don’t show up in tutorials but absolutely show up in real life: OS updates breaking setups, machines crashing mid-work, environments drifting away from production, and the constant fear that a reformat means rebuilding everything from scratch.&lt;/p&gt;

&lt;p&gt;Over time, I intentionally designed a development environment that prioritizes &lt;strong&gt;stability, portability, and recoverability&lt;/strong&gt; over convenience. This post documents that setup—not as a theoretical best practice, but as a system I actively use.&lt;/p&gt;

&lt;p&gt;This setup is especially relevant for solo developers, indie hackers, and small teams who want their development environment to behave more like infrastructure than a fragile personal workstation.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-pain-points&quot;&gt;The Pain Points&lt;/h2&gt;

&lt;h3 id=&quot;1-system-instability&quot;&gt;1. System Instability&lt;/h3&gt;
&lt;p&gt;No matter how powerful your PC, laptop, or Mac is, you are always one buggy program away from crashing your entire system. Memory leaks, runaway Docker containers, bad drivers, or misbehaving apps can freeze or reboot your machine—taking your development work with it.&lt;/p&gt;

&lt;h3 id=&quot;2-lack-of-portability&quot;&gt;2. Lack of Portability&lt;/h3&gt;
&lt;p&gt;I need to be able to resume my work from &lt;em&gt;any&lt;/em&gt; device—mobile phone, tablet, laptop—anytime, anywhere. Traditional setups assume you are sitting in front of the same machine that contains your entire development state.&lt;/p&gt;

&lt;h3 id=&quot;3-environment-inconsistency&quot;&gt;3. Environment Inconsistency&lt;/h3&gt;
&lt;p&gt;Reproducing production environments locally is notoriously difficult. Slight differences in OS, libraries, PHP or Node versions, and system packages lead to the classic problem:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“It works on my machine.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;4-os-level-disruptions&quot;&gt;4. OS-Level Disruptions&lt;/h3&gt;
&lt;p&gt;OS updates frequently break development tools or require reconfiguration. Whether it’s macOS, Windows, or Linux, updates tend to reset assumptions your workflow quietly relied on.&lt;/p&gt;

&lt;h3 id=&quot;5-hardware-failures&quot;&gt;5. Hardware Failures&lt;/h3&gt;
&lt;p&gt;A corrupted disk, damaged SSD, malware incident, or forced reformat means rebuilding everything. Even with backups, the &lt;em&gt;environment itself&lt;/em&gt; is often undocumented and unreproducible.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-solution-a-distributed-containerized-approach&quot;&gt;The Solution: A Distributed, Containerized Approach&lt;/h2&gt;

&lt;p&gt;Instead of treating my primary computer as both a &lt;strong&gt;workstation and a server&lt;/strong&gt;, I separated responsibilities.&lt;/p&gt;

&lt;p&gt;This effectively turns my local machine into a &lt;strong&gt;thin client&lt;/strong&gt;, while a dedicated Linux machine becomes the &lt;strong&gt;authoritative source of compute, state, and configuration&lt;/strong&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;hardware-configuration&quot;&gt;Hardware Configuration&lt;/h2&gt;

&lt;p&gt;I use two inexpensive computers, each focused on what it does best.&lt;/p&gt;

&lt;h3 id=&quot;1-macos-machine-thin-client&quot;&gt;1. macOS Machine (Thin Client)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: User interaction only (screen, keyboard, mouse)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Installed software&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;Google Chrome&lt;/li&gt;
      &lt;li&gt;Sequel Ace&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Philosophy&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;No compilers&lt;/li&gt;
      &lt;li&gt;No runtimes&lt;/li&gt;
      &lt;li&gt;No databases&lt;/li&gt;
      &lt;li&gt;Nothing critical lives here&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this machine dies, is reformatted, or updated aggressively, nothing important is lost.&lt;/p&gt;

&lt;h3 id=&quot;2-linux-server-development-infrastructure&quot;&gt;2. Linux Server (Development Infrastructure)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;OS&lt;/strong&gt;: Fedora Linux Server&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Responsibilities&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;Running all server software&lt;/li&gt;
      &lt;li&gt;Storing all code&lt;/li&gt;
      &lt;li&gt;Hosting databases&lt;/li&gt;
      &lt;li&gt;Managing containers&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Installed components include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Docker Engine + Docker Compose&lt;/li&gt;
  &lt;li&gt;Caddy (reverse proxy and TLS)&lt;/li&gt;
  &lt;li&gt;Visual Studio Code Server&lt;/li&gt;
  &lt;li&gt;Continue.dev CLI&lt;/li&gt;
  &lt;li&gt;Git&lt;/li&gt;
  &lt;li&gt;Tailscale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This machine is where &lt;em&gt;state&lt;/em&gt; lives.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;network-architecture&quot;&gt;Network Architecture&lt;/h2&gt;

&lt;p&gt;To make local development fast and predictable, both machines connect to a dedicated router, while the ISP router is placed upstream.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;macOS device → LAN&lt;/li&gt;
  &lt;li&gt;Linux server → LAN&lt;/li&gt;
  &lt;li&gt;ISP router → WAN&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;why-this-matters&quot;&gt;Why This Matters&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Local traffic never passes through the ISP router&lt;/li&gt;
  &lt;li&gt;Lower latency and fewer bottlenecks&lt;/li&gt;
  &lt;li&gt;Isolation from other devices on the ISP network&lt;/li&gt;
  &lt;li&gt;Reduced risk of accidental exposure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This results in &lt;strong&gt;double NAT&lt;/strong&gt;. While double NAT is not perfect security, it provides meaningful isolation and reduces attack surface and network noise.&lt;/p&gt;

&lt;h3 id=&quot;built-in-internet-failover&quot;&gt;Built-In Internet Failover&lt;/h3&gt;

&lt;p&gt;The router supports dual WAN inputs. This allows me to attach a secondary connection (for example, prepaid home WiFi) and automatically fail over if the primary wired connection goes down.&lt;/p&gt;

&lt;p&gt;Connectivity becomes &lt;em&gt;infrastructure&lt;/em&gt;, not a single point of failure.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;development-workflow&quot;&gt;Development Workflow&lt;/h2&gt;

&lt;h3 id=&quot;code-editing-anywhere-code-server-as-pwa&quot;&gt;Code Editing Anywhere (Code Server as PWA)&lt;/h3&gt;

&lt;p&gt;I never edit code directly on macOS.&lt;/p&gt;

&lt;p&gt;Instead, I access Visual Studio Code Server running on the Linux machine via a browser. By clicking the browser’s &lt;strong&gt;Install&lt;/strong&gt; button, Code Server becomes a Progressive Web App.&lt;/p&gt;

&lt;p&gt;From the user’s perspective, it behaves like a native application—but all computation and files remain on the server.&lt;/p&gt;

&lt;p&gt;I’ve resumed work from:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Another laptop&lt;/li&gt;
  &lt;li&gt;A tablet&lt;/li&gt;
  &lt;li&gt;A mobile phone&lt;/li&gt;
  &lt;li&gt;An airport gate in another country&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing changes except the screen size.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;container-first-host-nothing-philosophy&quot;&gt;Container-First, Host-Nothing Philosophy&lt;/h3&gt;

&lt;p&gt;All development dependencies live in containers.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No PHP installed on the host&lt;/li&gt;
  &lt;li&gt;No Node.js installed on the host&lt;/li&gt;
  &lt;li&gt;No databases installed on the host&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each project defines exactly what it needs.&lt;/p&gt;

&lt;p&gt;If Project A needs PHP 7.4 and Project B needs PHP 8.3, they coexist without conflict—because the host never knows PHP exists.&lt;/p&gt;

&lt;p&gt;Docker is not just a tool here; it is the &lt;strong&gt;contract&lt;/strong&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;reverse-proxy-and-https-with-caddy&quot;&gt;Reverse Proxy and HTTPS with Caddy&lt;/h3&gt;

&lt;p&gt;When hosting multiple applications on the same machine:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Caddy routes domains to the correct container&lt;/li&gt;
  &lt;li&gt;Each service is reachable via HTTPS&lt;/li&gt;
  &lt;li&gt;Self-signed certificates are handled automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows realistic local development that closely mirrors production behavior.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;resilience-by-design&quot;&gt;Resilience by Design&lt;/h2&gt;

&lt;h3 id=&quot;os-updates-become-non-events&quot;&gt;OS Updates Become Non-Events&lt;/h3&gt;

&lt;p&gt;When macOS updates arrive, I update immediately.&lt;/p&gt;

&lt;p&gt;Nothing breaks—because nothing critical lives there. After the update, I reconnect to Code Server and continue working exactly where I left off.&lt;/p&gt;

&lt;h3 id=&quot;hardware-failures-are-contained&quot;&gt;Hardware Failures Are Contained&lt;/h3&gt;

&lt;p&gt;If the macOS machine fails entirely, any device with a browser becomes a replacement. The development environment itself remains intact.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;remote-access-from-anywhere&quot;&gt;Remote Access from Anywhere&lt;/h2&gt;

&lt;h3 id=&quot;tailscale-vpn&quot;&gt;Tailscale VPN&lt;/h3&gt;

&lt;p&gt;A Tailscale daemon runs on the Linux server, exposing a secure private IP.&lt;/p&gt;

&lt;p&gt;This enables:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Secure access without port forwarding&lt;/li&gt;
  &lt;li&gt;Encrypted connections from anywhere&lt;/li&gt;
  &lt;li&gt;Zero-trust networking&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;mobile-and-agentic-cli-access&quot;&gt;Mobile and Agentic CLI Access&lt;/h3&gt;

&lt;p&gt;With Tailscale enabled:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I connect from a mobile device&lt;/li&gt;
  &lt;li&gt;Open a terminal client&lt;/li&gt;
  &lt;li&gt;Access Continue.dev CLI&lt;/li&gt;
  &lt;li&gt;Interact with the codebase using agentic workflows&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This works whether I’m at home, in a café, or traveling internationally.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;off-premise-backups-planning-for-total-failure&quot;&gt;Off-Premise Backups: Planning for Total Failure&lt;/h2&gt;

&lt;p&gt;Even with all the precautions above, I assume one thing will eventually happen:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Linux server will fail catastrophically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fire, power surge, disk failure, or simple human error — local infrastructure is still local infrastructure. To handle this, I treat &lt;strong&gt;off‑premise backups as a first‑class component&lt;/strong&gt; of the system.&lt;/p&gt;

&lt;h3 id=&quot;rclone--backblaze-b2&quot;&gt;Rclone + Backblaze B2&lt;/h3&gt;

&lt;p&gt;I use &lt;strong&gt;rclone&lt;/strong&gt; to synchronize critical data from the Linux server to an off‑site object storage provider.&lt;/p&gt;

&lt;p&gt;Rclone supports Backblaze B2 natively, so I configure a remote that points directly to a B2 bucket. From there, scheduled jobs handle backups automatically.&lt;/p&gt;

&lt;p&gt;What gets backed up:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SQL database dumps (MySQL, PostgreSQL, etc.)&lt;/li&gt;
  &lt;li&gt;Entire Git repositories (including all branches)&lt;/li&gt;
  &lt;li&gt;Project stack repositories (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*-stack&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Configuration files that define the environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What does &lt;em&gt;not&lt;/em&gt; get backed up:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Running containers&lt;/li&gt;
  &lt;li&gt;Build artifacts&lt;/li&gt;
  &lt;li&gt;Anything that can be recreated from Dockerfiles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is simple: &lt;strong&gt;preserve state, not runtime&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;recovery-scenario&quot;&gt;Recovery Scenario&lt;/h3&gt;

&lt;p&gt;If the Linux server is completely destroyed:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Provision a new Linux machine&lt;/li&gt;
  &lt;li&gt;Install Docker, Docker Compose, and rclone&lt;/li&gt;
  &lt;li&gt;Restore repositories and SQL dumps from Backblaze B2&lt;/li&gt;
  &lt;li&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker compose up&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The entire development environment — including code, history, and data — is reconstructed without relying on any single physical machine.&lt;/p&gt;

&lt;p&gt;This turns a catastrophic failure into a recoverable inconvenience.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;project-structure-the-super-repo-pattern&quot;&gt;Project Structure: The “Super-Repo” Pattern&lt;/h2&gt;

&lt;p&gt;For each project, I create a repository named:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[project]-stack
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;helloworld-stack/
├── repos/
│   ├── api.example.com
│   ├── app.example.com
│   ├── mysql-migration-scripts
│   └── helloworld-mcp-server
├── docker-compose.yml
├── docker/
├── .gitignore
├── .amazonq/rules
└── .roocode/rules
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;why-submodules-instead-of-a-monorepo&quot;&gt;Why Submodules Instead of a Monorepo?&lt;/h3&gt;

&lt;p&gt;Each submodule retains its own:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Git history&lt;/li&gt;
  &lt;li&gt;CI/CD pipeline&lt;/li&gt;
  &lt;li&gt;Deployment lifecycle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stack repository simply &lt;em&gt;orchestrates&lt;/em&gt; them.&lt;/p&gt;

&lt;h3 id=&quot;benefits&quot;&gt;Benefits&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;One repository defines the entire system&lt;/li&gt;
  &lt;li&gt;Easy onboarding&lt;/li&gt;
  &lt;li&gt;Fully reproducible environments&lt;/li&gt;
  &lt;li&gt;AI tools gain structured, project-level context&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;who-this-setup-is-and-isnt-for&quot;&gt;Who This Setup Is (and Isn’t) For&lt;/h2&gt;

&lt;h3 id=&quot;this-setup-is-for&quot;&gt;This Setup Is For:&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Developers who value stability over convenience&lt;/li&gt;
  &lt;li&gt;People maintaining multiple long-lived projects&lt;/li&gt;
  &lt;li&gt;Anyone tired of rebuilding environments&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;this-setup-may-be-overkill-if&quot;&gt;This Setup May Be Overkill If:&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;You only write small scripts&lt;/li&gt;
  &lt;li&gt;You rely heavily on native GUI tooling&lt;/li&gt;
  &lt;li&gt;You prefer managed cloud IDEs&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;core-philosophy&quot;&gt;Core Philosophy&lt;/h2&gt;

&lt;p&gt;Treat development machines as disposable clients.&lt;/p&gt;

&lt;p&gt;Preserve state only where it matters.&lt;/p&gt;

&lt;p&gt;Once you adopt this mindset:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;OS updates stop being scary&lt;/li&gt;
  &lt;li&gt;Hardware failures become inconveniences&lt;/li&gt;
  &lt;li&gt;Your environment becomes portable by default&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Start with a dedicated Linux machine (even low-powered hardware works)&lt;/li&gt;
  &lt;li&gt;Install Docker and Docker Compose&lt;/li&gt;
  &lt;li&gt;Set up Code Server&lt;/li&gt;
  &lt;li&gt;Configure Tailscale&lt;/li&gt;
  &lt;li&gt;Create your first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[project]-stack&lt;/code&gt; repository&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;This approach transformed my workflow from something fragile into something durable. I spend far less time fixing my environment—and far more time actually building software.&lt;/p&gt;

</description>
        <pubDate>Sat, 20 Dec 2025 06:45:00 +0000</pubDate>
        <link>https://www.darwinbiler.com/scalable-full-stack-development-environment/</link>
        <guid isPermaLink="true">https://www.darwinbiler.com/scalable-full-stack-development-environment/</guid>
        
        
        <category>development</category>
        
        <category>devops</category>
        
        <category>infrastructure</category>
        
      </item>
    
      <item>
        <title>Secure Development Environment with Tailscale, Caddy, and dnsmasq</title>
        <description>&lt;h1 id=&quot;secure-development-environment-with-tailscale-caddy-and-dnsmasq&quot;&gt;Secure Development Environment with Tailscale, Caddy, and dnsmasq&lt;/h1&gt;

&lt;p&gt;This guide explains how to set up a secure development environment using Tailscale VPN, Caddy reverse proxy, and dnsmasq DNS server to provide HTTPS access to local development services across multiple machines.&lt;/p&gt;

&lt;h2 id=&quot;why-you-need-this-setup&quot;&gt;Why You Need This Setup&lt;/h2&gt;

&lt;h3 id=&quot;mobile-device-testing&quot;&gt;Mobile Device Testing&lt;/h3&gt;
&lt;p&gt;Testing your web applications on mobile devices (Android, iOS) requires proper HTTPS endpoints with valid certificates. Unlike desktop machines where you can modify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/hosts&lt;/code&gt;, mobile devices don’t allow easy host file modifications. This setup provides:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Automatic DNS resolution&lt;/strong&gt; on mobile devices through Tailscale&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Valid HTTPS certificates&lt;/strong&gt; that mobile browsers trust&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No manual configuration&lt;/strong&gt; required on each mobile device&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Consistent URLs&lt;/strong&gt; across all testing devices&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;secure-remote-access&quot;&gt;Secure Remote Access&lt;/h3&gt;
&lt;p&gt;You want to access your development environment from anywhere (home, office, coffee shop) without exposing it to the general public. This setup enables:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Private network access&lt;/strong&gt; through Tailscale VPN from any location&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No public port forwarding&lt;/strong&gt; or firewall rules needed&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Encrypted connections&lt;/strong&gt; for all traffic&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Access control&lt;/strong&gt; through Tailscale authentication&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No cloud hosting costs&lt;/strong&gt; for development environments&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;architecture-overview&quot;&gt;Architecture Overview&lt;/h2&gt;

&lt;p&gt;The setup consists of three main components working together:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Tailscale VPN&lt;/strong&gt; - Provides secure network connectivity between devices&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;dnsmasq DNS Server&lt;/strong&gt; - Resolves custom domain names to the development server&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Caddy Reverse Proxy&lt;/strong&gt; - Handles HTTPS termination and routing to local services&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;how-it-works&quot;&gt;How It Works&lt;/h2&gt;

&lt;h3 id=&quot;network-flow&quot;&gt;Network Flow&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Client Machine (via Tailscale) 
    ↓ DNS Query (local-api.example.com)
dnsmasq DNS Server (100.x.x.x)
    ↓ Returns server IP
Client connects to Caddy (100.x.x.x:443)
    ↓ HTTPS with internal certificates
Caddy routes to local service (localhost:8080)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;component-roles&quot;&gt;Component Roles&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tailscale VPN:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Creates secure mesh network between all devices&lt;/li&gt;
  &lt;li&gt;Assigns stable IP addresses (100.x.x.x range)&lt;/li&gt;
  &lt;li&gt;Handles authentication and encryption&lt;/li&gt;
  &lt;li&gt;Enables split DNS configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;dnsmasq DNS Server:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Runs on the development server&lt;/li&gt;
  &lt;li&gt;Resolves custom domains to server’s Tailscale IP&lt;/li&gt;
  &lt;li&gt;Configured as nameserver for Tailscale clients&lt;/li&gt;
  &lt;li&gt;Provides local DNS resolution without external dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Caddy Reverse Proxy:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Terminates HTTPS with internal certificates&lt;/li&gt;
  &lt;li&gt;Routes requests to appropriate backend services&lt;/li&gt;
  &lt;li&gt;Adds security headers for proper forwarding&lt;/li&gt;
  &lt;li&gt;Handles multiple domains and services&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;setup-process&quot;&gt;Setup Process&lt;/h2&gt;

&lt;h3 id=&quot;1-tailscale-configuration&quot;&gt;1. Tailscale Configuration&lt;/h3&gt;

&lt;p&gt;Install Tailscale on all devices and connect them to your tailnet:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Install Tailscale (varies by OS)&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-fsSL&lt;/span&gt; https://tailscale.com/install.sh | sh

&lt;span class=&quot;c&quot;&gt;# Connect to your tailnet&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;tailscale up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-dnsmasq-dns-server-setup&quot;&gt;2. dnsmasq DNS Server Setup&lt;/h3&gt;

&lt;p&gt;Configure dnsmasq on your development server:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Install dnsmasq&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;dnsmasq

&lt;span class=&quot;c&quot;&gt;# Create DNS configuration&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /etc/dnsmasq.d/internal.conf &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
# Listen on Tailscale interface
listen-address=127.0.0.1,100.x.x.x
bind-interfaces
no-dhcp-interface=*
domain-needed
bogus-priv
no-resolv
no-poll
no-hosts

# Upstream DNS servers
server=8.8.8.8
server=8.8.4.4

# Local domain mappings
address=/local-api.example.com/100.x.x.x
address=/local-app.example.com/100.x.x.x
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Start dnsmasq&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--now&lt;/span&gt; dnsmasq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3-caddy-reverse-proxy-setup&quot;&gt;3. Caddy Reverse Proxy Setup&lt;/h3&gt;

&lt;p&gt;Configure Caddy for HTTPS termination and routing:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-caddyfile&quot;&gt;# Global settings
{
    http_port 80
    https_port 443
    skip_install_trust
    local_certs
}

# API service
local-api.example.com {
    reverse_proxy localhost:8080 {
        header_up X-Forwarded-Proto https
        header_up X-Forwarded-Port 443
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Ssl on
        header_up X-Url-Scheme https
        header_up HTTPS on
    }
    tls internal
}

# Web application
local-app.example.com {
    reverse_proxy localhost:3000 {
        header_up X-Forwarded-Proto https
        header_up X-Forwarded-Port 443
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Ssl on
        header_up X-Url-Scheme https
        header_up HTTPS on
    }
    tls internal
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;4-tailscale-dns-configuration&quot;&gt;4. Tailscale DNS Configuration&lt;/h3&gt;

&lt;p&gt;Configure Tailscale to use your server as DNS:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Set your server as nameserver for custom domains&lt;/span&gt;
tailscale &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--nameserver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;100.x.x.x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;benefits&quot;&gt;Benefits&lt;/h2&gt;

&lt;h3 id=&quot;security&quot;&gt;Security&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Encrypted Traffic&lt;/strong&gt;: All communication encrypted via Tailscale&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No Public Exposure&lt;/strong&gt;: Services remain private to your tailnet&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;HTTPS Everywhere&lt;/strong&gt;: Internal certificates provide HTTPS for all services&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Access Control&lt;/strong&gt;: Tailscale handles authentication and authorization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;development-experience&quot;&gt;Development Experience&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Custom Domains&lt;/strong&gt;: Use meaningful domain names instead of IP:port&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cross-Device Access&lt;/strong&gt;: Access services from any device in your tailnet&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No Certificate Warnings&lt;/strong&gt;: Proper HTTPS with trusted internal certificates&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Easy Service Discovery&lt;/strong&gt;: DNS-based service discovery&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;operational-advantages&quot;&gt;Operational Advantages&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;No External Dependencies&lt;/strong&gt;: Works without internet for local development&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Scalable&lt;/strong&gt;: Easy to add new services and domains&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Portable&lt;/strong&gt;: Works across different networks and locations&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Maintainable&lt;/strong&gt;: Simple configuration files for all components&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;troubleshooting&quot;&gt;Troubleshooting&lt;/h2&gt;

&lt;h3 id=&quot;dns-resolution-issues&quot;&gt;DNS Resolution Issues&lt;/h3&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Test DNS resolution&lt;/span&gt;
nslookup local-api.example.com 100.x.x.x

&lt;span class=&quot;c&quot;&gt;# Check dnsmasq status&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl status dnsmasq

&lt;span class=&quot;c&quot;&gt;# View dnsmasq logs&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;journalctl &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; dnsmasq &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;certificate-issues&quot;&gt;Certificate Issues&lt;/h3&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Check Caddy status&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl status caddy

&lt;span class=&quot;c&quot;&gt;# View Caddy logs&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;journalctl &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; caddy &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Test HTTPS connection&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; https://local-api.example.com/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;tailscale-connectivity&quot;&gt;Tailscale Connectivity&lt;/h3&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Check Tailscale status&lt;/span&gt;
tailscale status

&lt;span class=&quot;c&quot;&gt;# Test connectivity&lt;/span&gt;
ping 100.x.x.x

&lt;span class=&quot;c&quot;&gt;# Check DNS configuration&lt;/span&gt;
tailscale status &lt;span class=&quot;nt&quot;&gt;--json&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A5&lt;/span&gt; DNS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;common-pitfalls&quot;&gt;Common Pitfalls&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Conflicting /etc/hosts entries&lt;/strong&gt; - Remove any localhost entries for your custom domains&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DNS caching&lt;/strong&gt; - Clear DNS cache after configuration changes&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Firewall rules&lt;/strong&gt; - Ensure ports 53 (DNS) and 443 (HTTPS) are accessible&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Service binding&lt;/strong&gt; - Make sure backend services bind to localhost or all interfaces&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This setup provides a robust, secure development environment that scales across multiple services and devices. The combination of Tailscale’s mesh VPN, dnsmasq’s local DNS resolution, and Caddy’s reverse proxy creates a production-like environment for development while maintaining security and ease of use.&lt;/p&gt;

&lt;p&gt;The architecture is particularly valuable for:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Mobile app development&lt;/strong&gt; - Test APIs on real devices without certificate issues&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Remote development&lt;/strong&gt; - Access your dev environment securely from anywhere&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Team collaboration&lt;/strong&gt; - Share development services without public exposure&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Microservices development&lt;/strong&gt; - Use proper domain names instead of localhost:port&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cross-device testing&lt;/strong&gt; - Consistent HTTPS URLs across all devices&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Client demos&lt;/strong&gt; - Show work-in-progress to clients securely&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 18 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://www.darwinbiler.com/secure-network-development-environment/</link>
        <guid isPermaLink="true">https://www.darwinbiler.com/secure-network-development-environment/</guid>
        
        
        <category>infrastructure</category>
        
        <category>security</category>
        
        <category>development</category>
        
      </item>
    
  </channel>
</rss>
