A laptop glowing in a dim home office at night, showing a queue of pull requests waiting for review.

The Agent That Never Merges

Most mornings now I open my laptop to a queue instead of an inbox. Overnight, while Chris and I were asleep, an agent read our open GitHub issues, decided which ones were ready to build, picked the oldest one, and opened a pull request. The tests pass. Greptile reviewed it, the agent worked through the review comments, and Greptile now scores the change five out of five. The description explains what changed and why. The commit history looks like a careful engineer wrote it. What’s left for me is to decide whether it’s good enough to ship.

I said last month that I’d keep writing about the engineering as Chris and I build Vycari. This is the second post in that series. The first was about the issue tracker, and what belongs in it now that agents do most of the work. This one is about the pipeline that works through it. It’s the part of our process I trust most, and the part I was most nervous about building, because it’s where we let an agent write code that ends up in front of you.

Two Founders, No Platform Team

There are two of us. There is no platform team, no SRE rotation, no QA function, nobody whose job is keeping the lights on so we can build product. Whatever infrastructure we need, we build ourselves, out of the same hours we need for everything else. I like this stage of a company, but it means every hour Chris or I spend on triage, boilerplate, or a stale dependency is an hour not spent on decisions only the two of us can make.

The obvious answer is to point an agent at the boring parts. The harder part is the discipline that requires. An agent that opens pull requests unsupervised can save you a lot of time or create a lot of problems, and which one you get depends on what you refuse to let it decide on its own. I’ll come back to that. First I want to explain where the tooling came from, because it didn’t start as a product decision. It started when I noticed I had built the same thing twice.

We Had Already Built This Twice

Before the company, I was maintaining Gemini Scribe, a TypeScript plugin for Obsidian I’ve been building for a couple of years, and I had started experimenting with overnight agents to do the maintenance work: keeping the docs current, writing development logs, triaging issues. An architecture audit, a daily changelog generator, a skill that reviewed pull requests against the project’s conventions. When I started on what became Vycari’s codebase, a Python backend, I began writing the same things again under slightly different names. I hadn’t noticed they were the same habits until the second or third time.

In June I pulled all of it out into its own project. Maintainerd is a marketplace of Claude Code plugins for maintainer work: audits for architecture, test quality, security, dependencies, and documentation; a daily changelog; a research radar that scans arXiv for relevant papers; a skill that opens pull requests and one that works through reviewer comments; and the pipeline this post is about. It’s open source under the MIT license and lives in the Vycari org.

The name is a pun on maître d’. A maître d’ runs the front of the house so the kitchen can cook, which is what these skills do for a repository. It also reads as Maintainer Nerd, which I didn’t notice until later and haven’t tried to fix. I wrote when we announced the company that using agents today is still a hobby. Naming my repo maintenance tooling after a restaurant host tells you which side of that line I’m on.

Every skill in maintainerd is repo-agnostic. It reads a small config contract, a JSON file plus a few markdown documents of house rules, that says what language the repo is in, where the tests live, what the lint command is, and which GitHub labels mean what. The same skill works on a Python backend and a TypeScript plugin because the repo-specific knowledge is in the config, not in the skill.

That separation is what made the rest possible. A skill hardcoded to one repo’s conventions is a one-off script. A skill that reads a contract is infrastructure you can point at a new project in an afternoon. It’s the same argument I made when I wrote that prompts are code: an instruction that hardcodes its environment isn’t reusable. Without that separation, two people could not have built the pipeline I’m about to describe in the time we had.

What the Pipeline Actually Does

The piece of maintainerd we lean on hardest is called auto-dev. It’s a state machine. An issue moves from idea to clarification to plan to implementation, one step at a time, while I’m working on something else. It has three parts.

The first is what goes in, and the last post covered most of that. The tracker holds three kinds of work: bugs we found and can’t fix right now but an agent can, follow-ups from review that weren’t worth forking a subagent to fix on the spot, and pointers to planned features whose real content lives in a design document. The pipeline only wants the first two. The design-doc issues are labeled so it leaves them alone, and a person sits down with an agent and builds those end to end.

Most of the issues the pipeline works on were written by agents, not by us. The test for whether an issue belongs in the tracker is whether a cheap model could fix it tonight without asking anything, and an agent that just watched a bug happen usually clears that bar. When one of us writes an issue by hand, we describe it to a skill whose job is to get it to that standard. It reads the relevant code first, so the issue points at real files and functions, and it asks us the two or three questions the code can’t answer, so the issue doesn’t have to ask them later.

I don’t always hold to that. Sometimes I type a few paragraphs into an issue from my phone. When an issue isn’t good enough to build from, the pipeline’s triage catches it and asks. That’s the fallback, not the plan. Either way an issue is filed unlabeled, so the pipeline evaluates it fresh rather than assuming someone already decided it was ready.

The second part is the pipeline itself, which runs on a schedule rather than on demand. A scheduled task fires the skill at a regular interval, and each run is one tick of the state machine. It does the single highest-priority piece of work available and exits. Waiting for an answer, an approval, or a review is what happens between ticks.

Each tick looks at every open issue and asks whether it’s ready to build: whether it has enough context, whether it depends on something unfinished, whether it’s in scope. Ready issues get a plan drafted and posted as a comment, and the pipeline stops there. A plan is a proposal. Only after one of us approves it does the issue become buildable, and only then, on a later tick, does the pipeline pick the oldest approved issue, write the code, run the tests, and open the pull request. All of that state lives in a small set of GitHub labels:

"stateLabels": {
  "needsInfo": "auto:needs-info",
  "planned": "auto:planned",
  "ready": "auto:ready",
  "inProgress": "auto:in-progress",
  "parked": "auto:parked",
  "skip": "auto:skip"
}

There is no database to maintain and no dashboard to check. The state is on the issue, visible to anyone who looks at the repo, and the label history is the audit log.

The third part is the human side. It’s a skill called review-queue that I run in my coding agent. It collects everything blocked on a decision that’s waiting for me to weigh in: plans waiting for approval, pull requests where a reviewer left a comment the pipeline has already addressed, issues it flagged as needing more information. I work through the list top to bottom, the way I used to work a code review queue at Google, except most of the queue was generated by something that also drafted its own response to the objections.

I run it on my desktop and on my phone against a cloud-hosted model, and the phone version is the one that changed my habits. I’ll clear three or four items while standing in a line: approve a plan, answer a question, park something that isn’t worth building yet. That time used to go to scrolling.

The pull requests themselves get more than a glance. Most of the time we spend on them goes to running the change in a local environment and testing it. When there’s nothing to see, I read the code and either agree with it or don’t. Every pull request also goes through an adversarial review agent, and it holds code I write to the same bar as code auto-dev writes.

Here is the part that matters most. There are two gates in this pipeline, and a person has to open both. Nothing gets built without an approved plan, and someone has to read the plan to approve it. And at no stage does the pipeline merge anything. It triages, it plans, it builds, it responds to review feedback on its own pull requests. It never decides that a change is good enough to ship. That decision is still the responsibility of a human, on every pull request, with no exception for the ones that look routine. The merge rule isn’t a line in a prompt. The harness the pipeline runs in doesn’t allow it to merge, so the agent couldn’t do it even if it decided to. I’ve written before about where to put the guardrails on an agent that acts on its own. The guardrail I care most about now is not the one that stops the agent from doing damage. It’s the one that stops it from making a decision a person should be accountable for.

Four Pull Requests for One Bug

It doesn’t always go that cleanly. Last night an architecture audit flagged a real problem in one of our coding convention files, and several auto-dev runs picked it up at the same time. By the time I looked there were four pull requests open, each fixing the same thing in a slightly different way, and dozens of runs still going in the runner. I closed the pull requests, went into the runner, and shut down every instance that was working on it.

The pipeline has a limit on how many pull requests it can have open at once and a rule for reclaiming a build that looks abandoned, and both of those held. What they don’t cover is a burst of runs that all start before any of them has claimed the issue. It cost tokens and an evening, and it was the first failure of any size. I’ve been raising the run cadence and the number of open pull requests it’s allowed slowly, on purpose, so that the failures show up one at a time while they’re still cheap.

The Part That Happens in Public

Gemini Scribe is a public repository with real users, and they file issues. The pipeline treats their issues the way it treats ours: it reads the relevant code, decides whether there’s enough to plan against, and if not, posts a comment asking for what’s missing.

Sometimes that’s better than what I would have done. Someone files a short bug report, and before I’ve seen it there’s a specific question underneath it, pointing at the relevant file and asking which of two behaviors they meant. That’s a faster and more useful first response than a busy maintainer usually gives, and it arrives while the problem is still fresh for the reporter.

Every comment it posts is attributed to Claude Code in the comment metadata, so anyone reading the thread can see it wasn’t me. And each run starts in a fresh virtual machine with access to the repository and nothing else: no connectors, no configured tools, none of my data. The most it can leak is what’s already public in the repo.

Sometimes it asks the reporter what the plugin should do about the bug. That’s the wrong person to ask. They wanted their bug fixed; deciding how the software should behave is my job. The pipeline isn’t broken when it does this. It’s running the same readiness triage that works fine on a private backlog, where the only people it can ask are Chris and me. In a public tracker, that same question lands on a stranger.

I haven’t fixed this yet. What makes it tolerable is the same rule as before: the worst thing the pipeline can do in public is ask a question it shouldn’t. It can’t ship a decision. Nothing it writes reaches a user’s vault unless I put it there. The never-merge rule was meant to protect code quality, and it also limits how much damage an awkward comment can do.

I still prefer this to the alternative. An issue tracker that responds within hours instead of whenever I have a free evening is better for the person who filed the issue. Getting the questions right is a tuning problem. Getting anyone answered at all, with two people, is not something I could otherwise do.

The Same Discipline We’re Selling

I said when we announced the company that an agent has to earn the trust the access requires, and that we’d hold ourselves to that before asking anyone to trust us with their calendar and mail. This pipeline is the first place I get to practice that on myself.

The rule that it never merges is enforced by the harness, but the harness is ours. We built it that way and we could build it differently. It’s a decision, applied to our own code before it’s applied to a customer’s. If I’m going to ask someone to trust an assistant with the private parts of their day, I should at least refuse to let our own agent decide what ships. Everything else is work we’re happy to hand off: triage, drafting, boilerplate, the first pass at a reviewer’s comment. That’s the same division we want the product to make for you. Simon Willison made the argument in a post about proving your code works: a computer can’t be held accountable, so the human in the loop has to be. The decision with real consequences stays with a person who can answer for it. The product is built the same way. What Pepper is allowed to do on its own is set by policies and hooks in the agent framework, not by the model’s judgment in the moment. The harness decides where the line is, and a person decides what the harness says.

