<?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: SangheeSon</title>
    <description>The latest articles on DEV Community by SangheeSon (@higangssh).</description>
    <link>https://dev.to/higangssh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3797790%2Fc91a91fc-1512-418c-ab40-25d0b9078ab4.jpeg</url>
      <title>DEV Community: SangheeSon</title>
      <link>https://dev.to/higangssh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/higangssh"/>
    <language>en</language>
    <item>
      <title>I still don't want to give Claude SSH access, so I built a doctor for my homelab</title>
      <dc:creator>SangheeSon</dc:creator>
      <pubDate>Mon, 18 May 2026 01:32:36 +0000</pubDate>
      <link>https://dev.to/higangssh/i-still-dont-want-to-give-claude-ssh-access-so-i-built-a-doctor-for-my-homelab-2me6</link>
      <guid>https://dev.to/higangssh/i-still-dont-want-to-give-claude-ssh-access-so-i-built-a-doctor-for-my-homelab-2me6</guid>
      <description>&lt;p&gt;A few weeks ago I wrote about why I don't want to give Claude SSH access to my home server.&lt;/p&gt;

&lt;p&gt;It's not that AI agents are useless. It's the opposite. They got good enough that handing one a shell started to feel reckless.&lt;/p&gt;

&lt;p&gt;A shell isn't really an interface. It's a weapon with tab completion. It can read anything, delete anything, restart anything, and confidently run the wrong command on the wrong machine at 2am.&lt;/p&gt;

&lt;p&gt;So I've been building HomeButler in the other direction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Not "AI runs my server."&lt;br&gt;
"AI asks my server safe, structured questions."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The thing dashboards don't do
&lt;/h2&gt;

&lt;p&gt;The first version of HomeButler was mostly about visibility:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler status
homebutler docker list
homebutler ports
homebutler report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It worked. But after running it on my own homelab for a while, I noticed something.&lt;/p&gt;

&lt;p&gt;Raw status isn't enough.&lt;/p&gt;

&lt;p&gt;Most of the time I don't actually want to see every metric. I want to know four things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is something wrong?&lt;/li&gt;
&lt;li&gt;Is it urgent?&lt;/li&gt;
&lt;li&gt;What changed?&lt;/li&gt;
&lt;li&gt;What should I check next?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dashboards don't really answer those. They show you CPU, memory, disk, containers, ports, uptime, graphs, colors, tables — and then quietly hand the interpretation back to you.&lt;/p&gt;

&lt;p&gt;That's fine when I'm sitting at my desk. It's much less useful when I'm checking my phone half-awake, wondering if something is quietly on fire.&lt;/p&gt;

&lt;p&gt;For a small homelab I don't need a mini NOC. I need a calm answer.&lt;/p&gt;

&lt;p&gt;So I added a new command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler doctor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🩺 HomeButler Doctor — mac-mini

✅ CPU looks normal
✅ Memory looks normal
⚠️ Disk usage is high: 91%
⚠️ 1 container is stopped
⚠️ Public listener found on 0.0.0.0:8080
⚠️ Latest backup is older than 7 days

Suggested next steps:
→ homebutler docker list
→ homebutler ports
→ homebutler backup list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not "here is everything." More like "here is what deserves your attention."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more once an AI is in the loop
&lt;/h2&gt;

&lt;p&gt;This shape becomes a lot more interesting when an agent is involved.&lt;/p&gt;

&lt;p&gt;Imagine giving an agent SSH and asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Is my server okay?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now the agent has to decide what to run. Probably something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt;
free &lt;span class="nt"&gt;-m&lt;/span&gt;
docker ps
docker logs ...
ss &lt;span class="nt"&gt;-tulpn&lt;/span&gt;
systemctl status ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That can work. But the agent is now exploring my box through a general-purpose shell. It can run too much, see too much, or run the right command on the wrong host. The blast radius is "whatever the shell can do," which is everything.&lt;/p&gt;

&lt;p&gt;With HomeButler, the agent gets a much smaller surface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler doctor &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Structured output. Read-only. Bounded scope.&lt;/p&gt;

&lt;p&gt;The agent doesn't need to be the operator. It can be the interpreter. That distinction is the whole point of the project for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  What doctor actually checks
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;homebutler doctor&lt;/code&gt; is intentionally boring. That's the feature.&lt;/p&gt;

