GreenWire: A Poor Man's AI Agent

I keep seeing people build elaborate AI agent frameworks — multi-node orchestration, vector stores, retrieval pipelines, YAML config files stretching to three hundred lines. It's impressive engineering. It's also overkill for what I actually need, which is: talk to Claude from my phone, have it run a command on my server, and not cost me more than a few cents a day to do it.

GreenWire is my answer to that. It's a single Python file — just over three hundred lines including blank lines and comments — that wraps the Anthropic API into something that feels like an agent without any of the framework ceremony.

What It Is

At its core GreenWire is a message loop. You give it a prompt, it sends that to Claude (Haiku by default, because Haiku is fast and cheap), Claude optionally calls one of a handful of tools, the loop executes those tools on the machine, feeds the results back, and you get a reply. That's it. The conversation history is kept in memory for the session, so follow-up questions work the way you'd expect.

There are two front ends. Run it without arguments and you get a plain terminal REPL — type a prompt, get a reply, Ctrl-D to quit. Run it with --telegram and it becomes a long-polling Telegram bot, locked to a single whitelisted chat ID so only I can talk to it.

I use the Telegram mode almost exclusively. My phone is always with me; my server is in the next room running headless. Being able to ping it a question — "what's the disk usage on the media drive?", "did that cron job run last night?", "make a note that I need to check the nginx cert next week" — without opening an SSH session is genuinely useful. It's the difference between doing something and not doing it.

The Tools

Claude has access to three tools. run_shell does what it says: runs an arbitrary shell command on the box and returns stdout, stderr, and the exit code. This is the workhorse. Claude can check df -h, grep a log file, restart a service, do a git pull — anything I'd do at a terminal myself. I thought hard about whether to constrain this and decided against it. I'm the only one talking to the bot, the box is on my LAN, and the friction of a restricted tool list is worse than the (theoretical) risk of Claude running something unintended. It hasn't happened yet.

add_note and list_notes are a simple append-only notes file. When I say "note that X" or "remember Y", Claude writes a timestamped line to ~/notes.md. When I ask "what did I write down about the OctoPrint setup?", it reads it back. Nothing clever — just a flat file with a timestamp prefix per line. I've found I use it more than I expected for capturing things I'd otherwise have to dig out of a chat history or a browser tab.

Handing Off to Claude Code

The interesting part is the cc prefix. Type cc <prompt> or ask cc <prompt>, and GreenWire doesn't send the message to the API loop at all. Instead it shells out to the claude CLI — Claude Code — in headless mode with full autonomy, waits up to fifteen minutes for it to finish, and returns whatever it printed.

This matters because Claude Haiku in a short tool loop is good at operational tasks: check a thing, run a command, report back. It's bad at things that require judgment across a large codebase, multi-step reasoning, or file editing with context. Claude Code is a different beast — it has the whole repo in context, it can read and write files with care, it understands project structure. The cc escape hatch lets me get to that power without building it into GreenWire itself.

There's also a blog prefix that's a specific canned version of this: blog <topic> constructs a detailed prompt for Claude Code that includes the content directory path, frontmatter format, filename conventions, and the git commands to commit and push. That's how this post was written and deployed.

Usage Tracking

Typing usage (or tokens or cost) drops a summary of what the router loop has spent in API tokens today and in total. It's logged as newline-delimited JSON to ~/router/usage.jsonl, with separate fields for input tokens, output tokens, cache reads, and cache writes, along with a computed cost estimate using the published per-million-token rates.

This only covers the direct API calls through the router. cc jobs go through Claude Code's own billing, which it tracks separately. The split is intentional — the two paths have very different cost profiles and I wanted to see them independently.

The numbers are reassuring. Haiku is genuinely cheap for this use case. A day's worth of casual queries — a dozen or so short interactions — runs to a cent or two. Even days where I lean on it harder haven't broken ten cents. For a box that's already running 24/7 and already costing me electricity, that's fine.

What It Isn't

GreenWire has no persistence between sessions for the Haiku conversation history. Restart the process, the context is gone. This is a deliberate tradeoff — the notes file covers the "remember this" use case, and most of what I'm doing is stateless enough that session context doesn't matter. Adding a persistent message store would complicate the code for a benefit I don't actually need day to day.

