<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shiva Kadiri</title>
    <description>The latest articles on DEV Community by Shiva Kadiri (@shiva_kadiri).</description>
    <link>https://dev.to/shiva_kadiri</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4005652%2F63775bfa-b8ea-423d-8d6b-46433f889922.png</url>
      <title>DEV Community: Shiva Kadiri</title>
      <link>https://dev.to/shiva_kadiri</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shiva_kadiri"/>
    <language>en</language>
    <item>
      <title>If You Can't Run It Local, You're Not Ready to Deploy</title>
      <dc:creator>Shiva Kadiri</dc:creator>
      <pubDate>Wed, 15 Jul 2026 08:05:15 +0000</pubDate>
      <link>https://dev.to/shiva_kadiri/if-you-cant-run-it-local-youre-not-ready-to-deploy-506n</link>
      <guid>https://dev.to/shiva_kadiri/if-you-cant-run-it-local-youre-not-ready-to-deploy-506n</guid>
      <description>&lt;p&gt;I'm big on developer experience.&lt;/p&gt;

&lt;p&gt;As a leader, I want my team to be self-sufficient and handle any edge cases — without waiting on me, a shared staging box, or the one person who "knows how the env works."&lt;/p&gt;

&lt;p&gt;DX, for me, is operational: short feedback loops, reproducible failures, and a documented path from clone to a working critical path. When that path is missing, engineers spend cycles on VPN access, shared credentials, and "works on staging" instead of on the bug. Friction compounds. Clarity compounds faster. The sharpest test I know of that clarity is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you can't run it local, you're not ready to deploy.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy theater
&lt;/h2&gt;

&lt;p&gt;Plenty of teams ship every day. CI is green. There is a runbook somewhere.&lt;/p&gt;

&lt;p&gt;Then a bug shows up under a specific payload, migration, or timing window — and nobody can reproduce it without staging access, a VPN, three shared accounts, and a Slack thread titled "can someone restart the mock for me?"&lt;/p&gt;

&lt;p&gt;That is not shipping discipline. That is deploy theater: the appearance of readiness without the ability to own a failure on your own machine.&lt;/p&gt;

&lt;p&gt;If a new engineer — or you, on a fresh laptop — cannot bring the critical path up with a short, documented path, you do not have a deploy story. You have a hope story.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "run it local" actually means
&lt;/h2&gt;

&lt;p&gt;It does not mean cloning production into Docker Desktop. You do not need every managed service, every regional failover, every edge case of the cloud.&lt;/p&gt;

&lt;p&gt;It means enough fidelity for the work developers actually do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a real data store (or a close stand-in) with durable volumes&lt;/li&gt;
&lt;li&gt;mocks for dependencies you do not own&lt;/li&gt;
&lt;li&gt;an observability path you can hit from your app process (OTLP, logs, traces)&lt;/li&gt;
&lt;li&gt;config, APIs, and protocol tools you can exercise without a cloud account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Local is not a toy. Local is the cheapest place to be wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  What &lt;a href="https://github.com/shivakadiri/dev-tools" rel="noopener noreferrer"&gt;dev-tools&lt;/a&gt; does for local run
&lt;/h2&gt;

&lt;p&gt;I keep that fidelity in &lt;a href="https://github.com/shivakadiri/dev-tools" rel="noopener noreferrer"&gt;shivakadiri/dev-tools&lt;/a&gt;: a Docker Compose stack of development services. One command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is not an application. It is the local dependency plane — so your app (or agent, workflow, or API) can run against real-ish infrastructure on &lt;code&gt;localhost&lt;/code&gt; instead of a shared cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bootstrap
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Clone the repo, copy &lt;code&gt;.env.example&lt;/code&gt; → &lt;code&gt;.env&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker compose up -d&lt;/code&gt; (or &lt;code&gt;docker compose up -d &amp;lt;service&amp;gt;&lt;/code&gt; for a subset)&lt;/li&gt;
&lt;li&gt;Open documented URLs — Postgres on &lt;code&gt;5432&lt;/code&gt;, Grafana on &lt;code&gt;3000&lt;/code&gt;, WireMock on &lt;code&gt;9000&lt;/code&gt;, and the rest on fixed ports from &lt;code&gt;.env&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A Homepage dashboard aggregates those links so you are not hunting ports in a notes file.&lt;/p&gt;