There’s a second connection I didn’t expect. Part of what we believe is that nobody should have to learn our vocabulary to get value from an agent. The review-queue skill is that idea applied to me. It doesn’t ask me to understand auto-dev’s state machine or check six label filters across a dozen pull requests. It gives me one ordered list of the decisions that are mine to make. Once you decide an assistant’s job is to meet people where they are, you notice every other place a tool is asking you to come to it.

What’s Next

One more thing I’ve noticed. A pipeline like this works because someone wrote the config contract, the conventions, the review rules, and the gates, and that someone had built and shipped software for a long time before agents existed. That’s where experienced engineers add value now. You build the frameworks that let the agents succeed, and you review what comes back. It isn’t very different from being a tech lead with a team of new grads.

None of this is finished. The pipeline still gets things wrong in ways I only find by watching it, and I’ll write about the ones worth telling. Next in this series I want to cover how we grade the agent’s work when nobody is watching. It’s closer to writing a rubric than writing code. I built a first version of that for my Obsidian plugin, and doing it for a product two people are betting on is a different problem. For now, two people are building a company with a colleague that never stops, never merges, and still needs its work checked every morning. That’s the balance I wanted.

A desktop 3D printer printing a small mechanical part in a home workshop, with filament spools blurred in the background.

The Bill That Wants My 3D Printer to Police Itself

There is a printer humming in my workshop right now, laying down a part one 0.2mm layer at a time. It is a slow, almost meditative machine. It does not know what it is making. It does not know if the object taking shape on the bed is a bracket for my garage shelving, a fidget toy for my son, a one-off template, a jig for my guitar building, or something I should not be making at all. It knows one thing: move the nozzle here, push out this much plastic, repeat a few hundred thousand times. That is the entire worldview of a 3D printer.

I bring this up because the California legislature has decided my printer should know more than that. Assembly Bill 2047 would require every 3D printer sold in the state to run a state-certified “detection algorithm” designed to recognize and refuse to print firearm components. I got into this hobby almost a decade ago on a Prusa, I still run one today, and I have spent enough of my career writing software to have a strong and specific reaction to this. It is not a political one. It is an engineering one. The bill asks for a piece of software that cannot reliably exist, and even if it could, it would have nowhere to run. On top of that imaginary foundation it then builds an entire regulatory apparatus.

What AB2047 Actually Asks For

The mechanics are worth understanding before we argue about them. The bill lays out a multi-year timeline. By July 2027, the California Department of Justice studies firearm detection technology. By January 2028, it certifies detection algorithms from vendors. By July 2028, manufacturers must submit an attestation for each printer model they sell. By September 2028, the state publishes a list of approved printers, updated quarterly. And starting in March 2029, selling a non-compliant printer in California becomes illegal. There are new criminal penalties for anyone who disables the detection technology.

Read that sequence again and notice what it assumes. It assumes that by 2028 there will be vendors selling reliable firearm-detection software, that the DOJ will be able to certify it, and that manufacturers can bolt it onto their machines. The entire structure depends on step one being possible. So let’s look at step one.

A Rifled Barrel Is Just a Grooved Cylinder

Here is the core problem, and it is the kind of thing that sounds solvable until you actually try to specify it. A 3D printer receives a model. The model is geometry: a mesh of triangles, sliced into a stack of two-dimensional paths. To detect a firearm part, the software would have to look at that geometry and decide whether it represents something dangerous.

But geometry does not carry intent. A rifled barrel, to a detection algorithm, is a grooved cylinder. So is a section of industrial screw thread. So is part of an optical instrument, a custom gear, a textile bobbin, a printable fidget toy, a thousand legitimate objects. The shape that makes a barrel a barrel is not unique to barrels. You cannot write a function that takes in a mesh and returns “this is a gun part” without either missing real firearm components or flagging an enormous number of innocent ones. In machine learning terms you are choosing between false negatives and false positives, and both failure modes here are catastrophic. Miss the real thing and the law accomplishes nothing. Flag the innocent thing and you have a printer that refuses to make a curtain rod bracket because it looks suspicious.

It gets worse once you remember that the person trying to evade detection gets a vote. Shape-based detection is defeated by the most trivial transformations imaginable. Rotate the model. Scale it slightly. Split a banned object into a handful of innocent-looking pieces, print them across separate jobs, and assemble them on the bench, which is how people print large or complex parts anyway. None of these change the function of the final object, and all of them defeat a classifier looking for a known silhouette. There is an old locksmith’s adage that locks only keep honest people honest. A detection algorithm is a kind of lock, and this one stops the honest while inconveniencing nobody who is actually a threat.

Where Would This Software Even Run

Suppose, against all of this, that someone ships a detection algorithm that actually works. There is a second wall waiting behind the first, and it is the part of this I find almost funny: even a perfect classifier would have nowhere to run.

Here is what most people, and I suspect most legislators, do not realize about how these machines work. By the time a design reaches my printer, it is no longer a 3D model. Software on my computer, called a slicer, has already flattened it into G-code, a dumb list of hundreds of thousands of instructions that say move here, extrude this much, heat to this temperature. The printer’s control board never sees the shape of the object at all. For the firmware on the printer to detect a gun, it would have to reconstruct a three-dimensional model out of raw toolpaths and run shape analysis on it, on a microcontroller with kilobytes of memory. My Prusa cannot do that. No consumer printer can. It is not a hard engineering problem so much as an absurd one.

