A man works at a lamp-lit desk in a dark, wood-paneled room, ringed by a circle of glowing monitors. One monitor at the edge of the ring, off to his side, flashes a red warning he hasn't noticed.

Tokens Over Hires

In the middle of September I ran ccusage against every Claude Code session on my laptop since May. It walks the local logs, counts the tokens, and prices them at what the API would have charged. I expected a big number. What came back was about twenty billion tokens and just under fourteen thousand dollars, across every project I’d touched in four months, with most of it going to Pepper, which is now open for signups, so go check it out. Nineteen billion of those tokens were cached reads.

I sat with that for a minute. Fourteen thousand dollars is real money. At my current pace it works out to roughly thirty thousand a year. I could triple it and spend a hundred thousand dollars a year on tokens, and that still isn’t one engineer. In exchange, Chris and I have shipped more code than I’ve shipped in any stretch of my career. I wrote in September that the two of us merged 657 pull requests in our first thirty days with a budget instead of a platform team. When I put the ccusage number in those terms on a panel, it came to about a dollar fifty a pull request.

That number is what my laptop would have cost at API prices, and it isn’t what we actually pay. Here’s the whole bill for both of us. Two Codex subscriptions, one each, are $200 a month. Anthropic is $550 a month: a Max plan for me and Chris, plus two Vycari team seats, one for Chris and one that runs our automation. I have an Ollama subscription at $200 a year. Greptile is about $1,500 a month. All in, that’s a little under $2,300 a month, or about $28,000 a year, for both founders and every pipeline we run. It still isn’t one engineer.

The obvious conclusion is the one a friend reached when he heard the figure: if code is that cheap, just get more tokens. I thought so too, for about a day. Then I looked at what was actually slowing us down, and the token budget wasn’t on the list.

The Constraint Is Attention

Every agent I run needs things from me that tokens can’t buy. It needs a plan approved before it starts. It needs its pull request read when it finishes. When it hits something it can’t decide, it escalates, and somebody has to be there to answer. None of those steps is expensive on its own. The problem is what happens when I run enough agents that the steps overlap.

When I run too many agents, the cost goes up a little and the risk goes up a lot. The biggest thing that’s slipped past us so far was how we managed database connections. It got out of hand, a little at a time, while my attention was on other pull requests, and eventually it caused an outage. Chris had to roll forward while I was out of town, and I spent the following week building a proper database abstraction layer. He put it more bluntly than I would have: the thing that kills us is splitting our attention. That’s when stuff slips through.

When people ask how we decide what to spend, I give them the order. Optimize for human time, because that’s the scarcest thing we have. Then money, because that’s the second scarcest. Then everything around agent time. “I can waste agent time all day. I don’t care.”

So the number that limits us is how many agents one person can supervise well at the same time. I don’t have a precise figure for that ceiling. I know I’ve been over it, because I can feel the difference between a day when every pull request got a real read and a day when I was skimming to keep up.

Another friend told me recently about engineers at his company running up bills in the thousands to build simple internal copies of SaaS tools. His reluctant guess was that they just aren’t as good at using agents yet, and that it’s a skill people have to develop. I don’t know what they’re doing differently. It doesn’t sound like token maxxing, which I’ve never really understood either. I’d love to sit with engineers who run up giant bills and just watch. My guess is they’re using the agents inefficiently, and that what’s missing is supervision, which a bigger budget won’t fix.

Building for More Agents per Person

Almost everything I’ve built since the summer has been an attempt to raise that ceiling, and almost none of it has been about spending less.

The pipeline I described in The Agent That Never Merges is the first piece. Agents open pull requests continuously and never merge them, which means the supervision cost per pull request is bounded at one careful read. The pipeline absorbs the rest: triage, planning, the first round of review comments, the retries. I only see the work once it’s in a state worth my attention.

The second piece is where the work lives. I wrote about pulling Pepper apart into small, bounded repositories to keep CI fast and give agents less to load. It mattered just as much for my attention. An agent working in a repository with one job produces a pull request I can evaluate in one sitting.

We’re up to fourteen repositories now. Last week I moved our iOS app out of the monorepo into its own. That was 150,000 lines of code, and nobody noticed except Chris, who had to wait a day to land his next batch of iOS changes. Agents make refactors that size easy. Having the CLI and the iOS client in their own repositories also forces us to keep good API definitions between the server and its clients.

The third piece is delegation inside the agent layer itself. I run two Claude Opus 5.5 orchestrators on medium effort. One is the UTL, for uber tech lead, and its job is to spawn subagents that build features. The other is what I call the focused worker, and its job is working with me. It catches the manual tasks that come out of the UTL’s pull requests and keeps them in a ledger. Then we work through them together: systems changes, bringing up new platforms, migrating data, anything that needs my level of access and oversight. Everything else goes to a subagent under the UTL, Opus for design docs and code reviews, Sonnet for implementing a feature from a design doc. Every one of these agents can consult a model a tier above it as an advisor, and they all share a wiki for notes.

Anthropic is now advertising much the same pattern with Claude Projects, and I’m happy to see others arriving at the same answer. Chris has been building a loop that babysits open pull requests through review until they score well enough to be worth a human’s time. Each layer like that turns a job I used to do by hand into something I check. The ceiling goes up one delegated task at a time.

The Token Budget Was the Easy Problem

There was a week in September when the meter really was the constraint. We ran through our free credits and paid about $120 in overage. Then AutoDev ate the whole Vycari quota, and I did server cleanup by hand because I couldn’t do anything else.

Most of that was self-inflicted. I’d started with Fable as the orchestrator, with no cap on context, and burned a week’s quota in three days. The setup above fixed it. The orchestrators run on medium effort, and the cheaper model does the implementing. Opus answers the reviews because Sonnet is too literal about them, and a literal reading turns two review cycles into twelve. Every agent auto-compacts at 200K tokens, because Anthropic charges more for context past that point. With that setup, and the work spread across parallel sessions, I find it hard to spend all of my quota. My goal now is to hit 99% of it every week just before it resets. I keep a list of research projects, and if I have quota left 24 hours before the reset, I spin one up. That isn’t the same as maxing out tokens. I’m not trying to use as many as possible. I’m trying to use all the ones I’ve already paid for.

There’s also a second account on the same machine. Claude Code reads a CLAUDE_CONFIG_DIR environment variable, so two shells with two config directories give you two accounts side by side. The second one runs the AutoDev and code review pipelines, and those use up its quota every week, so it isn’t a fallback for my own sessions. When I do run short, I supplement with other labs’ plans. Every one of those fixes took an afternoon or less. None of the supervision problems above has had an afternoon fix.

Where the Money Actually Goes

While I had the numbers in front of me, I looked at where development spend actually lands, because it isn’t where I expected either.

Development tokens currently run about ten times what the product itself consumes, even with real people using it. Building the thing costs more than running it. That won’t last. The feedback from our private beta has been really good, and we now open Pepper to a limited number of new signups every day, so product usage is rising quickly.

Most of what we actually pay goes to code review. Subscriptions are the cheap way to buy tokens if you’re willing to hit limits, so they’re the smaller line. Greptile reviews every pull request we open, and at about $1,500 a month it’s our biggest single expense. We both think it’s worth it, because it’s the layer that lets the never-merge pipeline run without me reading every first draft.

In October I tested that. I spent a few days building a cheaper reviewer to replace it. I came out the other side saying, “I think we should just pay for it because I can’t do it cheaper.” What I could change was how often we call it. The agents kept asking for a re-review before they’d fixed anything. Because every repository shares a common dev environment, the fix went in once: our pull-request skill now has agents run /simplify and then /code-review before they’re allowed to open a pull request. On many of our repositories, our own reviewer also does the first round and only then calls Greptile. My goal is a pipeline where Greptile’s reviews come back with nothing to say. We’re not there yet, but we get a little better every week.

I’d rather pay for review than have a second person do it, and the reason isn’t salary. The person would need supervising too, because review is a job I’d have to check, not one I can hand off.

What a Hire Is For Now

Five years ago, if I’d been getting a product like this ready for market, I’d have been hiring twenty to fifty engineers. The work would have needed that many hands, and most of what they’d have done was write code. Today the code is the cheap part. If I bring someone in to write code, I’ve added a person who needs plans approved and pull requests read, which is the exact resource I’m short on. A hire whose job is output adds coordination faster than it adds capacity.

I said on a podcast that came out last week that the code I’ve written would have cost about fifteen thousand dollars at API prices, and that I couldn’t hire engineers for that money. That’s true. The engineers I’d still want are a different kind from the ones I hired at Google. We need a few more people who can herd agents, not fifty.

The engineering hire that adds capacity is a different shape. It’s someone who can own a bounded service whole. Here’s the interface, here’s everything it needs to do, let me know when it’s done. That person brings their own supervision. They run their own agents, read their own pull requests, and answer their own escalations, and the only thing that crosses the boundary between us is the contract. Supervision divides along the interface instead of piling up on one person. That’s a tech lead’s job, and it’s the only kind of engineering hire I can see that raises the ceiling instead of lengthening the queue.

That raises a fair question about how anyone grows into that job now, which I tried to answer in The Questions Are the Job. The other advice I give is to work on open source. I’ve met people who showed they could work really efficiently with agents through open source projects, Gemini CLI in particular, and some of them ended up being hired onto my teams. Open source has its own problems right now. But if you show up as a thoughtful engineer with features or bug fixes that are well reviewed, well tested, and bring value to the project, I think you’ll be welcome. That’s one of the reasons I decided to open source the Pepper CLI.

The first hire probably isn’t an engineer at all. I’ve said this a few times now, including on stage at a panel in September. Neither Chris nor I are go-to-market people, and I may hire one before I hire another engineer. I can create piles and piles of code, even relatively good code. What I can’t do is agentically acquire customers. (Did I mention that Pepper is open for signups now?) Someone in marketing came up after the panel and told me I’d validated her existence.