&lt;h3&gt;
  
  
  What you can actually do locally
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Persist and query data&lt;/strong&gt; — shared &lt;strong&gt;PostgreSQL&lt;/strong&gt; with pgvector on &lt;code&gt;localhost:5432&lt;/code&gt;. Several services (n8n, LiteLLM, Hoppscotch) use the same instance with separate databases. &lt;strong&gt;pgAdmin&lt;/strong&gt; is wired for admin work without installing a client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stub external APIs&lt;/strong&gt; — &lt;strong&gt;WireMock Studio&lt;/strong&gt; on &lt;code&gt;9000&lt;/code&gt; (plus a port range for stubs) so you can simulate third-party failure modes, latency, and contract drift without calling production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Emit and inspect telemetry&lt;/strong&gt; — &lt;strong&gt;Grafana (otel-lgtm)&lt;/strong&gt; with Loki, Tempo, Prometheus, and an OTel collector. Point your app at OTLP gRPC &lt;code&gt;4317&lt;/code&gt; or HTTP &lt;code&gt;4318&lt;/code&gt; and debug traces/logs/metrics before anything hits a cloud backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate and integrate&lt;/strong&gt; — &lt;strong&gt;n8n&lt;/strong&gt; for workflows against local services and mocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Call APIs end-to-end&lt;/strong&gt; — &lt;strong&gt;Hoppscotch&lt;/strong&gt; as a local API client against WireMock, your app, or anything else on the compose network / host.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run config without Azure&lt;/strong&gt; — &lt;strong&gt;Azure App Configuration emulator&lt;/strong&gt; with anonymous UI and HMAC keys, so feature flags and config clients work offline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run LLM work offline&lt;/strong&gt; — &lt;strong&gt;Ollama&lt;/strong&gt; for inference, &lt;strong&gt;Open WebUI&lt;/strong&gt; for chat, &lt;strong&gt;LiteLLM&lt;/strong&gt; as an OpenAI-compatible proxy (&lt;code&gt;/chat/completions&lt;/code&gt;) in front of local or cloud models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debug agents and MCP&lt;/strong&gt; — &lt;strong&gt;A2A Inspector&lt;/strong&gt; and &lt;strong&gt;MCP Inspector&lt;/strong&gt;. When the agent or MCP server runs on the host, containers reach it via &lt;code&gt;host.docker.internal&lt;/code&gt; (documented in the README).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Design choices that matter for DX
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One shared Postgres&lt;/strong&gt; instead of a database container per tool — fewer volumes, simpler backups, one place to reset state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ports and secrets in &lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt; — predictable &lt;code&gt;localhost&lt;/code&gt; endpoints, not random published ports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honest failure modes in docs&lt;/strong&gt; — e.g. Ollama OOM-killed on Mac when Docker Desktop memory is tight; App Config emulator via &lt;code&gt;platform: linux/amd64&lt;/code&gt; on Apple Silicon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That honesty is DX too. A local path that only works on a perfect day is not a local path.&lt;/p&gt;

&lt;p&gt;I am not arguing that every team should run this exact toolbox. I am arguing that &lt;strong&gt;having a dependency plane you can start in minutes&lt;/strong&gt; is how you treat developer experience as infrastructure. Steal the pattern: &lt;a href="https://github.com/shivakadiri/dev-tools" rel="noopener noreferrer"&gt;github.com/shivakadiri/dev-tools&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why local fidelity makes deploy honest
&lt;/h2&gt;

