Blog

  • Go fast, trip and fall

    Like any other terminally online tech person, December was a breaking point for me. Something truly changed with the capabilities of then-new models (and improvements in harnesses).

    I went all in. It wasn’t intentional, I felt compelled. On occasion, I even described it as an addiction.

    I thought I was going to be able to ship so fast. And I can. Sometimes. But – what’s the cost?

    No restraint on what you build means you’ll have no restraint on what you build.

    Feature Greed

    We’ve been working on bringing AI Chats to Beeper. The repository itself started humble, built by a non-technical colleague during a team meetup. It worked, got the job done and was a great starting point to explore the space.

    So I built out this thing. Started as AI Chats, and then I wanted a more OpenClaw-esque experience. I got…greedy? I built subagents, memory, advanced permissions mechanism (which is at v4 right now, this project never released!). That wasn’t enough. I wanted Beeper Desktop API integration so built MCP support. Users should be able to build custom agents just by talking! Brilliant.

    This is a Beeper bridge. I wanted to make sure we can deploy it into our infrastructure without building anything new there. This meant everything needed to live in an SQLite DB. But file system access is so important for the agent to organize! That’s what everybody else does. So naturally, I built a virtual file system.

    Agentic coding makes large bites feel small, but it’s an illusion. In one 24-hour blur, I merged 27,000 lines of code. Over just three months, a 700-line chat script mutated into a 130,000-line codebase.

    There is no way any human can review that much code, and there is no way LLM’s of today can write that much code without mistakes. Even if you ask it to make no mistakes.

    Compounding Booboos

    My model of choice nowadays, GPT 5.4, is too thorough, to the point where it decreases the quality of the code, and creates many abstractions that it later trips over itself.

    I stopped asking why and only asked what’s next. I built a custom link preview engine. A text-to-speech tool so the AI could send voice memos. A Gravatar scraper so the AI could fetch your profile picture. I even gave the agent a tool to file its own bugs in our issue tracker.

    As Mario (maker of Pi, probably the best agent library and the thing at the core of OpenClaw) put it in a recent post, this creates compounding booboos. Without a human bottleneck, tiny architectural errors mutate into a monster. I spent sad, exhausting hours hunting down fallback codepaths for things that never even shipped.

    At some point I decided to make the project into a meta framework. What a cool thing to build a fully E2EE way to interact with your agents like codex and OpenCode, from all your devices! I had all the primitives already, so why not?

    The Reckoning

    I kept building. I tested things! I glanced at the code. It worked!!!!

    Code was being reviewed! By CodeRabbit. As good as CodeRabbit is, it’s mainly for catching bugs, regressions. It’s not for checking taste. It only has the context of my immediate changes. And worse, it has the context of the existing codebase which wasn’t built with intention. An AI reviewer assumes the code you generated is the code you meant to write. It just confidently rubber-stamps your compounding booboos.

    As we got closer to launching the first milestone of this project, I wasn’t comfortable to ship to alpha users without looking at the code. Like, really looking at it. Of course, not ALL of it. That would be crazy (and borderline impossible).

    At the end of months (luckily this wasn’t the only thing I’ve been working on), I tried to fit a roadmap of a few months into weeks, and ended up with a mess of a codebase that’s taking so much time to untangle.

    What was I building? What’s the anchor? What user need am I solving right now?

    I made:

    • AI Chats
    • a meta framework for building agentic bridges
    • a worse version of OpenClaw
    • codex bridge (this one rocks, but I am the only user – how does it bring any value?)
    • OpenCode bridge
    • OpenClaw gateway companion
    • a helper meta bridge manager that’s solely for ai bridges
    • a helper CLI to tie it all up

    Pooped out of an LLM

    Even when I came to terms with what I had done, I was afraid to remove features. Ah it’s fine! I told myself. I can just make sure users don’t hit those paths, just build around it. A junior engineer mistake that I would have not made before. I would’ve never built without intention before.

    But I need to learn to be as eager to nuke things I vibed into a codebase as I am vibing things in. Why do I still care about keeping code that took a few hours to generate? Why have attachment to features that were pooped out of an LLM, while they can always be re-written, with much more intention and better design, albeit slower? Who cares if the thing you made has ALL the features if they were built before the need for them ever came?

    The Mortal Sin

    I, as a builder, built to satisfy my own itches. That’s a mortal sin.

    What my job is, and what I pride myself in, is keeping the user in focus. Release fast, get feedback, create a healthy feedback loop. Build for the user. Instead, the loop I satisfied was my own dopamine receptors.

    A product is more than its features and code. Producizing is where taste and execution makes the difference. Most of the feature I built were good ideas. They are still good ideas, I’m sure most of it we’ll pick up and re-build. But good ideas were never the bottleneck.

    I made rookie mistakes here. I built a codebase without understanding it, and I let it grow before any user demand.

    Today, like literally today, I’m staring at a branch called batuhan/sins. It touches 532 files and deletes 39,577 lines of code. And I still need to delete more. Way more.

    I lost my anchor, but deleting booboos is how I’m finding it again. Because if you go so fast that you forget who you are building for, you might be running but where the fuck are you running to?

  • Nobody Cares About Your App (By Default)

    I recently read Butterick’s Practical Typography. It’s a good reference book, the kind I’ll go back and check often at least until I have enough practice and enough opinions of my own. But my main takeaway had nothing to do with typography — it was about how universally important attention to detail and respect of the consumer are. Reader for writers, user for software builders, a hungry person for a chef.

    Who is software for?

    He has a table in Who is typography for? which summarizes something I think about often in such a clear way, I’ll steal and adapt it for what I do every day: building software.

    BuilderUser
    Attention spanLongShort
    Interest in what you builtHighLow
    Convinced they need itYesNo
    Cares about your visionYesNo

    Butterick’s original has “writer” and “reader” — the dynamic is identical. If you’ve worked on building consumer software long enough, you know most users are looking for reasons to stop giving you their time. This is most obvious in onboarding, since you have not given the user anything to care about yet.

    Superhuman famously required 1:1 onboarding calls for their $30/month email app. They wouldn’t let you use it until someone walked you through it.

    And as he says, the only person that’ll match your willingness to explore is probably your mother.

    Dogfooding can make you blind

    I used to think it’s an unbeatable advantage to work on things you use yourself. I still do. But it makes you blind.

    You know the intention behind every screen. You know the third tab is where the value is. You know the onboarding is a formality. The user knows none of this. They do not understand your intention, unless you give the care and attention to each and every screen to convey it.

    Maybe you use the software you build every day. Beeper is my most used app by screen time. But do you use it the same way as users? Just ask Snapchat.1 How would your users even know how best to use the thing?

    This is worse for products built by engineers, for engineers. It is so easy to think they’ll see the value in what you built because you are an engineer too and it is so obvious to you! But did you give enough care to be sure your intention is felt? Or, maybe you cared too much and were afraid of being misunderstood so you added a paragraph of text to explain how awesome the thing you built is.

    According to some sources, fewer than 2% of users tap “read more” on App Store descriptions. The screenshot carousel is your entire pitch.

    Well, I have news: nobody reads. Nobody cares, by default. You have to make sure you give your user enough love so they might, sometime in the future, start caring.

    So if you can’t trust your own eyes, what do you do?

    You can just try things

    Another maxim I’ll steal and bend to my will: “When in doubt, try it both ways.” Butterick’s point is that you shouldn’t try to resolve decisions with logic alone — make samples and get a visual reaction.

    Everyone has opinions and “rules” for everything in software. But you can’t know the taste of something before trying it. Sometimes you do the thing that converts slightly less, but it delights the user so you win in the long run.

    Only way to know how things will taste is to try them. Don’t debate, just build. Airbnb did.2 (This used to be expensive advice — AI changed that.)

    Butterick wrote his book about typography, but the underlying principle is the same: the craft is not for you. It’s for the person on the other side. Give them a reason to stay.


    1. Snapchat’s team used their own app daily, yet their 2018 redesign lost them 3 million daily active users in a quarter. Kylie Jenner’s single tweet about it wiped $1.3 billion off their market cap. Google Wave was built by brilliant engineers who loved it — users opened it and had no idea what to do. Dead within months.  ↩︎
    2. Instead of debating whether professional photos would help listings convert, Airbnb just rented a camera and tested it themselves in New York. Those listings got way more bookings. ↩︎
  • Almost forgot to remember

    I did remember to post today but delayed it and forgot. Story of my life.

    This was supposed to be a journal but within a few days I turned it to posting bullshit with no substance.

    I’m radically honest with everyone. Except myself. I guess I’m the only person who can shut me up in a way.

    Today was worse than yesterday for productivity but I had a lot of quality time with my wife. As long as tomorrow is better, everything is going to be alright.

    These posts exist for accountability and public commitment. So let me commit: tomorrow I’ll have a plan with a few metrics and I’ll post those metrics here everyday.

    I’m going to regret this in more ways than one.

  • Failing better

    I feel like I’m failing better than yesterday. I had some relapses where I went to X and YouTube because I’m still getting used to getting bored. I have more energy. Or at least I manifest it more, just talking with my wife more and walking around the house more. When time isn’t wasted on engaging with the feeds and the videos, I get to be bored and I engage life more. Like 10% more. But more.

    Better than yesterday is the aim. I was happier, and was able to finish things quicker, so I was better than yesterday.

    I’m still failing to live up to my own expectations and failing to execute my plans: I still don’t have good metrics. I said I need metrics. I still suck at following things on my to-do list. I still suck at not getting distracted easily.

    But better than yesterday. That’s what this is all about. See you tomorrow. And I almost forgot writing this!

  • Knowing it’s not my fault

    I know having ADHD is not my fault. I think I also know I shouldn’t blame myself for being different.

    What is my fault is not building and maintaining systems to make the best use of the cards I have. ADHD is a superpower and I’m not only failing to harness it to the full potential, I’m also failing to be a responsible adult in the society I live in. That doesn’t mean I must try to fit myself to the mould and do everything other people are able to. It means I must find my unique ways to create. It means learning how to manage a life with the divergence I have.

    Lately I’ve been running away from consuming content (articles, podcasts) that are about ADHD. I always resist things that can actually help me. I call it my self destructive tendencies.

    There was this video, linked above, which looked like a great chat about ADHD. I’ve been avoiding it even though I generally love listening to Trevor Noah’s podcast.

    Well, YouTube Music isn’t banned, and YouTube Music has podcasts, so this was one of the rare videos that I could justify to watch while my dopamine ban is in place. And I did. I’m glad I did. It was an insightful talk.

    Normally, what I would need to do in order to create a good blog post is summarize WHY it was insightful. But I’m not going to do that, I’ve got work to do, it seems like a fun thing to do but it also seems too ironic to procrastinate with it.

    That’s all. And yes, this is a second blog post within 30 minutes. There are no laws that says I can’t blog like I’m tweeting, this is my place!!!1