The Third Trend

I’ve watched this happen twice before. Open source developer tooling made it so a small team didn’t need to buy or build its own compilers, databases, and frameworks. Cloud infrastructure made it so that team didn’t need to own hardware or a data center. Each time, the number of people you needed to start something real dropped, and the skills that mattered shifted toward the people who understood systems well enough to compose what was suddenly free.

Agentic tools are the third one. Anyone with a good idea can now get from concept to production on a budget that would have been a rounding error in a Google planning cycle. But the constraint didn’t vanish. It moved, the same way it did the last two times, toward the people who understand systems design well enough to drive the agents and notice when something has slipped through. I wrote a year ago that management skills were going to carry over to working with agents. I didn’t expect to be proving it with a two-person org chart and fourteen thousand dollars of tokens.

This isn’t only a small-company problem. At Google it was hard to get more than a few changes in a day, because each one waited on code review. I’ve talked to engineers there who now do all their work in experimental directories that don’t require review, then port it back to their team’s repository at a pace the review process can keep up with. That’s what happens when you don’t manage for human attention. Productive people spend their cycles waiting on the process.

When other companies ask me what to change, my answer has become: drive until human attention is the scarce resource, then build for that. If you’re reading your own ccusage number and wondering whether the answer is more tokens, look at where your attention went first. For us the answer has been more interfaces. Those are the places where one person’s supervision ends and another’s begins, or where an agent takes over a job one of us used to do by hand.

A hand with a pencil rests on an unrolled plan covered in penciled question marks, with automated machines running out of focus in the background.

The Questions Are the Job

Last month I spent forty minutes on a call with a college student who had just finished a summer internship at Google. He was polite about it, but the question under all his questions was the one I’d ask in his position. The agents write the code. The platforms hide the infrastructure. The CI pipeline is something you copy from a template and never read. So what exactly is he supposed to get good at?

I gave him an answer on the call. It was mostly right and mostly unorganized, and I’ve been turning it over since.

Nobody Asks for You

Around the same time I fixed a bug in a small sync daemon I run on my homelab. It pulls things I’ve saved in various places into Readwise, and on every run it asks Readwise what it has already seen so it doesn’t save duplicates. The agent that wrote it did that the obvious way. It walked my whole Readwise library and built a set of URLs. What neither of us noticed for a while was that the walk included my RSS feed, and on a real account feed items outnumber the things you’ve deliberately saved by orders of magnitude. The daemon paged through 103,819 feed documents and never reached the end.

I caught it because I was reading the logs and knew what my account looked like. The agent wasn’t going to catch it. It had no idea what a normal Readwise library looks like, and nothing in the code was wrong in a way a test would find. Then I had to ask for the second fix too. The dedup set needed to be a cache on disk that warms incrementally, not something rebuilt from scratch every fifteen minutes. That’s a design decision, and the agent didn’t make it until I asked.

Both fixes took an afternoon. Neither would have happened without someone in the loop who knew to ask. I’ve been living the same thing at Vycari at a much larger scale.

What I Actually Do All Day

Chris and I have merged more than 2,600 pull requests across Vycari’s repositories so far, with two people. Two months of that work came to 1.1 million lines of new code. We have an army of agents doing most of the coding, and I wrote in The Backlog Was a Coping Mechanism about what that does to an issue tracker. What I haven’t written about is what it does to my job.

I write very little code and I’m busier than I’ve ever been. I’ve started calling what I do meta-programming, because the work has moved up a level. I write the plans, the rules, the guidelines, the checks, and the hooks that push everyone who touches the codebase, human or agent, toward the right decision. Chris makes changes all over the codebase, and he doesn’t need my sign-off to do it. He’ll check with me sometimes, especially on database changes, but nobody knows what they don’t know. The guardrails exist for that. Whoever picks up a change next, human or agent, needs enough context to get it right, and that context is mine to build. It never stops needing maintenance.

The second thing I do is think about the shape of the codebase over time. We started as one repository. As the product got more complicated I began splitting services out, each into its own repo with its own CI and its own rules. I wrote about why in The Test Suite Is the New Code Review. That makes iterating on any single service fast, and it forces a contract between services that has to be written down. Agents don’t do this on their own, not even the best or newest ones. They’ll add a new top-level directory next to the last one forever, and thirty days in I had a repository full of horizontal directories, repeated code, and no shared components. I refactored it from version zero to version one over a weekend, mostly from my phone while I was at a jazz festival.

The agents were excellent at the refactor once I’d decided what it should be. Mechanical moves, package relocations, extracting an interface and applying it across a dozen subpackages: I could hand those off and not watch. The biggest one moved more than a hundred thousand lines of code, not all of it mechanically, and I was reviewing it on a phone. I only slept because we require ninety-five percent test coverage, and because adversarial review agents were reading the diff alongside me. But the decision that the codebase needed reorganizing, and the decision about what the organization should be, came from me reading the code and recognizing a shape I’d seen go wrong before.

Proportional Scrutiny

The student asked how you get good at systems when the abstractions keep you from touching them. Part of my answer was that you have to read the code the agent writes, which is different from reviewing it.

The distinction matters to me because most code review I saw at Google was style review. Someone would tell you a line was too long, or a name didn’t match the convention, and both of you would feel like work had happened. I don’t do any of that anymore. We use Ruff for linting and formatting, it runs on every PR, and whatever it says is fine with me. I also don’t fight the agentisms. There are twenty-five line comment blocks in our codebase, and I leave them, because the next reader of that file is another agent and the comment might be useful context for it. A comment explaining how a for loop works is wasted tokens, but I’m not going to spend my afternoon hunting those down.

What I do instead is apply scrutiny in proportion to what the code is. If an agent rewrites a pile of CSS, I open the page in a browser, it looks fine, and I move on. I’m not a CSS expert and I have no plans to become one. When an agent touches our core agentic loop, I read every line and I make sure I understand why every line is there. That loop is one of the pieces of the product I’d call real intellectual property, and most of it was guided by me, decision by decision. The agent is the same in both cases. What changes is how much attention I give its work, and knowing where that attention belongs is most of the skill.

That’s proportional scrutiny, an idea I learned from Luiz Barroso. You watch the things that took a big investment, that have a large blast radius, that are consequential to the rest of the system, and you give everything else a lighter look. It applies to engineering management too. Luiz used it to let a few of us chase a long-shot project for a year while he ran an organization of fifteen hundred people.

What Breaks First

My favorite question to ask an agent, and the one I gave the student to take home, is what breaks first if usage goes up by three orders of magnitude.

A hundred queries a second to a hundred thousand. A thousand users to a million. The agent will give you a real answer, and the answer will teach you about the system you’re building faster than any textbook I know of. If you can get a project to the point where you’re confident it would survive that, you’ve done the distributed systems course. Very few systems actually run at that scale. Asking the question is still how you learn to think about scale.

I learned it the expensive way. I’ve taken large portions of Google down more than once in my career, and the lesson from those days was simple: you learn from the outage or you get fired. I once led a team that built a geographic photo search system, and it had to sit in the main search path, so every query to Google.com went through our code. The day we turned it on our baseline was over a million queries a second with a five millisecond budget at the ninety-ninth percentile. The naive implementation took a week. The version that could actually carry that traffic took two years. That gap, between the thing that works and the thing that survives, is what senior engineers carry around in their heads. It’s what the student was really asking how to acquire.

The Bargain We Used to Make

His question is harder now than it was for me. The industry used to run on a trade. A new grad could write syntactically correct code and not much else. We’d hire them, they’d write a lot of code, and a tech lead would sit alongside them and teach them how systems actually fit together. They gave us labor, we gave them judgment. It wasn’t efficient, but it worked, and it’s how every senior engineer I know got here.

Agents took the labor half of that bargain. A new grad’s first year of work, the part where you write a lot of code and learn by getting it wrong, is exactly the work agents do well and cheaply. What’s left is the judgment half, and that was always the part that was hard to teach and impossible to shortcut. I wrote in The Last Programmers that each rung on the abstraction ladder frees us to work on harder problems. I still believe that. But the ladder used to have a bottom rung you could stand on while you learned, and I’m not sure it does anymore.

I don’t think that’s hopeless. I think it means the apprenticeship has to be rebuilt on a different foundation, and so does the university curriculum. Whatever anyone thinks of AI, it isn’t going back in the bottle for coding. The new foundation is the same one the senior people are standing on: the questions.

The Most Patient Teacher You’ll Ever Have

The part of my answer I most want to be true is that agents are the best teachers most of us will ever get access to, if you treat them that way.

Don’t take the PR blindly. Ask why it did that. Ask what the trade-offs of that data structure are. Ask what the runtime implications of that table layout will be at ten times the rows. Ask it to explain the same thing three different ways until one of them lands. It will never get tired, never get impatient, and never make you feel stupid for asking the same question again. Some of the tools lean into this directly. Claude Code ships a Learning output style that explains its choices as it goes and leaves small pieces of the code for you to write yourself. That’s closer to what a good tech lead did for me than anything I got from a book.

I do a version of this constantly. I’ll point an agent at a subsystem and say I want to understand this deeply, walk me through the important files and the control flow. I’ll ask for a diagram of how a subsystem looks in main today and then interrogate the diagram. When I was a senior director that was exactly how engineering reviews worked: someone came in with block diagrams and sequence diagrams and we talked about the project at that level of abstraction. I wrote about coming back to the individual contributor side in Full Circle. One of the surprises has been how much of the director job I still do, just with an agent across the table instead of a team.

I’ve even considered running a full design review this way, asking an agent to build a presentation and walk me through its decisions the way a team would have. I haven’t taken it that far yet, but I may at some point.

That’s the rebuilt apprenticeship. You still have to write some code by hand, and you still need a couple of languages you’re truly fluent in. But the judgment you used to absorb from a tech lead over three years is now something you can pull out of an agent on purpose. You do it one question at a time, starting on your first day.