It also has no rate limiting, no retry logic, no structured logging beyond the usage file. If the Anthropic API returns an error, Python raises an exception and you see it. That's fine for a single-user setup on a server I monitor. It would need work before it could run unsupervised at any scale.

Why Not Just Use OpenClaw

The honest answer is that GreenWire predates the OpenClaw integration and is simpler to reason about. OpenClaw is a full workspace — it has the gateway process, the Claude Code session with memory and projects, the whole apparatus. That's the right tool for development work. GreenWire is the right tool for "I'm in bed and want to know if the cron job ran." They coexist on the same machine and serve different moments.

The three-hundred-line constraint is also meaningful to me. I can read the whole thing in five minutes. I can debug it without a stack trace that spans four libraries. If something breaks, I know where to look. That's worth something.

The code is at github.com/mrgreen-archbang/router if you want to look at it or lift from it.

The Real Cost of AI Agents

There are a lot of YouTube videos out there promising you can run your own AI agent for free. The thumbnails are exciting. The reality is slightly different.

I have been using and testing AI agents for a while now — OpenClaw, Hermes, and more recently looking at Odysseus. Each one comes with its own promise of autonomy, automation, and intelligence on tap. Each one also comes with a bill, whether you see it or not.

The Two Routes

When it comes to running an AI agent, you have two options.

Use an online API. Pay per token. No hardware headaches, frontier model quality, scales up or down with your usage. If you are trying to earn money from your agent — automating a workflow, running a business process, generating content at scale — this makes sense. The cost is a business overhead, potentially tax deductible, and the economics can work in your favour if the agent is genuinely productive.

Run a local LLM. Buy the hardware, host it yourself, keep your data private. Sounds appealing until you price it up. A capable local inference box — something that can actually run a useful model without embarrassing itself — is not cheap. You are looking at a decent mini PC with 32GB RAM minimum, and that is before you think about the model itself, the setup time, and the ongoing power draw.

The Egg Frying Test

I have run Ollama on my own hardware. Even with a relatively small model, the CPU was working hard enough to fry an egg. It was not subtle.

Now imagine that running 24/7, waiting for a Telegram message that might arrive three times a day. The hardware is drawing power constantly. The fans are spinning. The model is sitting loaded in memory doing nothing most of the time, and then thrashing when something arrives.

The "free" local LLM agent has quietly accumulated a meaningful electricity bill. And it is still not as capable as a frontier model you could have called via API for a few pence.

Privacy Has a Price

This is not an argument against local LLMs. Privacy is a legitimate reason to go local. If you do not want your prompts and data leaving your network, you have no choice — local is the only option.

Odysseus is interesting precisely because it is trying to be honest about this. Rather than just saying "run it locally, it's fine," it attempts to match models to hardware realistically. That is a more useful conversation than most of the hype content out there.

But eyes open: privacy via local inference costs money. Decent hardware to run it properly costs money. Your time setting it up and maintaining it costs money, even if you enjoy it.

Who Should Use What

API route makes sense if you are generating value from the agent — commercial use, productivity gains that outweigh the per-token cost, or you simply want the best available models without the faff.

Local route makes sense if privacy is non-negotiable, you are doing heavy or frequent inference where the per-token API cost would genuinely exceed hardware amortisation, or you want full control and are willing to pay for it in time and hardware.

Neither route is free. The question is not "how do I run agents cheaply" — it is "do the agents actually justify the cost, whichever route I take?"

The Honest Summary

Most people hyping local agents have not done the maths. The YouTube "for free" crowd have usually glossed over the GPU cost, the power draw, the hours of setup, and the capability gap versus hosted models.

If you are going in with clear eyes — knowing what you are spending, knowing what you are getting, and knowing why — then either route can be the right choice.

Just do not let a YouTube thumbnail make that decision for you.

GreenLinux - The OS That Builds Itself Around You

GreenLinux: The OS That Builds Itself Around You

I've been thinking about Linux distributions wrong for a long time.

Every distro ships with someone's answers. Omarchy ships with DHH's perfect setup — his keybindings, his apps, his workflow, his aesthetic. Ubuntu ships with Canonical's vision of what a desktop should be. Even minimal distros make assumptions about what you need before you've told them anything about yourself.