&lt;p&gt;When that plane runs on your laptop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feedback loops shrink from "wait for staging" to "change it and look" — migrations, stubs, OTLP, config.&lt;/li&gt;
&lt;li&gt;Experiments stay isolated. Blow up a volume. Reset WireMock. Replay the bad payload. Nobody else is blocked.&lt;/li&gt;
&lt;li&gt;You exercise the same observability path you will need in production — traces and logs on the happy path, not only during an incident.&lt;/li&gt;
&lt;li&gt;Onboarding is a checklist, not tribal knowledge: clone → env → compose up → hit a known URL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deploy then becomes a promotion of something you already understand. Not a leap of faith into an environment only three people can access.&lt;/p&gt;

&lt;h2&gt;
  
  
  DX debt looks familiar
&lt;/h2&gt;

&lt;p&gt;You will recognize the anti-patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docs that only describe cloud provisioning&lt;/li&gt;
&lt;li&gt;Environments that exist only behind secrets and shared clusters&lt;/li&gt;
&lt;li&gt;"Just use staging" as the default development workflow&lt;/li&gt;
&lt;li&gt;Local setup that takes a day and a tribal knowledge session&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are not "we'll improve DX later" items. They are release risk. Every hour a developer cannot reproduce a bug locally is an hour the incident clock runs without a controlled repro.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bar I use
&lt;/h2&gt;