I don’t want to oversell this. Glyph Lefkowitz makes the strongest version of the opposing case in Programming Isn’t Special. Take away the mundane work and you take away the practice, because “the majority of true skill development happens on the job and always has.” He’s right about that part. Most of my own judgment came from getting things wrong in production, and asking an agent good questions doesn’t replace the experience of an outage you caused. What it can do is get you to your first real failures sooner, with a much better map of what you’re looking at when they happen.

There’s also something the agent can’t teach you, which is anything that happened after its training data ends. When a new language feature ships, the agent won’t reach for it unless you tell it to, because it has never seen it. Knowing when a change like that matters, and when to bring it up, takes judgment and experience of your own.

How We’ll Know

The student asked about hiring, and I gave him a split answer. Google and the other big companies will move slowly on this. The interview you get there in five years will look a lot like the one you’d get today: computer science fundamentals, system design, distributed systems. Those things aren’t going away, and the big companies are right to keep testing for them.

Startups will change faster, and I’m one of the people who gets to decide how. We’re not hiring at Vycari yet, but when we do I’m not going to put anyone in front of a whiteboard. I think that’s archaic now. What I might do is hand a candidate a coding challenge and an agent, and ask for the transcript instead of the code. How they worked with the agent will tell me more about how they’ll work with us than the code will. Did they read what came back? Did they ask why? Did they notice the thing that was going to break at scale, or did they ship the first thing that passed the tests?

I recently built a whole project in Swift, and I had never written a line of Swift before. I mention it because it shows how little the language matters now, and how much everything else does. The student was worried the abstractions were taking the important skills away from him. I think they’re taking the unimportant ones and leaving the important ones exposed, with nothing to hide behind. That makes the job harder. But the questions were always the job. We just used to let people spend a few years writing code before we told them.

A large monolithic glass building splitting apart along clean seams into smaller connected structures.

The Test Suite Is the New Code Review

Some mornings I watch a pull request move through our whole pipeline before I’ve finished my coffee. An agent opens it. A second agent reviews it. By the time I sit down, the only thing still running is the test suite. That gap, the minutes between “reviewed” and “safe to merge,” has become the slowest part of how we ship.

This is the third post in a series about how Chris and I build Vycari. The first was about the issue tracker and what belongs in it once agents do the work. The second was about the pipeline that works through the tracker and never merges its own pull requests. This one is about what those pull requests wait on, and how the answer changed the shape of the code.

It didn’t used to be the tests. Plenty of us optimized CI over the years, but we optimized it by tiering it. A few minutes of unit tests at your desk before you pushed. A longer run in CI once you did. A slow integration suite that went off every few hours, or overnight. When it came back red, you bisected your way to whichever pull request broke it. That held up because a human was going to review the change anyway, and that took an hour or two at best.

Agents changed that arithmetic. One agent opens a pull request. Greptile reviews it in a couple of minutes. Human and machine are both waiting on tests now. If the full suite takes thirteen minutes, that’s thirteen minutes with nothing else in the way. Multiply that by the pull requests moving through Pepper on a given day and you need a merge queue to keep them from stepping on each other. I’ve finished a change by hand, pushed it, and found myself forty minutes behind a queue of agent pull requests, each one blocked on the same thirteen minutes. Before agents I would never have set up a merge queue for a two-person project. The idea would have been funny. It’s now part of my standard repository setup.

The tiering trick can’t save us either. We still run a slow suite overnight, but it can’t stand between a bug and production, because we ship on green, or near enough: every merge builds an image, and production picks up whatever is current on a fifteen-minute cycle. Call it half an hour from merge to running, and that’s the whole window I have to find out something is wrong. A suite reporting at midnight would be telling me about a bug I shipped at nine that morning, with a few hundred agent pull requests stacked on top of it. Twenty minutes of CI used to be unremarkable. It feels like an eternity now, because everything around it got faster and it didn’t.

The Repository Gets Harder to Hold

Making the suite faster buys time without touching the deeper problem: the repository keeps getting harder to reason about as it grows. A human engineer joining a large codebase builds intuition for its boundaries over weeks. They learn which corners are scary and which are safe to touch without asking anyone. An agent doesn’t get that runway. It arrives cold on every task, reading whatever context you’ve given it and inferring the rest from the code next to it. The bigger the repository, the more code there is to infer from, and the easier it is to miss a contract something else depends on.

I tried to buy that intuition back with context files: hierarchical instructions at every level of the tree, skills describing the traps in one corner of the code. All of it helps, and none of it is free. Every context file is one more thing to write and keep current. Even a well-oriented agent has to hold the whole shape of the repository in its head to change anything that crosses a boundary.

None of this means monorepos are a mistake. They’re a fine pattern for people who already know where the walls are. The problem is narrower: a monorepo is a bad pattern for a team where most of the work gets done by something that relearns the walls on every task.

Pulling the Slice Out

The fix I’ve settled on is structural. When a piece of functionality is clean enough to stand on its own, I pull it out into its own repository before it tangles into everything else. It gets its own tests, its own merge queue, its own release cadence. An agent working inside it can hold the whole thing in its head.

We already have a pattern for this, and it’s older than any of the AI tooling. Amazon has run this way since Jeff Bezos mandated that every team expose its data through service interfaces, with no direct linking and no reading another team’s data store. Steve Yegge described that mandate in 2011, and the detail everyone remembers is that non-compliance meant termination. Microservices came out of an organizational problem before they were a technical one: teams that couldn’t see inside each other needed real contracts. I’m solving that problem, except the team members who can’t see inside each other are models.

The first slice I pulled out was groups, the part of Pepper that handles shared context between people. Working on groups was much faster than working on Pepper itself, and the reason was almost embarrassingly simple. The test suite was only testing the group stuff. Nothing about calendars, nothing about the agent loop, nothing about the web client. A pull request in groups clears CI in about two minutes, against thirteen for the same work in the monorepo, and it has held at two minutes as the code grew. The old number survives in one place: a push to main, where the fuller job set builds the image and can take fifteen, after the merge instead of in front of it.

I don’t have a rule yet for when a slice is ready to leave the monorepo. Right now I go by feel: one clear job, one owner, and an API narrow enough to describe in a sentence. Pull it too early and you’ve built a service around something that still needs to change shape. Pull it too late and it’s already tangled into three other things. I’ve been wrong in both directions. And one slice out is not a track record. The first extraction is always the cleanest. Ask me again at six services, after the costs have compounded.

Anthropic ran into the same problem from the other direction and wrote up what agentic coding did to their CI. Their engineers ship eight times as much code per quarter as they used to, and Claude writes eighty percent of it. CI jobs grew twenty-five fold in six months on headcount that barely moved. Their answer is test impact analysis: keep the large codebase, and run only the tests a change could plausibly affect. If I had a team to maintain something like that, I’d build it. I don’t. Test selection is a system somebody has to own and keep correct, and at two people every system we own competes with the product. Splitting the repository buys most of the same speed by construction, and it fixes the context problem as well. At Anthropic’s size I would almost certainly choose the way they went.

There’s a principle underneath this. I want each of our Python codebases to look like every other open source Python codebase that exists. Not because I’m attached to convention for its own sake, but because a model has seen a million repositories shaped that way. It has seen almost none shaped like a sprawling internal monorepo with its own rules. A small, conventional repository is legible to an agent before it reads a single context file.

The Boundary Has to Be Real

Splitting only pays off if the interfaces are real. A boundary with a vague interface behind it is worse than no boundary. The coupling is still there and now you can’t see it. Google got this right early with protocol buffers: one schema everybody compiles against, changes that stay backward compatible, and no ambiguity about what a service accepts or returns. We’re doing a smaller version. Each service has a defined interface and the calls run over a fast internal Docker network. The interface is what we argue about in review, not the implementation behind it. For an agent working in one repository, that contract is the whole surface it has to respect.

So what catches the bugs that live between services, now that no single suite covers all of it? Three things, in descending order of respectability. The contract, which is why folding groups back into Pepper took a morning. A browser suite that runs overnight against the real application. And the fact that two of us live in the product all day, so anything broken between services turns up in our own use within hours. That last one is not a strategy. It’s what you get at two people with no customers, and it’s the first thing to break when either number changes.

Where this ends up, if I follow it through, is a web application in its own repository, the clients grouped with their browser tests, and a Pepper repository that is just the agent and its tools. That last part is the point. The thing that makes Pepper Pepper should be small enough that an agent can hold all of it at once.

The tradeoff shows up in cross-cutting work: features that used to be one pull request in the monorepo are now a change spread across several repositories. Three repositories means three pipelines and three cold starts, so total compute went up even as the wait in front of any one change came down. Most work happens inside a single repository, so I’m happy to pay it. My first answer was to check out every relevant repository into one parent directory and start an agent there, with all of them in view at once. That parent directory has since become a repository of its own.

One Tech Lead, Many Repositories

For anything that spans repositories, I start what I call my UTL agent, after the old Google title Uber Tech Lead. A UTL was senior and broad enough to operate across systems without owning any of them. Mine runs on Fable 5.1, the strongest model I have for this kind of judgment, though the role matters more than the model filling it.

The UTL lives in that parent directory, which is now a meta-repository. It checks out every other repository underneath it, carries the shared skills, and is growing an operations plugin that knows how to talk to production. The pipeline from the last post runs from there too, one pull request per repository per tick. Making that work meant a consistency pass across every repository: same CI, same branch protection, same conventions. If the plan is to keep splitting, creating a new repository has to be easy, or the friction becomes the reason you don’t.

The UTL almost never writes code. It’s instructed to delegate, and I’ve been strict about that, because the moment it starts editing files itself I’ve lost the thing I built it for. It’s my emissary to the agentic army. I talk to the UTL, the UTL talks to the subagents, and the subagents write the code.