&lt;p&gt;It checks the kinds of things I usually only notice once they've already become a problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;high CPU, memory, or disk usage&lt;/li&gt;
&lt;li&gt;stopped containers&lt;/li&gt;
&lt;li&gt;public bind ports&lt;/li&gt;
&lt;li&gt;missing or stale backups&lt;/li&gt;
&lt;li&gt;notification readiness&lt;/li&gt;
&lt;li&gt;whether &lt;code&gt;report&lt;/code&gt; has a baseline for change detection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's a strict mode for cron and CI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler doctor &lt;span class="nt"&gt;--strict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And because everything is machine-readable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler doctor &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An agent can consume the result directly. No scraping terminal output, no parsing colored text, no guessing what &lt;code&gt;df -h&lt;/code&gt; formatted on a particular distro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Report vs Doctor
&lt;/h2&gt;

&lt;p&gt;After using both for a while, I've started thinking about HomeButler as having two distinct kinds of answers.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;report&lt;/code&gt; answers: &lt;strong&gt;"What changed since last time?"&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It saves snapshots, compares the current state with the previous one, and summarizes notable changes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;doctor&lt;/code&gt; answers: &lt;strong&gt;"What looks risky right now?"&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler doctor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One looks backward. One looks at the current risk. Together they're much more useful than raw metrics, and honestly more useful than most of the dashboards I've run.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern I keep coming back to
&lt;/h2&gt;

&lt;p&gt;The longer I work on this, the more I think the framing matters more than the features:&lt;/p&gt;

&lt;p&gt;AI agents don't need more power by default. They need better tools.&lt;/p&gt;

&lt;p&gt;A shell gives an agent maximum power and maximum ambiguity. A narrow tool gives it less power but more meaning. For homelab ops, that tradeoff feels right to me. I don't want an agent freely roaming my server. I want it to ask specific, bounded questions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler doctor &lt;span class="nt"&gt;--json&lt;/span&gt;
homebutler report &lt;span class="nt"&gt;--json&lt;/span&gt;
homebutler inventory scan &lt;span class="nt"&gt;--json&lt;/span&gt;
homebutler backup drill uptime-kuma &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then explain the result in plain language.&lt;/p&gt;

&lt;p&gt;That's a very different security model from "here is SSH, good luck."&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;HomeButler is a single Go binary. No daemon, no database, no always-on service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap Higangssh/homebutler
brew &lt;span class="nb"&gt;install &lt;/span&gt;homebutler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/Higangssh/homebutler/main/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler init
homebutler doctor
homebutler report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;a href="https://github.com/Higangssh/homebutler" rel="noopener noreferrer"&gt;https://github.com/Higangssh/homebutler&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I'm still building this around one idea: the future of AI-assisted ops shouldn't be "give the agent a shell." It should be "give the agent a tool that says what it means."&lt;/p&gt;

&lt;p&gt;Genuine question for anyone running a homelab: what's the last thing your setup broke without warning? I'm collecting ideas for what &lt;code&gt;doctor&lt;/code&gt; should check next.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>go</category>
      <category>selfhosted</category>
    </item>
    <item>
      <title>Every developer deserves end credits</title>
      <dc:creator>SangheeSon</dc:creator>
      <pubDate>Sun, 03 May 2026 04:30:46 +0000</pubDate>
      <link>https://dev.to/higangssh/every-developer-deserves-end-credits-oh6</link>
      <guid>https://dev.to/higangssh/every-developer-deserves-end-credits-oh6</guid>
      <description>&lt;p&gt;When a movie ends, everyone gets credit. The grip. The caterer. The second assistant editor who probably saved the entire third act in post.&lt;/p&gt;

&lt;p&gt;When we ship software? &lt;code&gt;git log&lt;/code&gt; and a Slack thank-you that scrolls into the void by Monday.&lt;/p&gt;