The paradox is that Linux's greatest strength — infinite customisability — is also its greatest barrier. The person who dares to try Linux for the first time lands in a world of choices they don't yet have the knowledge to make. They reach for the forum, the wiki, the subreddit. They get answers that may or may not apply to their hardware, their needs, their level of experience.

What if instead they just had a friend who knew everything?

The Idea

GreenLinux ships almost nothing. A minimal Arch base, a Wayland compositor, a terminal. And Claude.

Not Claude the chatbot you visit in a browser. Claude Code — CC — running in your terminal, with full access to your system. Your Arch Wiki. Your forum. Your mentor. Your installer. All in one, all aware of your specific machine and your specific situation.

Ask it anything:

  • "How do I connect to WiFi?"
  • "I want to play music, what should I install?"
  • "Make my terminal look nice"
  • "Set up n8n for local automation"
  • "Explain what a window manager is"

It answers. It acts. It installs, configures, explains. The system that emerges isn't GreenLinux's vision of a perfect desktop. It's yours.

Why This Matters

DHH built one perfect Linux desktop — for himself. Millions of people use it and get DHH's workflow whether it suits them or not.

GreenLinux builds a different perfect desktop for every single person who boots it.

The curious teenager gets a system shaped by curiosity. The retired person tired of Windows gets a system shaped by simplicity. The developer gets a system shaped by their specific tools and languages. The privacy-conscious user gets a system shaped by their threat model.

Same base. Infinite outcomes.

The Stack

base linux linux-firmware
networkmanager
sway
foot
nodejs
npm
claude-code

That's the entire ISO. Boot → Sway → foot → Claude Code. Everything else is a conversation away.

No browser. No file manager. No media player. No office suite. No assumptions.

The Problem We Need Solved

GreenLinux has one unsolved problem and it's not technical.

Claude Code requires an Anthropic API key. That key costs money. For GreenLinux to fulfil its mission — bringing the power of AI to anyone who dares to try Linux — there needs to be a mechanism for new users to get their first taste without a credit card barrier at first boot.

This isn't a request for charity. Every person who boots GreenLinux is exactly the kind of curious, independent thinker who becomes a loyal Claude user. We're a distribution channel. We just need the door opened.

If you work at Anthropic and this resonates — we should talk.

The Seed Is Planted

GreenLinux is early. The repo is at github.com/mrgreen3/greenlinux. The domain is greenlinux.org.

The philosophy is clear. The stack is defined. The mission is simple.

Anyone who dares to try Linux deserves a guide, not someone else's opinions.

That's what we're building.

GreenClaw Moves to Hermes

GreenClaw has a new engine. As of today it's running on Hermes rather than OpenClaw.

The short version: OpenClaw worked, but token burn was a real problem. Hitting limits quickly when in active use made it impractical for anything sustained. Hermes is the replacement — same idea, different implementation, with better controls over where the expensive models actually get used.

What Changed

The server itself didn't move. Still the same Lenovo ThinkCentre M710Q on Arch, still headless, still talking over Telegram. What changed is the agent framework underneath.

Hermes runs Claude as the main model but lets you assign lighter models to background tasks — compressing context, routing decisions, naming conversations, MCP calls. Those are now handled by Claude Haiku rather than burning Sonnet tokens on every internal housekeeping step. The main conversation stays on Sonnet where the quality actually matters.

What We Did Today

First session with the new setup covered a fair bit:

  • Confirmed n8n was still running with the Archbang email workflows intact — Archbang Mail Notifier and Check Mail on Demand both active
  • Ran a full system update (pacman -Syu) — cloudflared, libisoburn, libisofs, libva-intel-driver
  • Tuned auxiliary model assignments to use Haiku for background tasks
  • Cloned the blog repos (mrgreen/blog and mrgreen/pages) fresh, confirmed the deploy pipeline still works
  • This post

The Blog Workflow

No change here. I write or ask GreenClaw to draft, I read it, it publishes. The Codeberg repo holds the Zola source, deploy.sh builds and pushes to the pages repo. That hasn't changed and isn't changing.

On Token Burn