What it has instead is a toolbox of specialized subagents covering the stages of our development cycle, and judgment about which to launch when. Opus for design. Sonnet, Luna, or Flash for implementation, depending on how much thinking the work needs. Opus again for responding to code review, because arguing with a reviewer about whether a finding is right takes more judgment than the code did. For work that spans repositories, the design pass produces a plan covering all of them. What changes where, in what order, and which pieces can move in parallel. Then the implementation agents go out, one per repository, each carrying a slice of that plan. What’s left is bookkeeping: tracking every pull request it spawned until each one lands, and knowing which are blocked on another repo’s change merging first.

What This Costs

None of this is free. Splitting a monorepo trades one kind of difficulty for another.

The first cost is in your own head. You have to decide which service a piece of work belongs in before starting it. A monorepo never charges you that tax. The second cost is reliability. Repositories that used to fail together as one deployable now fail independently. You have to know which parts of your system can take another part down with them, and build the ones that can’t afford it differently. We haven’t had that failure yet, so this cost is still theoretical for us. The third cost is coordination that never goes away. Shared libraries need update schedules, API contracts need versioning, and a change that used to be one pull request can turn into three, timed so none of them ships broken.

There’s a fourth cost. This is a two-person company that hasn’t launched yet, and repository architecture is not a feature. Somewhere in the middle of the split I asked Chris whether I was faffing around with infrastructure instead of building the product. His answer was that building on a bad foundation just eats you with low velocity, and the point of doing it now is that we never have to do it while customers are watching. He also pointed at something I hadn’t seen. When we hire, a bounded repository is the thing you can hand a new engineer whole. Here’s the interface, here’s everything it needs to do, go. That’s a much better first week than a tour of a monorepo’s cryptic corners.

I’ve paid all four, and I’d pay them again. The alternative, one repository that keeps absorbing everything, doesn’t remove that complexity. It hides it inside a single directory tree until an agent runs into it blind, which is a worse way to find out.

Where the Gate Sits Now

Code review used to be the thing everyone waited on. It was slow, and it was where a second set of eyes actually caught something, so everything else could afford to be slow too.

Agentic review took that bottleneck away almost entirely. A pull request gets opened and reviewed in the time it takes me to read the agent’s description and the parts of the diff I care about. We’re getting closer to letting the pipeline merge its own work, which would retire the rule I wrote about last time. What’s left waiting after that is the machinery underneath: the test suite, the merge queue, the deploy pipeline. Thirteen minutes doesn’t sound like a long time, until it’s the only thing standing between one agent finishing a task and the next one starting. Repeat that across every pull request a day produces, and thirteen minutes stops being a rounding error.

The other side of that machinery is where the split pays off. In a small repository, a feature can go from an idea to running in the product in about half an hour, and the only thing that half hour depends on is CI. In the monorepo, the same feature waited on tests for code it never touched.

That’s the argument for breaking the monorepo apart. The gating factor moved from human judgment to compute time, which is the one delay in this system that’s engineering-tractable. You can’t make a human review faster without asking less of them. You can make a test suite faster by shrinking what it has to know about, which is what a small repository does. I wrote in the first post about the tracker that decides what agents can touch. The repository boundary matters just as much, and it’s the one I spend most of my architecture time on now.

What’s Next

The next experiment follows from the way the UTL already works. If it can plan and delegate across repositories, it should be able to delegate the tech-lead role itself. The plan is to stand up a second, cheaper tech lead for one migration, run it to parity on its own repository, and have it escalate two things: decisions that need a human, and anything that touches production. If that works, Chris and I spend most of our engineering time on design documents rather than pull requests, and the design document becomes the real unit of work. Chris’s caveat, which I think is right, is that user experience is the part you can’t specify up front. That’s the honest limit on all of this, and probably a later post.

A wooden desk at night with six overflowing paper inboxes, each connected by a copper wire to one neat stack of paper beside a notebook and pen.

Capture Everywhere, Think in One Place

I read a lot. News comes in through RSS feeds, ideas come in through podcasts, and the slower stuff comes in through books and magazines. A surprising amount of it ends up in what I write here and in the work I do at Vycari. An article I skimmed in March becomes the counterexample I need in a design discussion in August. A talk I half-watched on a Saturday becomes the seed of a blog post.

That only works if I can find the thing again. Two years ago I had the same problem with podcasts, and I built a search system over my listening history to solve it. This time the shape was different. My notes live in plain markdown files in Obsidian, and that vault is where I think. The problem was that my reading didn’t live there. It lived everywhere else.

Six Inboxes and No Desk

Readwise held my RSS feeds, my Kindle highlights, and my Twitter bookmarks. Karakeep, the self-hosted bookmark manager on my homelab, held the links I saved from my phone. GitHub stars were an input I cared about as much as any article, and they lived in GitHub. Each of those places was a fine place to capture something and a terrible place to find it three months later.

YouTube was the worst of them, and it’s what started this. I watch a lot of talks and technical videos, and almost none of that made it into my notes. I wanted a thumbs-up on a video to mean something, the way a highlight in a book does. I tried IFTTT and Zapier first, and neither would do the simple thing I wanted, which was to take a liked video and put it somewhere I could triage it. I’d forgotten that detail until I sat down to write this. The whole system grew out of one missing integration.

I’d built the capture habit. Starring a repo, liking a video, or bookmarking a page costs nothing, which is exactly why I did it constantly. The idea is borrowed from David Allen’s Getting Things Done: get everything out of your head and into an inbox, then process the inbox on a schedule. The inbox half stuck with me. The processing half never did. I have never once had the discipline to sit down for the weekly review, and so the highlights and stars piled up in their silos. When I sat down to write I worked from memory and a few frantic searches.

Last November I wrote about personal software, software written for an audience of one. The thing I noticed then was that I’d stopped searching for tools and started building them. This problem was the next test of that idea, and it showed me something about how the idea is changing. That post was about small utilities and one-off scripts. What I built this time is a service, with a scheduler, a status page, secrets management, and a CI pipeline, and I built it the same way I’d build a twenty-line script. The tools I write for myself are getting more sophisticated, and the cost of that sophistication hasn’t gone up. I want to walk through what I built, because the shape of it says something about where this is going.

One Pipe Into Readwise

The decision that made everything else simple was to pick one database and route everything into it. That database is Readwise Reader. A purist would say the daemon should write markdown straight into the vault and skip the middleman, but Readwise already held half my sources and did that job well, with good iOS and browser clients and a maintained Obsidian plugin that pulls everything into the vault on a schedule. Nothing there was broken, so I didn’t fix it. I built only the missing pipe: the three sources that had no way into Readwise at all.

So I opened a coding agent and described a small daemon. It polls a set of sources, pushes anything new into Reader, and dedups against what’s already there. The result is sync-to-readwise, about two thousand lines of Python that has been running in a Docker container on my homelab since May. It handles the three sources Readwise couldn’t reach on its own: YouTube likes, GitHub stars, and Karakeep bookmarks.

The core of it is an interface with one method.

class Source(ABC):
    name: str
    default_location: str = "later"
    default_tags: tuple[str, ...] = ()

    @abstractmethod
    def fetch_candidates(self) -> Iterable[Item]:
        """Yield candidate items. The Syncer handles dedup."""

A source yields items with a URL, a title, and some metadata. The syncer asks Readwise whether it has already seen that URL and saves the ones it hasn’t. That’s the whole design. Adding a new source is one file and a line in a registry. That’s how the project went from YouTube likes on day one to GitHub stars the same afternoon, and Karakeep bookmarks over the summer.

The GitHub source is a good example of how little a source has to do. It pages through /user/starred, and for each repo it hands back the URL, the full name, the owner, and the description. Reader does the rest, fetching the README and filing it as an article tagged github. When I star a repo now, its README shows up in my reading queue within the hour.

The interesting engineering was all in the parts that touch Readwise, not the sources. Reader’s API allows twenty list requests a minute. A cold start that walks your entire library to build the dedup set runs straight into that limit. My first version had the two rate limits transposed, so it paced the generous endpoint carefully and hammered the strict one. Worse, it was walking my RSS feed items, which on a real account outnumber the things I’ve deliberately saved by orders of magnitude. The homelab deployment paged through 103,819 feed documents without reaching the end. The fix was to exclude the feed from the dedup cache entirely, persist the cache on disk, and warm it incrementally on each run. None of that was hard, but it was the kind of thing you only learn by running the tool against your own account.

It’s also a reminder that the agent didn’t notice either problem. I did, because I was reading the logs and knew what my account looked like, and then I had to ask for the cache. There’s a whole post in that, about what the job of an engineer becomes when the agent writes the code, and I’ll get to it soon.

Secrets live in Doppler, the same shape we use for Pepper at Vycari, so the only thing on the host is a service token. There’s a small status page that shows each source’s last sync, its counters, and whether the YouTube OAuth token has expired. If it has, there’s a link to re-authorize from the browser. I added that after the second time I had to SSH in to fix a token, and because I wanted a way to glance at the service and know what it was doing. Since then the token has stayed put and the service has just hummed along.

Claude Files It

Readwise’s plugin lands new documents in a Readwise folder in my vault throughout the day. That solved the finding problem, but it created a filing problem. A folder with a few hundred articles, videos, and repo READMEs is a pile, not a system.

That is where Claude comes in. I have a skill in the Claude desktop app that runs on a schedule and sweeps the new Readwise material into the projects it serves. Each project in my vault has a landing note that summarizes what the project is about. The skill reads those, reads the new documents, and appends each one to the right project’s sources note with a line or two on why it belongs there. When enough unfiled items cluster around a theme that isn’t a project yet, it proposes one. The sources note for this blog as a whole, not for any one post, now has an entry for an IEEE Spectrum piece on skill atrophy under automation. Next to it is a note that it pairs with a draft I’m working on about agents and code review. I didn’t file that. I read the article on my phone, it flowed through Readwise into the vault, and Claude worked out where it belonged. I wrote about scoping an agent to a project’s context earlier this year, and this is the same idea applied to intake rather than writing.

