<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://astro.build/">Astro</generator><link href="https://solmaz.io/feed/logs.xml" rel="self" type="application/atom+xml" /><link href="https://solmaz.io/" rel="alternate" type="text/html" /><updated>2026-09-05T08:40:48+00:00</updated><id>https://solmaz.io/feed/logs.xml</id><title type="html">Onur Solmaz blog | Logs</title><subtitle>Explorations in software, agentic systems, math, languages and more.</subtitle><author><name>Onur Solmaz</name></author><entry><title type="html">I built a coding agent two months before ChatGPT existed</title><link href="https://solmaz.io/log/2026/02/13/coding-agent-before-chatgpt/" rel="alternate" type="text/html" title="I built a coding agent two months before ChatGPT existed" /><published>2026-02-13T00:00:00+00:00</published><updated>2026-02-13T00:00:00+00:00</updated><id>https://solmaz.io/log/2026/02/13/coding-agent-before-chatgpt</id><content type="html" xml:base="https://solmaz.io/log/2026/02/13/coding-agent-before-chatgpt/"><![CDATA[<p>I built a <a class="concept-link" href="/graph/ai-coding-agent/">coding agent</a> back in 2022, 2 months before ChatGPT launched:</p>
<div class="responsive-embed"><iframe width="560" height="315" src="https://www.youtube.com/embed/okYmeoqHFCo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
<p>It’s super cool how I have come full circle. back in those days, we didn’t have <a class="concept-link" href="/graph/llm-tool-use/">tool calling</a>, reasoning, not even GPT 3.5!</p>
<p>It used <code class="language-plaintext highlighter-rouge">code-davinci-002</code> in a custom <a class="concept-link" href="/graph/jupyter-notebook-format/">Jupyter</a> kernel, a.k.a. the OG <a class="concept-link" href="/graph/agent-harness/">codex</a> code completion model. The kids these days probably have not seen <a href="https://www.youtube.com/watch?v=SGUCcjHTmGY">the original Codex launch video with Ilya, Greg and Wojciech</a>. If you have time, sit down to watch and realize how far we’ve come since August 2021, airing of that demo 4.5 years ago.</p>
<p>For some reason, I did not even dare to give codex bash access, lest it delete my home folder. So it was generating and executing Python code in a custom Jupyter kernel.</p>
<p>This meant that the conversations were using Jupyter <a href="https://nbformat.readthedocs.io/en/latest/">nbformat</a>, which is an array of cell input/output pairs:</p>
<pre><code>{
  "cells": [
    {
      "cell_type": "code",
      "source": "&lt;Input 1&gt;",
      "outputs": [
         ... &lt;Outputs 1&gt;
      ]
    },
    {
      "cell_type": "code",
      "source": "&lt;Input 2&gt;",
      "outputs": [
         ... &lt;Outputs 2&gt;
      ]
    }
  ]
}
</code></pre>
<p>In fact, this product grew into TextCortex’s current chat harness over time. After seeing ChatGPT launch, I repurposed icortex in a week into Flask to use <code class="language-plaintext highlighter-rouge">text-davinci-003</code> and we had ZenoChat, our own ChatGPT clone, before <em>Chat Completions</em> was in the API (it took them some months). It did not even have streaming, since Flask does not support ASGI.</p>
<p>As it turns out, <code class="language-plaintext highlighter-rouge">nbformat</code> is not the best format for a conversation. Instead of input/output pairs, <a class="concept-link" href="/graph/conversation-data-model/">OpenAI data model</a> used an tree of message objects, each with a <code class="language-plaintext highlighter-rouge">role: user|assistant|tool|system</code> and a <code class="language-plaintext highlighter-rouge">content</code> field which could host text, images and other media:</p>
<pre><code>{
  "mapping": {
    "client-created-root": {
      "id": "client-created-root",
      "message": null,
      "parent": null,
      "children": ["user-1"]
    },
    "user-1": {
      "id": "user-1",
      "message": {
        "id": "user-1",
        "author": { "role": "user", ... },
        "content": "Hello"
      },
      "parent": "client-created-root",
      "children": ["assistant-1"]
    },
    "assistant-1": {
      "id": "assistant-1",
      "message": {
        "id": "assistant-1",
        "author": { "role": "assistant", ... },
        "content": "Hi"
      },
      "parent": "user-1",
      "children": []
    }
  },
  "current_node": "assistant-1"
}
</code></pre>
<p>You will notice that the data model they serve from the API is an enriched version of the deprecating ChatCompletions API. Eg. whereas ChatCompletions <code class="language-plaintext highlighter-rouge">role</code> is a string, in OpenAI’s own backend has the <code class="language-plaintext highlighter-rouge">author</code> object that can store <code class="language-plaintext highlighter-rouge">name</code>, <code class="language-plaintext highlighter-rouge">metadata</code>, and other useful stuff for each entity in the conversation.</p>
<p>After reverse engineering it, I copied it to be TextCortex’s new data model, which it still remains, with some modifications.</p>
<p>I thought the tree structure being used to emulate message editing experience was very cool back in the days. OpenAI’s need for human annotation for later training and the user’s need for getting a different output, two birds in one stone.</p>
<p>Now I don’t know what to think of it, since CLI coding agents like Codex and Claude Code don’t have <a class="concept-link" href="/graph/conversation-branching/">branching</a>, just deleting back to a certain message. A part of me still misses branching in these CLI tools.</p>
<p>When I made icortex,</p>
<ul>
<li>we were still 8 months away (May 2023) from the introduction of “tool calling” in the API, or as it was originally called, “function calling”.</li>
<li>we were 2 years away (Sep 2024) from the introduction of OpenAI’s o1, the first <a class="concept-link" href="/graph/reasoning-language-model/">reasoning model</a>.</li>
</ul>
<p>both of which were required to make current coding agents possible.</p>
<p>In the video above, you can even see the approval <code class="language-plaintext highlighter-rouge">[Y/n]</code> gate before executing. I was so cautious, for some reason, presumably because smol-brained model generated the wrong thing 80% of the time. It is remarkable how much it resembles Claude Code, after all this time.</p>
<p>Definition of being too early…</p>
<hr>
<p>Repo: <a href="https://github.com/textcortex/icortex">github.com/textcortex/icortex</a></p>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">The farming analogy for AI doesn&#39;t hold up</title><link href="https://solmaz.io/log/2026/02/03/farming-analogy/" rel="alternate" type="text/html" title="The farming analogy for AI doesn&#39;t hold up" /><published>2026-02-03T00:00:00+00:00</published><updated>2026-02-03T00:00:00+00:00</updated><id>https://solmaz.io/log/2026/02/03/farming-analogy</id><content type="html" xml:base="https://solmaz.io/log/2026/02/03/farming-analogy/"><![CDATA[<p>People like the farmer analogy for AI.</p>
<p>Like before tractors and the industrial revolution, 80% of the population had to farm. Once they came, all those jobs disappeared.</p>
<p>So the analogy makes perfect sense. Instead of 30 people tending a field, you just need 1. Instead of 30 <a class="concept-link" href="/graph/software-engineering/">software developers</a>, you just need one.</p>
<p>Except that people forget one crucial thing about land: it’s a <a class="concept-link" href="/graph/land-scarcity/">limited resource</a>.</p>
<p>Unlike land, <a class="concept-link" href="/graph/digital-abundance/">digital space</a> is vast and infinite. Software can expand and multiply in it in arbitrarily complex ways.</p>
<p>If you wanted the farming analogy to keep up with this, you would have to imagine us creating continent-sized hydroponic terraces up until the stratosphere, and beyond…</p>
<div class="tweet-embed tweet-embed--placeholder align-center" data-radius="12px" style="border-radius: 12px">
  <div class="tweet-embed__placeholder">
    <pre><code>Tweet embed disabled to avoid requests to X.</code></pre>
  </div>