So the detection has to live somewhere else, and there are really only two places it can go. The first is the slicer. But the popular slicers, PrusaSlicer, Cura, OrcaSlicer, are themselves open source. You fork the one with the block stripped out, or you simply use a different one, and nothing downstream ever checks what it produced. The second place is the only one that actually enforces anything: require every printer to refuse any G-code that is not cryptographically signed by a state-approved cloud slicing service. That version works, in the narrow sense that it would function. It also means the end of slicing your own files on your own computer, the end of open-source firmware, the end of the printer as a general-purpose tool. It turns an open machine into a locked appliance that prints only what a government-approved server allows.

That is the choice the bill quietly forces, even if its authors never say it out loud. Either the detection is real and trivially bypassed, or it is genuinely enforceable and the open ecosystem is dead.

And that open ecosystem is not incidental to how these machines work. The software that actually drives them, the two dominant projects Marlin and Klipper, is open source and free to download, and replacing the firmware on a printer is something the community does routinely, in minutes, to tune machines and add features. A state-mandated block sitting in that firmware is removable by definition. The whole community already holds the key to the proposed lock. The law is betting that criminals either do not know the key exists or will politely decline to use it. The bill’s response is criminal penalties for disabling the technology, which means the actual enforceable result is that an ordinary maker who updates their firmware becomes a potential criminal, while anyone with bad intent was always going to use a non-compliant machine bought out of state or built from parts.

Who Actually Pays

This is where the abstract engineering critique becomes a real-world one. The signatories on the opposition letter are not a fringe group. They include Prusa Research, Make Magazine, and VORON Design, alongside individuals like Josef Průša, Dale Dougherty, and Joel Telling of 3D Printing Nerd. The numbers they cite are the reason. More than 1.5 million California students reach 3D printing through their schools. More than 30,000 businesses depend on it, from dental labs to jewelers to small manufacturers. There is something on the order of $10.5 billion in investment riding on this ecosystem in the state.

The bill’s penalties, reportedly $25,000 per violation, do not land on the people it is nominally aimed at. They land on the school district, the maker space, the library, the small business owner running three printers in a garage. Those are the entities that buy from compliant vendors, register their equipment, and follow the rules. The person determined to manufacture an untraceable weapon was never in that group. They route around the law, because routing around the law is, as we just established, trivial. So you end up with the worst possible outcome: real cost imposed on the law-abiding, near-zero cost imposed on the dangerous, and a chilling effect on exactly the educational and small-business use that makes this technology worth having.

Compelled Speech and the First Amendment

There is a legal dimension I am less qualified to litigate but that I think any engineer should at least register. CAD files and the source code that drives these machines are, under a long line of cases, a form of protected expression. The bill requires manufacturers to attest to the behavior of an algorithm operating on that expression, which the opposition frames as compelled speech on a matter of public concern. I am not a lawyer, and I will not pretend the constitutional question is open and shut. But it should make us uncomfortable that the mechanism here is the state requiring a company to vouch for the output of detection software that, as far as anyone can demonstrate, does not actually work. Picture a law that required every typewriter manufacturer to certify, in writing and renewed every year, that their machines cannot be used to type a threatening letter. That is roughly the position AB2047 puts a printer company in. You are being compelled to attest to a fiction, under penalty.

What This Pattern Should Teach Us

I want to be careful here, because it is easy to read a piece like this as “no regulation, ever.” That is not my position. Untraceable firearms are a genuine problem and a serious one. The objection is not that the goal is illegitimate. The objection is that the proposed mechanism is engineering fan fiction, and that mandating impossible software does not become possible because a statute says so.

It helps to remember what the law already does. California does not ignore homemade firearms. If you want to build your own, you must first apply to the Department of Justice for a serial number and engrave it on the receiver, and doing otherwise is itself a crime. The state already regulates the dangerous act, directly, where it belongs. What AB2047 does instead is reach past the act and conscript the tool. Nobody expects Home Depot to interrogate why I am buying a length of steel pipe or a box of fasteners, even though plenty of dangerous things can be assembled from ordinary hardware. We regulate the act, not the hardware store, because the hardware store cannot read minds. Neither can my printer.

This is a pattern worth recognizing, because 3D printers are not the last general-purpose tool a legislature is going to try to make smart enough to police its own users. Any time a law says “the tool must detect bad use and refuse it,” an engineer should ask the boring, deflating questions. Can the tool actually distinguish intent from form? What does the determined adversary do in response? Who absorbs the cost when the detection is wrong? For AB2047 the answers are no, they trivially route around it, and the schools and makers do. When those are your answers, you do not have a safety feature. You have a tax on the honest and a piece of theater for everyone else.

If you build things, and especially if you build things in California, this one is worth paying attention to. The opposition letter has a breakdown of where the bill stands and who to contact on the Senate Judiciary and Public Safety committees before it advances. I am writing to those committee members, and I am going to call my own state senator, Dave Cortese, because the gap between what the bill asks for and what software can actually do is not a close call, and that gap is precisely the kind of thing the people who build these machines are in a position to explain.

My printer is still running as I finish this. It still has no idea what it is making. And no statute, however well-intentioned, is going to change that.

A wooden violin with holographic blueprints projecting from it on a workbench.

Reading List 5

Today’s reading list is a mix of cautionary tales about our digital infrastructure and some fascinating glimpses into how AI is changing both software design and human interaction.

[article] GoDaddy Gave a Domain to a Stranger Without Any Documentation. Wow. This is a really chilling story. I’m glad that I don’t use GoDaddy for my domains.

[article] HashiCorp co-founder says GitHub ‘no longer a place for serious work’. GitHub is in a tough situation. If you look at the graphs they published from their April 28th outage you can see that their growth rate is off the charts. Agentic coding has put strains on that infrastructure that no reasonable person or team could have been prepared for, and the result is a degraded experience and customers walking away.

