Writing on software, systems, and hard-won lessons.
Writing on developer experience, systems thinking, and the mistakes behind both - covering AI workflows, continuous improvement, and the mental models that drive better decisions.
The original egoless programming principles are about mindset. Be kind. Don't take it personally. Critique the code, not the coder. Good advice, but mindset strains under pressure, fatigue, and deadlines. At 4pm on a Friday with a production bug, nobody's thinking about Weinberg's commandments.
Systems hold when willpower won't. Structure drives behaviour.
When something isn't working, the instinct is to tell people (or ourselves) to be more disciplined. Instead, I ask "is there an easier way?" To use a gaming analogy: git gud vs easy mode. Then how can I transfer that to team performance? Focus on processes first, find the pain points, then find the easier path that changes habits.
Enabling people to see the value of change matters, but it's not enough. I've seen teams agree a change is better, then slide back because the new way is more troublesome. That's why we have to go further than convincing people—we have to design the process so the desired behaviour is the most convenient path. When the right way is also the easy way, the change sticks.
Counterpoint: Systems can carry us, but they can't have the crucial conversations we need to keep each other accountable.
Please tell me what is annoying you. If nothing is annoying then I don't have any requirements to work towards improvement. Our CI tests went from 2 minutes to 8. No one said anything. When I finally noticed, it was annoying enough that I took a closer look and fixed the container cache. Everyone was happy with the improvement, but I was still annoyed so created a preflight checks script so we didn't have to wait for git pushes while trying to fix the static code analysis errors.
If something annoys you, it's probably unbearable for everyone else. Use your frustration as a detector. To make the right way easy, we first have to find the "hard way" and identify those friction points that make it difficult. You are essentially using annoyance as a diagnostic tool to redesign the environment. If you aren't annoyed, I don't have requirements.
Ever had that moment where you walk into a room to get something only to completely forget why you're there? That's called the doorway effect. I like to also call that a brain fart. One of my work mates is a brilliant quizzer. And one day they forgot their password, so asked me to help. I reset their password and the next day it was forgotten again. So I set them up with a password manager and they never had that problem again. But not every lapse has a software patch. It's always better when someone says "I completely blanked on how this works" compared to spending three hours pretending they haven't. Hidden mistakes become big problems.
Counterpoint: Forgetting is allowed. Not learning from it isn't.
The better you get at something, the harder it is to remember what it's like to not know it. Write docs for someone who arrived yesterday. Write code a new dev can understand in 5 minutes. Test both with someone who's never seen the system. Your future reader matters more than your current convenience. Write instructions that help to lower the learning curve. Be concise.
In systems, we build in safety nets. So if one component fails, another catches it. The same applies to communication: don't trust a single message to land. I've found that communicating important information effectively requires three delivery methods for me to be more certain everyone in the team has taken in the information.
First I'll mention it in the morning meeting, and half of the people were not paying enough attention. Later that day a Slack message is sent, and half of the people missed the notification or it got buried in other messages. Then the third depends on the situation, it might be public praise thanking someone for doing the thing. Then those who missed the instruction or forgot about it will get a friendly reminder.
Another benefit, is normalising the fact that everyone is not going to retain everything. We have to be proactive as communicators. And remember different people have different learning and memory styles - reading, listening, visual, systems.
Counterpoint: Repeating trivial stuff three times isn't useful, it's spam. Save this for what you think is most important and will be genuinely useful for the team.
I've seen people try to automate processes they don't understand, then can't figure out what's going wrong. Instead, manually go through the process first, documenting each step. You'll spot which steps are more complicated than they look. Then automate gradually. Going from 10 steps to 5 to 3 is usually easier than jumping straight from 10 to 3.
After a new feature went live, the form validation was correct and worked as expected. But we got this error that only showed in production due to caching: "Typed property must not be accessed before initialization". We rolled back the deployment, but the developer was still stressed, then quickly fixed the specific error detailed by the uncaught exception message and stack trace. Then we deployed the version with fix, and got the same error a few lines down.
When a bug comes through, I like to think about prevention. Being perfect is not a prevention, but asking yourself "is it possible I added the same error in another place" is important. Another example would be if you renamed a method and there was a method undefined error, then search for more occurrences that might have been missed.
Counterpoint: Don't overcorrect. Not every bug needs a post-mortem. Sometimes you fix it, check the nearby files, and get on with your day.
Some people panic when they see an error message, even when it shows exactly what's wrong and where. I worked with a programmer who self-admitted they didn't know what they were doing. They would look for similar functionality, copy and paste it, and use error messages to hack it until it worked. Not an ideal way to work to say the least, but the error messages got them there and the users were happy. Directions, not accusations.
Elegant solutions used to make me feel smart. Now when a fix is taking longer than expected, I step back and look for something simpler. Rewriting an entire module like a genius is worse than finding the ternary statement with flawed logic. Be the plumber who knows where to knock on the pipe.
Senior engineers optimise to be the expert everyone depends on. But if you're always number one, you become the bottleneck and you starve your team of the oxygen they need to grow.
After continually being asked the same question from 10 different people, I eventually changed my strategy. First person: I give them the answer. Second person asks the same thing: "let's find the answer together." Third person: "ask one of the other two, they know."
Instead of being the expert, create co-experts. That's a great way to scale, gives me more time for more interesting problems, and added benefit I can go on holiday in peace.
Don't hand off the grunt work. Hand off the glory work. People who solve every hard problem think they're being heroes. Actually, they're being joy thieves and stealing the "aha!" moments their team needs to grow.
For the mindset version, see Egoless Programming: Greatest Hits
AI coding agents are fast, but they don't know what you know. Without upfront planning, an agent will confidently scaffold an entire architecture around the wrong assumptions. And you won't notice unt...
Antifragility is my goal for developer experience. When something breaks, I want the fix to make it harder for that same thing to happen again.
What is claude insights: The /insights command in Claude Code generates an HTML report analysing your usage patterns across all your Claude Code sessions. It's designed to help us understand how we in...