</div>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">GitHub has to change</title><link href="https://solmaz.io/log/2026/01/17/github-has-to-change/" rel="alternate" type="text/html" title="GitHub has to change" /><published>2026-01-17T00:00:00+00:00</published><updated>2026-01-17T00:00:00+00:00</updated><id>https://solmaz.io/log/2026/01/17/github-has-to-change</id><content type="html" xml:base="https://solmaz.io/log/2026/01/17/github-has-to-change/"><![CDATA[<p>It is clear at this point is that GitHub’s trust and data models will have to change fundamentally to accommodate agentic workflows, or risk being replaced by other SCM</p>
<p>One <em>cannot</em> do these things easily with GitHub now:</p>
<ul>
<li>granular control: this <a class="concept-link" href="/graph/ai-coding-agent/">agent</a> running in this <a class="concept-link" href="/graph/sandboxing/">sandbox</a> can only push to this specific branch. If an agent runs amok, it could delete everybody’s branches and close <a class="concept-link" href="/graph/pull-request/">PRs</a>. GitHub allows for recovery of these, but still inconvenient even if it happens once</li>
<li>create a bot (exists already), but remove reviewing rights from it so that an employee cannot bypass reviews by tricking the bot to approve</li>
<li>in general make a distinction between HUMAN and AGENT so that you can create <a class="concept-link" href="/graph/github-access-control/">rulesets</a> to govern the relationships in between</li>
</ul>
<p>The fundamental problem with GitHub is trust: humans are to be trusted. If you don’t trust a human, why did you hire them in the first place?</p>
<p>Anyone who reviews and approves PRs bears responsibility. Rulesets exist and can enforce e.g. <a class="concept-link" href="/graph/code-ownership/">CODEOWNER reviews</a> or only let certain people make changes to a certain folder</p>
<p>But the initial repo setup on GitHub is allow-by-default. Anyone can change anything until they are restricted from it</p>
<p>This model breaks fundamentally with agents, who are effectively sleeper cells that will try to delete your repo the moment they encounter a sufficiently powerful <a class="concept-link" href="/graph/prompt-injection/">adversarial attack</a></p>
<p>For example, I can create a bot account on GitHub and connect <a href="https://clawd.bot">clawdbot</a> to it. I need to give it write permission, because I want it to be able to create PRs. However, I don’t want it to be able to approve PRs, because a coworker could just nag at the bot until it approves a PR that requires human attention</p>
<p>To fix this, you have to bend backwards, like create a @human team with all human coworkers, make them codeowner on /, and enforce codeowner reviews. This is stupid and there has to be another way</p>
<p>Even worse, this bot could be given internet access and end up on a <a href="https://x.com/elder_plinius">@elder_plinius</a> prompt hack while googling, and start messing up whatever it can in your organization</p>
<p>It is clear that GitHub needs to create a second-class entity for agents which are default low-trust mode, starting from a point of <a class="concept-link" href="/graph/principle-of-least-privilege/">least privilege</a> instead of the other way around</p>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Anthropic&#39;s pricing is stupid</title><link href="https://solmaz.io/log/2026/01/10/anthropics-pricing-is-stupid/" rel="alternate" type="text/html" title="Anthropic&#39;s pricing is stupid" /><published>2026-01-10T00:00:00+00:00</published><updated>2026-01-10T00:00:00+00:00</updated><id>https://solmaz.io/log/2026/01/10/anthropics-pricing-is-stupid</id><content type="html" xml:base="https://solmaz.io/log/2026/01/10/anthropics-pricing-is-stupid/"><![CDATA[<p>Anthropic earlier last year announced this <a class="concept-link" href="/graph/ai-inference-pricing/">pricing scheme</a></p>
<ul>
<li>$20 -&gt; 1x usage</li>
<li>$100 -&gt; 5x usage</li>
<li>$200 -&gt; 1̶0̶x̶ 20x usage</li>
</ul>
<p>As you can see, it’s not growing linearly. This is classic Jensen “the more you buy, the more you save”</p>
<p>But here is the thing. You are not selling hardware like Jensen. You are selling a software service <em>through an API</em>. It’s the worst possible pricing for the category of product. Long term, people will game the hell out of your offering</p>
<p>Meanwhile OpenAI decided not to do that. There is no quirky incentive for buying bigger plans. $200 chatgpt = 10 x $20 chatgpt, roughly</p>
<p>And here is where it gets funny. Despite not having such an incentive, you can get A LOT MORE usage from the $200 OpenAI plan, than the $200 Anthropic plan. Presumably because OpenAI has better unit economics (sama mentioned they are turning a profit on inference, if you are to believe)</p>
<p>Thanks to sounder pricing, OpenAI can do exactly what Anthropic cannot: offer GPT in <a class="concept-link" href="/graph/agent-harness/">3rd party harnesses</a> and win the <a class="concept-link" href="/graph/ai-model-competition/">ecosystem race</a></p>
<p>Anthropic has cornered itself with this pricing. They need to change it, but not sure if they can afford to do so in such short notice</p>
<p>All this is extremely bullish on open source 3rd party harnesses, OpenCode, Mario Zechner’s pi and such. It is clear developers want options. “Just give me the API”</p>
<p>I personally am extremely excited for 2026. We’ll get <a class="concept-link" href="/graph/open-weight-language-model/">open models</a> on par with today’s proprietary models, and can finally run truly sovereign <a class="concept-link" href="/graph/ai-coding-agent/">personal AI agents</a>, for much cheaper than what we are already paying!</p>
<hr>
<p><a href="https://www.linkedin.com/posts/osolmaz_anthropic-earlier-last-year-announced-this-activity-7415744438582263808-SxuE">Originally posted on linkedin</a></p>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Christmas of Agents</title><link href="https://solmaz.io/log/2026/01/03/christmas-of-agents/" rel="alternate" type="text/html" title="Christmas of Agents" /><published>2026-01-03T00:00:00+00:00</published><updated>2026-01-03T00:00:00+00:00</updated><id>https://solmaz.io/log/2026/01/03/christmas-of-agents</id><content type="html" xml:base="https://solmaz.io/log/2026/01/03/christmas-of-agents/"><![CDATA[<p>I believe a “Christmas of <a class="concept-link" href="/graph/ai-coding-agent/">Agents</a>” (+ New Year of Agents) is superior to “Advent of Code”.</p>
<p>Reason is simple. Most of us are employed. Advent of Code coincides with work time, so you can’t really immerse yourself in a side project.<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>
<p>However, Christmas (or any other long holiday without primary duties) is a better time to immerse yourself in a side project.</p>
<p>2025 was the eve of agentic coding. This was the first holiday where I had full credential to go nuts on a side project using agents. It was epic:</p>
<div class="tweet-embed tweet-embed--placeholder align-center" data-radius="12px" style="border-radius: 12px">
  <div class="tweet-embed__placeholder">
    <pre><code>Tweet embed disabled to avoid requests to X.</code></pre>
  </div>
</div>
<p>75k lines of <a class="concept-link" href="/graph/rust-programming/">Rust</a> later, here is what I’ve built during the first Christmas with agents, using OpenAI Codex</p>
<ul>
<li>A full <a class="concept-link" href="/graph/mobile-software-development/">mobile rewrite</a> and port of my Python Instagram <a class="concept-link" href="/graph/code-driven-video-production/">video production pipeline</a> (single video production time: 1hr -&gt; 5min)</li>
<li>Bespoke animation engine using primitives (think Adobe Flash, Manim)</li>
<li>Proprietary new <a class="concept-link" href="/graph/user-interface-toolkit/">canvas UI library</a> in Rust, because I don’t want to <a class="concept-link" href="/graph/vendor-lock-in/">lock myself into Swift</a></li>
<li>Thanks to that, it’s cross platform, runs both on desktop and iOS. It will be a breeze <a class="concept-link" href="/graph/cross-platform-software-development/">porting this to Android</a> when the time comes</li>
<li>A Rust port of <a class="concept-link" href="/graph/computer-vision-tracking/">OpenCV CSRT algorithm</a>, for tracking points/objects</li>
<li>In-engine font rendering using rustybuzz, so fonts render the same everywhere</li>
<li>Many other such things</li>
</ul>
<p>Why would I choose to do it that way? Because I have developed it primarily on desktop where I have much faster iteration speed. Aint nobody got time for iOS compilation and simulator. Once I finished the hard part on desktop, porting to iOS was much easier, and I didn’t lock myself in to Apple</p>
<p>Some of these would have been unimaginable without agents, like creating a UI library from scratch in Rust. But when you have infinite workforce, you can ask for crazy things like “create a textbox component from scratch”</p>
<p>What I’ve built is very similar in nature to CapCut, except that I am a single person and I’ve built it over 1 week</p>
<p>What have you built this Christmas with agents?</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1">
<p>You could maybe work in the evening after work, but unless you are slacking at work full time, it won’t be the same thing as full immersion. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Vibecoding this blog</title><link href="https://solmaz.io/log/2025/10/13/vibecoding-this-blog/" rel="alternate" type="text/html" title="Vibecoding this blog" /><published>2025-10-13T00:00:00+00:00</published><updated>2025-10-13T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/10/13/vibecoding-this-blog</id><content type="html" xml:base="https://solmaz.io/log/2025/10/13/vibecoding-this-blog/"><![CDATA[<p>I finally brought myself to develop certain features for this <a class="concept-link" href="/graph/static-website/">blog</a> which I wanted to do for some time, having a button to toggle light/dark mode, being able to permalink page sections, having a button to copy page content, etc.</p>
<p>I always have a tendency to procrastinate with cosmetics, so I developed a habit to mentally force myself not to care about looks and instead focus on the actual content. Doing the changes I have pulled off in the last 2 hours would have been impossible in pre-LLM era. So I kept the awful default Jekyll Minima theme, and did not spend more thought on it. I had actually went through many different themes in this blog before, and I had switched to Minima precisely because of that: I was spending too much time.</p>
<p>I really like <a class="concept-link" href="/graph/web-design/">designing things visually</a>. I had interest in <a class="concept-link" href="/graph/typography/">typography</a> while studying, and I even went as far to design a font, write all my notes in LaTeX, etc. Then I found out that such skills are not valued in the world, and had no luxury to dwell on such things anymore once I started working.</p>
<p>But now it’s different. When I can do what I want 10 times faster with 10 times less attention, I can just do the design I want. Before I thought it was a flex to use default themes, because it showed a) that the person does not care and b) that they had more important things to do.</p>
<p>Well, now my opinion has changed. In the era where making something look good takes a few hours, using a default theme means something else to me: lack of taste.</p>
<p>For this blog, I just <a href="https://htmx.org/essays/vendoring/">vendored</a> <a href="https://github.com/jekyll/minima">Minima</a> and let <a class="concept-link" href="/graph/ai-coding-agent/">gpt-5-codex</a> rip on it. <a class="concept-link" href="/graph/vendoring/">Vendoring pattern</a> is getting more popular with libraries like shadcn, and I expect it to be ever more popular with open source libraries, with AI tools becoming more prevalent.</p>
<p>I don’t expect <a class="concept-link" href="/graph/frontend-development/">simple frontend development</a> to be in a good place ever again. I don’t expect anyone to outsource simple static site development to humans anymore, when you can get the exact thing you want at virtually no cost.</p>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">CLAUDE.md to AGENTS.md Migration Guide</title><link href="https://solmaz.io/log/2025/09/08/claude-md-agents-md-migration-guide/" rel="alternate" type="text/html" title="CLAUDE.md to AGENTS.md Migration Guide" /><published>2025-09-08T00:00:00+00:00</published><updated>2025-09-08T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/09/08/claude-md-agents-md-migration-guide</id><content type="html" xml:base="https://solmaz.io/log/2025/09/08/claude-md-agents-md-migration-guide/"><![CDATA[<blockquote>
<p><strong>Update:</strong> Anthropic still doesn’t fully accept <a class="concept-link" href="/graph/agents-md-standard/">AGENTS.md</a>, so I created this: <a href="https://github.com/osolmaz/claude-md-symlinker"><code class="language-plaintext highlighter-rouge">claude-md-symlinker</code></a>.</p>
<p>Install it once and <a class="concept-link" href="/graph/ai-coding-agent/">Claude Code</a> can keep local <code class="language-plaintext highlighter-rouge">CLAUDE.md -&gt; AGENTS.md</code>
<a class="concept-link" href="/graph/symlink-automation/">symlinks</a> working for you. No manually creating shim files, no committing
Claude-branded files into your repos.</p>
<p>Install using the installer script, or give this page to Claude and ask it to install for you.</p>
<pre><code>curl -fsSL https://github.com/osolmaz/claude-md-symlinker/releases/latest/download/claude-md-symlinker-installer.sh | sh
</code></pre>
<p>This will install a Claude hook that will check whenever Claude traverses a certain directory, and do the migration automatically for you.</p>
<p>If you are paranoid about security, ask Claude to check the source code for any issues and install the symlinker from the source.</p>
</blockquote>
<p>This post will age like milk, because Anthropic will eventually adopt the company-agnostic <a href="https://agents.md/">AGENTS.md standard</a>.</p>
<p>For those that do not know, <a class="concept-link" href="/graph/agent-instruction-file/">AGENTS.md</a> is like robots.txt, but for providing plain text context to any AI agent working in your codebase.</p>
<p>It’s very stupid really. It’s not even worthy of being called a “standard”. The only rule is the name of the file.</p>
<p>Anthropic champions CLAUDE.md, named after their own agent Claude. Insisting on that stupid convention is like Google forcing websites to use <a href="https://en.wikipedia.org/wiki/Googlebot"><code class="language-plaintext highlighter-rouge">googlebot.txt</code></a> instead of <code class="language-plaintext highlighter-rouge">robots.txt</code>, or Microsoft <a href="https://en.wikipedia.org/wiki/Office_Assistant"><code class="language-plaintext highlighter-rouge">clippy.txt</code></a>.</p>
<p>Anyway, since this post will become irrelevant very soon, here are some AI-generated instructions on how to migrate your CLAUDE.md files to AGENTS.md.</p>
<h2 id="why-migrate">Why Migrate?</h2>
<ul>
<li><strong>Open Standard</strong>: AGENTS.md is an open standard that works with <a class="concept-link" href="/graph/coding-agent-interoperability/">multiple AI systems</a></li>
<li><strong>Interoperability</strong>: Maintains backward compatibility through symlinks</li>
<li><strong>Future-Proof</strong>: Not tied to a specific AI platform or tool</li>
<li><strong>Consistency</strong>: Standardizes agent instructions across the codebase</li>
</ul>
<h2 id="actual-migration-commands-used">Actual Migration Commands Used</h2>
<h3 id="step-1-rename-files">Step 1: Rename Files</h3>
<p>The following commands were used to rename existing CLAUDE.md files to AGENTS.md:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Find all CLAUDE.md files and rename them to AGENTS.md</span>
<span class="nf">find</span> <span class="nb">.</span> <span class="nv">-name</span> <span class="s">"CLAUDE.md"</span> <span class="nv">-type</span> f <span class="nv">-exec</span> <span class="nf">sh</span> <span class="nv">-c</span> <span class="s">'mv "$1" "${1%CLAUDE.md}AGENTS.md"'</span> _ <span class="p">{</span><span class="p">}</span> <span class="p">\</span><span class="p">;</span>
</code></pre></div></div>
<h3 id="step-2-update-content">Step 2: Update Content</h3>
<p>Replace Claude-specific references with agent-agnostic language:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Update file headers in all AGENTS.md files</span>
<span class="nf">find</span> <span class="nb">.</span> <span class="nv">-name</span> <span class="s">"AGENTS.md"</span> <span class="nv">-type</span> f <span class="nv">-exec</span> <span class="nf">sed</span> <span class="nv">-i</span> <span class="s">''</span> <span class="s">'s/This file provides guidance to Claude Code (claude.ai\/code)/This file provides guidance to AI agents/g'</span> <span class="p">{</span><span class="p">}</span> <span class="p">\</span><span class="p">;</span>
</code></pre></div></div>
<h3 id="step-3-update-gitignore">Step 3: Update .gitignore</h3>
<p>Add these lines to <code class="language-plaintext highlighter-rouge">.gitignore</code> to ignore symlinked CLAUDE.md files:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Add to .gitignore</span>
<span class="nf">cat</span> <span class="o">&gt;&gt;</span> .gitignore <span class="o">&lt;&lt;</span> <span class="s">'EOF'