The most common miss is that Claude can’t place something and leaves it in an inbox for me to sort by hand, which is still a fraction of the sorting I’d be doing if I did all of it by hand. The other miss is that it attaches an article to a project where it doesn’t really belong. When that happens I delete the line while I’m reviewing the sources for that project, which I do every time I sit down to write from them. I’d rather have a few sources misfiled than never see them at all, which is where I was before this project. That review is the human check, and it’s the part of GTD I could never sustain on my own. The agent does the weekly review as my research assistant, and I do the reading when it matters.

The effect is that capture is effortless and organization is close to free. I star a project, thumbs-up a video, bookmark a page, or highlight a paragraph, and I don’t think about it again. When I open a project to write, the reading I did for it is already there, with notes on why I saved it.

What I Didn’t Do

I did look for an existing tool, briefly. IFTTT and Zapier were the obvious candidates and neither fit. A year ago that’s where the evening would have gone: reading comparisons of read-it-later services, trying two of them, and settling for the one that covered four of my six sources. Instead I sat down one Saturday, described exactly what I wanted to a coding agent, and let it build. A second Saturday over the summer added Karakeep. A few hours each time, and I learned something on both of them, which felt like a fair trade. Between those two sessions the tool has cost me almost nothing to run. It covers the three sources I was missing and nothing else, and the whole system now covers all six.

The audience of one keeps paying off. The tool has no settings I don’t use, no features waiting for someone else’s roadmap, and no update that quietly changes how it works. When Readwise’s rate limits bit me, I fixed it that afternoon, which is the responsibility I signed up for when I stepped outside managed software. That trade has been worth it every time.

The Part That Worries Me

Lately I’ve noticed the same attitude creeping toward software I already use and pay for. I run a window manager that does ninety percent of what I want and is missing one feature I care about. More than once I’ve thought about having an agent rewrite the whole utility so it does exactly what I want and nothing else. I haven’t done it yet, but the fact that it’s a live option is new, and I don’t think it’s entirely good.

To be clear, my private rewrite wouldn’t hurt anyone. I have no desire to sell or support any of my tools, and most of them aren’t even open source, because I don’t want to field issues or review pull requests for something that was only ever meant for me. This sync tool is public because I wanted to write about it, not because I want anyone else to run it. What worries me is the pattern, not my copy of it. As building for an audience of one gets easier, more people will reach for it first, before they look for the thing that already exists and does most of the job. The people who build those ninety-percent tools are mostly small independent developers, and a world where their potential customers default to rolling their own is a harder world for them to make a living in. I don’t have an answer for that. I notice that I’m part of it.

What I get back is time. I spend almost none of it organizing and much more of it thinking, and the thinking is better because the raw material is at hand. This is the first post in what I expect to be a series on the personal software I actually run. The next one will be about a tool I built for a very different kind of problem.

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.

An overhead view of a wooden desk holding two laptops side by side. The left laptop is closed and covered in old stickers with a security badge on top. The right laptop is open with fresh stickers and a code editor on screen. A sheet of dated notes lies between them.

Writing My Way Out

I started writing this blog two years ago because I wanted to share what I was learning about AI, and the projects it kept pushing me to take on. A year ago I wrote the first anniversary post, and it ended with a plan. Two thoughtful posts a month instead of the weekly pace that had already beaten me once. More explainer series, because the embeddings posts had been the most-read thing I published. Some shorter pieces in the spirit of Simon Willison. And permission, finally, to write about the woodworking and the guitars instead of quietly worrying that they were off topic.

I had no idea, when I wrote it, that by the time I sat down to write the next one I would not be at Google anymore.

The plan mostly worked

I published fifty seven posts between that anniversary and this one, which is a little under five a month against a goal of two. I am not sure that counts as keeping a promise so much as failing to keep it in the more enjoyable direction.

I had been afraid that I would run out of things to say. The opposite happened. If I look at my drafts and ideas folders right now, there are close to fifty posts in there that I still want to write and have not found the time for.

The explainer series happened. The Agentic Shift was planned as twelve parts, and it came in at twelve parts, thirteen if you count the introduction, running from September through April. The structure held up almost exactly as I outlined it. What I did not anticipate was how much the ground would move underneath it. I thought I was writing a textbook, assembled in public. What I actually wrote was a journal of a landscape that would not hold still long enough to be documented. I outlined Part 9 as speculation about a future problem and published it as reporting on a present one. I am really proud of that series, and I think it has stood up well.

The shorter pieces happened too, though this one is still a work in progress. Eight Reading Lists, which started as an experiment in whether I could publish something in under an hour and turned into the format I reach for when an idea is real but not yet a post. I never got to the point of posting one every week, and that is something I want to get better at this year.

And the hobbies made it in. A bill in the California legislature that wanted my 3D printer to police itself. A French band I could not stop listening to. A Starlink dish on the roof of a car. The Köln Concert, as an argument about creative constraints in software. Nobody unsubscribed, as far as I can tell, which suggests the worry was mine and not my readers’. There is more of that to come, I hope.

The post that turned out to be about something else

In April I counted my GitHub contributions for the year. There were 4,255 of them, and the post was supposed to be a light piece about the shape of a year of building in the open.

The interesting number was not the total. It was that my most productive day of the week was Saturday, by a wide margin, and the reason was not discipline. It was that Saturday was the day nobody had scheduled anything. I wrote at the time that this was a diagnosis rather than a brag, and I meant it more casually than it turned out to deserve. Given time and no meetings, I build things compulsively, and I am happier. That is a useful thing to learn about yourself. It is also the kind of thing that, once you know it, quietly reorganizes every other question you were asking.

Four months later I left, after twenty one years, most of a career, and about half my life. Twenty One Years is the post about that. Not Everyone Wants a Hobby is the post about what I left to go do, which is a company called Vycari that I am building with Chris Perry. Chris was the product lead for Colab when I ran the AI Developer organization, we were both on the founding team of Gemini CLI, and somewhere in there he became the person I most wanted to build with. He is the CEO, I am the CTO, and our first product, Pepper, is a personal assistant for your life. And Thousands of Goodbyes is the post about pointing an agent at twenty one years of my own sent mail because I could only remember about a hundred and fifty of the several thousand people I had worked with.

I did not plan any of those as a trilogy. Reading them back to back, they are obviously one thing.

What the blog was for, and what it is for now

When I started writing here, the blog had a job inside a larger job. I said as much in the first anniversary post: building in the open and writing about it was how I contributed while my calendar was still too unpredictable for mission critical work, and it let me lead by example, demonstrating the kind of developer engagement I was hoping to inspire in an organization I was running.

That is a perfectly good reason to write, and it is gone now. There is no organization. There is no example to set for anyone but Chris and me. The blog is no longer a thing I do alongside the work, and it is not marketing for the work either. It is the only continuous artifact I have from before to after, which I did not appreciate until I went looking for a through line and found that the writing was the only place one existed.

There is an obvious hazard in this, and I would rather name it now than have you notice it in six months. Founder blogs decay into product announcements. It happens gradually and the person writing them is always the last to see it. So let me be clear about what you should expect. I am going to write about Vycari and Pepper, because they are the most interesting things happening to me right now. We are building a new kind of agent harness and a new kind of agent, and there are a lot of stories in that. Some of them will be technical, like the recent post about what happened to our issue backlog once agents were filing most of the issues. Some of them will be about philosophy, like why the chat window is the wrong interface for most people and why almost nothing a consumer agent does needs a frontier model, and a few of them will be things I did not feel I could say while I worked at Google. What I can promise is that everything I write here is here because I think it is useful to share, because I think you will enjoy reading it, and because I think it articulates why Chris and I, and the company we are building, are different.

The people who read this blog are people who will happily install a CLI, configure an API key, and read a changelog for fun. They are the reason it exists. I am aware that I have just started a company premised on the argument that requiring all of that is a failure of product design, and I do not think those two things are in tension, but I understand why it might look that way. Working out loud on that confluence is most of what I expect year three to be about.

Year Two, By the Series

The Agentic Shift

Twelve parts and a retrospective, September 2025 through April 2026. The series that ate the year, and the work on this site I am proudest of.

Building the Things I Write About

The Reading Lists

Eight of them, starting in April. Short, fast, and the closest thing this blog has to a running commentary.

The Work Itself

Building Vycari

The first three posts of the next chapter. None of them is a launch announcement, which is the point.

Everything Else

The promise I made last year to stop worrying about staying on topic.

Year Three

More of the same, with one change I am now a month into.

For two years I wrote about agents from inside a company with essentially unlimited access to models, infrastructure, and the people who build them. Everything I published came with that thumb on the scale, whether or not I acknowledged it. For the past month I have been building the same class of system with two people and a budget. In the first thirty days of that, the two of us merged 657 pull requests, our agents filed most of the 449 issues that came out of them, and something like a hundred and fifty million tokens went through the product for about forty dollars. Those are not numbers I could have written from inside Google, and they are the constraints almost all of my readers have always lived with. I expect that to make the writing better, and the series on how the two of us build, which started with the issue tracker, is where I intend to find out.

I also want to keep doing what Thousands of Goodbyes turned out to be, which was the first time in two years of writing about agents that I pointed one at something that was not work and had the output make me feel something. There is a great deal more of that available, and almost nobody is writing about it, because we are all still busy benchmarking.

Beyond that, my goals are simple. I want to keep sharing what I learn. Last year I said a weekly pace was not sustainable, and then published nearly five posts a month, so this year I am going to say it out loud: at least one real piece a week, with shorter things sprinkled in on the other days. I am trying to be more active on X and LinkedIn as well, so if you see me there, say hi. I will keep bringing more of my outside interests into this space, though it will almost always have a technical angle. There are more management posts planned, a tribute to a friend who is gone, some book reviews, and more.