&lt;p&gt;Before I trust a deploy story, I want this path to be boring:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone the repo&lt;/li&gt;
&lt;li&gt;Copy &lt;code&gt;.env.example&lt;/code&gt; (or equivalent)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker compose up -d&lt;/code&gt; (or the project's equivalent one-liner)&lt;/li&gt;
&lt;li&gt;Open a documented URL / hit a documented port&lt;/li&gt;
&lt;li&gt;See something real working — a UI, an API, a dashboard, a successful OTLP export — in minutes, not days&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If step 5 requires a ticket, a shared password in a vault nobody can find, or a cluster that is "usually up," the bar failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Own the failure path
&lt;/h2&gt;

&lt;p&gt;I'm big on developer experience because shipping is a human system. As a leader, self-sufficiency is the goal: every engineer should be able to reproduce the weird path, poke the edge case, and own the fix. A local dependency plane — tools, docs, and &lt;code&gt;compose up&lt;/code&gt; — is how you make that real.&lt;/p&gt;

&lt;p&gt;If you cannot run it local, you cannot fully debug it, reproduce it, or teach it. Deploying anyway is guessing.&lt;/p&gt;

&lt;p&gt;And guessing is the opposite of good developer experience.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I replaced homelab bash with agents — and the DX got weirdly good</title>
      <dc:creator>Shiva Kadiri</dc:creator>
      <pubDate>Wed, 15 Jul 2026 07:21:59 +0000</pubDate>
      <link>https://dev.to/shiva_kadiri/i-replaced-homelab-bash-with-agents-and-the-dx-got-weirdly-good-3f7e</link>
      <guid>https://dev.to/shiva_kadiri/i-replaced-homelab-bash-with-agents-and-the-dx-got-weirdly-good-3f7e</guid>
      <description>&lt;p&gt;Homelabs used to mean a folder of bash scripts, a wiki nobody updates, and one machine you are afraid to reboot.&lt;/p&gt;

&lt;p&gt;I wanted something different: &lt;strong&gt;talk to the lab like a product&lt;/strong&gt;, keep infra boring and reproducible, and make “did I break production-at-home?” a recoverable question instead of a weekend.&lt;/p&gt;

&lt;p&gt;So I built a small multi-agent control plane on top of Proxmox, Unifi  and TrueNAS — not a chatbot glued to SSH, but &lt;strong&gt;separate agent services&lt;/strong&gt; behind an orchestrator, with a UI that feels closer to Cursor than to Cockpit.&lt;/p&gt;

&lt;p&gt;This is the story of the agents, the infra, and the developer experience that made it worth doing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Everything lives in separate repos under &lt;a href="https://github.com/shivakadiri" rel="noopener noreferrer"&gt;@shivakadiri&lt;/a&gt; — one boundary per package:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Repo&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/shivakadiri/homelab-ui" rel="noopener noreferrer"&gt;homelab-ui&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Chat / History / Dashboard / Logs UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/shivakadiri/homelab-orchestrator" rel="noopener noreferrer"&gt;homelab-orchestrator&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Control plane + CLI (routes to agents)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/shivakadiri/homelab-unifi" rel="noopener noreferrer"&gt;homelab-unifi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;UniFi agent (JSON-over-HTTP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/shivakadiri/homelab-proxmox" rel="noopener noreferrer"&gt;homelab-proxmox&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Proxmox agent (A2A) + LXC provisioning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/shivakadiri/homelab-truenas" rel="noopener noreferrer"&gt;homelab-truenas&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;TrueNAS agent (MCP)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The shape of the system
&lt;/h2&gt;

&lt;p&gt;At a high level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UI  →  Orchestrator  →  Agent services
                          ├─ UniFi   (JSON-over-HTTP)
                          ├─ Proxmox (A2A)
                          └─ TrueNAS (MCP)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The UI never calls hypervisors or switches directly. It chats with a &lt;strong&gt;control plane&lt;/strong&gt;. The control plane routes intent to the right agent. Each agent owns one domain and one protocol.&lt;/p&gt;

&lt;p&gt;That split matters more than the LLM brand.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Repo&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Why that choice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;UniFi&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/shivakadiri/homelab-unifi" rel="noopener noreferrer"&gt;homelab-unifi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Langgraph remote agent&lt;/td&gt;
&lt;td&gt;I want to leverage existing REST Apis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/shivakadiri/homelab-proxmox" rel="noopener noreferrer"&gt;homelab-proxmox&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://a2a-protocol.org/" rel="noopener noreferrer"&gt;A2A&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;I want maximum capabilities as agent skills&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TrueNAS&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/shivakadiri/homelab-truenas" rel="noopener noreferrer"&gt;homelab-truenas&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;MCP&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;My data (memories, documents), I want as deterministic as possible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The orchestrator (&lt;a href="https://github.com/shivakadiri/homelab-orchestrator" rel="noopener noreferrer"&gt;homelab-orchestrator&lt;/a&gt;) is deliberately dumb about domain logic. It is a router, health aggregator, and event bus — not a god-object that knows VLANs &lt;em&gt;and&lt;/em&gt; ZFS &lt;em&gt;and&lt;/em&gt; LXC presets. The UI (&lt;a href="https://github.com/shivakadiri/homelab-ui" rel="noopener noreferrer"&gt;homelab-ui&lt;/a&gt;) only talks to that control plane.&lt;/p&gt;

&lt;p&gt;If you only take one architecture idea from this post: &lt;strong&gt;one agent per systems boundary, one protocol per agent, one orchestrator that does not pretend to be all three.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Infra first: make the lab feel like an app platform
&lt;/h2&gt;

&lt;p&gt;Agents are useless if the underlying platform is a junk drawer.&lt;/p&gt;

&lt;p&gt;I standardized guests as Proxmox LXCs with predictable IPs and names — the unglamorous stuff that makes everything else composable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Caddy&lt;/strong&gt; — TLS terminator (&lt;code&gt;*.klab&lt;/code&gt;, local CA)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AdGuard&lt;/strong&gt; — DNS that makes &lt;code&gt;homepage.klab&lt;/code&gt; and friends real&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Homepage&lt;/strong&gt; — human map of the lab&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Postgres + pgvector&lt;/strong&gt; — shared DB for apps that need state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama + LiteLLM&lt;/strong&gt; — local models behind an OpenAI-compatible gateway&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hoppscotch&lt;/strong&gt; — API client aimed at those same services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentik&lt;/strong&gt; — SSO / forward-auth for the pretty HTTPS surfaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;otel-lgtm&lt;/strong&gt; — Grafana’s all-in-one OTel backend for when something lies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of that is novel. The point is &lt;strong&gt;product shape&lt;/strong&gt;: HTTPS hostnames, SSO where humans click, Bearer tokens where machines call, DNS that matches the mental model.&lt;/p&gt;

&lt;p&gt;A concrete DX win: once &lt;code&gt;litellm.klab&lt;/code&gt; and &lt;code&gt;ollama.klab&lt;/code&gt; exist, agent code and API collections stop speaking raw &lt;code&gt;10.10.15.x&lt;/code&gt; forever. Your future self will thank you when you move a container.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secrets are not &lt;code&gt;.env&lt;/code&gt; cosplay
&lt;/h3&gt;

&lt;p&gt;Every agent defaults to &lt;strong&gt;dry-run&lt;/strong&gt;. Live mode pulls secrets from a pluggable store (macOS Keychain via &lt;code&gt;keyring&lt;/code&gt; in my case). Tests use an in-memory fake store.&lt;/p&gt;

&lt;p&gt;That sounds pedantic until you paste an API token into a compose file “just for now.”&lt;/p&gt;

&lt;p&gt;Rules that survived contact with reality:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dry-run by default&lt;/strong&gt; — agents boot safely on a laptop with no credentials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No secrets in repo-adjacent &lt;code&gt;.env&lt;/code&gt; for prod paths&lt;/strong&gt; — Keychain/service accounts only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Plan vs Agent&lt;/strong&gt; — Plan sends &lt;code&gt;dry_run: true&lt;/code&gt;; Agent sends &lt;code&gt;dry_run: false&lt;/code&gt;. Same chat, different blast radius.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Plan/Agent toggle in the UI is the same idea Cursor has: &lt;em&gt;propose&lt;/em&gt; vs &lt;em&gt;do&lt;/em&gt;. Homelab operators need that muscle memory even more than app developers — there is no staging VLAN that forgives you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agents as services, not notebooks
&lt;/h2&gt;

&lt;p&gt;It is tempting to put “the agent” in a Jupyter notebook or a single FastAPI file that SSHs everywhere.&lt;/p&gt;

&lt;p&gt;Resist that.&lt;/p&gt;

&lt;p&gt;Each agent is a small long-running service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET /health&lt;/code&gt; / metadata&lt;/li&gt;
&lt;li&gt;chat or &lt;code&gt;run&lt;/code&gt; entrypoints&lt;/li&gt;
&lt;li&gt;monitor hooks&lt;/li&gt;
&lt;li&gt;domain RPCs where needed (UniFi exposes live client inventory so Proxmox can &lt;strong&gt;auto-discover&lt;/strong&gt; &lt;code&gt;:8006&lt;/code&gt; hosts on the LAN)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Proxmox discovery is a good example of agent collaboration without a shared monolith:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;UniFi agent lists connected clients + IPs (live mode).&lt;/li&gt;
&lt;li&gt;Proxmox agent probes candidates for the Proxmox API.&lt;/li&gt;
&lt;li&gt;Orchestrator stays out of the SNMP weeds.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is multi-agent in the useful sense: &lt;strong&gt;specialists with contracts&lt;/strong&gt;, not a committee of personas arguing in one prompt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local LLMs without cosplaying cloud lock-in
&lt;/h3&gt;

&lt;p&gt;LiteLLM in front of Ollama gives you an OpenAI-shaped endpoint on the LAN. Agents can use cloud models when you want quality, and fall back to local / deterministic stubs when you want offline or CI-friendly behavior.&lt;/p&gt;

&lt;p&gt;The DX goal is not “never call Anthropic.” It is &lt;strong&gt;swap the brain without rewriting the hands&lt;/strong&gt; — tools, secrets, dry-run, and protocols stay stable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer experience is the product
&lt;/h2&gt;

&lt;p&gt;Homelab projects die when the feedback loop is “reboot and pray.”&lt;/p&gt;

&lt;p&gt;What improved the loop for me:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Chat as the primary interface
&lt;/h3&gt;

&lt;p&gt;The UI is Chat / History / Dashboard / Logs. Routing is automatic — no “pick UniFi from a dropdown” tax on every question. Follow-ups pin &lt;code&gt;session_id&lt;/code&gt; + agent so human-in-the-loop clarifications continue with the same specialist.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Observability early, not after the fire
&lt;/h3&gt;

&lt;p&gt;Dropping &lt;code&gt;grafana/otel-lgtm&lt;/code&gt; into an LXC is not “production observability.” It &lt;em&gt;is&lt;/em&gt; a place to send traces when an agent’s tool call fails in a way logs alone will not explain. Homelabs are perfect for OTel practice because the blast radius is your evening, not your employer’s SLO.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. API collections as living docs
&lt;/h3&gt;

&lt;p&gt;Hoppscotch collections for Ollama/LiteLLM beat README curl blocks that rot. Import environments with &lt;code&gt;https://…klab&lt;/code&gt; URLs — if you keep &lt;code&gt;http://10.x&lt;/code&gt; while the UI is HTTPS, browsers will gift you cryptic “Network Error / Unknown cause” mixed-content failures. Ask me how I know.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Provisioning scripts as episodic memory
&lt;/h3&gt;

&lt;p&gt;LXC presets (&lt;code&gt;caddy&lt;/code&gt;, &lt;code&gt;authentik&lt;/code&gt;, &lt;code&gt;otel-lgtm&lt;/code&gt;, …) live next to the Proxmox agent. When I say “add X on homelab02,” the path is: known VMID/IP/resources → nest Docker when needed → wire DNS → Caddy → Homepage card. The agent is the operator; the script is the runbook the agent (or I) can re-run.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Protocol diversity on purpose
&lt;/h3&gt;

&lt;p&gt;Using HTTP + A2A + MCP in one control plane sounds messy. In practice it forces clean client adapters and stops you from inventing a fourth private RPC. The orchestrator README becomes a compatibility chart, not folklore.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would tell past me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start with dry-run and Keychain&lt;/strong&gt;, not with model choice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give every human-facing service a hostname and TLS&lt;/strong&gt; before you build agents on top.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put SSO in front of UIs&lt;/strong&gt;, not in front of machine APIs that already have Bearer tokens (or you will debug Authentik redirects instead of JSON).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer small agent services&lt;/strong&gt; over one mega-agent with every Ansible module glued on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat DX as infra&lt;/strong&gt;: Plan/Agent modes, event websockets, health endpoints, importable API collections.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why bother?
&lt;/h2&gt;

&lt;p&gt;Because the homelab is the last place many of us can still own the full stack: network → hypervisor → identity → models → UI.&lt;/p&gt;

&lt;p&gt;Agents are having a moment in product engineering. A homelab is a ruthless playground for the same questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is a safe tool?&lt;/li&gt;
&lt;li&gt;What is a session?&lt;/li&gt;
&lt;li&gt;Who is allowed to mutate state?&lt;/li&gt;
&lt;li&gt;How do specialists coordinate without a shared brain?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your agents cannot provision an LXC, respect dry-run, and explain why DNS still points at the old box — they are not ready for your day job either.&lt;/p&gt;

&lt;p&gt;I am still iterating (always). But the lab finally feels less like a museum of containers and more like a &lt;strong&gt;developer platform with opinions&lt;/strong&gt; — and chatting with it is, embarrassingly, fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;UI: &lt;a href="https://github.com/shivakadiri/homelab-ui" rel="noopener noreferrer"&gt;github.com/shivakadiri/homelab-ui&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Orchestrator: &lt;a href="https://github.com/shivakadiri/homelab-orchestrator" rel="noopener noreferrer"&gt;github.com/shivakadiri/homelab-orchestrator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;UniFi agent: &lt;a href="https://github.com/shivakadiri/homelab-unifi" rel="noopener noreferrer"&gt;github.com/shivakadiri/homelab-unifi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Proxmox agent: &lt;a href="https://github.com/shivakadiri/homelab-proxmox" rel="noopener noreferrer"&gt;github.com/shivakadiri/homelab-proxmox&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;TrueNAS agent: &lt;a href="https://github.com/shivakadiri/homelab-truenas" rel="noopener noreferrer"&gt;github.com/shivakadiri/homelab-truenas&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  End State
&lt;/h2&gt;

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




&lt;p&gt;If you build something in this shape, I would love to hear what protocol split you chose — and what your first “Plan vs Agent” near-miss looked like.&lt;/p&gt;

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