# CLAUDE.md files (automatically generated from AGENTS.md via symlinks)
CLAUDE.md
**/CLAUDE.md
EOF</span>
</code></pre></div></div>
<h3 id="step-4-create-symlink-setup-script">Step 4: Create Symlink Setup Script</h3>
<p>Create <code class="language-plaintext highlighter-rouge">utils/setup-claude-symlinks.sh</code> with the following content:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/bin/bash</span>

<span class="c1"># Script to create CLAUDE.md symlinks to AGENTS.md files</span>
<span class="c1"># This allows CLAUDE.md files to exist locally without being committed to git</span>

<span class="nb">set</span> <span class="nv">-e</span>

<span class="nb">echo</span> <span class="s">"Setting up CLAUDE.md symlinks..."</span>

<span class="c1"># Change to repository root</span>
<span class="nb">cd</span> <span class="s">"<span class="nv"><span class="nv">$(</span><span class="nf">git</span> rev-parse --show-toplevel<span class="nv">)</span></span>"</span>

<span class="c1"># Find all AGENTS.md files and create corresponding CLAUDE.md symlinks</span>
<span class="nf">git</span> ls-files <span class="o">|</span> <span class="nf">grep</span> <span class="s">"AGENTS\.md$"</span> <span class="o">|</span> <span class="k">while</span> <span class="nb">read</span> <span class="nv">-r</span> <span class="nf">file</span><span class="p">;</span> <span class="k">do</span>
    <span class="nv">dir</span><span class="o">=</span><span class="nv"><span class="nv">$(</span><span class="nf">dirname</span> <span class="s">"<span class="nv">$file</span>"</span><span class="nv">)</span></span>
    <span class="nv">claude_file</span><span class="o">=</span><span class="s">"<span class="nv">${file<span class="o">/</span>AGENTS.md<span class="o">/</span>CLAUDE.md}</span>"</span>
    
    <span class="c1"># Remove existing CLAUDE.md file/link if it exists</span>
    <span class="k">if</span> <span class="p">[</span> <span class="nv">-e</span> <span class="s">"<span class="nv">$claude_file</span>"</span> <span class="p">]</span> <span class="o">||</span> <span class="p">[</span> <span class="nv">-L</span> <span class="s">"<span class="nv">$claude_file</span>"</span> <span class="p">]</span><span class="p">;</span> <span class="k">then</span>
        <span class="nf">rm</span> <span class="s">"<span class="nv">$claude_file</span>"</span>
        <span class="nb">echo</span> <span class="s">"Removed existing <span class="nv">$claude_file</span>"</span>
    <span class="k">fi</span>
    
    <span class="c1"># Create symlink</span>
    <span class="k">if</span> <span class="p">[</span> <span class="s">"<span class="nv">$dir</span>"</span> <span class="o">=</span> <span class="s">"."</span> <span class="p">]</span><span class="p">;</span> <span class="k">then</span>
        <span class="nf">ln</span> <span class="nv">-s</span> <span class="s">"AGENTS.md"</span> <span class="s">"CLAUDE.md"</span>
        <span class="nb">echo</span> <span class="s">"Created symlink: CLAUDE.md -&gt; AGENTS.md"</span>
    <span class="k">else</span>
        <span class="nf">ln</span> <span class="nv">-s</span> <span class="s">"AGENTS.md"</span> <span class="s">"<span class="nv">$claude_file</span>"</span>
        <span class="nb">echo</span> <span class="s">"Created symlink: <span class="nv">$claude_file</span> -&gt; AGENTS.md"</span>
    <span class="k">fi</span>
<span class="k">done</span>

<span class="nb">echo</span> <span class="s">""</span>
<span class="nb">echo</span> <span class="s">"✓ CLAUDE.md symlinks setup complete!"</span>
<span class="nb">echo</span> <span class="s">"  - CLAUDE.md files are ignored by git"</span>
<span class="nb">echo</span> <span class="s">"  - They will automatically stay in sync with AGENTS.md files"</span>
<span class="nb">echo</span> <span class="s">"  - Run this script again if you add new AGENTS.md files"</span>
</code></pre></div></div>
<h3 id="step-5-run-symlink-setup">Step 5: Run Symlink Setup</h3>
<p>Make the script executable and run it:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">chmod</span> +x utils/setup-claude-symlinks.sh
./utils/setup-claude-symlinks.sh
</code></pre></div></div>
<h2 id="top-level-agentsmd-note">Top-Level AGENTS.md Note</h2>
<p>Add this note to the main AGENTS.md file:</p>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gs"><span class="p">**</span><span>Note</span><span class="p">**</span></span>: This project uses the open AGENTS.md standard. These files are symlinked to CLAUDE.md files in the same directory for interoperability with Claude Code. Any agent instructions or memory features should be saved to AGENTS.md files instead of CLAUDE.md files.
</code></pre></div></div>
<h2 id="directory-structure-after-migration">Directory Structure After Migration</h2>
<pre><code>project/
├── AGENTS.md          # Primary agent instructions
├── CLAUDE.md          # Symlink to AGENTS.md (git ignored)
├── utils/
│   └── setup-claude-symlinks.sh  # Symlink setup script
├── backend/
│   ├── AGENTS.md      # Backend-specific instructions
│   └── CLAUDE.md      # Symlink to AGENTS.md (git ignored)
└── apps/
    ├── AGENTS.md      # Frontend-specific instructions
    ├── CLAUDE.md      # Symlink to AGENTS.md (git ignored)
    └── web/
        ├── AGENTS.md  # App-specific instructions
        └── CLAUDE.md  # Symlink to AGENTS.md (git ignored)
</code></pre>
<h2 id="content-update-examples">Content Update Examples</h2>
<h3 id="before-migration">Before Migration</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh"><span class="p">#</span> CLAUDE.md</span>

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
</code></pre></div></div>
<h3 id="after-migration">After Migration</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh"><span class="p">#</span> AGENTS.md</span>

This file provides guidance to AI agents when working with code in this repository.
</code></pre></div></div>
<h2 id="verification-commands">Verification Commands</h2>
<p>Verify the migration worked correctly:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Check all AGENTS.md files exist</span>
<span class="nf">find</span> <span class="nb">.</span> <span class="nv">-name</span> <span class="s">"AGENTS.md"</span> <span class="nv">-type</span> f

<span class="c1"># Verify symlinks are created</span>
<span class="nf">find</span> <span class="nb">.</span> <span class="nv">-name</span> <span class="s">"CLAUDE.md"</span> <span class="nv">-type</span> l

<span class="c1"># Check symlinks point to correct files</span>
<span class="nf">find</span> <span class="nb">.</span> <span class="nv">-name</span> <span class="s">"CLAUDE.md"</span> <span class="nv">-type</span> l <span class="nv">-exec</span> <span class="nf">ls</span> <span class="nv">-la</span> <span class="p">{</span><span class="p">}</span> <span class="p">\</span><span class="p">;</span>

