Sure, I should definitely write this up properly at some point!
The basic idea behind my workflow is that writing code isn’t the real bottleneck. The real bottleneck is understanding the problem and the code. So anything that generates code faster than I can understand it is a problem. So agent swarms are mostly useless, because they speed up code generation without improving understanding. Asking an agent to look at my code and see if I’ve overlooked anything, on the other hand, increases my understanding. Especially if I do the fixes myself.
Now, it’s also important that not all code requires equal understanding. Just like on human projects, there are parts I don’t care too much about, and parts that I watch like a hawk. Knowing which part is which is where experience helps. The core Rust traits in a system are very important. The 9th implementation of some trait may not be.
Similarly, I choose my models carefully. My model needs to be smart enough to debug a broken library, or to help me figure out mathematical invariants for a prop test. But it shouldn’t be so smart that I’m tempted to let it do a lot of work unsupervised. Somewhere between Sonnet 4.5 and Opus 4.6 is ideal. Fable is too smart. In practice, this means running open models like Qwen3.8 27B, Qwen3.8 Flash Next, or DeepSeek V4 Flash 0731. These are all smart enough to walk me through the interaction of two monads (say, flatMap and propFlatMap) if I ask. But they’re not smart enough to encourage true vibecoding and “not even reading the code.” Probably the largest I would consider for my own work is GLM 5.3 Flash, but you have to be really rich to run it locally.
My favorite agent harness is Pi. One session, no background agents, no TODO list, no plan mode, no fancy workflows. Maybe 1,500 tokens in my AGENTS.md, plus 2 or 3 tiny skills that tell the agent how I like to break down problems. (Which I do not share publicly, because I don’t want future agents to learn how I break down problems.)
For version control, I use jj. Using it really well isn’t any simpler than learning git. But it makes it easy to break up changes into multiple tiny pieces, and then interactively edit any of those pieces. I have some skills telling the agent to “break changes up Linux kernel style,” and how to write a good commit message. This allows me to review tiny, standalone pieces right in Zed and edit patch 3 of 4 all that I want.
I still invest time in my editor. I’m trying Zed these days, with Zeta2 as a code completion model. Zeta2 is nice, because it only completes obvious things, and it rarely completes more than 3 lines. If it has any doubt, it moves my cursor to the part I need to fill in. I work in Rust whenever I can, because I like Rust. And I very regularly drop into my editor and rough out traits, refactor things, and think with my fingers.
Overall, this process is good because it maximizes my understanding. And once a project passes 3,000 lines, a deeper understanding helps me move faster. Like, I started programming on the Apple IIe, and I like to imagine I’ve gotten pretty decent at it. Plus, it’s fun. Letting an agent write all the code would be like letting an agent go watch a fun movie for me.
But the north star of this process is that I’m optimizing for understanding, not speed. And from there, everything else is just making deliberate choices. My process has actually gotten more minimalist with time. And as agents have gotten smarter, I’ve become increasingly alienated from frontier models. I want a model that will punish me swiftly for trying to delegate too much understanding. It’s sort of like my kayak: It’s quite maneuverable, but it punishes sloppy technique by making me swim.
This is not the only process I use. Sometimes I just turn the agents off entirely, or limit them to research. But at its best, this understanding-focused process is like having a smart pair programmer or a faculty advisor. I can ask it for tips on what I’m overlooking, or I can say, “I don’t really feel like converting from the old Rust error handling library to the new one, so please do that for me.” But at each step, I focus on maintaining understanding. And if I do lose understanding, I also lose productivity.
Lovely write up, and really hits home for me. I haven’t considered simpler models but might try - I use Opus 5.5 and Fable and often find it way oversteps and drowns me in code.
One thing I would add - it may or may not be in your workflow - is the use of agents to understand ideas. Not only do I use agents to iterate on ideas and explore the design space, I will also have them walk me through ideas. I find agents really nice to play with a concept and break it apart. I do a lot of work in ML and computer vision, and I’ve found agents super useful to deep dive into concepts. They can generate examples, edge cases, intermediate representations - all sorts of good stuff. This is equally true when reviewing my colleagues work - I can go beyond line my line reading and really stress test things. But it comes back to understanding. The moment the agent is ahead of me I have to pump the breaks. Simply continuing with more code always ends in disaster and ultimately burns time.
I haven’t considered simpler models but might try - I use Opus 5.5 and Fable and often find it way oversteps and drowns me in code.
Using simpler models is partly about keeping me honest. Fable actually has pretty good taste about certain domains. Which means that by the time it does mess up, I have 2,000 lines of code to deal with.
For the “not getting drowned in code” part, I’m relying more on the other parts:
Using jj, which gives me patch-stack superpowers (at a price, though jjui and stakk help).
Asking the LLM for “Linux style patches” (one logical change per patch). This forces the LLM to think in small chunks.
Providing a custom skill about how to write a clear commit message.
Taken together, this can really simplify deep review.
One thing I would add - it may or may not be in your workflow - is the use of agents to understand ideas.
Yes. Agents are excellent at this. I often say, “So here’s how I’d like to handle this. Can you see a reason why this won’t work?” Then the agent points out 5 problems. Three of them are silly, but one of them means I need to to do a major rethink.
I also have a specialized skill which tells the model that the human is an experienced software designer with the magical ability to change the requirements. So if the model gets stuck on a messy design challenge, it gets maximum credit for flagging that to me. This actually gets many overenthusiastic models to stop more often and to explain why my plan was far too simple. That’s one of the points where I tend to start refactoring and typing.
Sure, I should definitely write this up properly at some point!
The basic idea behind my workflow is that writing code isn’t the real bottleneck. The real bottleneck is understanding the problem and the code. So anything that generates code faster than I can understand it is a problem. So agent swarms are mostly useless, because they speed up code generation without improving understanding. Asking an agent to look at my code and see if I’ve overlooked anything, on the other hand, increases my understanding. Especially if I do the fixes myself.
Now, it’s also important that not all code requires equal understanding. Just like on human projects, there are parts I don’t care too much about, and parts that I watch like a hawk. Knowing which part is which is where experience helps. The core Rust traits in a system are very important. The 9th implementation of some trait may not be.
Similarly, I choose my models carefully. My model needs to be smart enough to debug a broken library, or to help me figure out mathematical invariants for a prop test. But it shouldn’t be so smart that I’m tempted to let it do a lot of work unsupervised. Somewhere between Sonnet 4.5 and Opus 4.6 is ideal. Fable is too smart. In practice, this means running open models like Qwen3.8 27B, Qwen3.8 Flash Next, or DeepSeek V4 Flash 0731. These are all smart enough to walk me through the interaction of two monads (say, flatMap and propFlatMap) if I ask. But they’re not smart enough to encourage true vibecoding and “not even reading the code.” Probably the largest I would consider for my own work is GLM 5.3 Flash, but you have to be really rich to run it locally.
My favorite agent harness is Pi. One session, no background agents, no TODO list, no plan mode, no fancy workflows. Maybe 1,500 tokens in my AGENTS.md, plus 2 or 3 tiny skills that tell the agent how I like to break down problems. (Which I do not share publicly, because I don’t want future agents to learn how I break down problems.)
For version control, I use
jj. Using it really well isn’t any simpler than learninggit. But it makes it easy to break up changes into multiple tiny pieces, and then interactively edit any of those pieces. I have some skills telling the agent to “break changes up Linux kernel style,” and how to write a good commit message. This allows me to review tiny, standalone pieces right in Zed and edit patch 3 of 4 all that I want.I still invest time in my editor. I’m trying Zed these days, with Zeta2 as a code completion model. Zeta2 is nice, because it only completes obvious things, and it rarely completes more than 3 lines. If it has any doubt, it moves my cursor to the part I need to fill in. I work in Rust whenever I can, because I like Rust. And I very regularly drop into my editor and rough out traits, refactor things, and think with my fingers.
Overall, this process is good because it maximizes my understanding. And once a project passes 3,000 lines, a deeper understanding helps me move faster. Like, I started programming on the Apple IIe, and I like to imagine I’ve gotten pretty decent at it. Plus, it’s fun. Letting an agent write all the code would be like letting an agent go watch a fun movie for me.
But the north star of this process is that I’m optimizing for understanding, not speed. And from there, everything else is just making deliberate choices. My process has actually gotten more minimalist with time. And as agents have gotten smarter, I’ve become increasingly alienated from frontier models. I want a model that will punish me swiftly for trying to delegate too much understanding. It’s sort of like my kayak: It’s quite maneuverable, but it punishes sloppy technique by making me swim.
This is not the only process I use. Sometimes I just turn the agents off entirely, or limit them to research. But at its best, this understanding-focused process is like having a smart pair programmer or a faculty advisor. I can ask it for tips on what I’m overlooking, or I can say, “I don’t really feel like converting from the old Rust error handling library to the new one, so please do that for me.” But at each step, I focus on maintaining understanding. And if I do lose understanding, I also lose productivity.
score 2 · canonical
Lovely write up, and really hits home for me. I haven’t considered simpler models but might try - I use Opus 5.5 and Fable and often find it way oversteps and drowns me in code.
One thing I would add - it may or may not be in your workflow - is the use of agents to understand ideas. Not only do I use agents to iterate on ideas and explore the design space, I will also have them walk me through ideas. I find agents really nice to play with a concept and break it apart. I do a lot of work in ML and computer vision, and I’ve found agents super useful to deep dive into concepts. They can generate examples, edge cases, intermediate representations - all sorts of good stuff. This is equally true when reviewing my colleagues work - I can go beyond line my line reading and really stress test things. But it comes back to understanding. The moment the agent is ahead of me I have to pump the breaks. Simply continuing with more code always ends in disaster and ultimately burns time.
score 1 · canonical
Using simpler models is partly about keeping me honest. Fable actually has pretty good taste about certain domains. Which means that by the time it does mess up, I have 2,000 lines of code to deal with.
For the “not getting drowned in code” part, I’m relying more on the other parts:
jj, which gives me patch-stack superpowers (at a price, thoughjjuiandstakkhelp).Taken together, this can really simplify deep review.
Yes. Agents are excellent at this. I often say, “So here’s how I’d like to handle this. Can you see a reason why this won’t work?” Then the agent points out 5 problems. Three of them are silly, but one of them means I need to to do a major rethink.
I also have a specialized skill which tells the model that the human is an experienced software designer with the magical ability to change the requirements. So if the model gets stuck on a messy design challenge, it gets maximum credit for flagging that to me. This actually gets many overenthusiastic models to stop more often and to explain why my plan was far too simple. That’s one of the points where I tend to start refactoring and typing.
score 1 · canonical