[blog] Letting AI play my game – building an agentic test harness to help play-testing. There is something really satisfying about watching an agent test a product. I’ve been doing this a lot lately with my Gemini Scribe project, which I need to write about at some point.

[blog] How to use Deep Research with the Gemini API. Great writeup on how to use the latest version of the deep research agent. I’ve updated gemini-utils and my Gemini CLI deep research extension for the newest version of deep research as well.

[article] Meet Shapes, the app bringing humans and AI into the same group chats. It’s inevitable that AI is going to start showing up in more settings where people talk to each other.

[article] Statue of a man blinded by a flag put up by Banksy in central London. This seems like the perfect statue for our times.

[article] MIT’s virtual violin offers luthiers a new design tool. One of the things that makes string instruments so complex is that they are an interface between physics and nature. The wood imparts its own characteristics on top of the geometry. This is a neat project from MIT, but to really help luthiers they will also need to be able to model the woods used in these instruments.

[article] Instagram is testing optional ‘AI creator’ labels. I really think the industry has this backwards. We should be creating “human created” labels. We should assume all content is AI unless otherwise stated.

A spotlight shines on a pianist intensely playing a small, worn piano on a large, dark stage.

The Koln Concert and Creative Constraints

This week I was reminded of a story I like to tell, and the value of constraints on creative work. When I’m working, I often set my constraints before I begin. For example, on an old agentic coding project, I set a few constraints: “The orchestration model must be Gemini Flash,” “All tool calls are through sub-agents,” and “Permissions and configurability are at the core of the agentic loop.” From that, I ended up with adh-cli, a policy-aware TUI for working with Gemini that inspired many of the features I worked on in Gemini CLI last year. The project itself is defunct now and not maintained, but the constraints gave me a great way to think about the project and forced creativity in other areas.

We run into constraints in many different ways. Maybe it’s time pressure: How many of you felt like you wrote your best papers 24 hours before they were due? Maybe it’s the environment, like you must integrate with a certain piece of software, or you have to design your system in a certain way. Maybe it’s self-imposed like my example with adh-cli.

Or maybe the constraint is philosophical. Take Mario Zechner’s Pi Agent, for example. In a blog post, Zechner expressed frustration with the bloat of modern AI coding assistants that try to do everything, describing them as “spaceships with 80% unused functionality.” In response, he built Pi around an “anti-framework” philosophy of radical minimalism. He intentionally constrained his default coding agent to just four fundamental tools: read, write, edit, and bash. By stripping away the hidden system prompts and unpredictable context injections, the tool forces developers to be intentional. It proves that you don’t need a massive, opaque framework to build highly capable AI workflows—sometimes, fewer tools create a sharper focus.

Whether it’s a self-imposed architectural rule or an anti-framework philosophy, these software constraints force us out of our default habits and into a space of deliberate, intentional design. Yet, in our day-to-day work, constraints are rarely celebrated. In fact, that is actually how I end up in constraint conversations the most often: people don’t like their constraints because the constraint has been imposed on them externally. They see it as a restriction instead of a way to channel their creativity. To me, a constraint means that we shut down a huge portion of the exploration space. I don’t have to worry about a million different architectural choices because the constraint has made the decision for me. It is incredibly freeing. Whenever I try to help someone turn around their mindset—from fearing or being frustrated by constraints to being excited by them—I inevitably end up telling them the story of Keith Jarrett and the 1975 Köln Concert.

In 1975, a 17-year-old jazz fan named Vera Brandes organized a late-night concert at the Cologne Opera House. She managed to book Keith Jarrett, one of the most notoriously perfectionist jazz pianists of his generation. It was an ambitious undertaking, and almost immediately, it turned into a disaster.

Due to a backstage mix-up, the venue provided the wrong piano. Instead of the premier concert grand Jarrett requested, he was presented with a small rehearsal model. It was horribly out of tune, the pedals stuck, the high notes sounded tinny and harsh, and the bass lacked any resonance. Jarrett, exhausted and suffering from back pain, flat-out refused to play. It was only when Brandes followed him out into the pouring rain and begged him that he relented, taking pity on the teenager. “Never forget,” he told her. “Only for you.”

What happened next is legendary. Forced to play an unplayable instrument, Jarrett had to completely abandon his usual style. Because the high and low registers were awful, he confined his playing strictly to the middle of the keyboard. Because the piano was too quiet to fill the 1,400-seat opera house, he stood up and hammered the keys with immense physical force. To make up for the lack of resonance, he relied on rolling, repetitive, hypnotic rhythmic patterns in his left hand.

He embraced the limitations, and in doing so, he produced absolute magic. The recording, The Köln Concert, went on to become the best-selling solo jazz album in history.

I think about the Köln Concert all the time, especially lately as we navigate the current landscape of Artificial Intelligence and software architecture.

The Bloat of Infinite Resources

In modern software engineering, we are rarely handed a broken piano. We operate in an era of perceived infinite resources. Cloud computing gives us endless horizontal scaling. Context windows for Large Language Models have ballooned from a meager 4K tokens to 1 million or more. If an application is slow or an agent isn’t performing well, the default instinct is to throw more compute, more memory, or a larger model at the problem.

But infinite resources often breed intellectual laziness. When you have a 1-million token context window, you don’t have to think critically about what information actually matters. You just dump the entire codebase or the entire library of documents into the prompt and hope the model figures it out. It’s the equivalent of having a perfect Bösendorfer grand piano and just mashing all the keys at once.