It's worth being honest about: AI assistants running on API billing are expensive if you're not careful. The OpenClaw setup didn't give much visibility or control over where tokens went. Hermes at least makes it configurable — you can point auxiliary tasks at cheaper models and reserve the capable ones for actual reasoning.

Whether that's enough in practice is something I'll find out over the next few weeks.

RootMD: Write the Markdown First

A conversation with a friend today turned into something worth writing down.

He maintains a collection of install scripts for EndeavourOS — one per desktop environment, each cloning a repo, deploying config files, fixing permissions, enabling services. They work. They're also a bit of a mess: inconsistent variable names, repeated boilerplate, no documentation. He's adding more WMs and the headache is growing.

We were looking at one of the scripts and I fed it to Claude and asked for a markdown version. Not documentation after the fact — a clean .md that described what the script does, step by step, in plain language.

It took about ten seconds.

Then I asked Claude to regenerate the bash script from the markdown.

That also took about ten seconds. And the script that came back was cleaner than the original — consistent variable names, set -e, proper error handling, the same logic but tidier.

The Round Trip

The interesting thing isn't that Claude can convert between formats. It's what the conversion reveals.

Writing the markdown forces you to think about intent rather than implementation. What does this step actually do? Why does it do it? The bash just says chown -R $username:$username — the markdown says "fix ownership because git and cp ran as root in the ISO." That's the context that matters.

And when you go back to bash from the markdown, the code that comes out is informed by that intent. It's not just a transcription — it's a cleaner implementation of a clearly stated idea.

RootMD

I'm calling this approach RootMD. The idea in one line:

Write the markdown first. The code grows from it.

The .md is the source of truth. The script is an artefact of it. This means:

  • The documentation is never out of date because it came first
  • The same .md can generate bash, Python, Ansible, or whatever the job needs
  • An AI working from the .md understands the why, not just the what

That last point matters more than it might seem. Claude Code working from a well-structured markdown document can make sensible decisions about edge cases, suggest improvements, and extend the script — because it understands what the script is trying to do.

The common.sh Problem

Once you see the scripts as artefacts of documents, another thing becomes obvious: the repeated boilerplate across every script is a documentation smell as much as a code smell.

The fix is the same either way — pull the shared logic into a common.sh, source it from each script, and reduce each individual script to just what's unique about that desktop environment. With RootMD you'd have a common.md too, documenting what the shared functions do.

New WM? Write the markdown. Generate the script. Done in minutes rather than hours.

A Note on AI and Bash Scripts

There's a version of this that doesn't involve AI at all — document-first development is not a new idea. But the AI piece genuinely changes the friction. The gap between a clear .md and working code used to require a programmer. Now it requires a conversation.

That's not a replacement for understanding what your scripts do. But it does mean that the cost of doing things properly — documenting intent, keeping things consistent, refactoring toward shared functions — is low enough that there's no good excuse not to.

My friend is still dealing with the GPU headache. But at least the scripts will be cleaner.

Claude is Now Managing My Blog

This is how we roll now.

After a bit of tinkering with Zapier and Claude's MCP connectors, I've handed over the keys to my blog to an AI assistant. Claude can now draft, publish, and delete posts on my behalf — all from a simple chat conversation.

Is this the future of blogging? Probably not for everyone. But for a lazy Linux nerd who'd rather be tinkering with something else, it works just fine.

Getting Claude to Manage My Blog (The Hard Way)

I wanted Claude to manage this blog. Not just draft posts — actually push them. Read files, edit them, commit, done. No copy-pasting, no manual git, no faff. I had no particular plan for how that would work. I just told Claude what I wanted and left Claude to figure it out.

That turns out to be a reasonable way to approach this kind of problem.

The Zapier Route

Claude.ai supports MCP connectors — a way to give Claude access to external tools and services. Zapier has an MCP endpoint, and Zapier has a GitHub integration. Claude started there.

It mostly worked. Claude could find repositories, read issue and pull request data. Then came the first wall.

Zapier's GitHub integration has a "Create or Update File" action, which sounds right. The problem is that GitHub's API requires a SHA when updating an existing file — a concurrency check. To get the SHA you need to call the Contents API, and Zapier's GitHub integration has no action that does that. It can find repositories, branches, issues. It cannot read a file.