&lt;p&gt;I wanted to fix that. So I built &lt;strong&gt;gitcredits&lt;/strong&gt; — a CLI that takes your git history and rolls it like end credits.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Higangssh" rel="noopener noreferrer"&gt;
        Higangssh
      &lt;/a&gt; / &lt;a href="https://github.com/Higangssh/gitcredits" rel="noopener noreferrer"&gt;
        gitcredits
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Git log doesn't do them justice. Turn your contributors into movie stars.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;gitcredits&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Git log&lt;/code&gt; doesn't do them justice. Turn your contributors into movie stars.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/Higangssh/gitcredits/assets/demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHigangssh%2Fgitcredits%2FHEAD%2Fassets%2Fdemo.gif" alt="gitcredits demo" width="720"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Quick install (recommended)&lt;/h3&gt;
&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;curl -sL https://raw.githubusercontent.com/Higangssh/gitcredits/main/install.sh &lt;span class="pl-k"&gt;|&lt;/span&gt; sh&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Supports macOS (Intel/Apple Silicon), Linux (x86_64/ARM64), and Windows (x86_64 via Git Bash).&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Pre-built binaries&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Download the latest release for your platform from &lt;a href="https://github.com/Higangssh/gitcredits/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Go&lt;/h3&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;go install github.com/Higangssh/gitcredits@latest&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;From source&lt;/h3&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/Higangssh/gitcredits.git
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; gitcredits
go build -o gitcredits &lt;span class="pl-c1"&gt;.&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c1"&gt;cd&lt;/span&gt; your-repo
gitcredits

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or target another repository directly&lt;/span&gt;
gitcredits /path/to/your-repo&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;That's it. Run &lt;code&gt;gitcredits&lt;/code&gt; inside a Git repository, or pass a target repository path directly.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Themes&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Matrix&lt;/strong&gt; — digital rain with text resolve effect:&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;gitcredits --theme matrix&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/Higangssh/gitcredits/assets/matrix-demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHigangssh%2Fgitcredits%2FHEAD%2Fassets%2Fmatrix-demo.gif" alt="gitcredits matrix theme" width="720"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spider-Man&lt;/strong&gt; — glitch effects with radial web transitions:&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;gitcredits --theme spiderman&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/Higangssh/gitcredits/assets/spiderman-demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHigangssh%2Fgitcredits%2FHEAD%2Fassets%2Fspiderman-demo.gif" alt="gitcredits spider-man theme" width="720"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Export to GIF&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Save the credits as a high-quality GIF — perfect for READMEs, presentations, or sharing.&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;gitcredits --output credits.gif
gitcredits --output credits.gif --theme matrix
gitcredits --output credits.gif --theme spiderman
gitcredits /path/to/your-repo --output credits.gif&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Requires &lt;a href="https://github.com/charmbracelet/vhs" rel="noopener noreferrer"&gt;VHS&lt;/a&gt; and…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Higangssh/gitcredits" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Run it in any repo:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Your contributors scroll up the terminal, movie-style. Names, commit counts, the whole thing. It's the closing scene of your project — except your project is still running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I made it
&lt;/h2&gt;

&lt;p&gt;I've been shipping side projects and contributing to open source for a while now, and something kept bothering me: the people who help you build something almost never get a moment.&lt;/p&gt;

&lt;p&gt;A teammate who debugged a nasty race condition at 2am. A stranger on GitHub who opened a PR fixing your typo. The reviewer who caught the security bug before it shipped. They get a commit hash. Maybe a line in &lt;code&gt;CONTRIBUTORS.md&lt;/code&gt; if you remember.&lt;/p&gt;

&lt;p&gt;Movies figured this out a hundred years ago. Everyone who touched the thing gets their name on screen, in big letters, while music plays. It costs nothing and it means everything.&lt;/p&gt;

&lt;p&gt;So I gave that to git.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it (30 seconds)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/Higangssh/gitcredits@latest
&lt;span class="nb"&gt;cd &lt;/span&gt;your-favorite-repo
gitcredits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Works on any git repo. No config, no setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built with
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Go&lt;/strong&gt; — single binary, no dependencies to fight&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bubble Tea&lt;/strong&gt; — the TUI framework that makes terminal animations actually pleasant to write&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lipgloss&lt;/strong&gt; — for styling that doesn't look like 1995&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The scroll animation was the fun part. Getting it to feel like &lt;em&gt;credits&lt;/em&gt; and not like &lt;em&gt;a list scrolling&lt;/em&gt; took more iterations than I want to admit. Easing curves matter, even in a terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;I'm thinking about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom themes (Star Wars crawl, anyone?)&lt;/li&gt;
&lt;li&gt;Music support (yes, really)&lt;/li&gt;
&lt;li&gt;Per-file credits — who actually wrote this function?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of that sounds fun, the repo is open. PRs welcome. You'll get your name in the credits.&lt;/p&gt;




&lt;p&gt;Every contributor deserves a moment on screen. Even if the screen is a terminal.&lt;/p&gt;

&lt;p&gt;⭐ &lt;a href="https://github.com/Higangssh/gitcredits" rel="noopener noreferrer"&gt;github.com/Higangssh/gitcredits&lt;/a&gt; — star it if it made you smile.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>go</category>
      <category>cli</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I don't want to give Claude SSH access to my home server</title>
      <dc:creator>SangheeSon</dc:creator>
      <pubDate>Wed, 29 Apr 2026 13:47:36 +0000</pubDate>
      <link>https://dev.to/higangssh/i-dont-want-to-give-claude-ssh-access-to-my-home-server-2gjl</link>
      <guid>https://dev.to/higangssh/i-dont-want-to-give-claude-ssh-access-to-my-home-server-2gjl</guid>
      <description>&lt;p&gt;AI agents are getting scary good at ops work.&lt;/p&gt;

&lt;p&gt;Claude Code, Codex, OpenHands — they can SSH into a server, read logs, restart containers, fix configs. It works.&lt;/p&gt;

