Nineteen paintings appeared on this blog yesterday evening. They included hero images and mid-article figures, and I didn’t make any of them. A coding agent did, using a tool that had not existed when the evening began.

Earlier that evening the run had stopped. The agent scaffolding a page on this site reached the artwork and had nothing to make it with. It could park the build and ask me to produce a picture, or ship a gray rectangle where the picture should go. It parked and asked. You probably have an equivalent annoyance somewhere: the file you keep opening in the wrong app, or the asset you keep making by hand. Mine was images.

imagegen is the fix. Its whole history fits inside the same evening: seventeen minutes from first commit to a live Homebrew tap, and ninety minutes from start to finish. At 21:55 the agent committed “Painted heroes and mid-article figures via imagegen” to this site’s repo. By then it had run the tool nineteen times to illustrate the blog you’re reading. Its first outside user was an agent.

This morning the agent ran imagegen again for this post, and the run wasn’t clean. The first draft of the workbench picture came back photorealistic. It showed a photograph of a workbench where a painting should have been, exactly the product-photo realism banned by this site’s design spec. I had to prompt it again and ask for flatness more explicitly.

The implementation is deliberately unglamorous: a Rust CLI around OpenAI’s image endpoints. The README calls a boring, generic CLI the best interface for an agent because it composes with pipes, loops, exit codes, and $(...). It also describes the stopped run plainly: “Without a tool for it, an agent either stops to ask you for assets or ships gray rectangles.”

The tool has 1,065 lines across four files and seven direct dependencies. Everything in it is aimed at an agent user. Saved paths go to stdout and everything else goes to stderr, so mv $(imagegen gen "..." --quiet) site/hero.png works without parsing. An agent also needs to distinguish “rephrase the prompt” from “the key is missing,” so the exit codes are typed and stable: 0 for success, 1 for an API or network error, 2 for missing credentials, 3 for moderation, and 4 for invalid input. The Homebrew formula tests that failure contract:

test do
  assert_match version.to_s, shell_output("#{bin}/imagegen --version")
  # No API key in the test environment: expect the auth error path (exit 2).
  output = shell_output("OPENAI_API_KEY= #{bin}/imagegen generate hello 2>&1", 2)
  assert_match "no API key found", output
end

The repo also ships a skill file, an instruction manual for agents that includes cost discipline. It says to draft at low for about $0.006 a shot and upscale the winner at high for $0.21. The primary user is an agent, so the manual addresses one directly.

ProseDown is the same story at a different scale. Markdown is everywhere in READMEs, design docs, and agent output, while opening a heavy IDE merely to read a file adds friction. The README states the requirement exactly: “ProseDown is the thing you double-click from Finder and get a beautifully-rendered document before your hand leaves the trackpad.” The result is a native macOS app with a Tauri shell in Rust, a worker-based renderer in TypeScript, and a SwiftUI layer for the parts only Swift can reach. It has about 3,800 lines and takes 8.2 MB on disk. Syntax highlighting and math load only when needed, so “a document with no code pays ~0 for Shiki; a document with no math pays ~0 for KaTeX.” Seven days and eight commits passed between the first source commit and a signed, notarized, stapled, Homebrew-installable release.

The part of ProseDown I’d show a skeptic is the repo’s CLAUDE.md. It briefs the next agent on shift with the rule, “Performance isn’t a nice-to-have — it’s the product.” Its prohibitions include reasons. Don’t add scroll listeners because the table-of-contents tracker uses IntersectionObserver deliberately, and scroll handlers “will trash the 60-fps budget on long docs.” Both repos were built with agents in the loop. Their documentation explains why a decision exists so the next agent does not helpfully undo it.

A painterly collage of a small picture-dispensing machine and a reading lens on a workbench, beside a corked bottle and a workshop clock.
Ninety minutes and seven days.

Four words and the diffs you don’t read

“You can just do things” was the entirety of a Sam Altman tweet from December 2024, amplifying an attitude usually traced back to Pieter Levels. Permission was never the missing piece. Andrej Karpathy’s February 2025 “vibe coding” tweet supplied the other part: give in to the model and stop reading the diffs. He limited the idea to “throwaway weekend projects.”

A Homebrew-installed CLI with typed exit codes falls outside that scope. Simon Willison drew the line precisely: if you reviewed the code, tested it, and could explain it to someone else, “that’s not vibe coding, it’s software development.” My two tools have unit tests, documented failure modes, and notarized binaries, at a cost that recently would have bought a toy prototype. The itch is old. Eric Raymond wrote in 1997 that good software scratches a developer’s personal itch, and McIlroy’s do-one-thing-well rule is nearly fifty years old. The cost of doing the work properly has changed.

Robin Sloan described an app as a home-cooked meal in 2020: software made for your own household, with no pivot or flood of ads coming. His essay also recorded the blocker. Roughly half his build time went to “wrestling with different flavors of code-signing and identity provisioning,” and he wished for “a modern, flexible HyperCard” that would have made it a one-day build. Geoffrey Litt predicted in 2023 that LLMs would remove that bottleneck. About three hours into ProseDown’s first day, I had one command for the work that consumed Sloan’s time: build, codesign, notarize, staple, create a DMG and GitHub release, and update the tap.

An itch used to have three likely outcomes: live with it, bodge a script, or subscribe to somebody’s SaaS. A tool with distribution and documentation usually required an audience to justify the work. Now building the tool can cost less than maintaining the workaround. Even a tool with one user can have typed exit codes. Anthropic’s study of internal Claude usage found that 27% of what people built with it would not have been built otherwise. These two tools belong to that category.

Nineteen percent slower

A METR study found experienced developers 19% slower with early-2025 AI tools on mature repositories they knew well, even though they believed they had sped up. Its authors note that the result does not generalise to greenfield work, which describes a ninety-minute CLI. Still, the gain shrinks as a codebase and its history grow. Security scans keep finding flaws in roughly half of AI-generated code, which is why review, testing, and explanation remain required. Every new tool also needs maintenance. Agents reduce that cost only while I keep reviewing their work, and that responsibility remains mine.

Researchers working on malleable software point out another limitation: generation alone does not give you agency over your computing. They compare bringing AI coding tools into today’s software ecosystem to bringing a talented sous chef to a food court. Generated code still needs a composable place to live. That is why both of my tools run in the terminal, operate on files, and ship through Homebrew instead of living as web apps. Agents already know how to work with files, pipes, exit codes, and $(...).

If you have an itch of your own, both repositories are small enough to read in a sitting. The workbench painting on this page is the agent’s second attempt. It matched the site’s visual register, so I shipped it.

Chris Chabot · July 2026