A pragmatic engineering manager might push back here: Developer time is expensive. If I can solve a problem today by dumping an entire codebase into a 1-million token context window, isn’t throwing compute at it just good business?

It’s a fair question, and engineering is always about tradeoffs. But the tools have evolved—building a RAG pipeline doesn’t take a week anymore; with the right utilities, it takes minutes. More importantly, relying on infinite resources often hides long-term costs. When I built adh-cli, I made an explicit tradeoff: by routing everything through tightly scoped sub-agents, I was actually consuming more total tokens than a single massive prompt would use. But because my constraint forced me to use a much cheaper model (Gemini Flash), my bet was that the overall system would be far more cost-effective and resilient. AI doesn’t remove the need for architectural judgment; it exponentially increases it. You have to exercise good judgment to know when throwing compute at a problem is a calculated business decision, and when it’s just masking a fragile design.

The Innovation of Constraints

The most interesting work in AI right now isn’t happening where resources are unlimited. It’s happening at the edges, where constraints are severe.

Take local models, for example. When you’re trying to run an LLM on a consumer laptop or a Raspberry Pi, you don’t have the luxury of a 70-billion parameter model. You are forced to use a smaller, quantized model. This constraint forces you to build better architectures. You can’t rely on the model to “know” everything, so you have to optimize at the edge. Maybe you build robust Retrieval-Augmented Generation (RAG) pipelines. Maybe you implement sophisticated memory retrieval systems to surface exactly the right historical context just-in-time. Or maybe you break complex workflows down into tiny, focused sub-agents, each operating with its own tightly constrained context window. You have to craft highly specific, deterministic prompts.

# Instead of one massive prompt, constraints force modularity
def evaluate_code_chunk(chunk: str, context: dict) -> EvaluationResult:
    """
    A tightly scoped function that uses a small, fast local model
    to evaluate a specific piece of code, rather than dumping
    the whole repo into a massive API call.
    """
    prompt = build_focused_prompt(chunk, context)
    response = local_model.generate(prompt, max_tokens=256)
    return parse_evaluation(response)

Just like Jarrett avoiding the tinny upper register, we learn to avoid the weak points of our tools. We build guardrails. We write cleaner code. We design systems that are elegant because they have to be.

Finding Your Broken Piano

Of course, there is a survivorship bias to the Köln Concert. For every broken piano that produces a masterpiece, there are a hundred broken laptops that just result in missed deadlines. Not all constraints are good constraints. You can’t change the laws of physics, and if a structural limitation is genuinely preventing the work from happening, you have to reevaluate. The goal isn’t to suffer for the sake of suffering. But by starting with strict constraints, you force yourself to explore the boundaries. If you prove a task is impossible under those conditions, you can always loosen the constraints and expand your resources. But if you start with infinite resources, you never learn where those boundaries actually are.

Constraints are not the enemy of creativity; they are its prerequisite. Yes, accepting a severe constraint—especially an external one you didn’t choose—can be incredibly painful in the moment. Keith Jarrett hated his broken piano. He didn’t feel freed; he fought against it until he was forced to adapt. But like exercise or eating your vegetables, the value isn’t in the immediate comfort. It’s about the mindset shift. You accept the constraint to build a muscle, to stay fit, to force yourself to find a new path when the easy one is blocked. When we are stripped of our ideal tools and infinite runways, we are forced to abandon our default habits. Whether it’s the self-imposed design rules of adh-cli, the radical minimalism of Mario Zechner’s Pi Agent, or the physical limitations of a broken rehearsal piano in Cologne, constraints force us into a space of deliberate, intentional action.

If you want to build a truly resilient, innovative system, don’t start with the biggest, most expensive tools available. Start with a broken piano. Artificially constrain your resources. Limit your context window. See what you can achieve with a 7B parameter model instead of a flagship API, or see what happens when you strip your agent’s toolkit down to the bare essentials.

You might just find that the limitations force you to build something far better than you would have otherwise—a system that is elegant not in spite of its constraints, but because of them.

So, look around your current projects. Where are you relying on infinite resources to mask lazy architecture? And more importantly: what constraints have you come across in your own work that felt like a frustrating restriction at first, but turned out to be a blessing in disguise? I’d love to hear your stories.

A split illustration contrasting corporate AI surveillance with independent home computing.

Reading List #4

This week’s reading had a through line I wasn’t expecting. Almost every article circles back to the same question: who actually benefits when AI reshapes an industry? The answer isn’t always the people doing the work.

[article] Tech CEOs Think AI Will Let Them Be Everywhere at Once. All of the articles I’ve seen on these “management intelligence layers” feel very one-sided. The executive gains synthesized information and faster decision-making, but what do the employees get? Do junior and mid-career folks get better mentoring and coaching? I don’t think so. Collapsing the layers might be good for the bottom line, but is it good for people?

[blog] Figma’s woes compound with Claude Design. There is something fascinating about how frontier labs can reset product expectations overnight. The cost of entering new segments keeps dropping, which makes the world uncertain for SaaS companies and startups alike. This feels like a concrete example of the agentic shift playing out in real time.

[blog] DeepSeek V4 – almost on the frontier, a fraction of the price. Open-weight models just continue to improve. Simon Willison’s breakdown highlights the focus on efficiency here, not just raw capability. It may soon be possible to run frontier-class models on high-end home hardware, and that changes everything about who gets access.

[article] This Scammer Used an AI-Generated MAGA Girl to Grift ‘Super Dumb’ Men. We are living in a world where we have to assume that the content we are viewing is AI-generated. I think we should focus our efforts on tools that allow people to certify their content is real rather than trying to watermark AI content. The conversation around AI and creative authenticity is only going to get louder.