&lt;p&gt;But I still won't give my home server an SSH key for an agent.&lt;/p&gt;

&lt;p&gt;A shell is too sharp. It can inspect anything. It can delete anything. It can &lt;code&gt;rm -rf&lt;/code&gt; the wrong path very fast and very confidently.&lt;/p&gt;

&lt;p&gt;I want the agent to &lt;em&gt;help&lt;/em&gt; operate my server, not &lt;em&gt;be&lt;/em&gt; the operator.&lt;/p&gt;

&lt;p&gt;So I've been building &lt;strong&gt;HomeButler&lt;/strong&gt; in the opposite direction: not "AI runs my server," but "AI talks to my server through a narrow, structured interface."&lt;/p&gt;

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

&lt;p&gt;HomeButler is a single Go binary. No daemon. No database. No always-on web service.&lt;/p&gt;

&lt;p&gt;You can copy it onto a server, run it from cron, pipe it into a script, open the web dashboard, or hook it into Claude Desktop via MCP. Same binary, same core, different surfaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────────────────┐
│  Layer 3 — Chat Interface                        │
│  Telegram · Slack · Discord · Terminal · Browser │
└──────────────────────┬───────────────────────────┘
                       │
┌──────────────────────▼───────────────────────────┐
│  Layer 2 — AI Agent                              │
│  Claude · LangChain · n8n · OpenClaw             │
└──────────────────────┬───────────────────────────┘
                       │  CLI exec or MCP (stdio)
┌──────────────────────▼───────────────────────────┐
│  Layer 1 — Tool (homebutler)   ← YOU ARE HERE    │
│                                                  │
│   CLI · MCP · Web    → same internal/ core       │
│   system · docker · ports · backup · watch       │
└──────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent gets explicit, JSON-returning operations. It can't reach outside this surface. The blast radius of a wrong call is bounded.&lt;/p&gt;

&lt;p&gt;I sleep better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things HomeButler does that I actually care about
&lt;/h2&gt;

&lt;p&gt;There's a long feature list in the README. Three of them are why I keep working on this.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;report&lt;/code&gt; — what &lt;em&gt;changed&lt;/em&gt;, not just what &lt;em&gt;is&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Most homelab dashboards show &lt;em&gt;state&lt;/em&gt;. Beautiful graphs, lots of dots.&lt;/p&gt;

&lt;p&gt;But my home server doesn't fail because I lack data. It fails because I don't notice the right change at the right time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🏠 Homebutler Report — mac-mini

── Current Status ──
   CPU: 5.0% · Memory: 8.3/16.0 GB · Disk: 4%
   Containers: 1 running, 1 stopped · Public ports: 5

── Needs Attention ──
   ⚠️  1 container(s) stopped

── Notable Changes ──
   No significant changes since last report.

── Suggested Actions ──
   → Address items in 'Needs attention' above.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First run takes a baseline. Every run after diffs against the last snapshot and tells you what moved. &lt;code&gt;--json&lt;/code&gt; for piping into agents.&lt;/p&gt;

&lt;p&gt;What I want it to answer is just three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What looks wrong?&lt;/li&gt;
&lt;li&gt;What changed?&lt;/li&gt;
&lt;li&gt;What should I check next?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not "here's a graph, you figure it out."&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;code&gt;watch&lt;/code&gt; — the 3 AM container death problem
&lt;/h3&gt;

&lt;p&gt;Your container crashed at 3 AM. Why? By morning, the logs are gone, the container is back up, and you have no idea what happened.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;watch&lt;/code&gt; catches the moment it dies, saves the pre-death and post-restart logs, and analyzes the cause:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[03:14:22] INCIDENT: nginx (incident nginx-20260410-031422-7a2124)
  Crash: OOM — process killed by SIGKILL (oom, confidence: high)
  ⚠ FLAPPING: acute (3 restarts in short window)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses exit codes (137 = OOM, 139 = segfault, 143 = SIGTERM) plus log pattern matching (&lt;code&gt;panic:&lt;/code&gt;, &lt;code&gt;Out of memory&lt;/code&gt;, &lt;code&gt;FATAL&lt;/code&gt;) to categorize the crash. Flapping detection flags processes stuck in restart loops — acute (3+ in 10 min) or chronic (5+ in 24h).&lt;/p&gt;

&lt;p&gt;Supports Docker (real-time event stream), systemd, and PM2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler watch add nginx           &lt;span class="c"&gt;# interactive: pick docker / systemd / pm2&lt;/span&gt;
homebutler watch start               &lt;span class="c"&gt;# foreground monitoring&lt;/span&gt;
homebutler watch &lt;span class="nb"&gt;history&lt;/span&gt;             &lt;span class="c"&gt;# list past incidents&lt;/span&gt;
homebutler watch show &amp;lt;incident-id&amp;gt;  &lt;span class="c"&gt;# full crash report&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the feature I built for myself first. Every homelabber has had a 3 AM container death they couldn't explain.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;code&gt;backup drill&lt;/code&gt; — "having a backup" vs "being able to restore"
&lt;/h3&gt;

