Entries for July 2025

  1. Portrait of Onur Solmaz
    Onur Solmaz · Log · /2025/07/13

    Workaround for Claude Code running `python` instead of `uv`

    uv is now the de facto default Python package manager. I have already deleted all pythons from my system except for the one that has to be installed for other packages in brew.

    Unfortunately, Claude Code often ignores instructions in CLAUDE.md files to use uv run python instead of plain python commands. Even with clear documentation stating “always use uv”, Claude Code will attempt to run python directly, leading to “command not found” errors in projects that rely on uv for Python environment management.

    The built-in Claude Code hooks and environment variable settings also don’t reliably solve this issue due to shell context limitations.

    The reason is that Claude (and most other AI models) take time to catch up to such changes, because their learning horizon is longer, up to months to years. Somebody will need to include this information explicitly in the training data.

    Until then, we can prevent wasting tokens by mapping python and python3 to uv.

    I personally don’t want to map these globally, because a lot of other packages might depend on system installed pythons, like brew packages, gcloud CLI and so on.

    Because of that, I map them at the project level, using direnv:

    An OK-ish solution: direnv + dynamic wrapper scripts

    We can force Claude Code (and any developer) to use uv run python by dynamically creating wrapper scripts in a .envrc file that direnv automatically loads when entering the project directory.

    This will override python and python3 to map to uv run python, and also print a nice message to the model:

    Use "uv run python ..." instead of "python ..." idiot.

    This is probably not the best solution, but it is a solution. Feel free to suggest a better one.

    Step 1: Install direnv

    # macOS
    brew install direnv
    
    # Ubuntu/Debian
    sudo apt install direnv
    
    # Add to your shell (bash/zsh)
    echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc  # or ~/.bashrc
    source ~/.zshrc  # or restart terminal
    

    Step 2: Setup direnv with dynamic wrapper scripts

    # Create .envrc file in project root
    cat > .envrc << '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 > "$TEMP_BIN_DIR/python" << 'INNER_EOF'
    #!/bin/bash
    echo "Use \"uv run python ...\" instead of \"python ...\" idiot"
    exec uv run python "$@"
    INNER_EOF
    
    cat > "$TEMP_BIN_DIR/python3" << '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
    
    # Allow direnv to load this configuration
    direnv allow
    

    Step 3: Update .gitignore

    # Add direnv generated files to .gitignore
    echo "# direnv generated files" >> .gitignore
    echo ".direnv/" >> .gitignore
    

    Step 4: Update documentation

    Add to your CLAUDE.md something like this:

    ## 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 <script.py>` (NOT `python <script.py>`)
    - **Run module**: `uv run -m <module>` (e.g., `uv run -m pytest`)
    - **Add dependencies**: `uv add <package>` (e.g., `uv add requests`)
    - **Add dev dependencies**: `uv add --dev <package>`
    - **Remove dependencies**: `uv remove <package>`
    - **Install all dependencies**: `uv sync`
    - **Update lock file**: `uv lock`
    - **Run with specific package**: `uv run --with <package> <command>`
    

    How It Works

    1. direnv automatically loads .envrc when you cd into the project directory
    2. .envrc dynamically creates executable wrapper scripts in .direnv/bin/
    3. Scripts display a helpful message and redirect to uv run python
    4. .direnv/bin/ is prepended to PATH, overriding system python commands
    5. Works for any shell session in the directory (Claude Code, terminal, IDE)

    To see if it works:

    cd your-project/
    python -c "print('Hello World')"  # Shows message, uses uv
    python3 --version                 # Shows message, uses uv
    

    Let me know if this doesn’t work for you, or if you find a better solution.

  2. Portrait of Onur Solmaz
    Onur Solmaz · Log · /2025/07/05

    Day 47 of Claude Code god mode

    I started using Claude Code 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.1

    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 TextCortex, 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.

    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.

    Things I have implemented using Claude Code

    TextCortex Monorepo

    The most important contribution, I merged our backend, frontend and docs repos into a single monorepo in less than 1 day, with all CI/CD and automation. This lets us use our entire code and documentation context while triggering AI agents.

    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.

    JSON-DOC TypeScript renderer

    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.

    Claude Code PR Autodoc Action

    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.

    Claude Code Sandbox

    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.

    TextCortex Agentic RAG implementation

    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.

    Fixed i18n

    I had a system in mind for auto-translating strings 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 r…ded, 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.2

    Tackling small-to-mid-size tasks without context switching

    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.

    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.

    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.

    Side projects

    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 Horse. It’s like an AI personal trainer, but it only counts your push-ups for now. But even that was a complex enough computer vision task.

    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 Rust, over the course of 2-3 weekends.

    I knew nothing about cross-compiling Rust code to iOS, 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.

    You can see more about it on my sports Instagram here.

    It’s all about completing the loop

    Agentic workflows work best when you have a good verifier (like tests) which lets you create a good feedback loop. This might be the compiler output, a Playwright MCP server, running pytest, spinning up a local server and making a request, and so on.

    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.

    Swearing at AI

    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.

    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.

    The empathic reader should be aware that emotional reactions to AI reveal more about one’s own psychological state than the AI’s.

    On Claude Code skeptics

    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. Dario Amodei was not bluffing when he said that a white collar bloodbath is coming.

    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.

    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.


    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.

    1. 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. 

    2. 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.