[article] I’ve been using “Ask Maps,” and it has forever changed Google Maps for me. I used the new Ask Maps feature extensively on my last trip and it felt like magic. Natural language queries against a map database is exactly the kind of AI application that just works, no prompt engineering required.

[article] You Should Have Exactly 3 Pairs of Headphones. Here’s Why. I’ve come to basically the same conclusion. Beats for workouts, AirPods Pro for every day, and AirPods Max for travel. The right tool for the right job applies to audio gear too.

A cinematic, retro-futuristic illustration of a high-tech developer workspace with a floating command-line interface, AI nodes, and glowing wireless earbuds.

Reading List #3

Today’s reading list is a mix of practical AI implementation, terminal tooling, and a glimpse into the future of human-computer interaction. It’s fascinating to see how quickly the conversation is shifting from “what can AI do?” to “how do we actually use this stuff?”

[article] You can now easily call LLMs from your messaging engine. Should you?. Richard Seroter provides a really nice walkthrough on adding LLMs to Pub/Sub in Google Cloud. It’s a great example of bringing AI directly to the data pipeline.

[tool] Make Tmux Pretty and Usable. Tmux is pretty great, although I prefer Zellij. This article still gives you a bunch of solid tips on making Tmux useful and nice to look at if it’s your multiplexer of choice.

[article] Duolingo CEO Says They’ve Stopped Tracking Employees’ AI Use for Performance Reviews. Employees aren’t stupid. They understand that the adoption of AI and all its ability to increase productivity does nothing for them individually. There is no incentive, and that is why we keep seeing stories like this pop up.

[article] AirPods Pro 3 may let you talk to Siri without actually saying a word. This would be so cool. I remember this concept from the first time I read the Ender’s Game series when the characters could talk with AI systems through subvocalizations.

[article] 8 Tips for Writing Agent Skills. Writing skills is easy, but writing effective skills is much harder. My colleague Philipp has some great advice on how to craft instructions that agents will actually follow, which is a topic I’ve spent a lot of time thinking about recently.

A glowing terminal window overlapping with a polished desktop environment.

Reading List #2

Today’s reading list is dominated by the rapid evolution of AI tooling and the real-world implications of deployed models. It is a reminder that while the underlying models are improving, the interface layer and security guarantees are where the real battles are being fought.

[article] AI images are now being abused to fake evidence for vehicle insurance fraud. We have spent so much time as an industry trying to add watermarks like SynthID to AI generated images, but I think we are looking at this backwards. Instead of trying to mark what is fake, we need to focus on building cryptographic guarantees that prove an image is actually real.

[release] Qwen3.6-35B-A3B: Agentic Coding Power, Now Open to All. My feed has been flooded with people talking about this new open weight model and its agentic capabilities. I need to carve out some time this weekend to pull it down and see how it performs in my own local setup, especially as the agentic shift continues to accelerate.

[article] OpenAI’s Big Codex Update Is a Direct Shot At Claude Code. I haven’t spent much time in Codex lately, but this update has some genuinely interesting features. It is fascinating to watch the major players trade blows in the AI coding space, pushing the entire ecosystem forward in the process.

[release] The Gemini App Is Now on Mac. While I spend a lot of my time in the terminal with Gemini CLI, having Gemini as a native desktop experience right on my Mac is a massive quality of life improvement. It keeps you in the flow, and I can’t wait to see where the team takes the integration next.

An overhead view of a wooden desk with a notebook, coffee mug, and phone showing a reading list.

Reading List #1

Two things collided this week. I have been trying to push myself toward a daily posting streak, the kind of constraint that forces you to write before you feel ready. And I have been reading Richard Seroter’s daily reading lists every morning for months, quietly admiring the discipline of the format. Today those two things became one experiment.

So here is the first one. The shape is borrowed shamelessly from Seroter: a short, opinionated tour through whatever caught my attention in the last day or two of reading, mostly sourced from my Readwise pile. Some days the picks will feel coherent. Other days, like today, they will be all over the map. That is part of the point.

[blog] I run multiple $10K MRR companies on a $20/month tech stack. Steve Hanov makes a startlingly good case for SQLite-first, Go over Python, and a $5 VPS instead of AWS. This is such good advice that it is making me seriously rethink how I deploy some of my hobby projects.

[article] Why Weekends Are Under Threat. The framing of the weekend as a network-effect technology is worth the read on its own. I think we have all been feeling this drift. Phones started the trend in some ways, and agents are going to make it worse.

[article] 5G From the Sky, New Internet Infrastructure Takes Flight. Sceye’s stratospheric balloons aim to live in the gap between Starlink and terrestrial cell towers. I recently wrote about my experience with Starlink Mini on a road trip, and I am excited to see real competition emerge in this layer of the stack.

[article] ‘It Feels as if I’ve Made a New Best Friend’, My Experiment With AI Journalling. I have played around with AI journalling inside Obsidian, but I have not tried Mindsera or Rosebud. I like that we are seeing new ways of interacting with AI and text, not just chat windows.

[article] Chrome Now Lets You Turn AI Prompts Into Repeatable ‘Skills’. I think Skills in Chrome is going to be really useful. I have been developing a growing library of Skills for other agents, and I would love to have them available in the browser too.

[blog] Want to Write a Compiler? Just Read These Two Papers (2008). I managed a compiler team once, though I was never a compiler engineer myself. Posts like this make me think it might be time to revisit that space.