&lt;p&gt;These are different things. I learned this the hard way.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;backup drill&lt;/code&gt; boots your backup in an &lt;strong&gt;isolated Docker network&lt;/strong&gt;, runs an HTTP health check against the booted app, and tears it all down. Like a fire drill for your data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🔍 Backup Drill — uptime-kuma

  📦 Backup: backup_2026-04-04_1711.tar.gz (18.6 MB)
  🔐 Integrity: ✅ tar valid (8 files)
  🚀 Boot: ✅ container started in 0s
  🌐 Health: ✅ HTTP 200 on port 58574
  ⏱️  Total: 2s

  ✅ DRILL PASSED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero risk to your running services — completely isolated environment, random port, separate network. If the drill fails, your backup is theater. Better to find out today than on the day you actually need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this shape, not another dashboard
&lt;/h2&gt;

&lt;p&gt;Portainer, Netdata, CasaOS, Uptime Kuma — these are all great. I run several of them. They solve real problems.&lt;/p&gt;

&lt;p&gt;But on a small home server, my bottleneck isn't observability. It's me, the operator, with five tabs open trying to remember what "normal" looked like yesterday.&lt;/p&gt;

&lt;p&gt;A small structured CLI fits that gap better than another tab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cron-friendly&lt;/strong&gt; — &lt;code&gt;homebutler report --json | jq&lt;/code&gt; at 8 AM with my coffee&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Script-friendly&lt;/strong&gt; — exit codes that mean something, JSON everywhere&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent-friendly&lt;/strong&gt; — MCP server built in, works with Claude Desktop / ChatGPT / Cursor out of the box&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Air-gap friendly&lt;/strong&gt; — single binary, no daemon, no phone-home&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dashboard is &lt;em&gt;also&lt;/em&gt; there (&lt;code&gt;homebutler serve&lt;/code&gt; for a &lt;code&gt;go:embed&lt;/code&gt; web UI), but it's opt-in. The default mode is "command you run, answer you get, exit."&lt;/p&gt;

&lt;h2&gt;
  
  
  The bigger bet
&lt;/h2&gt;

&lt;p&gt;I think the next interesting interface for ops isn't a prettier dashboard. It's the conversation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Is anything weird with the server?"&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Claude calls &lt;code&gt;homebutler report&lt;/code&gt; via MCP, reads the JSON, summarizes)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;"Yeah — Vaultwarden has been restarting every ~2 hours since yesterday. Want me to pull the crash logs?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For that to be safe, the agent needs a &lt;em&gt;narrow&lt;/em&gt; tool, not a shell. That's what HomeButler is becoming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;Higangssh/homebutler/homebutler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/Higangssh/homebutler/main/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler init        &lt;span class="c"&gt;# interactive setup&lt;/span&gt;
homebutler report      &lt;span class="c"&gt;# baseline + summary&lt;/span&gt;
homebutler watch tui   &lt;span class="c"&gt;# terminal dashboard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/Higangssh/homebutler" rel="noopener noreferrer"&gt;https://github.com/Higangssh/homebutler&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Site: &lt;a href="https://homebutler.dev" rel="noopener noreferrer"&gt;https://homebutler.dev&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you run a homelab, I'd love to hear: &lt;strong&gt;what's the one thing you wish someone would just tell you about your server every morning?&lt;/strong&gt; That's the next thing I want &lt;code&gt;report&lt;/code&gt; to answer.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>selfhosted</category>
      <category>opensource</category>
      <category>go</category>
    </item>
    <item>
      <title>My friend unplugged my Raspberry Pi — so I built a homelab manager</title>
      <dc:creator>SangheeSon</dc:creator>
      <pubDate>Sun, 29 Mar 2026 13:47:01 +0000</pubDate>
      <link>https://dev.to/higangssh/my-friend-unplugged-my-raspberry-pi-so-i-built-a-homelab-manager-401g</link>
      <guid>https://dev.to/higangssh/my-friend-unplugged-my-raspberry-pi-so-i-built-a-homelab-manager-401g</guid>
      <description>&lt;p&gt;It started with an accident.&lt;br&gt;