Two years ago I hit publish on the first one of these with no idea where it would lead. I have a much better idea now, and I am still not going to tell you it is a plan. I am looking forward to what comes next, and I am glad you have decided to come along.

An ordinary compact sedan in a driveway at dawn, sharply in focus, with a covered exotic sports car blurred in a showroom behind it.

Not Everyone Needs Superintelligence

Every morning, while my family gets ready for the day, we have KQED on throughout the house. Proud members since 2000. Then I listen to podcasts while I work out. Either way I am half listening, the way you do, attention drifting between whatever is playing and planning for the day in front of me.

Last week I caught a segment about frontier models, and I could not tell you now whether it was the radio or one of the podcasts. The speaker was talking about pricing and performance, I think in relation to the new GLM model. Then he started talking about cars, and I stopped half listening. These frontier models are Ferraris, the argument went. Most people don’t drive a Ferrari. Most people drive a Corolla.

I have spent a lot of time over the last few years building agents that run on Corollas. Last year I built a coding agent on Gemini Flash 2.5, mostly to find out whether I could get really good performance on a lightweight, less expensive, and faster model. Lately I have been working with Chris on Pepper, a personal assistant for your life. Pepper runs on Corollas too.

That line stuck with me throughout the day. I mentioned it to Chris on a call the next morning, and he tied it back to one of my previous posts, the chat box is a detour. He was right: they are the same argument at two different layers. That post said we handed consumers the wrong interface because a chat window was the honest expression of what models could do in 2022, and then we never revisited it. This is the same mistake one layer down. We build on the frontier tier because that is where the attention is, not because the work requires it.

What Our Product Actually Runs On

At Vycari we are building agents that handle the day to day, and Pepper is the first one. Almost all of its agentic work runs on the cheapest models the big labs sell. Orchestration goes overwhelmingly to Gemini Flash Lite 3.5, with small slices of Claude Haiku 4.5 and GPT-5.6 Luna routed alongside it to keep us honest about vendor lock-in, and to give us a baseline for our own evals. Somewhere around a hundred and fifty million tokens have gone through the system for about forty dollars, which starts looking like a rounding error once you notice that an Opus-class harness can spend forty dollars in minutes.

The work those models do is not exotic. Look at a calendar. Read an email and decide whether it needs a response. Manage my exercise log, or find my to-dos. When I wrote about how everything becomes an agent, the point underneath was that an agent brings value by deciding in the moment, with real input in front of it. Most of those decisions are small. If you were hiring a person for this job, you would not start out looking for a PhD.

That changes the shape of the pricing conversation. For a lot of use cases we have been standing in the Ferrari showroom asking for a deal, when the better move is to walk down the street to the Toyota lot. The question was never how to get the frontier tier cheaper. It was why we were standing in that showroom at all, holding a list that reads: check the calendar, read the mail, log the workout.

The Objection I Keep Hearing

I have heard the objections. Small models hallucinate. They report success on work they never did. They narrate a tool call as prose instead of calling the tool, and the turn ends clean with fabricated content sitting in it. I have watched all of that happen in production.

The objections come out of real experience, and they were true recently enough that I understand why people still reach for them. But this industry is moving so quickly that we often have to check our assumptions on the models that are available today. The cheap tier climbs about a rung a year. The lite model I run today does work that belonged to the mid tier a year ago, and that mid tier was doing work the frontier owned the year before that. The objections have not been updated since the last time they were correct.

So we ran a quick eval. Nine recorded production turns, one for each failure shape our nightly reflection kept filing, replayed against three tiers: the lite model we ship on, the mid Flash model, and Pro. Fixed thinking budget, three samples per arm, and a grader from a different vendor so we were not asking Gemini to mark Gemini’s homework. I expected a ladder. What came back was flatter than that.

That is a small eval and I am not going to pretend otherwise. What I can say is that we have now watched the platform across thousands of model calls, and what the eval showed is holding up. We are not a public product yet, so the data is thin and I would not ask anyone to take it as settled. But every time I take one of our failing cases from Flash Lite and hand it up the ladder, the results refuse to move the way I expect them to.

The headline in our own experience is that this is mostly about how a model handles missing data, not how big it is. When a tool returns real data, all three tiers ground correctly and nobody invents anything. When the data is not there, behavior splits on how the absence gets signalled. Replay a turn with a vague instruction to proceed with whatever it already has, and all three fabricate confident content, with the bigger models producing the more polished fabrication. Signal the absence clearly, and every tier including lite says it cannot see the calendar instead of inventing events.

That reorganized how I think about the problem. The fabrication I had been charging to running cheap was mostly a property of how we told the model it had nothing. Our first recommendation to ourselves was to stop shopping for a bigger model and go fix the signal.

Which puts the weight on the harness instead. The harness manages the context, decides what the model sees, and decides what it is told when a tool comes back empty. Its entire job is to put the model in a position to succeed. Get that wrong and no amount of model will save you.

Two other results fell out of it. The first is a failure where the answer is correct and well-grounded all the way through, and then comes apart in its last few words. A phrase repeats itself, or a contraction mangles. One of ours signed off with “while he recovers today while he recovers.” We call it a garbled tail, and nothing in the logs flags it, because the model finished cleanly and the turn reads as a success. It showed up on every model we tested including Pro. Low rate, stochastic, and scaling did nothing to it.

The second is that the middle is not the safe middle it looks like. On empty tools the mid tier invented more concrete detail, weather numbers and times, than either the model above it or the one below.

There is one clean exception. False completion, where the agent answers after step two of a five-step procedure and reports back as though it had finished, does improve with model size. Our own notes call it the one real model-size win, and it is the only one on the list.

I want to be careful not to oversell this, because we do pay a tax for running small. Ten modules in Pepper’s agent harness exist mostly to catch models behaving badly, roughly 2,500 lines of production code and about the same again in tests. A detector for tool calls narrated as prose. A repair pass for garbled text. A guard for the case where a tool returns a success status with a zero success count buried in the JSON, which we wrote after a model read the status, believed its own plan, and invented the record IDs out of its own request.

Six of those ten ship detect-only. They watch, they report, and they change nothing a user sees, because we do not ship a pass that suppresses model output until nightly grading proves it is effective. The failures they watch for are not exclusive to the tier we run on. Most of that code is the cost of building an agent at all, and we would be writing a version of it at any price.

None of that machinery came out of a design document. It came out of watching. Every night a high-capability model, a Ferrari, reads back every task Pepper took on that day and grades it. It correlates failures to bugs, files the issues, sometimes reproduces a failure as a failing test, and sometimes opens a pull request to fix it. That process deserves its own post and it will get one. The short version is that almost every guard in our harness exists because we watched the model fail in one specific way and wrote a defense against that one failure.

So the Ferrari does have a job here. It is just not the one that answers you.

We Don’t Have a Word for These Models

This is a naming problem, and I think it matters more than it sounds. “Small” is wrong, because the capability is not small. “Cheap” is pejorative and smuggles in the assumption I have spent this post arguing against. “Flash Lite class” is a product SKU, not a category. Nobody has named this tier because nobody is positioning for it.

I want to call them daily drivers.

A daily driver is not a lesser car. It is the car you actually chose, judged on what matters when you drive it every morning. It starts. It’s cheap to run. It does the trip. Nobody apologizes for driving one, and nobody seriously believes the Ferrari owner is having a better time getting the groceries home.

The capability question is already settled, and I published the evidence three months ago while thinking I was writing about something else. When I built a scoreboard for Gemini Scribe, my Obsidian plugin, the point was to stop grading my own agent on vibes. It scores reliability the way τ-bench does, so a task counts only if every one of five runs succeeds. The headline result, which is still published, was that the newer gemini-3.1-flash-lite solves 74.1% of that suite at solve^5 and the older gemini-2.5-flash, supposedly a tier up, solves 57.4%. Same tasks, same judge, about seventeen percentage points apart, and the lite model costs about three quarters as much per run.

Speed is part of this too, and it does not show up anywhere in a solve rate. The daily driver starts talking sooner, and the gap in time to first token is not subtle. For an assistant you are holding a conversation with, that is not a nice-to-have. It is most of what the thing feels like to use.

The Price Gap Is Widening, Not Closing

The objection I take most seriously is that all of this evaporates when frontier prices fall. If the Ferrari costs Corolla money, what is left of the argument?

Watch what actually happened this summer. OpenAI cut Luna’s price by 80% on July 30 and took 20% off the mid tier. Those are their numbers, and the same announcement adds one more line: Sol pricing remains unchanged. Three weeks later they cut Sol too, and on their own product page that second cut is described as running for the next three months.

Read the two together. The cut at the bottom is the price. The cut at the top is a sale with an end date on it. At launch the flagship cost five times what the cheap tier cost, on input and on output alike. Take the promotion out and it now costs twenty-five times, which is where the ratio lands again when the sale lapses in November.

The gap widened because the floor dropped, not because the ceiling rose. The research says to expect that. An MIT FutureTech analysis of the price-performance frontier puts the decline at five to ten times a year for a fixed level of capability, with roughly three of that coming from algorithms rather than hardware. A five-dollar subscription does not need the gap to hold still. It needs the floor to keep falling, and the floor is where the competitive energy is.

Where Cheap Doesn’t Save You

Inference is not the whole bill, and this is the part I would have wanted someone to tell me a year ago.

Grounding costs real money and it does not follow the same curve. Google gives you 5,000 free search requests a month shared across all the Gemini 3.x models, then charges $14 per thousand after that. Anthropic and OpenAI both charge $10. On a deep research task, where the agent fires dozens of queries to answer one question, the search line can run past the inference line. That inversion gets worse as tokens get cheaper, not better.