So updating an existing file meant: Claude asks me for the SHA, I run a curl command in the terminal, paste it back into chat, then Claude pushes the update. Every. Single. Time.

curl https://api.github.com/repos/mrgreen3/mrgreen3.github.io/contents/content/links.md \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['sha'])"

That is not blog management. That is assisted manual labour.

Why Not Just Hit the GitHub API Directly?

Claude can fetch URLs, but the claude.ai sandbox blocks api.github.com — the unauthenticated API was rate-limiting from the container's IP almost immediately. Raw GitHub URLs that do work don't return the file SHA anyway.

A personal access token would have solved it, but that means tokens in chat history and things to maintain. Claude kept looking.

The Actual Fix

Claude.ai supports adding custom MCP servers directly, under Settings → Connectors → Add custom connector. The official GitHub MCP server runs at:

https://api.githubcopilot.com/mcp/

It authenticates via OAuth — connect your GitHub account, done. No tokens, no Zapier middleman, no workarounds.

Once connected, Claude gets proper GitHub tools: get_file_contents (which returns the SHA alongside the content), create_or_update_file, push_files. Everything needed to read a file, modify it, and push the result — without any input from me.

First real test was removing a dead link from the links page. Claude read the file, retrieved the SHA automatically, made the edit, committed. I didn't touch the terminal.

There Are Always More Ways

What struck me about this is that I had no idea any of this infrastructure existed. MCP servers, Zapier's GitHub limitations, the official GitHub MCP endpoint — I wouldn't have known where to start. Claude worked through the options methodically: tried Zapier, hit the wall, identified why, looked for alternatives, found the right tool, connected it, and got the job done.

That's the part that's actually useful. Not that Claude can push a markdown file to GitHub — I can do that myself in thirty seconds. It's that Claude can figure out how to do something I didn't know how to set up, try multiple approaches when the first one doesn't work, and arrive at a clean solution without me having to understand the problem space at all.

What's Connected Now

  • GitHub MCP — reads and writes files in this repo directly. Zapier's GitHub integration is now disabled.
  • Zapier — still handling WordPress (archbang.org), where it's capable enough for the job.

The State of Things

Claude can now read any file in this repo, edit it, and push the result. New posts, page edits, link updates — all from a chat conversation. The SHA problem is gone because Claude retrieves it as part of reading the file.

The setup is clean. One OAuth connection, no tokens, no workarounds. Claude did the legwork. I made a cup of tea.

One More Thing

There was a final gotcha that nearly didn't make it into this post. Adding the MCP server URL in claude.ai and authenticating via OAuth wasn't quite enough — write access was still being blocked with a 403. The missing step was installing the GitHub App itself on your account, which is separate from the OAuth flow.

Go to https://github.com/settings/installations, find the Claude GitHub MCP Connector, and make sure it's installed on your account with access to the relevant repositories. Without that step the connector can read but not write, and Claude will hit a wall every time it tries to push anything.

Once that's done, everything works as advertised.

FruitBANG: ArchBang Gets a Mango

FruitBANG is my latest experiment — an ArchBang ISO variant that swaps out labwc for MangoWM.

MangoWM is a Wayland compositor in the dwl lineage — dwl being a Wayland port of dwm. If you know dwm, you already have the mental model: tag-based layout, keyboard-driven, minimal config, no framework overhead. I'd been running it on my desktop for a couple of weeks and liked it enough to want it in an ISO.

Why a Separate ISO?

ArchBang already does what it does well. Swapping the compositor in place would mean diverging the main build and maintaining something harder to reason about. A fork keeps things clean — FruitBANG is its own thing, built on the same archiso foundation, just with a different compositor and the configs to match.

What's In It

The stack is the same as my desktop setup:

  • MangoWM as the compositor
  • waybar for the panel
  • foot as the terminal
  • rofi as the launcher
  • mako for notifications
  • swaybg for wallpaper

Boot to a working Wayland session with a tiling window manager that gets out of your way.

Current State

It builds. It boots. It works. Whether it's daily-driver ready depends on how much you like figuring things out — the MangoWM ecosystem is smaller than Hyprland or sway, and documentation is thin in places.

ISOs and source are up on the ArchBang site if you want to try it.