My friend was at my place, tripped over a cable, &lt;br&gt;
and unplugged my Raspberry Pi. The SD card got &lt;br&gt;
corrupted. Network partition gone. Files — gone. &lt;br&gt;
I had to re-flash everything from scratch.&lt;br&gt;
No backup. No remote monitoring. No alerts. &lt;br&gt;
I didn't even know it was down until I tried &lt;br&gt;
to SSH in the next day.&lt;br&gt;
That's when I decided: &lt;strong&gt;never again.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;If you run a homelab, you probably know the drill:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSH into each server manually&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;docker ps&lt;/code&gt; to check containers&lt;/li&gt;
&lt;li&gt;Forgot which port Uptime Kuma is on&lt;/li&gt;
&lt;li&gt;No idea if your disk is 90% full&lt;/li&gt;
&lt;li&gt;Deploying a new app means writing YAML by hand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I had 2 servers (Mac Mini + Raspberry Pi 5). &lt;br&gt;
Managing them was death by a thousand SSH sessions.&lt;/p&gt;
&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Higangssh/homebutler" rel="noopener noreferrer"&gt;&lt;strong&gt;homebutler&lt;/strong&gt;&lt;/a&gt; &lt;br&gt;
— a single 15MB Go binary that manages &lt;br&gt;
your entire homelab.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check all servers at once&lt;/span&gt;
homebutler status &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;span class="c"&gt;# Install an app in 30 seconds&lt;/span&gt;
homebutler &lt;span class="nb"&gt;install &lt;/span&gt;uptime-kuma
&lt;span class="c"&gt;# Container resource usage&lt;/span&gt;
homebutler docker stats
&lt;span class="c"&gt;# Wake a sleeping machine&lt;/span&gt;
homebutler wake nas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No Docker required to run it. No database.&lt;br&gt;
No config files to write (there's an init wizard).&lt;br&gt;
Just download and go.&lt;/p&gt;
&lt;h2&gt;
  
  
  One-Command App Install
&lt;/h2&gt;

&lt;p&gt;This is the feature I'm most proud of.&lt;br&gt;
Instead of writing docker-compose files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler &lt;span class="nb"&gt;install &lt;/span&gt;jellyfin &lt;span class="nt"&gt;--media&lt;/span&gt; /mnt/movies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. It:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checks if Docker is running&lt;/li&gt;
&lt;li&gt;Checks if the port is available&lt;/li&gt;
&lt;li&gt;Generates docker-compose.yml&lt;/li&gt;
&lt;li&gt;Pulls the image and starts the container&lt;/li&gt;
&lt;li&gt;Verifies it's running&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Currently supports 6 apps: uptime-kuma,&lt;br&gt;
vaultwarden, filebrowser, it-tools, gitea,&lt;br&gt;
and jellyfin.&lt;/p&gt;
&lt;h2&gt;
  
  
  Built-in AI Integration
&lt;/h2&gt;

&lt;p&gt;homebutler includes a built-in MCP server&lt;br&gt;
with 15 tools. Connect it to Claude, ChatGPT,&lt;br&gt;
or Cursor, and you can manage your homelab&lt;br&gt;
from chat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Install uptime-kuma on the raspberry pi"&lt;/li&gt;
&lt;li&gt;"What's the CPU usage on all servers?"&lt;/li&gt;
&lt;li&gt;"Restart the nginx container"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AI part is completely optional.&lt;br&gt;
homebutler works perfectly as a standalone CLI.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Tech
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Go — single binary, cross-compiled for Linux/macOS (ARM + x86)&lt;/li&gt;
&lt;li&gt;cobra — CLI framework with auto-generated help and shell completion&lt;/li&gt;
&lt;li&gt;go:embed — web dashboard baked into the binary&lt;/li&gt;
&lt;li&gt;Bubble Tea — terminal TUI dashboard&lt;/li&gt;
&lt;li&gt;No frameworks for HTTP — just net/http&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole thing is 15MB. Zero runtime dependencies.&lt;/p&gt;
&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;More installable apps (targeting 15+)&lt;/li&gt;
&lt;li&gt;Scheduled backups with one-command restore&lt;/li&gt;
&lt;li&gt;Server down notifications (Telegram/Discord)&lt;/li&gt;
&lt;li&gt;Reverse proxy auto-configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;Higangssh/homebutler/homebutler
&lt;span class="c"&gt;# or&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/Higangssh/homebutler/main/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler init    &lt;span class="c"&gt;# setup wizard&lt;/span&gt;
homebutler status  &lt;span class="c"&gt;# see your server&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/Higangssh/homebutler" rel="noopener noreferrer"&gt;https://github.com/Higangssh/homebutler&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Demo video: &lt;a href="https://www.youtube.com/watch?v=MFoDiYRH_nE" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=MFoDiYRH_nE&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;What's your homelab stack?&lt;br&gt;
I'd love to know what apps you'd want homebutler to support next.&lt;/p&gt;

</description>
      <category>go</category>
      <category>selfhosted</category>
      <category>docker</category>
      <category>opensource</category>
    </item>
    <item>
      <title>git log is boring. So I made this instead.</title>
      <dc:creator>SangheeSon</dc:creator>
      <pubDate>Tue, 10 Mar 2026 15:26:49 +0000</pubDate>
      <link>https://dev.to/higangssh/git-log-is-boring-so-i-made-this-instead-bco</link>
      <guid>https://dev.to/higangssh/git-log-is-boring-so-i-made-this-instead-bco</guid>
      <description>&lt;p&gt;Ever watched a movie and thought "damn, those end credits look cool"? Now imagine that — but for your Git contributors.&lt;/p&gt;

&lt;p&gt;git log is boring. git shortlog -sn is slightly less boring. But neither of them makes your contributors feel like the stars they are.&lt;/p&gt;

&lt;p&gt;I wanted something fun. Something you could run at a team demo or after a big release. Something that makes people go "wait, what is that?"&lt;/p&gt;

&lt;p&gt;So I built gitcredits&lt;/p&gt;

&lt;p&gt;gitcredits demo&lt;/p&gt;

&lt;p&gt;It's a single binary. You run gitcredits in any Git repo, and it rolls your contributors like movie credits — complete with ASCII art titles, starfield background, and smooth scrolling.&lt;/p&gt;

&lt;p&gt;How it works&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reads your Git history&lt;/li&gt;
&lt;li&gt;Extracts contributors, commit counts, recent features&lt;/li&gt;
&lt;li&gt;Renders it all as a terminal animation using Bubble Tea (&lt;a href="https://github.com/charmbracelet/bubbletea" rel="noopener noreferrer"&gt;https://github.com/charmbracelet/bubbletea&lt;/a&gt;) + Lip Gloss (&lt;a href="https://github.com/charmbracelet/lipgloss" rel="noopener noreferrer"&gt;https://github.com/charmbracelet/lipgloss&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No config files. No setup. Just run it in any Git repo.&lt;/p&gt;

&lt;p&gt;Themes&lt;/p&gt;

&lt;p&gt;The default theme gives you Star Wars-style scrolling credits with a starfield.&lt;/p&gt;

&lt;p&gt;But my favorite is the Matrix theme — digital rain with a text resolve effect:&lt;/p&gt;

&lt;p&gt;matrix theme&lt;/p&gt;

&lt;p&gt;What it shows&lt;/p&gt;

&lt;p&gt;• Title — your repo name in big ASCII art&lt;br&gt;
• Project Lead — whoever has the most commits&lt;br&gt;
• Starring — all contributors with their commit counts&lt;br&gt;
• Notable Scenes — recent feat/fix commits&lt;br&gt;
• Stats — total commits, contributors, stars, language, license&lt;/p&gt;

&lt;p&gt;Why I built it&lt;/p&gt;

&lt;p&gt;I've been contributing to open source for a while, and I realized there's no fun way to celebrate the people behind a project. GitHub's contributor graph is nice, but it's just a chart.&lt;/p&gt;

&lt;p&gt;I wanted something that felt like a moment. Run it at the end of a sprint. Run it at a hackathon. Run it just because your terminal deserves better.&lt;/p&gt;

&lt;p&gt;Check it out&lt;/p&gt;

&lt;p&gt;GitHub: (&lt;a href="https://github.com/Higangssh/gitcredits" rel="noopener noreferrer"&gt;https://github.com/Higangssh/gitcredits&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;It's open source, MIT licensed, and contributions are welcome 🎬&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I built a single binary to manage all my homelab servers from Telegram</title>
      <dc:creator>SangheeSon</dc:creator>
      <pubDate>Sat, 28 Feb 2026 07:29:25 +0000</pubDate>
      <link>https://dev.to/higangssh/i-built-a-single-binary-to-manage-all-my-homelab-servers-from-telegram-3e4i</link>
      <guid>https://dev.to/higangssh/i-built-a-single-binary-to-manage-all-my-homelab-servers-from-telegram-3e4i</guid>
      <description>&lt;p&gt;I run 3 servers at home — a Mac Mini, a Raspberry Pi, and a NAS. Managing them used to mean opening 3 SSH sessions, running the same commands on each, and switching between terminal tabs at 2 AM when something breaks.&lt;/p&gt;

&lt;p&gt;I got tired of it. So I built &lt;a href="https://github.com/Higangssh/homebutler" rel="noopener noreferrer"&gt;homebutler&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The moment that started it all
&lt;/h2&gt;

&lt;p&gt;3 AM. Phone buzzes. Disk alert on my NAS — 91% full. &lt;/p&gt;

&lt;p&gt;Old workflow: grab laptop → SSH into NAS → check what's eating disk → restart the problem service → SSH into the other servers to make sure they're fine → go back to sleep 40 minutes later.&lt;/p&gt;

&lt;p&gt;I wanted this instead: pick up phone → read the alert → type "what's eating disk?" → type "restart postgres" → sleep. All from one chat window.&lt;/p&gt;

&lt;h2&gt;
  
  
  What homebutler does
&lt;/h2&gt;

&lt;p&gt;It's a single Go binary (~13MB, zero dependencies) that does two things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. CLI for your terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;homebutler status &lt;span class="nt"&gt;--all&lt;/span&gt;

🖥 mac-mini &lt;span class="o"&gt;(&lt;/span&gt;darwin/arm64&lt;span class="o"&gt;)&lt;/span&gt;
   CPU: 23% | Memory: 5.2/8.0 GB | Disk: 37%

🖥 raspberry-pi &lt;span class="o"&gt;(&lt;/span&gt;linux/arm64&lt;span class="o"&gt;)&lt;/span&gt;
   CPU: 12% | Memory: 1.6/4.0 GB | Disk: 47%

🖥 nas-box &lt;span class="o"&gt;(&lt;/span&gt;linux/amd64&lt;span class="o"&gt;)&lt;/span&gt;
   CPU: 8% | Memory: 12.4/32 GB | Disk: 87% ⚠️
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One command, all servers. It connects to remote servers over SSH in parallel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. MCP server for AI chat&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;homebutler speaks &lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;MCP&lt;/a&gt;, so Claude, ChatGPT, Cursor — anything that supports MCP — can use it as a tool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"homebutler"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"homebutler@latest"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what it looks like in practice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🚨 &lt;strong&gt;Alert: CPU at 92% on nas-box&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Me: "What's eating CPU?"&lt;/p&gt;

&lt;p&gt;Bot: postgres — 85.2%&lt;/p&gt;

&lt;p&gt;Me: "Restart postgres"&lt;/p&gt;

&lt;p&gt;Bot: ✅ Done. CPU 92% → 12%&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No SSH. No laptop. No dashboard login.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's inside
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;System monitoring&lt;/strong&gt; — CPU, memory, disk, uptime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker management&lt;/strong&gt; — list, restart, stop, view logs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wake-on-LAN&lt;/strong&gt; — power on machines from anywhere&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port scanner&lt;/strong&gt; — see what's listening&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network scan&lt;/strong&gt; — discover LAN devices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-server SSH&lt;/strong&gt; — manage all servers from one place&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web dashboard&lt;/strong&gt; — dark-themed UI, embedded in the binary&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerts&lt;/strong&gt; — threshold-based notifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON output&lt;/strong&gt; — pipe-friendly for scripts and AI&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why a single binary?
&lt;/h2&gt;

&lt;p&gt;I've tried Netdata, Glances, CasaOS. They all need Docker, or a running daemon, or a web server that's always on.&lt;/p&gt;

&lt;p&gt;homebutler is different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy one file to your Pi. Done.&lt;/li&gt;
&lt;li&gt;No Docker. No Node. No Python. No config server.&lt;/li&gt;
&lt;li&gt;Runs when you need it, sleeps when you don't.&lt;/li&gt;
&lt;li&gt;Air-gapped install? Just &lt;code&gt;scp&lt;/code&gt; the binary.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Multi-server: the part I'm most proud of
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ~/.config/homebutler/config.yaml&lt;/span&gt;
&lt;span class="na"&gt;servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mac-mini&lt;/span&gt;
    &lt;span class="na"&gt;local&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;raspberry-pi&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.1.30&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pi&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nas-box&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.1.20&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once configured, every command works across all servers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;homebutler docker list &lt;span class="nt"&gt;--all&lt;/span&gt;    &lt;span class="c"&gt;# containers on every server&lt;/span&gt;
homebutler alerts &lt;span class="nt"&gt;--all&lt;/span&gt;         &lt;span class="c"&gt;# alerts from everywhere&lt;/span&gt;
homebutler serve                &lt;span class="c"&gt;# web dashboard for all servers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Homebrew&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;Higangssh/tap/homebutler

&lt;span class="c"&gt;# npm (for MCP server)&lt;/span&gt;
npx &lt;span class="nt"&gt;-y&lt;/span&gt; homebutler@latest

&lt;span class="c"&gt;# Go&lt;/span&gt;
go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/Higangssh/homebutler@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/Higangssh/homebutler" rel="noopener noreferrer"&gt;github.com/Higangssh/homebutler&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's MIT licensed, open source, and I'm actively maintaining it. If you run a homelab, I'd love to hear what you think.&lt;/p&gt;

</description>
      <category>go</category>
      <category>opensource</category>
      <category>docker</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