<span class="c1"># Verify content is agent-agnostic</span>
<span class="nf">grep</span> <span class="nv">-r</span> <span class="s">"Claude Code (claude.ai/code)"</span> <span class="nb">.</span> <span class="nv">--include</span><span class="o">=</span><span class="s">"*.md"</span> <span class="o">|</span> <span class="nf">grep</span> AGENTS.md
</code></pre></div></div>
<h2 id="maintenance">Maintenance</h2>
<h3 id="adding-new-agentsmd-files">Adding New AGENTS.md Files</h3>
<p>When you add new AGENTS.md files, run the symlink setup script:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./utils/setup-claude-symlinks.sh
</code></pre></div></div>
<h3 id="checking-symlink-status">Checking Symlink Status</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># List all symlinks</span>
<span class="nf">find</span> <span class="nb">.</span> <span class="nv">-name</span> <span class="s">"CLAUDE.md"</span> <span class="nv">-type</span> l <span class="nv">-exec</span> <span class="nf">ls</span> <span class="nv">-la</span> <span class="p">{</span><span class="p">}</span> <span class="p">\</span><span class="p">;</span>

<span class="c1"># Check for broken symlinks</span>
<span class="nf">find</span> <span class="nb">.</span> <span class="nv">-name</span> <span class="s">"CLAUDE.md"</span> <span class="nv">-type</span> l <span class="o">!</span> <span class="nv">-exec</span> <span class="nb">test</span> <span class="nv">-e</span> <span class="p">{</span><span class="p">}</span> <span class="p">\</span><span class="p">;</span> <span class="nv">-print</span>
</code></pre></div></div>
<h2 id="benefits-of-this-approach">Benefits of This Approach</h2>
<ol>
<li><strong>Backward Compatibility</strong>: Existing tools expecting CLAUDE.md files continue to work</li>
<li><strong>Git Clean</strong>: CLAUDE.md files are not tracked in version control</li>
<li><strong>Automatic Sync</strong>: Symlinks ensure CLAUDE.md always matches AGENTS.md</li>
<li><strong>Easy Maintenance</strong>: Single script handles all symlink creation/updates</li>
<li><strong>Open Standard</strong>: Future-proof with the open AGENTS.md standard</li>
</ol>
<h2 id="troubleshooting">Troubleshooting</h2>
<h3 id="broken-symlinks">Broken Symlinks</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Remove all CLAUDE.md symlinks and recreate</span>
<span class="nf">find</span> <span class="nb">.</span> <span class="nv">-name</span> <span class="s">"CLAUDE.md"</span> <span class="nv">-type</span> l <span class="nv">-delete</span>
./utils/setup-claude-symlinks.sh
</code></pre></div></div>
<h3 id="permission-issues">Permission Issues</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Make sure script is executable</span>
<span class="nf">chmod</span> +x utils/setup-claude-symlinks.sh
</code></pre></div></div>
<p>This migration preserves all existing functionality while adopting the open AGENTS.md standard for better interoperability.</p>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Workaround for Claude Code running `python` instead of `uv`</title><link href="https://solmaz.io/log/2025/07/13/claude-code-python-override/" rel="alternate" type="text/html" title="Workaround for Claude Code running `python` instead of `uv`" /><published>2025-07-13T00:00:00+00:00</published><updated>2025-07-13T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/07/13/claude-code-python-override</id><content type="html" xml:base="https://solmaz.io/log/2025/07/13/claude-code-python-override/"><![CDATA[<p><a href="https://docs.astral.sh/uv/">uv</a> is now the de facto default <a class="concept-link" href="/graph/uv-package-manager/">Python package manager</a>. I have already deleted all <code class="language-plaintext highlighter-rouge">python</code>s from my system except for the one that has to be installed for other packages in <code class="language-plaintext highlighter-rouge">brew</code>.</p>
<p>Unfortunately, <a class="concept-link" href="/graph/ai-coding-agent/">Claude Code</a> often ignores instructions in <code class="language-plaintext highlighter-rouge">CLAUDE.md</code> files to use <code class="language-plaintext highlighter-rouge">uv run python</code> instead of plain <code class="language-plaintext highlighter-rouge">python</code> commands. Even with clear documentation stating “always use uv”, Claude Code will attempt to run <code class="language-plaintext highlighter-rouge">python</code> directly, leading to “command not found” errors in projects that rely on uv for <a class="concept-link" href="/graph/python-environment-management/">Python environment management</a>.</p>
<p>The built-in Claude Code hooks and environment variable settings also don’t reliably solve this issue due to shell context limitations.</p>
<p><strong>The reason is that Claude (and most other AI models) take time to catch up to such changes, because their <a class="concept-link" href="/graph/llm-training-corpus/">learning horizon</a> is longer, up to months to years. Somebody will need to include this information explicitly in the training data.</strong></p>
<p>Until then, we can prevent wasting tokens by mapping <code class="language-plaintext highlighter-rouge">python</code> and <code class="language-plaintext highlighter-rouge">python3</code> to <code class="language-plaintext highlighter-rouge">uv</code>.</p>
<p>I personally don’t want to map these globally, because a lot of other packages might depend on system installed <code class="language-plaintext highlighter-rouge">python</code>s, like <code class="language-plaintext highlighter-rouge">brew</code> packages, <code class="language-plaintext highlighter-rouge">gcloud</code> CLI and so on.</p>
<p>Because of that, I map them at the project level, using <a href="https://direnv.net/">direnv</a>:</p>
<h3 id="an-ok-ish-solution-direnv--dynamic-wrapper-scripts">An OK-ish solution: direnv + dynamic wrapper scripts</h3>
<p>We can force Claude Code (and any developer) to use <code class="language-plaintext highlighter-rouge">uv run python</code> by dynamically creating <a class="concept-link" href="/graph/shell-command-wrapper/">wrapper scripts</a> in a <code class="language-plaintext highlighter-rouge">.envrc</code> file that <a href="https://direnv.net/">direnv</a> automatically loads when entering the project directory.</p>
<p>This will override <code class="language-plaintext highlighter-rouge">python</code> and <code class="language-plaintext highlighter-rouge">python3</code> to map to <code class="language-plaintext highlighter-rouge">uv run python</code>, and also print a nice message to the model:</p>
<p><code class="language-plaintext highlighter-rouge">Use "uv run python ..." instead of "python ..." idiot</code>.</p>
<p>This is probably not the best solution, but it is <em>a</em> solution. Feel free to suggest a better one.</p>
<h3 id="step-1-install-direnv">Step 1: Install direnv</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># macOS</span>
brew <span class="nf">install</span> direnv

<span class="c1"># Ubuntu/Debian</span>
<span class="nf">sudo</span> <span class="nf">apt</span> <span class="nf">install</span> direnv

<span class="c1"># Add to your shell (bash/zsh)</span>
<span class="nb">echo</span> <span class="s">'eval "$(direnv hook zsh)"'</span> <span class="o">&gt;&gt;</span> ~/.zshrc  <span class="c1"># or ~/.bashrc</span>
<span class="nb">source</span> ~/.zshrc  <span class="c1"># or restart terminal</span>
</code></pre></div></div>
<h3 id="step-2-setup-direnv-with-dynamic-wrapper-scripts">Step 2: Setup direnv with dynamic wrapper scripts</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Create .envrc file in project root</span>
<span class="nf">cat</span> <span class="o">&gt;</span> .envrc <span class="o">&lt;&lt;</span> <span class="s">'EOF'
#!/bin/bash
# Create temporary bin directory for python overrides
TEMP_BIN_DIR="$PWD/.direnv/bin"
mkdir -p "$TEMP_BIN_DIR"

# Create python wrapper scripts
cat &gt; "$TEMP_BIN_DIR/python" &lt;&lt; 'INNER_EOF'
#!/bin/bash
echo "Use \"uv run python ...\" instead of \"python ...\" idiot"
exec uv run python "$@"
INNER_EOF

cat &gt; "$TEMP_BIN_DIR/python3" &lt;&lt; 'INNER_EOF'
#!/bin/bash
echo "Use \"uv run python ...\" instead of \"python3 ...\" idiot"
exec uv run python "$@"
INNER_EOF

# Make them executable
chmod +x "$TEMP_BIN_DIR/python" "$TEMP_BIN_DIR/python3"

# Add to PATH
export PATH="$TEMP_BIN_DIR:$PATH"
EOF</span>

<span class="c1"># Allow direnv to load this configuration</span>
direnv allow
</code></pre></div></div>
<h3 id="step-3-update-gitignore">Step 3: Update .gitignore</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Add direnv generated files to .gitignore</span>
<span class="nb">echo</span> <span class="s">"# direnv generated files"</span> <span class="o">&gt;&gt;</span> .gitignore
<span class="nb">echo</span> <span class="s">".direnv/"</span> <span class="o">&gt;&gt;</span> .gitignore
</code></pre></div></div>
<h3 id="step-4-update-documentation">Step 4: Update documentation</h3>
<p>Add to your <code class="language-plaintext highlighter-rouge">CLAUDE.md</code> something like this:</p>
<pre><code>## Python Package Management with uv

**IMPORTANT**: This project uses `uv` as the Python package manager. ALWAYS use `uv` instead of `pip` or `python` directly.

DO NOT RUN:

```bash
python my_script.py
# OR
chmod +x my_script.py
./my_script.py
```

INSTEAD, RUN:

```bash
uv run my_script.py
```

### Key uv Commands

- **Run Python code**: `uv run &lt;script.py&gt;` (NOT `python &lt;script.py&gt;`)
- **Run module**: `uv run -m &lt;module&gt;` (e.g., `uv run -m pytest`)
- **Add dependencies**: `uv add &lt;package&gt;` (e.g., `uv add requests`)
- **Add dev dependencies**: `uv add --dev &lt;package&gt;`
- **Remove dependencies**: `uv remove &lt;package&gt;`
- **Install all dependencies**: `uv sync`
- **Update lock file**: `uv lock`
- **Run with specific package**: `uv run --with &lt;package&gt; &lt;command&gt;`
</code></pre>
<h3 id="how-it-works">How It Works</h3>
<ol>
<li><strong><a class="concept-link" href="/graph/direnv/">direnv</a></strong> automatically loads <code class="language-plaintext highlighter-rouge">.envrc</code> when you <code class="language-plaintext highlighter-rouge">cd</code> into the project directory</li>
<li><code class="language-plaintext highlighter-rouge">.envrc</code> dynamically creates executable wrapper scripts in <code class="language-plaintext highlighter-rouge">.direnv/bin/</code></li>
<li>Scripts display a helpful message and redirect to <code class="language-plaintext highlighter-rouge">uv run python</code></li>
<li><code class="language-plaintext highlighter-rouge">.direnv/bin/</code> is prepended to PATH, overriding system python commands</li>
<li>Works for any shell session in the directory (Claude Code, terminal, IDE)</li>
</ol>
<p>To see if it works:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> your-project/
python <span class="nv">-c</span> <span class="s">"print('Hello World')"</span>  <span class="c1"># Shows message, uses uv</span>
python3 <span class="nv">--version</span>                 <span class="c1"># Shows message, uses uv</span>
</code></pre></div></div>
<p>Let me know if this doesn’t work for you, or if you find a better solution.</p>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Day 47 of Claude Code god mode</title><link href="https://solmaz.io/log/2025/07/05/day-47-of-claude-code/" rel="alternate" type="text/html" title="Day 47 of Claude Code god mode" /><published>2025-07-05T00:00:00+00:00</published><updated>2025-07-05T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/07/05/day-47-of-claude-code</id><content type="html" xml:base="https://solmaz.io/log/2025/07/05/day-47-of-claude-code/"><![CDATA[<p>I started using <a class="concept-link" href="/graph/ai-coding-agent/">Claude Code</a> on May 18th, 2025. I had previously given it a chance back in February, but I had immediately WTF’d after a simple task cost 5 USD back then. When Anthropic announced their 100 USD flat plan in May, I jumped ship as soon as I could.<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>
<p>It’s not an overstatement that my life has drastically changed since then. I can’t post or blog anything anymore, because I am busy working every day on ideas, at <a href="https://textcortex.com">TextCortex</a>, and on side projects. I now sleep regularly 1-2 hours less than I used to and my sleep schedule has shifted around 2 hours.</p>
<p>But more importantly, I feel exhilaration that I have never felt as a developer before. I just talk to my computer using a speech to text tool (Wispr Flow), and my thoughts turn into code close to real time. I feel like I have enabled god mode IRL. We are truly living in a time where imagination is the only remaining bottleneck.</p>
<h3 id="things-i-have-implemented-using-claude-code">Things I have implemented using Claude Code</h3>
<h4 id="textcortex-monorepo"><strong>TextCortex Monorepo</strong></h4>
<p>The most important contribution, I merged our backend, frontend and docs repos into a <a class="concept-link" href="/graph/monorepo/">single monorepo</a> in less than 1 day, with all CI/CD and automation. This lets us use our entire code and documentation context while triggering AI <a class="concept-link" href="/graph/agent-workflow/">agents</a>.</p>
<p>We can now tag @claude in issues, and it creates PRs. Non-developers have started to make contributions to the codebase and fix bugs. Our organization speed has increased drastically in a matter of days. I will write more about this in a future post.</p>
<h4 id="json-doc-typescript-renderer"><a href="https://github.com/textcortex/JSON-DOC/pull/15">JSON-DOC TypeScript renderer</a></h4>
<p>JSON-DOC is a file format we are developing at TextCortex. I implemented the browser viewer for the format in 1 workday, in a language I am not fluent in. It was a rough first draft, but the architecture was correct and our frontend team could then take it over and polish it. Without Claude Code, I predict it would have taken at least 2-3 weeks of my time to take it to that level.</p>
<h4 id="claude-code-pr-autodoc-action"><a href="https://github.com/textcortex/claude-code-pr-autodoc-action">Claude Code PR Autodoc Action</a></h4>
<p>We are not using this anymore, but it’s a GitHub Action that triggers in every PR and adds documentation about that PR to the repo.</p>
<h4 id="claude-code-sandbox"><a href="https://github.com/textcortex/claude-code-sandbox">Claude Code Sandbox</a></h4>
<p>Still work-in-progress, but it is supposed to give you an OpenAI Codex like experience with running Claude Code locally on your own machine. We have big plans for this.</p>
<h4 id="textcortex-agentic-rag-implementation">TextCortex Agentic RAG implementation</h4>
<p>The next version of our product, I revamped our chat engine completely to implement agentic RAG. Since our frontend had long running issues, I had to recreate our chat UI from scratch, again in 1 day. Will be rolled out in a few weeks, so I cannot write about it yet.</p>
<h4 id="fixed-i18n">Fixed i18n</h4>
<p>I had a system in mind for <a class="concept-link" href="/graph/internationalization/">auto-translating strings</a> in a codebase for 2 years, when GPT-4 came out. I finally implemented that in 1 day. We had previously used DeepL which did some really stupid mistakes like translating “Disabled” (in the computer sense) as “behindert” in German, which means <em>r…ded</em>, or “Tenant” (enterprise software) as “Mieter” (renter of a real estate). The new system generates a context for each string based on the surrounding code, which is then used to translate the string to all the different languages. There is truly no point in paying for a SaaS for i18n anymore, when you can automate it with GitHub Actions and ship it statically.<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup></p>
<h3 id="tackling-small-to-mid-size-tasks-without-context-switching">Tackling small-to-mid-size tasks without context switching</h3>
<p>Perhaps the most important effect of agentic development is that it lets you do all the things you wanted to, but couldn’t before, because it was too big of a context switch.</p>
<p>There are certain parts of a codebase that require utmost attention, like when you are designing a data model, the API endpoint schemas, and so on. Mostly backend. But once you know your backend is good enough, you can just rip away on the frontend side with Claude Code, because you know your business data and logic is safe.</p>
<p>I have finished so many of these that it would make this post too long. To give one example, I implemented a Discord bot that we can use to download whole threads, so that we can embed it in the monorepo or create GitHub issues automatically.</p>
<h3 id="side-projects">Side projects</h3>
<p>My performance on my side projects has also increased a lot. I am able to ship in 1 weekend day close to 2 weeks worth of dev-work. Thanks to Claude Code, I was able to ship my new app <a href="https://horse.fit">Horse</a>. It’s like an AI personal trainer, but it only counts your push-ups for now. But even that was a complex enough <a class="concept-link" href="/graph/computer-vision-tracking/">computer vision task</a>.</p>
<p>I had previously only written the Python algo for detecting push-ups. Claude Code let me develop the backend, frontend and the low-level engine in <a class="concept-link" href="/graph/rust-programming/">Rust</a>, over the course of 2-3 weekends.</p>
<p>I knew nothing about <a class="concept-link" href="/graph/mobile-software-development/">cross-compiling Rust code to iOS</a>, yet I was able to do the whole thing, FFI and all, in 20 minutes, which worked out of the box. Important takeaway: AI makes it incredibly easy to port well-tested codebases to different languages. I predict an increased rate of Rust-ification of open source projects.</p>
<p>You can see more about it on my sports Instagram <a href="https://www.instagram.com/stories/highlights/18511599592034978/">here</a>.</p>
<h3 id="its-all-about-completing-the-loop">It’s all about completing the loop</h3>
<p>Agentic workflows work best when you have a good verifier (like tests) which lets you create a good <a class="concept-link" href="/graph/automated-testing/">feedback loop</a>. This might be the compiler output, a Playwright MCP server, running <code class="language-plaintext highlighter-rouge">pytest</code>, spinning up a local server and making a request, and so on.</p>
<p>Once you complete the loop, you can just let AI rip on it, and come back to a finished result after a few minutes or hours.</p>
<h3 id="swearing-at-ai">Swearing at AI</h3>
<p>I have developed a new and ingrained habit of swearing at Claude Code, in the past couple of weeks. I frequently call it “idiot”, “r…d”, “absolute f…g moron” and so on. With increasing speed comes increasing impatience, and frustration when the agent does not get something despite having the right context.</p>
<p>I think there is something deeply psychological about feeling these kind of emotions towards AI. I know it’s an entity that does not retain memory or learn as a human does, but I still insult it when it fails at a task. I feel like it mostly works, but I have not done any scientific experiments to prove it.</p>
<p>The empathic reader should be aware that emotional reactions to AI reveal more about one’s own psychological state than the AI’s.</p>
<h3 id="on-claude-code-skeptics">On Claude Code skeptics</h3>
<p>Claude Code is a great litmus test to detect whoever is a deadweight at a company. If your employees cannot learn to use Claude Code to do productive work, you should most likely fire them. It’s not about the product or Anthropic itself, but the upcoming agentic development paradigm. <a href="https://www.axios.com/2025/05/28/ai-jobs-white-collar-unemployment-anthropic">Dario Amodei was not bluffing when he said that a white collar bloodbath is coming</a>.</p>
<p>I have since then introduced multiple people to Claude Code, all good developers. All of them were initially skeptical, but the next day all of them texted me “wow”-like messages. The fire is spreading.</p>
<p>The 100 USD plan was initially the main obstacle to people trying it out, but now it’s available in the 17 USD plan, so I expect to see very rapid adoption in the following months.</p>
<hr>
<p>I got done in 47 days more work than I previously did in 6-12 months. I am curious how TextCortex will look in 6 months from now.</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1">
<p>I previously had the insight that Claude Code would perform better than Cursor, because the model providers have control over what tool data to include in the dataset, whereas Cursor is approaching the model as an outsider and trying to do trial and error on what kind of interfaces the model would be good at. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2">
<p>Disclaimer, our founder Jay had already done work to use GPT-4o for automating translations, what I added on top was the context generation and improvements in automation. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Predictions by Anthropic Researchers</title><link href="https://solmaz.io/log/2025/06/04/dwarkesh-sholto-trenton-2/" rel="alternate" type="text/html" title="Predictions by Anthropic Researchers" /><published>2025-06-04T00:00:00+00:00</published><updated>2025-06-04T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/06/04/dwarkesh-sholto-trenton-2</id><content type="html" xml:base="https://solmaz.io/log/2025/06/04/dwarkesh-sholto-trenton-2/"><![CDATA[<p>Dwarkesh Patel has recently interviewed Sholto Douglas and Trenton Bricken for a second time, and the podcast is very enlightening in terms of how the big AI labs think in terms of their economic strategy:</p>
<div class="responsive-embed"><iframe width="560" height="315" src="https://www.youtube.com/embed/64lXQP6cs5M?start=3651" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
<p>(Clicking will start the video around the 1hr mark, the part that is relevant to this post.)</p>
<p>According to Sholto and Trenton, the following have been largely “solved” by now:</p>
<ul>
<li><strong>Advanced math/programming:</strong>
<ul>
<li>“Math and competitive programming fell first.” <em>(Sholto)</em></li>
</ul>
</li>
<li><strong>Routine online interactions:</strong>
<ul>
<li>“Flight booking is totally solved.” <em>(Sholto)</em></li>
<li>Successfully “planning a camping trip,” navigating complicated websites. <em>(Trenton)</em></li>
</ul>
</li>
</ul>
<p>And below are their predictions for what will be solved by next year, around May 2026:</p>
<ul>
<li><strong><a class="concept-link" href="/graph/ai-model-reliability/">Reliable</a> web/<a class="concept-link" href="/graph/automation/">software automation</a>:</strong>
<ul>
<li>Photoshop edits with sequential effects: “Totally.” <em>(Sholto)</em></li>
<li>Handling complex site interactions (e.g., managing cookies, navigating tricky interfaces): “If you gave it one person-month of effort, then it would be solved.” <em>(Sholto)</em></li>
</ul>
</li>
</ul>
<p>And below are what they predict will probably not be solved by next year:</p>
<ul>
<li><strong>Fully autonomous, high-trust tasks:</strong>
<ul>
<li>“I don’t think it’ll be able to autonomously do your taxes with a high degree of trust.” <em>(Sholto)</em></li>
</ul>
</li>
<li><strong>Generalized tax preparation:</strong>
<ul>
<li>“It will get the taxes wrong… If I went to you and I was like, ‘I want you to do everyone’s taxes in America,’ what percentage of them are you going to fuck up?” <em>(Sholto)</em></li>
</ul>
</li>
<li><strong>Models’ self-awareness of its own reliability and confidence:</strong>
<ul>
<li>“The unreliability and confidence stuff will be somewhat tricky, to do this all the time.” <em>(Sholto)</em></li>
</ul>
</li>
</ul>
<hr>
<p>I interpret this and the rest of the interview as follows:</p>
<blockquote>
<p>The labs can now “solve”<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> any <a class="concept-link" href="/graph/knowledge-work/">white-collar task</a> or job segment if they put their resources into it. From now on, it is a question of how much it would pay off.</p>
</blockquote>
<p>In other words, if the labs think it will make more money to automate accounting (or any other task), then they will create <a class="concept-link" href="/graph/ai-benchmark/">benchmarks</a> for that and start optimizing. Until now, they have mostly been optimizing for <a class="concept-link" href="/graph/software-engineering/">software engineering</a><sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>, because of high immediate payoff.</p>
<hr>
<p>Below are some job segments that <em>I</em> predict to be affected first (not Sholto or Trenton):</p>
<ul>
<li><strong>Marketing &amp; copywriting</strong>: actually the first segment that already fell. Many AI companies (including <a href="https://textcortex.com/">TextCortex</a>) was initially focused on this segment. Automation in this sector will increase even more in the upcoming years.</li>
<li><strong>Customer service &amp; support</strong>: many countries where this is outsourced to, like India, will be affected.</li>
<li><strong>Data entry, bookkeeping &amp; accounting tasks</strong>: while it is a dream to automate bookkeeping, accounting, taxes, etc. it will most likely fall last due to regulations and low margin for fuckups.</li>
<li><strong>Paralegal &amp; contract-review tasks</strong>: Many companies popped up to target the legal system. Current law forbids automated lawyering in the US and most of the world. It will eventually fall as well, starting first with paralegal tasks, advisory services, etc.</li>
<li><strong>Internal IT &amp; systems administration</strong>: will be automated the fastest, because it is being optimized for under the software engineering umbrella.</li>
<li><strong>Real estate &amp; insurance processing</strong>: related companies will see that they are able to save a lot of money with AI. There will be a lot of competitive pressure in every country once the first few players are successfully automate their processes. These will most likely be smaller players, who will disrupt incumbents.</li>
<li><strong>Product/project management (routine parts)</strong>: cue recent Microsoft layoffs<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup>, ending 600k comp. product manager positions. It is already happening, and will only accelerate.</li>
</ul>
<hr>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1">
<p>Automate a considerable part of it, so that the work will turn into mainly managing <a class="concept-link" href="/graph/ai-coding-agent/">AI agents</a>. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2">
<p>E.g. the <a href="https://openai.com/index/swe-lancer/">SWE-Lancer</a> benchmark by OpenAI. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:3">
<p>See <a href="https://www.theguardian.com/technology/2025/may/13/microsoft-layoffs">this article</a>. <em>The company’s chief financial officer, Amy Hood, said on an April earnings call that the company was focused on “building high-performing teams and increasing our agility by reducing layers with fewer managers”. She also said the headcount in March was 2% higher than a year earlier, and down slightly compared with the end of last year.</em> <a href="#fnref:3" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">SCP-3434: Istanbul Taxi Superorganism</title><link href="https://solmaz.io/log/2025/05/31/scp-3434/" rel="alternate" type="text/html" title="SCP-3434: Istanbul Taxi Superorganism" /><published>2025-05-31T00:00:00+00:00</published><updated>2025-05-31T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/05/31/scp-3434</id><content type="html" xml:base="https://solmaz.io/log/2025/05/31/scp-3434/"><![CDATA[<p><strong>Item #:</strong> SCP-3434</p>
<p><strong>Object Class:</strong> Euclid</p>
<p><strong>Special Containment Procedures:</strong> SCP-3434 cannot be fully contained due to its diffuse nature and integration into civilian infrastructure. Foundation agents embedded within Istanbul’s Transportation Coordination Center (UKOME) are to monitor taxi activity patterns for anomalous behavior spikes. Mobile Task Force ████ has been assigned to investigate and neutralize extreme manifestations within SCP-3434.</p>
<p>Individuals exhibiting temporal disorientation after utilizing taxi services in Istanbul should be administered Class-B amnestics and monitored for 72 hours post-incident. Under no circumstances should Foundation personnel utilize SCP-3434 instances for transportation unless authorized for testing purposes.</p>
<p><strong>Description:</strong> SCP-3434 is a defensive <a class="concept-link" href="/graph/superorganism/">superorganism</a> manifesting as a <a class="concept-link" href="/graph/collective-consciousness/">collective consciousness</a> within approximately 17,000 taxi vehicles operating in Istanbul, Turkey. Individual taxis display coordinated behaviors atypical for independently operated vehicles, functioning as a <a class="concept-link" href="/graph/distributed-neural-network/">distributed neural network</a> despite lacking any detectable communication infrastructure.</p>
<p>SCP-3434 exhibits three primary anomalous properties:</p>
<ol>
<li>
<p><strong><a class="concept-link" href="/graph/temporal-distortion/">Temporal Distortion</a>:</strong> Passengers experience significant time dilation upon entering affected vehicles. Discrepancies between perceived and actual elapsed time range from minutes to several hours, with no correlation to distance traveled or traffic conditions. GPS data from affected rides consistently shows corruption or retroactive alteration.</p>
</li>
<li>
<p><strong><a class="concept-link" href="/graph/economic-predation/">Economic Predation</a>:</strong> The collective demonstrates uncanny ability to extract maximum possible fare from each passenger through coordinated deception, including meter “malfunctions,” route manipulation, and inexplicable knowledge of passenger financial status. Credit card readers experience a ████ failure rate exclusively for non-local passengers.</p>
</li>
<li>
<p><strong><a class="concept-link" href="/graph/territorial-defense/">Territorial Defense</a>:</strong> SCP-3434 displays extreme hostility toward competing transportation services. Since 2011, all attempts by ridesharing platforms to establish operations have failed due to coordinated interference including simultaneous vehicle failures, GPS anomalies affecting only competitor vehicles, and physical blockades formed with millisecond precision.</p>
</li>
</ol>
<p><strong>Incident Log 3434-A:</strong>
On 14/09/2024, Agent ████ ████ was assigned to investigate temporal anomalies reported in the Beyoğlu district. Agent ████ entered taxi license plate 34 T ████ at 14:22 local time for what GPS tracking indicated would be a 12-minute journey to Taksim Square.</p>
<p>Agent ████ emerged at 14:34 local time at the intended destination. However, biological markers and personal chronometer readings indicated Agent ████ had experienced approximately 8 months of subjective time. Physical examination confirmed accelerated aging consistent with temporal displacement. Agent exhibited severe psychological distress and no memory of the elapsed period.</p>
<p>The taxi driver, when questioned, displayed no anomalous knowledge and insisted the journey had taken “only 15 minutes, very fast, no traffic.” The meter showed a fare of ████, approximately 40 times the standard rate. Driver claimed this was “normal price, weekend rates.”</p>
<p>Post-incident analysis of the taxi revealed no anomalous materials or modifications. The vehicle continues to operate within the SCP-3434 network without further documented incidents.</p>
<p><strong>Interview Log:</strong></p>
<blockquote>
<p><strong>Interviewed:</strong> ███████ (Driver of taxi license plate 34 T ████)</p>
<p><strong>Dr. ████:</strong> How long have you been driving this route?</p>
<p><strong>███████:</strong> Route? What route? The city tells us where to go.</p>
<p><strong>Dr. ████:</strong> The city?</p>
<p><strong>███████:</strong> You wouldn’t understand. You’re not connected. But we all hear it. Every corner, every passenger, every lira. We are Istanbul, and Istanbul is us.</p>
<p><strong>Dr. ████:</strong> Can you elaborate on-</p>
<p><strong>███████:</strong> Your hotel is 20 minutes away. It will take us an hour. The meter is broken. Only cash.</p>
</blockquote>
<p><strong>Addendum 3434-1:</strong> Research into historical records reveals references to unusual taxi behavior in Istanbul dating back to 1942, coinciding with the introduction of the first motorized taxi services. The phenomenon appears to have evolved in complexity with the city’s growth.</p>
<p><strong>Addendum 3434-2:</strong> Foundation economists estimate SCP-3434’s collective annual revenue exceeds ████ million Turkish Lira, with 0% reported to tax authorities. Attempts to audit individual drivers result in temporary disappearance of all documentation and the spontaneous malfunction of all electronic devices within a 10-meter radius.</p>
<p><strong>Note from Site Director:</strong> “Under no circumstances should personnel attempt to ‘outsmart’ SCP-3434 by pretending to be locals. They already know. They always know.”</p>
<hr>
<p>I am on vacation, so here is a little bit of fun with some grounded fiction.</p>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Auto-generating pull request documentation with Claude Code and GitHub Actions</title><link href="https://solmaz.io/log/2025/05/24/claude-code-pr-autodoc-action/" rel="alternate" type="text/html" title="Auto-generating pull request documentation with Claude Code and GitHub Actions" /><published>2025-05-24T00:00:00+00:00</published><updated>2025-05-24T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/05/24/claude-code-pr-autodoc-action</id><content type="html" xml:base="https://solmaz.io/log/2025/05/24/claude-code-pr-autodoc-action/"><![CDATA[<p>Anthropic has just released a <a class="concept-link" href="/graph/github-action/">GitHub Action</a> for integrating <a href="https://www.anthropic.com/claude-code">Claude Code</a> into your GitHub repo. This lets you do very cool things, like <strong>automatically generating <a class="concept-link" href="/graph/repository-documentation/">documentation for your pull requests</a> after you merge them</strong>. Skip to the next section to learn how to install it in your repo.</p>
<p>Since <a class="concept-link" href="/graph/ai-coding-agent/">Claude Code</a> is envisioned to be a basic Unix utility, albeit a very smart one, it is very easy to use it in GitHub Actions. The action is very simple:</p>
<ul>
<li>It runs after a <a class="concept-link" href="/graph/pull-request/">pull request</a> is merged.</li>
<li>It uses Claude Code to generate a documentation for the pull request.</li>
<li>It creates a new pull request with the documentation.</li>
</ul>
<p>This is super useful, because it saves context about the repo into the repo itself. The documentation generated this way is very useful for not only humans, but also for AI agents. A future AI can then learn about what was done in a certain PR, without looking at Git history, issues or PRs. In other words, it lets you automatically break GitHub’s walled garden, using GitHub’s native features <sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>.</p>
<h2 id="installation">Installation</h2>
<ol>
<li>Save your <code class="language-plaintext highlighter-rouge">ANTHROPIC_API_KEY</code> as a secret in the repo you want to install this action. You can find this page in <code class="language-plaintext highlighter-rouge">https://github.com/&lt;your-username-or-org-name&gt;/&lt;your-repo-name&gt;/settings/secrets</code>. If you have already installed Claude Code in your repo by running <code class="language-plaintext highlighter-rouge">/install-github-app</code> in Claude Code, you can skip this step.</li>
<li>Save the following as <code class="language-plaintext highlighter-rouge">.github/workflows/claude-code-pr-autodoc.yml</code> in your repo:</li>
</ol>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">name</span><span class="p">:</span> Auto<span class="p">-</span>generate PR Documentation

<span class="na">on</span><span class="p">:</span>
  <span class="na">pull_request</span><span class="p">:</span>
    <span class="na">types</span><span class="p">:</span> <span class="p">[</span>closed<span class="p">]</span>
    <span class="na">branches</span><span class="p">:</span>
      <span class="p">-</span> main

<span class="na">jobs</span><span class="p">:</span>
  <span class="na">generate-documentation</span><span class="p">:</span>
    <span class="c1"># Only run when PR is merged and not created by bots</span>
    <span class="c1"># This prevents infinite loops and saves compute resources</span>
    <span class="na">if</span><span class="p">:</span> <span class="p">|</span><span class="s">
      github.event.pull_request.merged == true &amp;&amp;
      github.event.pull_request.user.type != 'Bot' &amp;&amp;
      !startsWith(github.event.pull_request.title, 'docs: Add documentation for PR')</span>
    <span class="na">runs-on</span><span class="p">:</span> ubuntu<span class="p">-</span>latest
    <span class="na">permissions</span><span class="p">:</span>
      <span class="na">contents</span><span class="p">:</span> write
      <span class="na">pull-requests</span><span class="p">:</span> write
      <span class="na">id-token</span><span class="p">:</span> write

    <span class="na">steps</span><span class="p">:</span>
      <span class="p">-</span> <span class="na">uses</span><span class="p">:</span> textcortex/claude<span class="p">-</span>code<span class="p">-</span>pr<span class="p">-</span>autodoc<span class="p">-</span>action@v1
        <span class="na">with</span><span class="p">:</span>
          <span class="na">anthropic_api_key</span><span class="p">:</span> $<span class="p">{</span><span class="p">{</span> secrets.ANTHROPIC_API_KEY <span class="p">}</span><span class="p">}</span>
</code></pre></div></div>
<p>There are bunch of parameters you can configure, like minimum number of diff lines that will trigger the action, or the directory where the documentation will be saved. To learn about how to configure these parameters, visit the GitHub Action repo itself: <a href="https://github.com/textcortex/claude-code-pr-autodoc-action">textcortex/claude-code-pr-autodoc-action</a>.</p>
<h2 id="usage">Usage</h2>
<p>After you merge a PR, the action will automatically generate documentation for it and open a new PR with the documentation. You can then simply merge this PR, and the documentation will be added to the repo, by default in the <code class="language-plaintext highlighter-rouge">docs/prs</code> directory.</p>
<h2 id="thoughts-on-claude-code">Thoughts on Claude Code</h2>
<p>I was curious why Anthropic had not released an agentic coding app on Claude.ai, and this might be the reason why.</p>
<p>The main Claude Code action is not limited to creating PR documentation. You tag <code class="language-plaintext highlighter-rouge">@claude</code>, in any comment, and Claude Code will answer questions or implement the changes you ask for.</p>
<p>While OpenAI and Google is busy creating sloppy chat UXs for agentic coding (Codex and Jules) and forcing developers to work on their site, Anthropic is taking Claude directly to the developers’ feet and integrate Claude Code into GitHub.</p>
<p>Ask any question in a GitHub PR, and Claude Code will answer your questions, implement requested changes, fix bugs, typos, styling issues.</p>
<p>You don’t need to go to code Codex or Jules website to follow up on your task. Why should you? Developer UX is already “solved” (well yes but no).</p>
<p>Anthropic bets on GitHub, what already works. That’s why they have probably already won developers.</p>
<p>The only problem is that it costs a little bit too much for now.</p>
<p>In the long run, I am not sure if GitHub will be enough for following up async agentic coding tasks in parallel. Anthropic might soon launch their own agentic coding app. GitHub itself might evolve and create a better real-time chat UX. But unless that UX really blows my mind, I will most likely just hang out at GitHub. If you are an insider, or you know what Anthropic is planning to do, please let us know in the HN comment section.</p>
<hr>
<p><a href="https://github.com/textcortex/claude-code-pr-autodoc-action">claude-code-pr-autodoc-action</a> was developed by me, 80% using Claude Code and 20% using Cursor with Claude Opus 4.</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1">
<p><a href="https://stephango.com/file-over-app">File over app by Steph Ango</a>. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Working on the weekend</title><link href="https://solmaz.io/log/2025/04/26/working-on-the-weekend/" rel="alternate" type="text/html" title="Working on the weekend" /><published>2025-04-26T00:00:00+00:00</published><updated>2025-04-26T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/04/26/working-on-the-weekend</id><content type="html" xml:base="https://solmaz.io/log/2025/04/26/working-on-the-weekend/"><![CDATA[<p>Certain types of work are best done in one go, instead of being split into separate sessions. These are the types of work where it is more or less clear what needs to be done, and the only thing left is execution. In such cases, the only option is sometimes to work over the weekend (or lock yourself in a room <a class="concept-link" href="/graph/uninterrupted-work/">without communication</a>), in order not to be interrupted by people.</p>
<hr>
<p>There was a 2-year old <a class="concept-link" href="/graph/technical-debt/">tech debt</a> at <a href="https://textcortex.com">TextCortex</a> backend. Resolving it required a <a class="concept-link" href="/graph/software-refactoring/">major refactor</a> that we wanted to do since one year. I finally paid that tech debt 2 weeks ago, by working a cumulative of 24 hours over 2 days, creating a diff of 5-6k lines of Python code and 90 commits over 105 files.</p>
<p>The result:</p>
<ul>
<li>No more <a class="concept-link" href="/graph/backend-performance-optimization/">request latencies</a> or dropped requests.</li>
<li>Much faster responses.</li>
<li><a class="concept-link" href="/graph/cloud-cost-optimization/">50% reduction in Cloud Run costs</a>.</li>
<li>Better memory and CPU utilization.</li>
<li>Faster startup times.</li>
</ul>
<p>I’ve broken some eggs while making this omelette—bugs were introduced and fixed. I could finish the task because I had <a class="concept-link" href="/graph/code-ownership/">complete code ownership</a> and worked over the weekend without blocking other people. Stuff like this can only happen in startups, or startup-like environments.</p>
<p><a href="/assets/images/log/2025-04-26-working-on-the-weekend1.png"><img src="/assets/images/log/2025-04-26-working-on-the-weekend1.png" alt="TextCortex"></a></p>
<p>Credit also goes to our backend engineer Tugberk Ayar for helping <a class="concept-link" href="/graph/stress-testing/">stress testing</a> the new code.</p>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Don&#39;t delete to fix</title><link href="https://solmaz.io/log/2025/02/26/dont-delete-to-fix/" rel="alternate" type="text/html" title="Don&#39;t delete to fix" /><published>2025-02-26T00:00:00+00:00</published><updated>2025-02-26T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/02/26/dont-delete-to-fix</id><content type="html" xml:base="https://solmaz.io/log/2025/02/26/dont-delete-to-fix/"><![CDATA[<p>If you are a developer, you are annoyed by this. If you are a user, you were most likely guilty of this. I am talking <a class="concept-link" href="/graph/bug-reporting/">reporting</a> that something is broken, AND deleting it.</p>
<p>This happened to me too many times: User experiences a bug with an object. Their first instinct is to delete it, and create a new one. They report it. I cannot <a class="concept-link" href="/graph/bug-reproduction/">reproduce and fix</a> it.</p>
<p>If you have a car and it stops working, you don’t throw it in the trash and then call the service to fix it. But when it comes to software, which has virtually zero cost of creation, this behavior somehow becomes widespread.</p>
<p>This is similar to other user behavior like smashing the mouse and keys when a computer gets stuck. It is physically impossible for such an action to speed up a digital process, but many of us instinctively do it.<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> Deleting to fix is a similar behavior, which I suspect got ingrained by crappy Microsoft software. The default way of fixing Windows machines is to “format the disk”, and reinstalling Windows. Nobody asks, “why do I have to start from scratch?”. The “End User” deletes to fix by default, because the End User does not understand. <em>“Have you tried turning it off and on again?”</em></p>
<p>The concept of “<a class="concept-link" href="/graph/mechanical-sympathy/">Mechanical Sympathy</a>” is relevant: having an understanding of how a tool works, being able to feel inside the box. We can extend this to “Developer Sympathy”: having an <a class="concept-link" href="/graph/developer-sympathy/">understanding of how a software was developed</a>, how it changes over time, how it can break, how it can be fixed.</p>
<p>Any troubleshooting must be done in a <a class="concept-link" href="/graph/non-destructive-troubleshooting/">non-destructive way</a>. When a user deletes an object, two things can happen: it is hard-deleted, which makes the issue impossible to reproduce. If it is instead <a class="concept-link" href="/graph/soft-deletion/">soft-deleted</a>, it might be <a class="concept-link" href="/graph/data-restoration/">restored</a>, but developers will mostly not bother, depending on the issue.</p>
<p>The users cannot be expected to care either. Their time is valuable. They deserve things that “just work”. So we need to come up with other workarounds:</p>
<ul>
<li>Everything should be soft-deleted by default in non-sensitive contexts, and should be easy to restore.</li>
<li>Any reporting form should include instructions to warn the user against deleting.</li>
<li>Even better, the reporting should happen through an internal system, and should automatically block deletion once a ticket is created.</li>
</ul>
<hr>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1">
<p>I can’t remember the name of this inequality or find it online, please comment on the <a href="https://news.ycombinator.com/item?id=43183565">Hacker News thread</a> if you know what it’s called. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Warmup and cooldown</title><link href="https://solmaz.io/log/2025/02/21/warmup-cooldown/" rel="alternate" type="text/html" title="Warmup and cooldown" /><published>2025-02-21T00:00:00+00:00</published><updated>2025-02-21T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/02/21/warmup-cooldown</id><content type="html" xml:base="https://solmaz.io/log/2025/02/21/warmup-cooldown/"><![CDATA[<p>One common thing about sports noobs<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> is that they don’t <a class="concept-link" href="/graph/exercise-warm-up/">warm up</a> before and <a class="concept-link" href="/graph/exercise-cooldown/">cool down</a> after an exercise. They might be convinced that it is not necessary, and they also don’t know how to do it properly. They might complain from prolonged injuries, like joint pain.</p>
<p>The thing about <strong>serious exercise</strong>, be it <a class="concept-link" href="/graph/strength-training/">strength training</a>, running, stretching, and so on, is that you are pushing your body beyond its limits. This is called <strong><a class="concept-link" href="/graph/progressive-overload/">overload</a></strong>. If you do this over a long term period, it is called <strong>progressive overload</strong>. This is what gives you real power, real speed, ability to do middle splits, and so on.</p>
<p>When you start with an intention to do <strong>serious exercise</strong>, and you immediately start loading heavily without warming up, you will get <strong><a class="concept-link" href="/graph/exercise-injury-prevention/">injured</a></strong> very quickly and have to take days or weeks of break.</p>
<p>For example, if you directly jump at the heaviest dumbbells you can lift and start doing bicep curls the moment you get to the gym, you will destroy your wrists, elbows, and/or shoulders. You will not realize it immediately. After a few weeks or months, you will start feeling pain, and will have to stop training altogether.</p>
<p>A common thing about noobs who injure themselves early on is that they have fierce willpower, but they don’t listen to their bodies, and they don’t have a good understanding of their current capabilities. They have an idea of where they want to be, and they are prepared to push towards it. But because they are impatient, don’t have good mind-body connection, and don’t know how to plan for long-term progress, they push themselves too far too fast.<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup></p>
<p>Being able to sustain injury-free long-term practice is a skill in itself, and perhaps the most underrated among non-professional gym-goers and athletes. There is no fancy Latin/Greek name for it, like there is for other things like cardio, plyometrics, hypertrophy, and so on. A crucial idea is missing from mainstream fitness.</p>
<p>Therefore, I coin the term and define it here:</p>
<blockquote>
<p><strong><a class="concept-link" href="/graph/parathletics/">Parathletics</a></strong>: The practices that let you successfully sustain injury-free long-term practice of a physical activity.</p>
</blockquote>
<p>The word comes from Greek παρά (para-) meaning “beside/alongside” and ἀθλητικός (athlētikós) meaning “athletic”, “relating to an athlete”<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup>.</p>
<p>Two main parathletic practices are <strong>warmup</strong> and <strong>cooldown</strong>.</p>
<p>Before starting a workout, <strong>warm up</strong> your body by moving your <strong>every</strong> joint, from the neck to the toes, through its <a class="concept-link" href="/graph/joint-mobility/">range of motion</a> and increase the blood flow to your muscles. If you plan to do heavy loads, build up to them with lighter weights first.</p>
<p>After finishing a workout, <strong>cool down</strong> your body by stretching <strong>every</strong> joint and muscle group, and especially the ones you just trained. The more hardcore your workout, the more you need to stretch.</p>
<p>Skipping these will result in injury, decrease in mobility, and delay in reaching your goals.</p>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1">
<p>Including me before I started to receive proper training. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2">
<p>Me running in 2017. I tried to lower my pace below 5:00 per km too quickly, less than a year after I started running. I had to stop because my heart fatigued for 2-3 days after running, with increased troponin levels in my blood. I never got serious about running since then. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:3">
<p>Which eventually comes from ἆθλος (âthlos) which was used to mean “contest”, “prize”, “game”, “struggle” and similar things. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>]]></content><author><name>Onur Solmaz</name></author></entry><entry><title type="html">Satya Nadella on knowledge work</title><link href="https://solmaz.io/log/2025/02/20/satya-nadella-on-knowledge-work/" rel="alternate" type="text/html" title="Satya Nadella on knowledge work" /><published>2025-02-20T00:00:00+00:00</published><updated>2025-02-20T00:00:00+00:00</updated><id>https://solmaz.io/log/2025/02/20/satya-nadella-on-knowledge-work</id><content type="html" xml:base="https://solmaz.io/log/2025/02/20/satya-nadella-on-knowledge-work/"><![CDATA[<p>Satya Nadella, shares his thinking on the future of <a class="concept-link" href="/graph/knowledge-work/">knowledge work</a> (<a href="https://youtu.be/4GLSzuYXh6w?t=1555">link to YouTube</a> for those who don’t want to read) on Dwarkesh Patel Podcast. He thinks that white collar work will become more like factory work, with <a class="concept-link" href="/graph/enterprise-ai-agent/">AI agents</a> used for end-to-end optimization.</p>
<blockquote>
<p><strong>Dwarkesh:</strong> Even when you have working <a class="concept-link" href="/graph/agent-workflow/">agents</a>, even when you have things that can do remote work for you, with all the compliance and with all the inherent bottlenecks, is that going to be a big bottleneck, or is that going to move past pretty fast?</p>
<p><strong>Satya:</strong> It is going to be a real challenge because the real issue is <a class="concept-link" href="/graph/change-management/">change management</a> or process change. Here’s an interesting thing: one of the analogies I use is, just imagine how a multinational corporation like us did forecasts pre-PC, and email, and spreadsheets. Faxes went around. Somebody then got those faxes and did an interoffice memo that then went around, and people entered numbers, and then ultimately a forecast came, maybe just in time for the next quarter.</p>
<p>Then somebody said, “Hey, I’m just going to take an Excel spreadsheet, put it in email, send it around. People will go edit it, and I’ll have a forecast.” So, the entire forecasting business process changed because <strong>the work artifact and the workflow changed</strong>.</p>
<p>That is what needs to happen with AI being introduced into knowledge work. In fact, when we think about all these agents, the fundamental thing is <strong>there’s a new work and workflow</strong>.</p>
<p>For example, even prepping for our podcast, I go to my copilot and I say, “Hey, I’m going to talk to Dwarkesh about our quantum announcement and this new model that we built for game generation. Give me a summary of all the stuff that I should read up on before going.” It knew the two Nature papers, it took that. I even said, “Hey, go give it to me in a podcast format.” And so, it even did a nice job of two of us chatting about it.</p>
<p>So that became—and in fact, then I shared it with my team. I took it and put it into Pages, which is our artifact, and then shared. So the new workflow for me is I think with AI and work with my colleagues.</p>
<p>That’s a fundamental change management of everyone who’s doing knowledge work, suddenly figuring out these new patterns of “How am I going to get my knowledge work done in new ways?” That is going to take time. It’s going to be something like in sales, and in finance, and supply chain.</p>
<p>For an incumbent, I think that this is going to be one of those things where—you know, let’s take one of the analogies I like to use is what manufacturers did with Lean. I love that because, in some sense, if you look at it, Lean became a methodology of how one could take an end-to-end process in manufacturing and become more efficient. It’s that <a class="concept-link" href="/graph/lean-manufacturing/">continuous improvement</a>, which is reduce waste and increase value.</p>
<p><strong>That’s what’s going to come to knowledge. This is like Lean for knowledge work, in particular. And that’s going to be the hard work of management teams and individuals who are doing knowledge work, and that’s going to take its time.</strong></p>
<p><strong>Dwarkesh:</strong> Can I ask you just briefly about that analogy? One of the things Lean did is physically transform what a factory floor looks like. It revealed bottlenecks that people didn’t realize until you’re really paying attention to the processes and workflows.</p>
<p>You mentioned briefly what your own workflow—how your own workflow has changed as a result of AIs. I’m curious if we can add more color to what will it be like to run a big company when you have these AI agents that are getting smarter and smarter over time?</p>
<p><strong>Satya:</strong> It’s interesting you ask that. I was thinking, for example, today if I look at it, we are very email heavy. I get in in the morning, and I’m like, man my inbox is full, and I’m responding, and so I can’t wait for some of these Copilot agents to automatically populate my drafts so that I can start reviewing and sending.</p>
<p>But I already have in Copilot at least ten agents, which I query them different things for different tasks. I feel like there’s a new inbox that’s going to get created, which is my millions of agents that I’m working with will have to invoke some exceptions to me, notifications to me, ask for instructions.</p>
<p>So at least what I’m thinking is that there’s a <a class="concept-link" href="/graph/agent-infrastructure/">new scaffolding</a>, which is the agent manager. It’s not just a chat interface. I need a smarter thing than a chat interface to manage all the agents and their dialogue.</p>
<p>That’s why I think of this Copilot, as the UI for AI, is a big, big deal. Each of us is going to have it. So basically, think of it as: <strong>there is knowledge work, and there’s a knowledge worker. The knowledge work may be done by many, many agents, but you still have a knowledge worker who is dealing with all the knowledge workers. And that, I think, is the interface that one has to build.</strong></p>
</blockquote>
<p>If you got confused for a second there like me, Lean here is not referring to the <a href="https://en.wikipedia.org/wiki/Lean_(proof_assistant)">open source proof assistant</a> but <a href="https://en.wikipedia.org/wiki/Lean_manufacturing">lean manufacturing</a>.</p>
<p>Whereas it is nice to dream, the actual sentiment on Microsoft Copilot and AI integration in Microsoft Office is along the following lines:</p>
<p><a href="https://x.com/willccbb/status/1892006177434706336"><img src="/assets/images/log/2025-02-20-cursor-for-powerpoint.png" alt=""></a></p>
<p>I have written about this <a href="/monetize-ai-not-the-editor">in a previous post</a>:</p>
<blockquote>
<p>There is going to be an <a class="concept-link" href="/graph/ai-native-software/">AI-native</a> “Microsoft Office”, and it will not be created by Microsoft. Copilot is not it, and Microsoft knows it. Boiling tar won’t turn it into sugar.</p>
</blockquote>]]></content><author><name>Onur Solmaz</name></author></entry></feed>