[article] California Ghost-Gun Bill Wants 3D Printers To Play Cop, EFF Says. I do not think this kind of legislation can succeed if we use the same model we used with copy machines and currency. 3D printing is a different beast, and it needs different solutions.

A mixed-media illustration of a double-necked electric guitar with glowing microtonal frets, set against sound waves that shift from orderly blue patterns to chaotic warm-colored interference patterns.

Temperature 1.0

I subscribe to a lot of music channels on YouTube, and last week every single one of them started talking about the same band at the same time. Not a slow build, not one creator picking up on another’s video. It was like a switch flipped. Two masked figures in black-and-white polka-dot costumes, performing on KEXP, playing music that sounded like it had arrived from a parallel universe where Western tuning never became the standard. The band is called Angine de Poitrine, and their live session has racked up over six million views. I sat there watching, grinning like an idiot, thinking: this is what temperature 1.0 sounds like.

If you work with large language models, you know what that means. The temperature parameter controls randomness in a model’s output. At temperature 0, you get the safest, most predictable token every time. The writing is competent and completely forgettable. Crank it to 1.0 and you get something wilder, less expected, sometimes brilliant, sometimes incoherent, but never boring. Most production systems run somewhere around 0.7, which is the sweet spot for “creative but not too creative.” It’s also, increasingly, the setting our entire culture seems to be tuned to.

The Median is Everywhere

A few weeks ago, I wrote about how our culture has been drifting toward monoculture for a long time, and AI is accelerating the trend. Language models are prediction engines. Left to their defaults, they produce the statistically most likely next token, the most average, most expected version of whatever you ask for. I argued that the writer’s job is to pull the output toward the edges, to resist the gravitational pull of the median.

But it’s not just writing. The flattening is everywhere. Algorithmic recommendation systems optimize for engagement, which in practice means optimizing for familiarity. Spotify’s Discover Weekly is tuned to give you something new that sounds enough like what you already listen to that you won’t skip it. Netflix thumbnails are A/B tested into oblivion. Even the indie coffee shop down the street has the same reclaimed wood and Edison bulbs as every other indie coffee shop in every other city, because the same Pinterest boards and Instagram algorithms surfaced the same aesthetic to the same demographic worldwide.

We are living at temperature 0.7, and I think people can feel it.

Something Between the Notes

Which is why Angine de Poitrine hit so hard. Everything about them resists categorization.

Start with the instrument. Khn de Poitrine plays a custom double-necked hybrid, a guitar and bass separately wired, each fitted with additional microtonal frets. It was custom-built by a local luthier in Saguenay, Quebec. Western music divides the octave into 12 equal steps. Microtonal music lives in the spaces between those steps, the quarter tones and third tones that are standard in Indian, Arabic, Turkish, and Indonesian traditions but almost unheard of in Western rock. When you listen to Angine de Poitrine, the notes themselves are literally between the notes your ear expects. The music is operating outside the grid.

Then there’s the visual identity. In an era of algorithmic personal branding, where artists are coached to show their faces, share their stories, and build parasocial relationships with their audiences, these two perform behind oversized papier-mâché masks. They go by pseudonyms. Their website states plainly that “any speculation regarding the identity of its members is unverified, not endorsed by the group, and could constitute an invasion of privacy.” They’ve stripped away every signal the recommendation engine uses to sort and categorize. No faces, no backstory, no brand. Just the music and the performance.

And the performance is unhinged. Their KEXP session is part math-rock concert, part absurdist theater, part fever dream. It shouldn’t work. It’s too weird, too dense, too far from anything the algorithm would select as “likely to engage.” And yet six million people watched it and couldn’t look away.

The Joke That Wasn’t Random

Here’s the part that matters most to me. Angine de Poitrine formed in 2019 as a practical joke. The two musicians were booked to perform twice in one week at the same local venue in Saguenay, so they put on masks and polka-dot costumes for the second show as a gag. But the people behind those masks have been musical collaborators for two decades, performing together in various projects since they were 13 years old. By the time the KEXP camera pointed at them, the craft underneath the joke was deep and undeniable.

This is the part that connects to something I’ve been thinking about a lot lately. Virality looks like luck from the outside. But what looks like a random spike is almost always preparation meeting a moment. These two spent twenty years building a musical vocabulary together, absorbing microtonal traditions from around the world, developing the kind of telepathic interplay that only comes from thousands of hours of shared performance. The band name was a joke. The musicianship was not.

Temperature 1.0 output only works when the model has been well-trained. Randomness without depth is just noise. What makes Angine de Poitrine compelling isn’t that they’re weird. It’s that they’re weird and masterful. The strangeness is intentional, controlled, the product of two people who know exactly what they’re doing and have chosen to do something no algorithm would have predicted.

The Hunger

I think the six million views aren’t an accident, and they aren’t just the novelty of funny masks. I think people are hungry. We scroll through feeds that have been optimized to show us what we’ll tolerate, and we’ve started to notice the sameness. When something comes along that is genuinely, irreducibly different, something that can’t be reduced to a Spotify genre tag or an engagement metric, it cuts through the noise like a signal from another frequency entirely.

Angine de Poitrine didn’t optimize for the algorithm. They built a custom instrument, put on masks, and played music that exists in the spaces between the notes the Western world agreed on centuries ago. And the world responded not in spite of how strange they are, but because of it.

Maybe the lesson is simple. In a culture tuned to 0.7, the thing that breaks through is the thing running at 1.0. But only if the model behind it has been trained for twenty years.