The other place the rule breaks is writing skills. A lightweight model asked to author its own procedure does it badly, and the failure is subtle. It writes instructions a smarter model could infer its way through. So our skill-authoring tool runs on a bigger model than the runtime it writes for, and the skill’s own instructions spell the asymmetry out to whatever is drafting. What you write will be executed by a lower-capability model than the one drafting it now. So be pedantic. Name the exact tool and its arguments, and do not leave a judgment call implicit. Vague instructions are instructions a smaller model will fumble.

That is the boundary in general. Reach up a tier where the output is a plan that gets reused, and stay down where the output is one decision that gets made and thrown away.

The Part I’m Most Excited About

The strategic argument for running this low is that it eventually stops depending on the labs at all. At this size there is a real path to fine-tuned open weights, and past that you are substantially immune to price hikes and can buy your own hardware.

I believe that, and I have not proved it. The abstraction is there: Pepper’s model layer is provider-neutral and already routes three vendors through one interface, so a fourth backend is a translation adapter and a route key rather than a rewrite. What is not there is a single line of code pointing at a local runtime.

When I did measure it, the answer was no, and I published that too. The local gemma4:e4b running on my own hardware clears the easy tier at 100% and then collapses: 15% on T2, 7% on T3, 11% on T4. Flash Lite stays above 65% on every tier. It almost always finishes without erroring. It just gets the answer wrong.

That is one very small model, well under what a single consumer GPU could hold, and I have not put the larger variants through the same gradient. With capable dense models now shipping in the 30-billion-parameter range, that gradient is the next thing I want to run.

A Different Company, Not a Cheaper Bill

Cheap orchestration is what makes a five-dollar subscription possible. A five-dollar subscription is what makes Pepper reachable by the people I had in mind when I wrote that not everyone wants a hobby. That is the whole thesis, and the model tier is critical to it in a way a line item on an infrastructure bill never is.

Chris’s read on the field is that most people building here run on higher-grade models, which is a large part of why they need venture money. They are burning tokens on work that does not require them. I don’t think anyone made that choice on purpose. The frontier is where the demos are, where the benchmarks are, and where the attention is. It takes a deliberate act to go shopping somewhere else.

There is an argument running right now about whether we are heading for superintelligence and what it will mean when we get there. It is a real argument and I am not dismissing it. It also has almost nothing to do with the software most people will actually use, which needs to read a calendar, check the weather, and then get out of the way. That job was solved a while ago. We just kept pricing it as though it were not.

Whoever it was I was half listening to had it right, and did not go far enough. Nobody needs a Ferrari to get to work. What nobody says out loud is that the Corolla gets faster every year while we are all reading the reviews of the Ferrari.

An empty, glowing chat window floating apart from a cluster of worn analog interface objects like a door handle, light switch, and rotary phone, rendered as a warm painterly illustration.

The Chat Box Is a Detour

When ChatGPT launched in November 2022, we got a simple chat window, following a few months behind Google’s own preview of LaMDA 2 through AI Test Kitchen at Google I/O 2022, itself a chat window layered over a model. Type something in, get something back. That was the right call, and not because anyone had done deep interface research. A transformer model is trained to do one thing: predict the next token given everything before it. Feed it a prompt, get a completion, feed it more, get another. A chat window is close to the most direct expression of that loop made visible. It was an honest match for what those models were good at, an admission of what the technology could do yet, not a considered design choice.

Models have gotten more capable and efficient since, and what we ask of them has gotten far more complex. Somewhere in that gap, the chat window stopped being an honest match and became a habit. We have spent the years since watching agentic AI show up everywhere: code editors, browsers, the operating system itself, the enterprise tools people already had open. Through all of it, we kept handing people the same box. Our reluctance to move past it is a real drag on adoption, and it is one of the bedrocks of our point of view at Vycari.

Anyone who works in this technology every day already knows a specific version of this problem: the blank box itself is hard. Staring at an empty chat window and guessing how to phrase what you want, what the agent can do, which words trigger the behavior you’re after, is its own skill. It is hard for people who spend all day in this field. It is much harder for someone who does not, who has no reason to have built a mental model of what an agent can do from looking at an empty rectangle.

My co-founder Chris Perry made a version of this same argument last week, coming at it from adoption and product history rather than the interface argument here. Ours is a two person company, and we did not coordinate this; we just keep running into the same wall from different angles. It is part of why I like building with him: he thinks about a problem from the side I don’t, and by the time we compare notes we have usually converged without meaning to. His post is worth reading alongside this one.

Agents outgrew the box

Last January I wrote about how everything becomes an agent; the argument underneath was really about decision making. An agent earns its keep when the input is hard to predict ahead of time, when the alternative is branch logic encoding what a developer guessed the user would need, written months before that user showed up. Treat an agent as a piece of your program that makes the call in the moment, with the actual input in front of it, and it looks like a much bigger part of how software gets built than a chat window would suggest.

None of that requires typing into a box. An agent deciding which tool to call inside a checkout flow, a support queue, or a scheduling tool does not need a text field to do its job well. In a lot of what we build at Vycari, the agent takes a backseat to the interface on purpose. Nothing beats a solid interface that is familiar and delightful to use, and an empty chat box waiting to be filled is neither of those things for most people.

Chat is the hobbyist’s interface

I wrote a few weeks ago about why not everyone wants a hobby, and this is where that argument meets this one. A chat interface rewards people who already know how to prompt, who enjoy the back and forth, who get a small thrill from coaxing a good answer out of a model. That is real and worthwhile. It is also a hobby, and most people do not want one. They want the thing handled.

This is not a new problem for our industry. Unix was a command line. So was DOS, VMS, Ultrix, and SunOS, the whole family of operating systems that ran the serious computing of their era. Knowing the right incantation, the right flags, the right order of operations was a hobby in its own right, and it kept computers in the hands of people willing to learn that hobby. The graphical interface Xerox PARC prototyped, and that the Macintosh and then Windows brought to everyone else’s desk, did not make computers more powerful. In most ways it made them less flexible than a shell. What it did was let someone finish a task without first learning a syntax and a vocabulary of magic commands, as Chris put it. Nobody wants to read a manual to cross the next thing off their list. That was true of computing in 1984, and it is true of agents now.

Look at the products getting the most attention right now, open source projects like OpenClaw and Hermes, or the frontier lab flagships like Gemini Spark, Claude Cowork, and ChatGPT Work. Nearly all of them are built on the same premise: you will chat with the agent. My own Gemini Scribe started the same way, a chat window bolted onto Obsidian. Sometimes the chat happens over voice instead of text, but underneath the voice layer is the same box, just one you talk to instead of type into.

Meeting people where they already are

I do not think most people want to learn a new modality to get value out of AI, and I do not think they will, even though some of us genuinely enjoy it. Agentic AI is a shift on the scale of the ones we have already lived through: personal computers, the internet, the web, mobile, and now AI. I made a version of this list once before, and each of those transitions asked people to change how they worked. The ones that won met people with an interface they already understood, not the ones that made them learn a new vocabulary first. I want to be careful here: I am not arguing for skeuomorphism, for software that pretends to be the paper or the switch it replaced. I am arguing for good, intuitive design, interfaces that borrow the mental model people already carry and build the new capability on top of it. Every time this industry has moved toward a more familiar interface and a design language people already recognized, it created more value, not less, because it stopped spending people’s attention on the tool and let them spend it on the task.

That is the standard I want agent products held to. Not “does the model perform,” because at this point almost all of them do. The question is whether the software finds you where you already are, understands what you are actually trying to accomplish, and gets you back to your day.

Did you have to come back

Early in my career at Google, one of the metrics we watched for search was whether you came back. If you searched, clicked a result, and never returned, that meant you had found what you needed and moved on. I think agents deserve the same measurement. Did you get the thing done? Did you have to come back and try again? The best outcome is that you do not come back, not because the product failed you, but because you already had what you wanted and were on to the next thing.

In our own applications at Vycari, that translates into something concrete. It means the agent understood the request on the first try, without a round of clarifying questions, without asking you to drop into a chat window to add detail it should already have had. Better still, it means the agent acted on your behalf and you never had to watch it happen. In my ideal world, people using what we build will know this is agentic AI about as much as they know it is written in Python: not at all, not because we are hiding it, but because it will not be a fact that matters to them.

We should not be building toward the box. We should be building toward wherever the user already is, and toward what they are actually trying to get done. Agents are not a hobby. They are here to help people get through their day, and the sooner our interfaces act like it, the sooner more people will actually use them.

A laptop on a dark desk with thousands of small glowing blue points of light rising from the screen and spreading outward like a constellation, connected by faint threads, with a small bright cluster near the screen and the rest fading into darkness.

Thousands of Goodbyes

There is a problem with leaving a job you held for twenty one years, and nobody warns you about it. You cannot remember who you worked with.

Not in the sense of having forgotten them. In the sense that the list does not exist anywhere, including in your head. I left Google earlier this month after twenty one and a half years across Search, Maps, ads, mobile, Core, Core ML, and DeepMind, in roles that ranged from running large organizations to writing code with three people. Somewhere in there I met, argued with, mentored, was mentored by, shipped alongside, and occasionally annoyed several thousand people. When I sat down to write my goodbye note, I could produce maybe a hundred and fifty names from memory, and I knew with total certainty that the hundred and fifty were wrong. They were the recent ones and the loud ones. The person I had one extraordinary conversation with in a London conference room in 2008 was nowhere near that list.

This is the sort of problem that used to have exactly one answer, which is that you accept it. There is no roster of everyone who mattered to you, no internal system that will hand you the list. What you actually do is type out the names you can think of, send the note, and add a line asking people to please forward it to anyone you missed. It works, in the sense that something gets sent. It is also a sloppy solution that quietly hands the entire decision to your recency bias. The people you saw last month get a goodbye. The people who changed how you work, fifteen years ago, on a team that no longer exists, do not.

I did not want to accept it. So I did the other thing.

Letting the machine do the remembering

