<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Docker on houdeshell.dev</title><link>https://houdeshell.dev/tags/docker/</link><description>Recent content in Docker on houdeshell.dev</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>© CRH</copyright><lastBuildDate>Fri, 12 Jun 2026 14:00:00 -0400</lastBuildDate><atom:link href="https://houdeshell.dev/tags/docker/index.xml" rel="self" type="application/rss+xml"/><item><title>Software that I &lt;img class='title-icon' src='https://houdeshell.dev/static/images/lego-heart.svg' alt='heart' /></title><link>https://houdeshell.dev/software/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><guid>https://houdeshell.dev/software/</guid><description>&lt;p>I bounce between Mac, Windows, and Linux daily. Honestly, the tools matter more than the OS at this point. Great software is great software, and I&amp;rsquo;ve been lucky enough to build a career on top of things other people built well.&lt;/p>
&lt;p>This is the stuff I actually reach for. Not a &amp;ldquo;best of&amp;rdquo; list, not sponsored, not comprehensive. Just software that makes me better at what I do. Or at least makes the work more fun.&lt;/p>
&lt;style>
.sw-grid {
display: flex;
flex-direction: column;
margin: 1.6em 0 2.6em;
counter-reset: sw;
border-top: 1px solid var(--border);
}
.sw-card {
display: grid;
grid-template-columns: 44px 130px 1fr;
grid-template-areas:
"num tag title"
"num tag desc";
column-gap: 1.5em;
row-gap: 0.3em;
align-items: baseline;
padding: 1em 6px 1em 4px;
border-bottom: 1px solid var(--border);
counter-increment: sw;
transition: background 0.2s ease, padding-left 0.2s ease;
}
.sw-card::before {
content: counter(sw, decimal-leading-zero);
grid-area: num;
align-self: baseline;
font-family: var(--font-mono);
font-size: 0.72em;
font-weight: 500;
letter-spacing: 0.08em;
color: var(--text-muted);
transition: color 0.2s ease;
}
.sw-card:hover {
background: rgba(251, 60, 0, 0.035);
padding-left: 12px;
}
.sw-card:hover::before {
color: #fb3c00;
}
.sw-card .sw-tag {
grid-area: tag;
align-self: baseline;
font-family: var(--font-mono);
font-size: 0.7em;
font-weight: 500;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text-secondary);
background: none;
border: none;
padding: 0;
margin: 0;
transition: color 0.2s ease;
}
.sw-card:hover .sw-tag {
color: #fb3c00;
}
.sw-card h3 {
grid-area: title;
margin: 0 !important;
font-size: 1.02em !important;
font-weight: 600 !important;
letter-spacing: -0.005em !important;
border: none !important;
padding: 0 !important;
color: var(--text) !important;
text-decoration: none !important;
}
.sw-card h3::before {
content: none !important;
}
.sw-card h3 a {
color: var(--text);
text-decoration: none;
border-bottom: 1px solid transparent;
transition: color 0.2s ease, border-color 0.2s ease;
}
.sw-card:hover h3 a {
color: #fb3c00;
border-bottom-color: rgba(251, 60, 0, 0.4);
}
.sw-card p {
grid-area: desc;
margin: 0 !important;
font-size: 0.88em;
color: var(--text-secondary);
line-height: 1.55;
}
.sw-card p a {
color: var(--text);
text-decoration: none;
border-bottom: 1px dashed var(--accent-line);
}
.sw-card p a:hover {
color: #fb3c00;
border-bottom-color: #fb3c00;
}
.sw-card code {
background: rgba(0, 0, 0, 0.04) !important;
color: var(--text) !important;
border-color: var(--border) !important;
}
@media (max-width: 640px) {
.sw-card {
grid-template-columns: 1fr;
grid-template-areas:
"num"
"tag"
"title"
"desc";
row-gap: 0.35em;
padding: 0.95em 4px;
}
.sw-card:hover {
padding-left: 4px;
}
}
&lt;/style>
&lt;h2 id="software-development" class="md-heading">
Software Development
&lt;a class="md-heading-anchor" href="#software-development" aria-label="Link to Software Development">#&lt;/a>
&lt;/h2>
&lt;div class="sw-grid">
&lt;div class="sw-card">
&lt;span class="sw-tag">IDE&lt;/span>
&lt;h3 id="jetbrains-rider" class="md-heading">
&lt;a href="https://www.jetbrains.com/rider/"target="_blank" rel="noopener noreferrer">JetBrains Rider&lt;/a>
&lt;a class="md-heading-anchor" href="#jetbrains-rider" aria-label="Link to JetBrains Rider">#&lt;/a>
&lt;/h3>
&lt;p>Cross-platform .NET IDE. Fast, smart, and doesn&amp;rsquo;t need Visual Studio&amp;rsquo;s weight to get the job done.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">IDE&lt;/span>
&lt;h3 id="visual-studio" class="md-heading">
&lt;a href="https://visualstudio.microsoft.com/"target="_blank" rel="noopener noreferrer">Visual Studio&lt;/a>
&lt;a class="md-heading-anchor" href="#visual-studio" aria-label="Link to Visual Studio">#&lt;/a>
&lt;/h3>
&lt;p>The OG. Heavy, but when you need the full .NET debugging experience, nothing else comes close.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">editor&lt;/span>
&lt;h3 id="vs-code" class="md-heading">
&lt;a href="https://code.visualstudio.com/"target="_blank" rel="noopener noreferrer">VS Code&lt;/a>
&lt;a class="md-heading-anchor" href="#vs-code" aria-label="Link to VS Code">#&lt;/a>
&lt;/h3>
&lt;p>Extension ecosystem is unmatched. Somehow Electron done right.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">editor&lt;/span>
&lt;h3 id="neovim" class="md-heading">
&lt;a href="https://neovim.io/"target="_blank" rel="noopener noreferrer">Neovim&lt;/a>
&lt;a class="md-heading-anchor" href="#neovim" aria-label="Link to Neovim">#&lt;/a>
&lt;/h3>
&lt;p>Vim reborn. Lua config, LSP native, and a plugin ecosystem that won&amp;rsquo;t quit. &lt;code>:wq&lt;/code> is a lifestyle.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">version control&lt;/span>
&lt;h3 id="git" class="md-heading">
&lt;a href="https://git-scm.com/"target="_blank" rel="noopener noreferrer">Git&lt;/a>
&lt;a class="md-heading-anchor" href="#git" aria-label="Link to Git">#&lt;/a>
&lt;/h3>
&lt;p>The version control system that won. Love it or hate it, you can&amp;rsquo;t ship without it.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">version control&lt;/span>
&lt;h3 id="lazygit" class="md-heading">
&lt;a href="https://github.com/jesseduffield/lazygit"target="_blank" rel="noopener noreferrer">lazygit&lt;/a>
&lt;a class="md-heading-anchor" href="#lazygit" aria-label="Link to lazygit">#&lt;/a>
&lt;/h3>
&lt;p>Terminal UI for git that makes interactive rebases feel like cheating.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">JSON&lt;/span>
&lt;h3 id="jq" class="md-heading">
&lt;a href="https://jqlang.github.io/jq/"target="_blank" rel="noopener noreferrer">jq&lt;/a>
&lt;a class="md-heading-anchor" href="#jq" aria-label="Link to jq">#&lt;/a>
&lt;/h3>
&lt;p>&lt;code>sed&lt;/code> for JSON. Once you learn the syntax, you&amp;rsquo;ll pipe everything through it.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">database&lt;/span>
&lt;h3 id="jetbrains-datagrip" class="md-heading">
&lt;a href="https://www.jetbrains.com/datagrip/"target="_blank" rel="noopener noreferrer">JetBrains DataGrip&lt;/a>
&lt;a class="md-heading-anchor" href="#jetbrains-datagrip" aria-label="Link to JetBrains DataGrip">#&lt;/a>
&lt;/h3>
&lt;p>SQL IDE that actually understands your schema. Autocomplete that works across joins.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">database&lt;/span>
&lt;h3 id="dbeaver" class="md-heading">
&lt;a href="https://dbeaver.io/"target="_blank" rel="noopener noreferrer">DBeaver&lt;/a>
&lt;a class="md-heading-anchor" href="#dbeaver" aria-label="Link to DBeaver">#&lt;/a>
&lt;/h3>
&lt;p>Universal database tool that actually works. Connect to anything, query everything.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">database&lt;/span>
&lt;h3 id="ssms" class="md-heading">
&lt;a href="https://learn.microsoft.com/en-us/sql/ssms/"target="_blank" rel="noopener noreferrer">SSMS&lt;/a>
&lt;a class="md-heading-anchor" href="#ssms" aria-label="Link to SSMS">#&lt;/a>
&lt;/h3>
&lt;p>Microsoft SQL Management Studio. If you&amp;rsquo;re in SQL Server land, you already know.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">database&lt;/span>
&lt;h3 id="postgresql" class="md-heading">
&lt;a href="https://www.postgresql.org/"target="_blank" rel="noopener noreferrer">PostgreSQL&lt;/a>
&lt;a class="md-heading-anchor" href="#postgresql" aria-label="Link to PostgreSQL">#&lt;/a>
&lt;/h3>
&lt;p>The database that keeps getting better. Extensions, JSON support, and rock-solid reliability.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">containers&lt;/span>
&lt;h3 id="docker" class="md-heading">
&lt;a href="https://www.docker.com/"target="_blank" rel="noopener noreferrer">Docker&lt;/a>
&lt;a class="md-heading-anchor" href="#docker" aria-label="Link to Docker">#&lt;/a>
&lt;/h3>
&lt;p>&amp;ldquo;Works on my machine&amp;rdquo; became &amp;ldquo;works on every machine.&amp;rdquo; Changed how we ship software.&lt;/p>
&lt;/div>
&lt;/div>
&lt;h2 id="ai" class="md-heading">
AI
&lt;a class="md-heading-anchor" href="#ai" aria-label="Link to AI">#&lt;/a>
&lt;/h2>
&lt;div class="sw-grid">
&lt;div class="sw-card">
&lt;span class="sw-tag">agent&lt;/span>
&lt;h3 id="claude-code" class="md-heading">
&lt;a href="https://docs.anthropic.com/en/docs/claude-code"target="_blank" rel="noopener noreferrer">Claude Code&lt;/a>
&lt;a class="md-heading-anchor" href="#claude-code" aria-label="Link to Claude Code">#&lt;/a>
&lt;/h3>
&lt;p>AI pair programmer in your terminal. It&amp;rsquo;s writing this page right now.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">agent&lt;/span>
&lt;h3 id="vs-code-agents" class="md-heading">
&lt;a href="https://code.visualstudio.com/"target="_blank" rel="noopener noreferrer">VS Code Agents&lt;/a>
&lt;a class="md-heading-anchor" href="#vs-code-agents" aria-label="Link to VS Code Agents">#&lt;/a>
&lt;/h3>
&lt;p>Native agent mode inside the editor. Let the assistant plan, edit files, and run commands without leaving VS Code or babysitting a separate CLI.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">agent&lt;/span>
&lt;h3 id="codex" class="md-heading">
&lt;a href="https://github.com/openai/codex"target="_blank" rel="noopener noreferrer">Codex&lt;/a>
&lt;a class="md-heading-anchor" href="#codex" aria-label="Link to Codex">#&lt;/a>
&lt;/h3>
&lt;p>OpenAI&amp;rsquo;s open-source coding agent. Terminal-native, sandboxed by default, and you can swap the model behind it whenever.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">platform&lt;/span>
&lt;h3 id="azure-ai-foundry" class="md-heading">
&lt;a href="https://azure.microsoft.com/en-us/products/ai-foundry"target="_blank" rel="noopener noreferrer">Azure AI Foundry&lt;/a>
&lt;a class="md-heading-anchor" href="#azure-ai-foundry" aria-label="Link to Azure AI Foundry">#&lt;/a>
&lt;/h3>
&lt;p>Microsoft&amp;rsquo;s AI app stack. Build agents, point them at your data, ship them on Azure. The enterprise wrapper for everything you&amp;rsquo;d otherwise glue together yourself.&lt;/p>
&lt;/div>
&lt;/div>
&lt;h2 id="infrastructure" class="md-heading">
Infrastructure
&lt;a class="md-heading-anchor" href="#infrastructure" aria-label="Link to Infrastructure">#&lt;/a>
&lt;/h2>
&lt;div class="sw-grid">
&lt;div class="sw-card">
&lt;span class="sw-tag">orchestration&lt;/span>
&lt;h3 id="kubernetes" class="md-heading">
&lt;a href="https://kubernetes.io/"target="_blank" rel="noopener noreferrer">Kubernetes&lt;/a>
&lt;a class="md-heading-anchor" href="#kubernetes" aria-label="Link to Kubernetes">#&lt;/a>
&lt;/h3>
&lt;p>Container orchestration that makes you mass produce YAML for a living.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">orchestration&lt;/span>
&lt;h3 id="k3s" class="md-heading">
&lt;a href="https://k3s.io/"target="_blank" rel="noopener noreferrer">K3s&lt;/a>
&lt;a class="md-heading-anchor" href="#k3s" aria-label="Link to K3s">#&lt;/a>
&lt;/h3>
&lt;p>All of Kubernetes in a single binary. Perfect for homelab, edge, and production deployments.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">IaC&lt;/span>
&lt;h3 id="terraform--opentofu" class="md-heading">
&lt;a href="https://www.terraform.io/"target="_blank" rel="noopener noreferrer">Terraform&lt;/a> / &lt;a href="https://opentofu.org/"target="_blank" rel="noopener noreferrer">OpenTofu&lt;/a>
&lt;a class="md-heading-anchor" href="#terraform--opentofu" aria-label="Link to Terraform / OpenTofu">#&lt;/a>
&lt;/h3>
&lt;p>Infrastructure as code. OpenTofu if you prefer the open-source fork without the license drama.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">networking&lt;/span>
&lt;h3 id="tailscale" class="md-heading">
&lt;a href="https://tailscale.com/"target="_blank" rel="noopener noreferrer">Tailscale&lt;/a>
&lt;a class="md-heading-anchor" href="#tailscale" aria-label="Link to Tailscale">#&lt;/a>
&lt;/h3>
&lt;p>WireGuard-based mesh VPN that just works. Connect everything without opening a single port.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">observability&lt;/span>
&lt;h3 id="grafana" class="md-heading">
&lt;a href="https://grafana.com/"target="_blank" rel="noopener noreferrer">Grafana&lt;/a>
&lt;a class="md-heading-anchor" href="#grafana" aria-label="Link to Grafana">#&lt;/a>
&lt;/h3>
&lt;p>Dashboards for everything. Pairs with Prometheus, Loki, and Tempo for the whole observability stack.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">Kubernetes&lt;/span>
&lt;h3 id="k9s" class="md-heading">
&lt;a href="https://k9scli.io/"target="_blank" rel="noopener noreferrer">k9s&lt;/a>
&lt;a class="md-heading-anchor" href="#k9s" aria-label="Link to k9s">#&lt;/a>
&lt;/h3>
&lt;p>Terminal UI for Kubernetes. Makes cluster management feel like a video game. Way faster than raw &lt;code>kubectl&lt;/code>.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">Kubernetes&lt;/span>
&lt;h3 id="lens" class="md-heading">
&lt;a href="https://k8slens.dev/"target="_blank" rel="noopener noreferrer">Lens&lt;/a>
&lt;a class="md-heading-anchor" href="#lens" aria-label="Link to Lens">#&lt;/a>
&lt;/h3>
&lt;p>The Kubernetes IDE. When you want to point and click your way through a cluster without shame.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">it's complicated&lt;/span>
&lt;h3 id="cloudflare" class="md-heading">
&lt;a href="https://www.cloudflare.com/"target="_blank" rel="noopener noreferrer">Cloudflare&lt;/a>
&lt;a class="md-heading-anchor" href="#cloudflare" aria-label="Link to Cloudflare">#&lt;/a>
&lt;/h3>
&lt;p>You love them. You hate them. Your DNS is already there. Their edge network is everywhere, their pricing is unbeatable, and their product sprawl is terrifying. Stockholm syndrome as a service.&lt;/p>
&lt;/div>
&lt;/div>
&lt;h2 id="shell--terminal" class="md-heading">
Shell &amp;amp; Terminal
&lt;a class="md-heading-anchor" href="#shell--terminal" aria-label="Link to Shell &amp;amp; Terminal">#&lt;/a>
&lt;/h2>
&lt;div class="sw-grid">
&lt;div class="sw-card">
&lt;span class="sw-tag">shell&lt;/span>
&lt;h3 id="bash" class="md-heading">
&lt;a href="https://www.gnu.org/software/bash/"target="_blank" rel="noopener noreferrer">Bash&lt;/a>
&lt;a class="md-heading-anchor" href="#bash" aria-label="Link to Bash">#&lt;/a>
&lt;/h3>
&lt;p>The shell that&amp;rsquo;s been there since before you were born. Simple, portable, everywhere.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">shell&lt;/span>
&lt;h3 id="zsh" class="md-heading">
&lt;a href="https://www.zsh.org/"target="_blank" rel="noopener noreferrer">Zsh&lt;/a>
&lt;a class="md-heading-anchor" href="#zsh" aria-label="Link to Zsh">#&lt;/a>
&lt;/h3>
&lt;p>Bash&amp;rsquo;s cooler sibling. Tab completion, globbing, and plugin support that actually makes the terminal enjoyable.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">prompt&lt;/span>
&lt;h3 id="starship" class="md-heading">
&lt;a href="https://github.com/starship/starship"target="_blank" rel="noopener noreferrer">Starship&lt;/a>
&lt;a class="md-heading-anchor" href="#starship" aria-label="Link to Starship">#&lt;/a>
&lt;/h3>
&lt;p>Cross-shell prompt written in Rust. Fast, pretty, and infinitely configurable.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">multiplexer&lt;/span>
&lt;h3 id="tmux" class="md-heading">
&lt;a href="https://github.com/tmux/tmux"target="_blank" rel="noopener noreferrer">tmux&lt;/a>
&lt;a class="md-heading-anchor" href="#tmux" aria-label="Link to tmux">#&lt;/a>
&lt;/h3>
&lt;p>Terminal multiplexer. SSH into a box, detach, come back tomorrow. Your session is still there.&lt;/p>
&lt;/div>
&lt;div class="sw-card">
&lt;span class="sw-tag">coreutils&lt;/span>
&lt;h3 id="eza" class="md-heading">
&lt;a href="https://github.com/eza-community/eza"target="_blank" rel="noopener noreferrer">eza&lt;/a>
&lt;a class="md-heading-anchor" href="#eza" aria-label="Link to eza">#&lt;/a>
&lt;/h3>
&lt;p>Modern replacement for &lt;code>ls&lt;/code>. Colors, git status, and tree view out of the box. Written in Rust, obviously.&lt;/p>
&lt;/div>
&lt;/div>
&lt;h2 id="utilities--apps" class="md-heading">
Utilities / Apps
&lt;a class="md-heading-anchor" href="#utilities--apps" aria-label="Link to Utilities / Apps">#&lt;/a>
&lt;/h2>
&lt;div class="sw-grid">
&lt;div class="sw-card">
&lt;span class="sw-tag">macOS&lt;/span>
&lt;h3 id="alttab" class="md-heading">
&lt;a href="https://alt-tab-macos.netlify.app/"target="_blank" rel="noopener noreferrer">AltTab&lt;/a>
&lt;a class="md-heading-anchor" href="#alttab" aria-label="Link to AltTab">#&lt;/a>
&lt;/h3>
&lt;p>Why does macOS think a minimized window is an inactive window and not let you switch to it? This fixes that.&lt;/p>
&lt;/div>
&lt;/div></description></item><item><title>About</title><link>https://houdeshell.dev/about/</link><pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate><guid>https://houdeshell.dev/about/</guid><description>&lt;div class="about-intro">
&lt;p class="about-tagline">&lt;span class="about-tagline-slash">//&lt;/span> bit herder. pointer wrecker. yaml apologist.&lt;/p>
&lt;/div>
&lt;p>I&amp;rsquo;m a bit herder, a pointer wrecker, and HTTP is my best friend. &lt;code>0xA3&lt;/code> &amp;amp; &lt;code>0x7C&lt;/code> are also my friends, but not &lt;code>0x08&lt;/code>.&lt;/p>
&lt;p>I spend my days somewhere between writing code and making sure other people can write better code. I love distributed systems, low-level embedded devices, and anything that has a &lt;code>content-type&lt;/code>. I also have an unhealthy relationship with YAML, but that&amp;rsquo;s a Kubernetes problem.&lt;/p>
&lt;h2 id="the-day-job" class="md-heading">
The day job
&lt;a class="md-heading-anchor" href="#the-day-job" aria-label="Link to The day job">#&lt;/a>
&lt;/h2>
&lt;p>During the day, I lead engineering and operations at &lt;a href="https://www.energycap.com"target="_blank" rel="noopener noreferrer">EnergyCAP&lt;/a>, a SaaS platform that helps organizations track utility spend, energy consumption, and sustainability goals across massive building portfolios. We&amp;rsquo;re talking &lt;strong>$100B+ in utility bill spend&lt;/strong> tracked across &lt;strong>350,000+ sites&lt;/strong>. Government, education, healthcare, commercial real estate. If it has a meter, we probably manage it.&lt;/p>
&lt;p>I started here as a developer in 2009 and have been building ever since: through senior roles, into leadership, and eventually into the VP seat where I get to shape both the tech and the teams behind it. Some days that means architecture decisions. Most days it means removing blockers so smart people can do their best work. And yes, sometimes it&amp;rsquo;s just meetings about meetings.&lt;/p>
&lt;p>My philosophy is simple: &lt;strong>technology should serve people&lt;/strong>. Build teams where people feel safe to be wrong, give them the tools to be great, and get out of the way.&lt;/p>
&lt;h3 id="things-i-geek-out-about" class="md-heading">
Things I geek out about
&lt;a class="md-heading-anchor" href="#things-i-geek-out-about" aria-label="Link to Things I geek out about">#&lt;/a>
&lt;/h3>
&lt;p>Distributed systems, container orchestration, database performance tuning, developer tooling, process dumps, leadership that doesn&amp;rsquo;t suck, making engineers&amp;rsquo; lives better, and the eternal quest for a perfect terminal setup.&lt;/p>
&lt;h2 id="i-also-talk-at-things" class="md-heading">
I also talk at things
&lt;a class="md-heading-anchor" href="#i-also-talk-at-things" aria-label="Link to I also talk at things">#&lt;/a>
&lt;/h2>
&lt;p>I like getting on stage and nerding out about the things I&amp;rsquo;ve learned the hard way. My talks tend to fall into a few buckets, and yes, I have strong opinions about all of them.&lt;/p>
&lt;h3 id="ai--the-developer-experience" class="md-heading">
AI &amp;amp; the developer experience
&lt;a class="md-heading-anchor" href="#ai--the-developer-experience" aria-label="Link to AI &amp;amp; the developer experience">#&lt;/a>
&lt;/h3>
&lt;p>The AI wave hit and I leaned in. I&amp;rsquo;ve talked about using LLMs as debugging partners, building RAG pipelines that actually know your business context, and the ethical lines we should be drawing as we hand more work to machines.&lt;/p>
&lt;ul class="talk-list">
&lt;li>My Rubber Duck is a Large Language Model&lt;/li>
&lt;li>Unleashing the Power of the AI Wizards: Retrieval-Augmented Generation Spells&lt;/li>
&lt;/ul>
&lt;h3 id="kubernetes--cloud-native" class="md-heading">
Kubernetes &amp;amp; cloud native
&lt;a class="md-heading-anchor" href="#kubernetes--cloud-native" aria-label="Link to Kubernetes &amp;amp; cloud native">#&lt;/a>
&lt;/h3>
&lt;p>I was late to the Kubernetes party, and I&amp;rsquo;ll tell you all about it. From lightweight K3s workshops to navigating the 900+ services in the CNCF landscape, to making the case that cloud-native principles work even when you&amp;rsquo;re not in the cloud.&lt;/p>
&lt;ul class="talk-list">
&lt;li>Kubernetes Chronicles: Late to the Party, Big on Adventure!&lt;/li>
&lt;li>K3s: Half the Size, Twice as Awesome (workshop)&lt;/li>
&lt;li>Orchestrating Machine Learning Workloads with Kubernetes&lt;/li>
&lt;li>Exploring the Cloud Native Landscape&lt;/li>
&lt;li>Cloud Native is Only for the Cloud, Right?&lt;/li>
&lt;li>Nomad: Orchestration Doesn't Start with a K&lt;/li>
&lt;/ul>
&lt;h3 id="performance--databases" class="md-heading">
Performance &amp;amp; databases
&lt;a class="md-heading-anchor" href="#performance--databases" aria-label="Link to Performance &amp;amp; databases">#&lt;/a>
&lt;/h3>
&lt;p>I&amp;rsquo;ve spent an unreasonable amount of time staring at query plans. These talks cover squeezing performance out of SQL Server, using DMVs like cheat codes, and that one time we took a 10-hour process down to 10 minutes.&lt;/p>
&lt;ul class="talk-list">
&lt;li>ReArchitecting Data: 10 Hours to 10 Minutes&lt;/li>
&lt;li>Mastering SQL Server Performance Optimization (workshop)&lt;/li>
&lt;li>SQL Server DMVs That Give Me Superpowers&lt;/li>
&lt;li>Achieving Continuous High Performance with Query Store&lt;/li>
&lt;li>Practical High Performance: C# Edition&lt;/li>
&lt;li>Intrinsics in .NET: Start Somewhere&lt;/li>
&lt;/ul>
&lt;h3 id="production-war-stories--leadership" class="md-heading">
Production war stories &amp;amp; leadership
&lt;a class="md-heading-anchor" href="#production-war-stories--leadership" aria-label="Link to Production war stories &amp;amp; leadership">#&lt;/a>
&lt;/h3>
&lt;p>Production breaks. Systems fail. The interesting part is what you do next. I also talk about the human side: what I&amp;rsquo;ve learned (and gotten wrong) leading engineering teams.&lt;/p>
&lt;ul class="talk-list">
&lt;li>Bug Squashing with Process Dumps&lt;/li>
&lt;li>Recovery by Design: A Postmortem Adventure&lt;/li>
&lt;li>Joining the Cloud: Our Journey&lt;/li>
&lt;li>TIL as a CTO&lt;/li>
&lt;/ul>
&lt;h3 id="the-wildcard" class="md-heading">
The wildcard
&lt;a class="md-heading-anchor" href="#the-wildcard" aria-label="Link to The wildcard">#&lt;/a>
&lt;/h3>
&lt;p>Sometimes you just want to build something fun with your hands.&lt;/p>
&lt;ul class="talk-list">
&lt;li>Paper Circuits: Origami for a New Generation&lt;/li>
&lt;/ul>
&lt;h2 id="lets-talk" class="md-heading">
Let&amp;rsquo;s talk
&lt;a class="md-heading-anchor" href="#lets-talk" aria-label="Link to Let’s talk">#&lt;/a>
&lt;/h2>
&lt;p>I drink a bit too much coffee while rambling on about technology. If you&amp;rsquo;re willing to have a conversation, I&amp;rsquo;m ready to buy you a cup.&lt;/p>
&lt;dl class="contact-list">
&lt;dt>email&lt;/dt>&lt;dd>&lt;a href="mailto:chris@houdeshell.dev">chris@houdeshell.dev&lt;/a>&lt;/dd>
&lt;dt>github&lt;/dt>&lt;dd>&lt;a href="https://github.com/choudeshell">choudeshell&lt;/a>&lt;/dd>
&lt;dt>linkedin&lt;/dt>&lt;dd>&lt;a href="https://www.linkedin.com/in/choudeshell/">choudeshell&lt;/a>&lt;/dd>
&lt;dt>bluesky&lt;/dt>&lt;dd>&lt;a href="https://bsky.app/profile/choudeshell.bsky.social">@choudeshell.bsky.social&lt;/a>&lt;/dd>
&lt;/dl></description></item><item><title>Now</title><link>https://houdeshell.dev/now/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><guid>https://houdeshell.dev/now/</guid><description>&lt;h2 id="focus" class="md-heading">
Focus
&lt;a class="md-heading-anchor" href="#focus" aria-label="Link to Focus">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>AI at &lt;code>/\$DAYJOB/&lt;/code>.&lt;/strong> Production agents on real customer data. Compliance edges, evals, on-call playbooks.&lt;/li>
&lt;li>&lt;strong>Upgrading Azure infrastructure.&lt;/strong> Modernizing the stack we run customer workloads on.&lt;/li>
&lt;/ul>
&lt;h2 id="thinking" class="md-heading">
Thinking
&lt;a class="md-heading-anchor" href="#thinking" aria-label="Link to Thinking">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>AI.&lt;/strong> Where it pays off and where it just adds latency.&lt;/li>
&lt;li>&lt;strong>Team.&lt;/strong> Shape, growth, what each person&amp;rsquo;s pulling toward.&lt;/li>
&lt;li>&lt;strong>The price of the cloud.&lt;/strong> Watching cluster spend while AI workloads scale up unpredictably.&lt;/li>
&lt;/ul>
&lt;h2 id="reading" class="md-heading">
Reading
&lt;a class="md-heading-anchor" href="#reading" aria-label="Link to Reading">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>TODO — drop in current books, longreads, or RSS finds here. The shelf changes monthly.&lt;/li>
&lt;/ul></description></item><item><title>Running Ubuntu on Apple's Container</title><link>https://houdeshell.dev/post/2026-06-12_ubuntu-on-apple-container/</link><pubDate>Fri, 12 Jun 2026 14:00:00 -0400</pubDate><guid>https://houdeshell.dev/post/2026-06-12_ubuntu-on-apple-container/</guid><description>&lt;p>After &lt;a href="https://houdeshell.dev/post/2026-06-12_macos-container-tool/">getting Apple&amp;rsquo;s &lt;code>container&lt;/code> running&lt;/a>, the thing I actually wanted was a normal Ubuntu box to poke around in. That took one more step than I expected: systemd.&lt;/p>
&lt;p>A container runs whatever its &lt;code>CMD&lt;/code> is as PID 1. The stock &lt;code>ubuntu:26.04&lt;/code> image doesn&amp;rsquo;t ship an init, so you boot into a bare shell and not much else. If you want services, units, and a machine that behaves like a real Ubuntu install, systemd has to be the thing running as init. So you build your own image.&lt;/p>
&lt;p>Here&amp;rsquo;s the Dockerfile. Most of it is the well-worn systemd-in-a-container cleanup: install systemd, then delete the units that make no sense inside a container so it doesn&amp;rsquo;t sit there trying to start hardware that isn&amp;rsquo;t there.&lt;/p>
&lt;div class="code-block" data-lang="dockerfile">&lt;span class="code-lang" aria-hidden="true">dockerfile&lt;/span>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> ubuntu:26.04&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> container container&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apt update -y &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt upgrade -y &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt install -y systemd init&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="nb">cd&lt;/span> /lib/systemd/system/sysinit.target.wants/&lt;span class="p">;&lt;/span> &lt;span class="k">for&lt;/span> i in *&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="nv">$i&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>systemd-tmpfiles-setup.service &lt;span class="o">]&lt;/span> &lt;span class="o">||&lt;/span> rm -f &lt;span class="nv">$i&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">done&lt;/span>&lt;span class="o">)&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>rm -f /lib/systemd/system/multi-user.target.wants/*&lt;span class="p">;&lt;/span>&lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>rm -f /etc/systemd/system/*.wants/*&lt;span class="p">;&lt;/span>&lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>rm -f /lib/systemd/system/local-fs.target.wants/*&lt;span class="p">;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>rm -f /lib/systemd/system/sockets.target.wants/*udev*&lt;span class="p">;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>rm -f /lib/systemd/system/sockets.target.wants/*initctl*&lt;span class="p">;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>rm -f /lib/systemd/system/basic.target.wants/*&lt;span class="p">;&lt;/span>&lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>rm -f /lib/systemd/system/anaconda.target.wants/*&lt;span class="p">;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">VOLUME&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="s2">&amp;#34;/sys/fs/cgroup&amp;#34;&lt;/span> &lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">CMD&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;/usr/sbin/init&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>
&lt;p>Build it, create a machine from it, and run:&lt;/p>
&lt;div class="terminal">&lt;div class="terminal-bar" aria-hidden="true">&lt;span class="terminal-dot dot-red">&lt;/span>&lt;span class="terminal-dot dot-yellow">&lt;/span>&lt;span class="terminal-dot dot-green">&lt;/span>&lt;span class="terminal-title">zsh&lt;/span>&lt;/div>&lt;pre class="terminal-body">&lt;code>&lt;span class="t-prompt">❯&lt;/span> &lt;span class="t-bin">container&lt;/span> &lt;span class="t-cmd">build -t local/devel -f devel.dockerfile&lt;/span>
&lt;span class="t-out">[+] Building 356.1s (7/7) FINISHED&lt;/span>
&lt;span class="t-out"> =&amp;gt; [resolver] fetching image docker.io/library/ubuntu:26.04&lt;/span>
&lt;span class="t-out"> =&amp;gt; [internal] load build definition from Dockerfile&lt;/span>
&lt;span class="t-out"> =&amp;gt; [linux/arm64 1/3] RUN apt update -y &amp;amp;&amp;amp; apt upgrade -y &amp;amp;&amp;amp; apt install -y systemd init&lt;/span>
&lt;span class="t-out"> =&amp;gt; [linux/arm64 2/3] RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do ... )&lt;/span>
&lt;span class="t-out"> =&amp;gt; exporting to oci image format&lt;/span>
&lt;span class="t-out">local/devel:latest&lt;/span>
&lt;span class="t-out">&lt;/span>
&lt;span class="t-prompt">❯&lt;/span> &lt;span class="t-bin">container&lt;/span> &lt;span class="t-cmd">machine create --name devel --set-default local/devel&lt;/span>
&lt;span class="t-out">devel&lt;/span>
&lt;span class="t-out">&lt;/span>
&lt;span class="t-prompt">❯&lt;/span> &lt;span class="t-bin">container&lt;/span> &lt;span class="t-cmd">machine run&lt;/span>
&lt;span class="t-out">chris.houdeshell@devel:/Users/chris.houdeshell$&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;p>That last line is the Ubuntu shell. You&amp;rsquo;re in.&lt;/p>
&lt;p>What the flags are doing, quickly:&lt;/p>
&lt;ul>
&lt;li>&lt;code>container build -t local/devel -f devel.dockerfile&lt;/code>: &lt;code>-t&lt;/code> tags the image as &lt;code>local/devel&lt;/code>; &lt;code>-f&lt;/code> points at the Dockerfile by name, since I didn&amp;rsquo;t name it &lt;code>Dockerfile&lt;/code>.&lt;/li>
&lt;li>&lt;code>container machine create --name devel --set-default local/devel&lt;/code>: builds a VM named &lt;code>devel&lt;/code> from that image. &lt;code>--set-default&lt;/code> makes it the machine everything else targets, so I don&amp;rsquo;t have to spell out the name on every command.&lt;/li>
&lt;li>&lt;code>container machine run&lt;/code>: boots the default machine and drops me into its shell.&lt;/li>
&lt;/ul>
&lt;p>One thing worth knowing: that build ran just shy of six minutes. The tool is young and the build path isn&amp;rsquo;t quick yet, so don&amp;rsquo;t assume it hung.&lt;/p></description></item><item><title>Apple's Container Tool</title><link>https://houdeshell.dev/post/2026-06-12_macos-container-tool/</link><pubDate>Fri, 12 Jun 2026 10:00:00 -0400</pubDate><guid>https://houdeshell.dev/post/2026-06-12_macos-container-tool/</guid><description>&lt;p>Apple has a CLI for running Linux containers on macOS now. It&amp;rsquo;s called &lt;a href="https://github.com/apple/container"target="_blank" rel="noopener noreferrer">&lt;code>container&lt;/code>&lt;/a>, and the part I care about is that it doesn&amp;rsquo;t need Docker Desktop.&lt;/p>
&lt;p>The design choice that makes it interesting: there&amp;rsquo;s no single shared Linux VM that every container piles into. Each container gets its own lightweight VM. So you get real isolation for free, boots are quick, and it all sits on top of Apple&amp;rsquo;s Containerization Swift package. Images are plain OCI, so the registries and the &lt;code>pull&lt;/code>/&lt;code>build&lt;/code>/&lt;code>push&lt;/code> workflow you already know carry over. The requirements are stricter than I&amp;rsquo;d like, though: Apple silicon, macOS 26 or newer.&lt;/p>
&lt;p>You install it from a signed package on the &lt;a href="https://github.com/apple/container/releases"target="_blank" rel="noopener noreferrer">releases page&lt;/a>, then start the background service. The service is where I tripped.&lt;/p>
&lt;p>Run anything before it&amp;rsquo;s up and you get this:&lt;/p>
&lt;div class="terminal">&lt;div class="terminal-bar" aria-hidden="true">&lt;span class="terminal-dot dot-red">&lt;/span>&lt;span class="terminal-dot dot-yellow">&lt;/span>&lt;span class="terminal-dot dot-green">&lt;/span>&lt;span class="terminal-title">zsh&lt;/span>&lt;/div>&lt;pre class="terminal-body">&lt;code>&lt;span class="t-prompt">❯&lt;/span> &lt;span class="t-bin">container&lt;/span> &lt;span class="t-cmd">machine create --name dev --set-default fedora:latest&lt;/span>
&lt;span class="t-err">Error: interrupted: &amp;#34;XPC connection error: Connection invalid&amp;#34;&lt;/span>
&lt;span class="t-out">Ensure container system service has been started with `container system start`.&lt;/span>
&lt;span class="t-out">&lt;/span>
&lt;span class="t-prompt">❯&lt;/span> &lt;span class="t-bin">container&lt;/span> &lt;span class="t-cmd">system start&lt;/span>
&lt;span class="t-out">Launching container-apiserver...&lt;/span>
&lt;span class="t-out">Testing access to container-apiserver...&lt;/span>
&lt;span class="t-out">Verifying machine API server is running...&lt;/span>
&lt;span class="t-out">No default kernel configured.&lt;/span>
&lt;span class="t-out">Install the recommended default kernel from [https://github.com/kata-containers/kata-containers/releases/download/3.28.0/kata-static-3.28.0-arm64.tar.zst]? [Y/n]: y&lt;/span>
&lt;span class="t-out">Installing kernel...&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;p>&lt;strong>&lt;code>XPC connection error: Connection invalid&lt;/code> is not a bug.&lt;/strong> The system service just isn&amp;rsquo;t running. Start it with &lt;code>container system start&lt;/code>, say yes to the default kernel, and you&amp;rsquo;re good.&lt;/p>
&lt;p>Docker Desktop on a Mac has always felt like more machinery than I needed. This is lighter. Give it a spin.&lt;/p></description></item><item><title>A Single Border and a Better Radius</title><link>https://houdeshell.dev/post/2026-06-10_a-single-border-and-a-better-radius/</link><pubDate>Wed, 10 Jun 2026 10:00:00 -0400</pubDate><guid>https://houdeshell.dev/post/2026-06-10_a-single-border-and-a-better-radius/</guid><description>&lt;p>I read the release notes. I just opened a Finder window and it &lt;em>feels&lt;/em> better, and it took me a second to figure out why.&lt;/p>
&lt;p>&lt;img loading="lazy" src="finder-macos27.png"
alt="Finder in macOS 27 with a single vertical border between the sidebar and content, and softened window corners"/>&lt;/p>
&lt;p>It&amp;rsquo;s two things. There&amp;rsquo;s now a single vertical border between the sidebar and the content pane, so the two regions actually feel like two regions instead of one dark expanse where the divider was only implied by a shift in shade. And the inner corners got a slightly larger, more consistent radius that lines up with the outer window. That&amp;rsquo;s it. No new feature, nothing to learn.&lt;/p>
&lt;p>&lt;strong>The smallest possible line in the right place does more than any amount of gradient or shadow.&lt;/strong> One border to say &amp;ldquo;this is a boundary,&amp;rdquo; one radius to make the corners agree with each other, and the window stops feeling vague.&lt;/p>
&lt;p>Good detail work is invisible until you go back to the old version and feel how much you weren&amp;rsquo;t seeing.&lt;/p></description></item><item><title>You're the Typist</title><link>https://houdeshell.dev/post/2026-05-27_youre-the-typist/</link><pubDate>Wed, 27 May 2026 10:00:00 -0400</pubDate><guid>https://houdeshell.dev/post/2026-05-27_youre-the-typist/</guid><description>&lt;p>There&amp;rsquo;s a question I ask engineers when they hand me an AI generated PR: &amp;ldquo;walk me through what this does.&amp;rdquo;&lt;/p>
&lt;p>If they can, the PR is usually fine. If they can&amp;rsquo;t, the PR is almost always broken. Not visibly broken. Not the kind of broken that fails a test. The kind of broken that ships, sits in production for six months, and then takes down a service at 2am because nobody knew the cache invalidation only ran on the leader.&lt;/p>
&lt;p>AI doesn&amp;rsquo;t fix that. AI makes it worse.&lt;/p>
&lt;p>&lt;strong>AI is a multiplier.&lt;/strong> It multiplies whatever you bring to it. If you understand the problem, AI gets you to a working solution faster than any tool we&amp;rsquo;ve ever had. If you don&amp;rsquo;t, it gets you to something that &lt;em>looks&lt;/em> like a working solution faster than any tool we&amp;rsquo;ve ever had. Those are very different things, and the difference doesn&amp;rsquo;t show up until later.&lt;/p>
&lt;p>The engineers I see thriving with AI right now read every line. They push back when the model takes a shortcut they don&amp;rsquo;t like. They ask &amp;ldquo;why&amp;rdquo; three times. They notice when the generated code uses a pattern they&amp;rsquo;ve never seen, and they stop to learn it before they accept it. AI doubles their throughput because they were already good. It also doubles their learning rate, because every prompt is a chance to see how an experienced engineer (which is what the model is impersonating) would have approached the same problem.&lt;/p>
&lt;p>The engineers I see drowning treat the model like an oracle. They accept the diff. They run the tests. The tests pass, so they ship. They have no mental model of what they just merged. Six months in, they&amp;rsquo;ve shipped a hundred PRs and learned nothing. The codebase has grown faster than their understanding of it, and the gap is widening.&lt;/p>
&lt;p>Here&amp;rsquo;s the test I&amp;rsquo;d give anyone using AI heavily. Pick a PR from last week. Open it without the model. Explain every block out loud. Why this data structure? Why this error path? What happens if this call times out? What does this loop do on the empty case? If you can&amp;rsquo;t answer those questions about your own merged code, AI isn&amp;rsquo;t helping &lt;em>you&lt;/em>. It&amp;rsquo;s helping the model, and you&amp;rsquo;re the typist.&lt;/p>
&lt;p>This isn&amp;rsquo;t just an engineering problem. Engineering managers and product managers fall into the same trap, one rung up. If you used AI to write a JIRA ticket and you can&amp;rsquo;t explain it five minutes later, your problem is different than you think. The ticket isn&amp;rsquo;t the artifact. The thinking behind the ticket is. If the model did the thinking and you hit save, you&amp;rsquo;ve handed your team a task that nobody on your side actually owns. The first time an engineer pushes back with a real question, the whole thing falls apart, and the engineer figures out fast that there&amp;rsquo;s no one home behind the requirements.&lt;/p>
&lt;p>&lt;strong>Use AI. Lean into it. Just don&amp;rsquo;t outsource the part of the job that was ever actually yours.&lt;/strong>&lt;/p></description></item><item><title>KQL Reads Like a Sentence</title><link>https://houdeshell.dev/post/2026-05-23_kql-reads-like-a-sentence/</link><pubDate>Sat, 23 May 2026 10:00:00 -0400</pubDate><guid>https://houdeshell.dev/post/2026-05-23_kql-reads-like-a-sentence/</guid><description>&lt;p>Watch a smart, curious person try to learn SQL. They get through &lt;code>SELECT * FROM x WHERE y&lt;/code> and they&amp;rsquo;re fine. Then they hit &lt;code>JOIN&lt;/code>, or &lt;code>GROUP BY&lt;/code>, or a correlated subquery, and the floor opens up. Most never come back.&lt;/p>
&lt;p>KQL is the opposite. It reads left to right, the way the human brain wants to think about data.&lt;/p>
&lt;div class="code-block" data-lang="kusto">&lt;span class="code-lang" aria-hidden="true">kusto&lt;/span>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">PageViews
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| where TimeGenerated &amp;gt; ago(7d)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| where ClientCountryOrRegion == &amp;#34;United States&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| summarize count() by bin(TimeGenerated, 1d), Page
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| top 10 by count_&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>
&lt;p>Read it out loud. &amp;ldquo;Take page views, where time is in the last seven days, where the country is the US, summarize by day and page, give me the top ten.&amp;rdquo; That sentence is the query. Nothing is hidden, nothing is out of order.&lt;/p>
&lt;p>The verbs are English. &lt;code>where&lt;/code>. &lt;code>summarize&lt;/code>. &lt;code>project&lt;/code>. &lt;code>extend&lt;/code>. &lt;code>take&lt;/code>. &lt;code>top&lt;/code>. There&amp;rsquo;s no &lt;code>CROSS APPLY&lt;/code> lurking three chapters in.&lt;/p>
&lt;p>&lt;strong>You can do useful work on day one without ever learning a join.&lt;/strong> That matters more than engineers remember. Every join is a cliff for a non-engineer, and SQL puts that cliff in front of trivial questions. KQL puts the cliff somewhere on chapter five.&lt;/p>
&lt;p>Add to that:&lt;/p>
&lt;ul>
&lt;li>Sane defaults — &lt;code>take 100&lt;/code> to peek, results are always tabular&lt;/li>
&lt;li>Time-series operators baked in — &lt;code>ago&lt;/code>, &lt;code>bin&lt;/code>, &lt;code>series_decompose&lt;/code>&lt;/li>
&lt;li>Autocomplete that actually understands your schema&lt;/li>
&lt;li>A query pane that gives you instant feedback the moment you stop typing&lt;/li>
&lt;/ul>
&lt;p>KQL isn&amp;rsquo;t the right tool for everything. I&amp;rsquo;d never reach for it to build a transactional system. But for letting smart, curious people answer their own questions about their own data, I haven&amp;rsquo;t seen anything better.&lt;/p>
&lt;p>&lt;em>Take all that with a grain of salt — I wrote a KQL-to-SQL parser and generator, so I&amp;rsquo;m clearly not sure what any of this means.&lt;/em>&lt;/p></description></item><item><title>Inverse AI Consulting</title><link>https://houdeshell.dev/post/2026-05-15_inverse-ai-consulting/</link><pubDate>Fri, 15 May 2026 15:00:00 -0400</pubDate><guid>https://houdeshell.dev/post/2026-05-15_inverse-ai-consulting/</guid><description>&lt;p>&lt;a href="https://x.com/mitchellh/status/2055380239711457578"target="_blank" rel="noopener noreferrer">Mitchell Hashimoto wrote a post on X&lt;/a> that I haven&amp;rsquo;t stopped thinking about.&lt;/p>
&lt;blockquote>
&lt;p>It&amp;rsquo;s frightening, because the psychosis folks operate under an almost absolute &amp;ldquo;MTTR is all you need&amp;rdquo; mentality: &amp;ldquo;its fine to ship bugs because the agents will fix them so quickly and at a scale humans can&amp;rsquo;t do!&amp;rdquo; We learned in infrastructure that MTTR is great but you can&amp;rsquo;t yeet resilient systems entirely.&lt;/p>&lt;/blockquote>
&lt;p>I love AI. I lean into it harder than most people I work with and know. Engineering is genuinely better because of AI. Daily and categorically.&lt;/p>
&lt;p>Purely AI written systems will scale to a point of complexity no human can ever understand. For a while it looks fine. Defects close, bug reports trend down, dashboards stay green. Then the defect close rate tapers. Token burn per defect climbs. Eventually, AI changes cause on average more defects than they close, and the whole system becomes unstable. &lt;strong>The decay.&lt;/strong>&lt;/p>
&lt;p>AI amplifies good thinking. AI amplifies good engineering. AI also amplifies bad thinking and bad engineering.&lt;/p>
&lt;p>When that happens, I expect a new type of consulting to emerge. Call it &lt;strong>Inverse AI&lt;/strong>. An involution. The same specialists who get called for an active breach, or when production data is gone and the backups failed. People who walk into a doomed AI generated codebase, distill out the core design principles nobody bothered to write down, and rebuild from scratch with good thinking and good engineering &amp;ndash; using AI.&lt;/p>
&lt;p>This time with with humans in the seat where it counts.&lt;/p>
&lt;p>The decay isn&amp;rsquo;t a reason to be against AI. It&amp;rsquo;s a reason to be honest about what comes next.&lt;/p></description></item><item><title>How I Run 1:1s</title><link>https://houdeshell.dev/post/2026-05-02_how-i-run-1on1s/</link><pubDate>Tue, 05 May 2026 09:00:00 -0400</pubDate><guid>https://houdeshell.dev/post/2026-05-02_how-i-run-1on1s/</guid><description>&lt;p>I&amp;rsquo;ve been running 1:1s for years and I still get them wrong. The version of &amp;ldquo;wrong&amp;rdquo; has changed. Early on, my 1:1s were status meetings with the lights off. Manager asks what you&amp;rsquo;re working on. Engineer recites their pile. Manager says &amp;ldquo;anything blocking you?&amp;rdquo;. Engineer says no, even when they mean yes. Forty-five minutes evaporate.&lt;/p>
&lt;p>That isn&amp;rsquo;t a 1:1. It&amp;rsquo;s a standup with a longer time slot.&lt;/p>
&lt;p>I figured out it was wrong because of one engineer. Smart, quiet, on a team I&amp;rsquo;d inherited. We&amp;rsquo;d had eight or nine &amp;ldquo;great&amp;rdquo; 1:1s in a row. He left to go work somewhere else and on his way out told me, in different words, that he didn&amp;rsquo;t think I knew anything about him. He was right. I knew what he was working on, what his blockers were, what he&amp;rsquo;d shipped that quarter. I didn&amp;rsquo;t know what he wanted out of his career, what he was sick of, what his last manager had broken in him that I was busy perpetuating. Everything I knew about him was project-shaped.&lt;/p>
&lt;p>That cost me an engineer, and it cost me about three months of figuring out how to run these meetings differently.&lt;/p>
&lt;h2 id="the-frame" class="md-heading">
The frame
&lt;a class="md-heading-anchor" href="#the-frame" aria-label="Link to The frame">#&lt;/a>
&lt;/h2>
&lt;p>This is your meeting. You set the agenda. If you want to talk through a tricky design problem, talk it through. If you want to vent about a teammate, vent. If you want to plan the next two years of your career, plan. If you want to talk about your kid&amp;rsquo;s soccer team, fine. I have a notes doc I never make you open.&lt;/p>
&lt;p>I do bring things. Three or four every week. Coaching I want to give, feedback I owe, context you&amp;rsquo;d want, a decision I want your read on. Mine goes after yours. If we run out of time and I never got to my list, that&amp;rsquo;s okay. My list keeps. Yours might not.&lt;/p>
&lt;h2 id="one-question-that-does-most-of-the-work" class="md-heading">
One question that does most of the work
&lt;a class="md-heading-anchor" href="#one-question-that-does-most-of-the-work" aria-label="Link to One question that does most of the work">#&lt;/a>
&lt;/h2>
&lt;p>I used to have a list. Three questions, same every week, the kind of thing that lands in a leadership newsletter. They worked, mostly. They also made me predictable, which made the answers predictable.&lt;/p>
&lt;p>Now I mostly ask one thing and let it breathe:&lt;/p>
&lt;p>&lt;strong>&amp;ldquo;What&amp;rsquo;s draining you right now?&amp;rdquo;&lt;/strong>&lt;/p>
&lt;p>The honest answer is rarely the project. It&amp;rsquo;s a person, a process, or something they don&amp;rsquo;t want to admit they&amp;rsquo;re avoiding. Half the time the first answer is &amp;ldquo;nothing, I&amp;rsquo;m good,&amp;rdquo; and then five minutes later something real comes out because the question planted a seed. Naming the drain doesn&amp;rsquo;t fix it. It just lets us start.&lt;/p>
&lt;p>If they bring me energy instead, fine. I roll with it. The point of the question is to give them permission to say something they probably haven&amp;rsquo;t said out loud yet.&lt;/p>
&lt;h2 id="what-i-stopped-doing" class="md-heading">
What I stopped doing
&lt;a class="md-heading-anchor" href="#what-i-stopped-doing" aria-label="Link to What I stopped doing">#&lt;/a>
&lt;/h2>
&lt;p>I&amp;rsquo;d love to write you a clean bullet list of antipatterns. The truth is messier, and most of them are mistakes I made before I learned to stop.&lt;/p>
&lt;p>I used to ask for a status update at the top of every 1:1. I told myself I was &amp;ldquo;checking in.&amp;rdquo; I was filling silence. Now if I&amp;rsquo;m asking what they shipped, it&amp;rsquo;s because I genuinely don&amp;rsquo;t know, which means I&amp;rsquo;m not paying attention to the team. JIRA exists. Standups exist. The 1:1 isn&amp;rsquo;t where that goes.&lt;/p>
&lt;p>I used to ambush. The &amp;ldquo;by the way, we&amp;rsquo;re concerned about your output&amp;rdquo; drop, slipped into a 1:1 because I didn&amp;rsquo;t have the spine to schedule it as its own meeting. Every time I did it, I blew up trust for a quarter. Performance feedback gets its own slot, its own framing, its own heads-up. Not a sneak attack between &amp;ldquo;how was your weekend&amp;rdquo; and &amp;ldquo;what&amp;rsquo;s on your mind?&amp;rdquo;.&lt;/p>
&lt;p>I used to solve for them. They&amp;rsquo;d bring me a problem and I&amp;rsquo;d hand them the answer thirty seconds later because it felt helpful and made me feel useful. It made them dependent. &amp;ldquo;What would you do?&amp;rdquo; is the better question, even when I already know what I&amp;rsquo;d do. Especially then.&lt;/p>
&lt;h2 id="cadence" class="md-heading">
Cadence
&lt;a class="md-heading-anchor" href="#cadence" aria-label="Link to Cadence">#&lt;/a>
&lt;/h2>
&lt;p>Weekly, 30 minutes, on the calendar. Not &amp;ldquo;ad-hoc when we both have time.&amp;rdquo; Ad-hoc never happens. Ad-hoc is what people say when they don&amp;rsquo;t actually want the meeting.&lt;/p>
&lt;p>I cancel mine more than I&amp;rsquo;d like. Sprint demo collides, customer call drops in, an outage at 2am. I always reschedule. I never delete. The person sees that a 1:1 with me is a slot that survives the rest of the calendar. That matters more than they&amp;rsquo;ll ever tell me.&lt;/p>
&lt;p>Skip one, fine. Skip two in a row, that&amp;rsquo;s a signal you&amp;rsquo;re sending whether you mean to or not. Skip three and you&amp;rsquo;ve made the problem for yourself.&lt;/p>
&lt;h2 id="the-unsexy-part" class="md-heading">
The unsexy part
&lt;a class="md-heading-anchor" href="#the-unsexy-part" aria-label="Link to The unsexy part">#&lt;/a>
&lt;/h2>
&lt;p>Nobody puts this on a leadership thread because it doesn&amp;rsquo;t tweet well. The actual work of 1:1s is being there, in this meeting, every week, for years. Not the clever question. Not the great coaching moment that lives rent-free in their head five years later, though those happen and you&amp;rsquo;ll remember them. The week-after-week of showing up, paying attention, and remembering the things they told you last month so you can ask about them this month.&lt;/p>
&lt;p>Most of it is just that. Show up. Pay attention. Remember.&lt;/p>
&lt;p>The engineer who left taught me one more thing on his way out, without meaning to. He&amp;rsquo;d told me about his daughter&amp;rsquo;s blights in passing about six weeks earlier, and I never asked about it again. Not because I didn&amp;rsquo;t care. Because I forgot, and he noticed.&lt;/p>
&lt;p>I write things down now.&lt;/p></description></item></channel></rss>