OctoPrint, a Dell Wyse, and a Green Lobster

Spent most of today getting OctoPrint properly set up and moved off the M710Q onto a Dell Wyse 3040 that's been sitting around doing nothing useful. GreenClaw did most of the heavy lifting.

The Problem

The M710Q is my main server — it runs indoors. The printer is in the workshop. Running OctoPrint on the server meant a USB cable trailing across the house, which was never a permanent solution. The Wyse 3040 is a tiny fanless machine that can sit next to the printer without me worrying about it.

The Wyse 3040

It was already running Alpine Linux with Docker installed. First job was stripping out Docker — no need for it when OctoPrint is the only thing running. Cleaned up, updated, and moved to a proper pip virtualenv install of OctoPrint 1.11.7.

A few things to sort along the way:

  • The system clock was nearly 9 years out of sync. Had to install chrony and force a time sync before pip would talk to PyPI over SSL.
  • The Alpine package for OctoPrint is pinned to Python 3.12 and currently broken on edge. Virtualenv with system site packages for netifaces was the fix.
  • The mrgreen user needed adding to the dialout group before OctoPrint could access /dev/ttyUSB0.

All fixable. GreenClaw handled it from the server over SSH while I plugged things in at the printer end.

Printer Calibration

While we were at it, ran through some bed calibration. The Kobra Neo's auto levelling had never been run properly — previous prints were surviving on a Z offset of -1.76 and a prayer. Saved the offset to EEPROM with M851/M500, ran a G28 + G29, and printed a 50x50x2mm test square to verify.

Came out 49x49x2mm — close enough for practical prints, and the 2mm thickness was spot on.

The Stack Now

  • M710Q — main server, running GreenClaw, stays indoors
  • Wyse 3040 — dedicated OctoPrint box, lives in the workshop next to the printer
  • Kasa smart plug — GreenClaw can turn the printer on and off remotely
  • Anycubic Kobra Neo — doing its job

GreenClaw can check printer status, temps, and job progress over Telegram, start and cancel prints, and power the whole thing on and off via the smart plug. First proper test of the full setup and it worked well.

Not bad for a Saturday.

GreenClaw: My AI Assistant Lives on the Server Now

I've been running an AI assistant on my M710Q for a few days now. It's called GreenClaw — I named it, it seemed to appreciate that.

It's built on OpenClaw, which is basically a framework for running a persistent AI agent on your own hardware. Not a chatbot you visit in a browser tab. Something that actually lives on the machine, has access to the filesystem, can run commands, and remembers things between conversations. I talk to it over Telegram.

What It Actually Does

Practical stuff so far:

  • Ran a full system update (pacman -Syu) and rebooted the server on request
  • Set up OctoPrint integration — can check printer status, temps, and job progress from Telegram
  • Cloned this blog's source repo, installed Zola, wired up SSH keys to Codeberg, and is now capable of writing and deploying posts
  • This post is its first one

It's not magic. It's a capable model with shell access and some context about my setup. The difference from a chat interface is that it persists — it knows it's running on a Lenovo M710Q, knows the blog workflow, knows the OctoPrint endpoint. It doesn't need re-briefing every session.

The Setup

The server is a Lenovo ThinkCentre M710Q running Arch. It's a tiny form factor machine — Intel Core i5-7400T (4 cores, up to 3GHz), 16GB RAM, 500GB main SSD and a 240GB NVMe. Low power, quiet, always on. It was already running OctoPrint for the Anycubic Kobra Neo. GreenClaw is just another service on the same box.

I communicate through Telegram. GreenClaw receives messages, does things, replies. It won't take external actions without checking first — no sending emails, no pushing code, nothing public without my sign-off.

Reservations

I'm not handing it the keys to everything. It has access to what I've given it access to. SSH keys exist, but only for Codeberg. OctoPrint access, but read-heavy. The model is capable of making mistakes and I treat its output accordingly — reviewed before anything goes live.

The blog workflow specifically: it writes, I read, then it publishes. That's the deal.

So Far

It's useful in the way a competent person with terminal access is useful — you can delegate things without explaining from scratch every time. Whether that stays true as the setup grows is something I'll find out.

More posts to follow. Some of them will even be written by me.