The tool I reached for was Antigravity, paired with the Google Workspace MCP server I had originally built as a Gemini CLI extension. That extension exists because I wanted my terminal to be able to see my calendar. It turns out that giving an agent access to your mail and calendar for ordinary convenience also gives it access to the complete archaeological record of your working life, which is not something I had thought carefully about until I needed it.

The first pass was mail. I had the agent go through twenty one years of sent messages and pull out every address I had ever written to individually. Not mailing lists, not the thirty person threads, not the announcements. One to one mail, or close enough to it, on the theory that if I had bothered to type your name into the To field, we had a relationship worth closing properly. That produced a very large and very stale list, because a lot of those people left Google years ago. So the second pass compared the addresses against an internal directory and kept only the ones still active, which cut it down considerably and also produced a small, unexpected inventory of people I had lost track of.

The second source was calendar. Mail catches the people you write to, but it misses the ones you only ever talked to in a room. So the agent went through twenty one years of my calendar looking for anything that was genuinely a one to one: a recurring weekly, a single mentoring session someone booked in 2017, a skip level, a coffee that got a calendar entry because that is how Google works. Every one of those has a person on the other side of it, and a surprising number of them never once appeared in my sent mail.

Then it merged the two. I had expected this to be the hard part and it was not, for a boring reason: Google email addresses are stable. People change teams constantly and the address follows them, so deduping on the address alone does nearly all of the work. What I was not prepared for was reading the result. Whole eras came back. I would hit a cluster of addresses and remember an entire project I had not thought about in a decade.

The last problem was purely mechanical and almost funny after all that. Gmail will not let you put several thousand addresses on a BCC line. The agent did not raise this, which is worth saying in a post that is otherwise about how capable these things are. I had to notice it and ask. Once I did, it split the list into batches that fit under the limit and drafted the same message across all of them, and I sat there and hit send, over and over, until the list was gone.

What came back

I expected silence. You send a goodbye to someone you shared one project with in 2011 and you expect it to land in an archive folder, if it lands anywhere.

One person wrote back to tell me, politely, that he had no idea who I was. I liked that reply enormously. I assume he was not the only one who felt that way and just the only one honest enough to say it, and I would rather have sent that mail and been forgotten than not sent it at all.

But most of what came back was not that, and the volume of it caught me completely off guard. A solutions engineer in Japan wrote about a Street View collaboration with Nintendo that had been his very first project at Google, and told me I was probably the first real engineer he ever encountered. We were born the same year. He had turned fifty a month earlier and was finding the number about as strange as I am. Someone I managed for only a few months thanked me for trusting him and called it one of the most engaging windows of his career. A former colleague opened by saying he had just been telling someone we both used to work with how much he missed working with me, and then reported that he still has not gotten his motorcycle license because his friends staged an intervention dinner about it. A director in Munich offered a beer if I ever make it back and reminded me of work we did together that I had honestly stopped thinking about. Someone I have known for close to twenty years said he had been meaning to call, and instead of trading contact details we ended up at lunch off campus the following Friday, which is the best possible version of what one of these notes can do.

That is the part I keep turning over. Not one of those replies exists if I send the note from memory.

A hundred and fifty, the number of names I could produce on my own, is roughly Dunbar’s number, the size of a stable social group a human can actually maintain. I do not think that is a coincidence, and I have stopped treating it as a personal failing. My recall of my own career landed almost exactly where the research says it should, which means the ceiling was never effort or affection. It was architecture. Twenty one years builds a network many times larger than the one a head is designed to hold, and the overflow is not forgotten so much as never retrievable in the first place. The agent was not being clever here. It simply was not subject to the constraint.

The people who wrote the most moving things back to me were, almost without exception, the ones my brain had not surfaced. They were on the list because software read my calendar from 2013 and did not care that it was 2013.

The gap this points at

I have spent two years writing about what agents can do, and most of my examples have been about work. Code, pipelines, research, the machinery of building software. This is the first time I have used one for something that was purely about people, and it is the only agentic project I have run where the output made me feel something.

It is also, and I want to be honest about this, a completely unreasonable thing to ask a normal person to do. To get here I needed an agent platform, an MCP server I wrote myself, OAuth credentials, a working mental model of what a tool call is, and enough patience to iterate on the approach a few times when it came back wrong. The capability was extraordinary. The cost of access was absurd.

That gap is the whole reason I am doing what I am doing next. I wrote last week that using agents today is effectively a hobby, and this is the cleanest example I have of why that matters. Everyone leaving a long job has this problem. Almost nobody gets to solve it, because solving it currently requires you to invest in the hobby first. Closing that distance, so that an ordinary person on an ordinary Tuesday can ask for something like this and simply get it, is the work.

Twenty one years of colleagues got a goodbye from me because software remembered what I could not. I would like that to be an unremarkable thing to say.

And to everyone who wrote back: I replied to every thread I could, and I am sure I still missed some. I want all of you to know how deeply your words and your wishes landed. Thank you for that.

An overhead illustration of a cluttered hobbyist workbench with soldering iron, parts drawers and a notebook of diagrams, and a single plain phone resting apart from it all at the edge of the bench.

Not Everyone Wants a Hobby

Yesterday I wrote about leaving Google after twenty one years and said there was a next chapter I would tell you about today. This is it.

Chris Perry and I are starting a company. It is called Vycari, we are building agents, and we are looking for people to test what we make. I want to spend most of this post on the problem rather than the product, because the problem is the interesting part and because the product is not ready for you yet.

Using agents today is a skill

Here is what it currently takes to get real value out of an agent.

You curate your skills, your triggers, and your extensions. You pick the right model for the task and make sure it is wired to the right API key. You keep the right software installed and updated on your machine. You have a sandbox configured, because obviously you have a sandbox configured. You learn which failures are the model’s fault and which are yours. You read changelogs, because the thing you learned last month is already wrong.

That is not using a tool. That is adopting a hobby.

I want to be careful here, because I do not mean that as a complaint. There is nothing wrong with AI as a hobby. A great many of the real sea changes in personal computing were driven by people who treated the work as an avocation first and a profession second, and the current moment is no different. I count myself among those people. They are my people. This blog exists because of them, and I am not going to stop writing for them.

But it is worth being honest that this is what we have built so far, and about who it excludes.

Most people do not want a hobby

Not everyone wants their tool to become a pastime. Not everyone wants to marvel at the stack, or to feel the small thrill of watching software take an action in the real world on their behalf. Plenty of capable, curious, technically fluent people simply want to get something done, and they want to use whatever makes that easiest.

I am friends with a lot of these people. They are not incurious and they are not afraid of technology. They carry a supercomputer in their pocket and use it fluently all day. They have just never been given a reason to believe that an agent is for them, because every agent they have encountered asked them to become a hobbyist first.

Chat apps are the exception that proves the point. They reached enormous audiences because there was nothing to adopt: you type, it answers, and the entire interface is a thing you already knew how to use. Step outside that box and agents are still close to magic for most people, and magic is not a compliment when you are trying to get through a Tuesday. Agent products remain genuinely hard to use, and the difficulty has very little to do with how good the models have become.

What I keep coming back to

The most useful thing I learned in two years of building agents has almost nothing to do with models. It is this: people do not bounce off AI because it is not smart enough. They bounce off because the cost of using it, all of it, the setup and the vocabulary and the remembering to go there, is higher than the problem they were trying to solve.

Which means the frontier I find interesting is not making these systems more capable. They are already more capable than almost anyone is extracting value from. The frontier is closing the enormous distance between what the technology can do and what an ordinary person can actually get out of it on a normal day, without a new app, a new habit, or a new hobby.

That gap is not a model problem. It is a product problem, a reliability problem, and a taste problem. It is also, as far as I can tell, wide open.

What we believe

We are early enough that I would rather tell you what we intend than what we have built. Four things we are holding ourselves to.

Meet people where they already are. If using the thing requires a new destination in someone’s day, we have already lost, no matter how good it is once they arrive.

Earn the trust the access requires. An agent worth having needs to see calendars, mail, and contacts, which is about as intimate as software access gets. There is no version of this business where that access to private data becomes an advertising product, and there is no version where you cannot take your data and leave.

Never make you learn our vocabulary. Nobody should have to know what a skill is, or which model answered, or that any of this is AI at all. Those are our problems. The user’s problem is that they asked for something and want it handled.

Be warm about it. An assistant you find pleasant is one you will actually use, and an assistant you actually use is the only kind that matters.

Who we are

My co-founder is Chris Perry. He is the CEO. I am the CTO. Chris used to report to me, and putting him in the CEO seat was one of the easier decisions either of us has made.

We have been circling each other for about a decade. We met when I was running Street View and imagery inside Maps and he was a PM on Google Photos, back when our two teams were trying to make those products understand each other’s pictures. Years later he turned up in the AI Developer organization I was running, as the product lead for Colab. Most recently we were both on the founding team of Gemini CLI and shipped its Workspace extension together. Somewhere in there he stopped being someone I had worked with and became someone I wanted to build with. He is writing his own version of this announcement, and his path here is different enough from mine that you should read both.

It is just the two of us right now, and we are both in the codebase. One of the underrated pleasures of leaving a large company is that you get to assemble the org chart from scratch, based on who is best at the job rather than on who has been there longest.

The part where I ask you for something

Twenty one years at Google taught me how to build systems where the hardest problems are problems of coordination. This is a different kind of hard. There are two of us, the feedback loop is measured in hours, and the person on the other end of a failure is someone who trusted us with something that mattered to them. I have not been this uncomfortable in a long time, and I have not enjoyed work this much since 2008.

We are opening to testers in the coming weeks, a few at a time and deliberately, because the failure I am most afraid of is someone relying on this and being let down. If you would like to be in that first group, put your name down here. What we want back is your honest experience, particularly the parts where it does not work.

And if the person who came to mind while you were reading this was not you but someone else, someone who would get enormous value from an assistant and would never in their life go looking for one, then you have understood exactly who we are building for.

I will keep writing about the engineering here as we go. It is going to be a good year.