<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Narthur Online</title><description>Nathan Arthur&apos;s mostly-weekly newsletter: tools, things built, and running a one-person software business.</description><link>https://nathanarthur.com</link><item><title>Hills to Die On</title><link>https://nathanarthur.com/writing/hills-to-die-on</link><guid isPermaLink="true">https://nathanarthur.com/writing/hills-to-die-on</guid><description>Or, more accurately, to avoid dying on.</description><pubDate>Wed, 16 Sep 2026 17:45:57 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/hills-to-die-on/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I find myself using this rubric when deciding how much I should push back on something that doesn’t feel quite right.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Reversibility:&lt;/strong&gt; Would it be difficult to reverse this decision later?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blast radius:&lt;/strong&gt; Is the impact of getting this decision wrong large?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Forward binding:&lt;/strong&gt; Will this decision change how future decisions are made?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If I can answer “no” to all three questions, it isn’t something I should overthink.&lt;/p&gt;
&lt;p&gt;I use these three questions in a variety of situations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A colleague makes a recommendation I’m not sure about.&lt;/li&gt;
&lt;li&gt;Something in a pull request doesn’t look quite like I’d do it.&lt;/li&gt;
&lt;li&gt;A coding agent makes a call I don’t fully understand yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If one of those questions is a “yes,” I need to dig in and maybe push back. Otherwise, I’m comfortable letting it go.&lt;/p&gt;
&lt;p&gt;This framework is similar to &lt;a href=&quot;https://aws.amazon.com/executive-insights/content/how-amazon-defines-and-operationalizes-a-day-1-culture/&quot;&gt;Amazon’s one-way and two-way doors idea&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ve been using these questions for a decade now, but it was only recently that I captured the rubric in writing. I did so because &lt;a href=&quot;https://github.com/narthur/skills/tree/main/skills/review/review-loop&quot;&gt;the code review skill&lt;/a&gt; I was working on was burying me in findings, and I noticed I was asking the same three questions while reviewing each issue the skill found. Defining these questions and adding them to the skill allowed it to address a large number of its low-confidence findings without requiring my input, letting me focus on the few decisions that warrant my attention.&lt;/p&gt;
&lt;p&gt;Having these questions in my back pocket has helped me to avoid a lot of stress and conflict at work, and has let me more easily focus my attention on what actually matters.&lt;/p&gt;
</content:encoded></item><item><title>Words In Mouths</title><link>https://nathanarthur.com/writing/words-in-mouths</link><guid isPermaLink="true">https://nathanarthur.com/writing/words-in-mouths</guid><pubDate>Tue, 08 Sep 2026 16:26:31 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/words-in-mouths/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Recently I had a realization that seems obvious in retrospect.&lt;/p&gt;
&lt;p&gt;LLMs should default to avoiding speaking in any author’s voice, whether that’s the robot’s or the human’s.&lt;/p&gt;
&lt;p&gt;Unless explicitly asked to, it should avoid using “I” and “me” when writing documents, emails, and other prose artifacts. By default it should never put words in the user’s mouth.&lt;/p&gt;
&lt;p&gt;I think this would be an improvement for users and for society.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It would stop nudging users to become &lt;a href=&quot;https://christophermoravec.com/episode-30-dont-be-a-secret-cyborg/&quot;&gt;secret cyborgs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;It would result in more professional documents.&lt;/li&gt;
&lt;li&gt;It would help slow the breakdown of trust in written communication.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve never had a work secretary, but I imagine that’s how they work. When you ask your secretary to call someone for you they don’t pretend to be you making the call. They speak in a professional manner without drawing attention to the person making the call.&lt;/p&gt;
&lt;p&gt;Why haven’t the big labs made this the default? Why is Claude so eager to write any outgoing communication as if I had written it? It’s kind of baffling.&lt;/p&gt;
&lt;p&gt;To be clear: I am not without sin. I’ve been a secret cyborg. I’ve asked Claude for something, it’s given me the email in my voice, and I’ve taken the lazy way out: copy, paste, send. I have no excuse. But I wish Claude hadn’t made it the default, easy option.&lt;/p&gt;
&lt;p&gt;In response to this realization, I worked with Claude to add this to my global CLAUDE.md file to try to do better moving forward:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Default to prose that makes no reference to the author. Describe the thing; don’t narrate it as me. No “I”, “me”, “my”, no thanks, apologies, feelings or motives offered on my behalf.&lt;/p&gt;
&lt;p&gt;Write in my voice only when I explicitly ask for it. This holds even for something I am going to sign or send — a letter, an email, a statement. Err toward no reference to the author; if first person is wanted, I will ask for it or add it myself.&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>Why I’m Leaving Render.com</title><link>https://nathanarthur.com/writing/why-im-leaving-rendercom</link><guid isPermaLink="true">https://nathanarthur.com/writing/why-im-leaving-rendercom</guid><pubDate>Thu, 03 Sep 2026 16:59:54 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/why-im-leaving-rendercom/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://render.com/&quot;&gt;Render.com&lt;/a&gt; is a fantastic service. It’s a cloud provider that makes the right stuff easy.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The happy path is &lt;a href=&quot;https://render.com/docs/git-provider&quot;&gt;automatic deploys&lt;/a&gt; from your git provider.&lt;/li&gt;
&lt;li&gt;It has first-class infrastructure-as-code support via &lt;a href=&quot;https://render.com/docs/infrastructure-as-code&quot;&gt;its blueprint files&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;It skips the complex IAM systems of AWS and GCP.&lt;/li&gt;
&lt;li&gt;It ships a limited (though growing) number of primitives that can be used to build the majority of things I’d want to build. Currently &lt;a href=&quot;https://render.com/docs&quot;&gt;around ten&lt;/a&gt;, depending on how you count, compared to &lt;a href=&quot;https://docs.aws.amazon.com/&quot;&gt;more than 300 at AWS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Its &lt;a href=&quot;https://render.com/pricing&quot;&gt;pricing&lt;/a&gt; is straight-forward and predictable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve been a fairly big user of render.com for a while, even hosting &lt;a href=&quot;https://taskratchet.com/&quot;&gt;TaskRatchet&lt;/a&gt; on it for two years.&lt;/p&gt;
&lt;p&gt;For a while now I’ve been migrating off of Render.com, moving most of my work to Cloudflare. The only things I’m still hosting on Render.com are a few static websites.&lt;/p&gt;
&lt;p&gt;Why the switch?&lt;/p&gt;
&lt;p&gt;The main reason: It’s expensive.&lt;/p&gt;
&lt;p&gt;Simple pricing doesn’t mean cheap. And my usage pattern, building many side projects which probably won’t get much usage, is just about the worst scenario. A server project typically needs at minimum a public computer service and a PostgreSQL database. To avoid cold starts and losing data, that means paying, at minimum, $7 / month for the compute service and $6 / month for the database, or $13 / month all-in. And that’s even if I’m the only one ever using the project. if I want five such projects, I’m easily paying $65 / month or more.&lt;/p&gt;
&lt;p&gt;So at this point Cloudflare turns out to be a way better fit. It’s way cheaper, and the architectures it naturally pushes you toward mean I’m paying for what I use rather than paying for instance that are doing nothing most of the time. Plus Cloudflare-hosted projects tend to be really fast. Since I’m using Claude Code, I don’t have any issues configuring the cloud infrastructure. And it gives me more flexibility in how I can build things while still avoiding the incredible complexity of something like AWS.&lt;/p&gt;
&lt;p&gt;I’m happy with the move.&lt;/p&gt;
</content:encoded></item><item><title>The Limits of Vibe Coding</title><link>https://nathanarthur.com/writing/the-limits-of-vibe-coding</link><guid isPermaLink="true">https://nathanarthur.com/writing/the-limits-of-vibe-coding</guid><pubDate>Thu, 27 Aug 2026 17:53:25 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/the-limits-of-vibe-coding/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’ve been thinking about where we’re at with vibe coding, defined as the ability of non-technical people to build and maintain software using LLMs.&lt;/p&gt;
&lt;p&gt;My conclusion: Vibe coding works great as a way to quickly build small prototypes and jump-start new applications. But it falls short when it comes to maintaining quality software for the long-term.&lt;/p&gt;
&lt;p&gt;The reasons are these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LLMs do what you ask them to do, and avoid getting sidetracked.&lt;/li&gt;
&lt;li&gt;A non-technical person doesn’t have the vocabulary of software architecture.&lt;/li&gt;
&lt;li&gt;A non-technical person doesn’t have the ability to attribute difficulty in developing the software to the underlying architectural problems.&lt;/li&gt;
&lt;li&gt;Good architectural decisions are made where software architecture, the domain, and the roadmap overlap.&lt;/li&gt;
&lt;li&gt;The world changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;llms-do-what-you-ask&quot;&gt;LLMs Do What You Ask&lt;/h4&gt;
&lt;p&gt;By design, LLMs do what you ask them to do and avoid doing what you don’t ask them to do. This is normally what you want. You have a task to complete—a feature to add, a bug to fix, a design change to make. You don’t want the LLM getting distracted by a side quest.&lt;/p&gt;
&lt;p&gt;What this means, though, is that code messes don’t get cleaned up. As long as the LLM mades a little bit of a mess even a small percentage of the time, the codebase is likely to degrade over time. And the non-technical builder doesn’t have the ability to look at the code, see where the mess is, and ask the LLM to clean it up.&lt;/p&gt;
&lt;h4 id=&quot;lacking-the-vocabulary-of-software-architecture&quot;&gt;Lacking the Vocabulary of Software Architecture&lt;/h4&gt;
&lt;p&gt;A non-technical person can tell an LLM what they want to build. They can describe the features they want and how it should look and behave. But they don’t have the knowledge of software architecture to know how to ask the LLM to structure the codebase. So the LLM will make a best guess.&lt;/p&gt;
&lt;h4 id=&quot;lacking-the-ability-to-attribute&quot;&gt;Lacking the Ability to Attribute&lt;/h4&gt;
&lt;p&gt;As a codebase becomes messier, the LLM begins to struggle making the user-visible changes the builder asks for. But without the knowledge of what makes for good code and what makes a project well-structured, the builder is ill-equipped to know where to point the LLM to have it correct the situation. The builder is likely to attribute the trouble to poor prompting or the model becoming dumber, instead of on underlying code smells.&lt;/p&gt;
&lt;h4 id=&quot;the-architectural-decision-nexus&quot;&gt;The Architectural Decision Nexus&lt;/h4&gt;
&lt;p&gt;You might think the solution would be to simply tell the LLM to “use good architecture,” or otherwise give it a philosophy of architecture to work from.&lt;/p&gt;
&lt;p&gt;The problem is that good architectural decisions can’t be made in a vacuum. Choosing an architecture is deciding what should be hard in the future and what should be easy. And that depends on your domain model and your product roadmap. Starting with good software architecture principles is not enough.&lt;/p&gt;
&lt;p&gt;Architectural decisions are bets on how the context of your application will change over time, and choosing how to structure your codebase in an attempt to make it easy to adapt to those shifts.&lt;/p&gt;
&lt;h4 id=&quot;the-world-changes&quot;&gt;The World Changes&lt;/h4&gt;
&lt;p&gt;Software is never finished. This is because the context in which it lives is always changing. User needs change. Hardware substrates change. Protocols change. The languages, libraries, and frameworks we depend on change. The security landscape changes. What’s considered “best practice” changes. A perfectly clean, sane codebase slowly turns into a poorly-optimized mess over years, even if no one’s modified it. The ground moves.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I wouldn’t bet on this state of affairs being permanent. Perhaps someday we’ll have fully-autonomous agents that proactively track the context of a piece of software and update its architecture accordingly. Consider this to be a snapshot in time of the challenges faced by non-technical builders who want to push their vibe coding to the limit.&lt;/p&gt;
</content:encoded></item><item><title>Job Search Coaching, Hand-Writing Code, RSS Feeds</title><link>https://nathanarthur.com/writing/job-search-coaching-hand-writing</link><guid isPermaLink="true">https://nathanarthur.com/writing/job-search-coaching-hand-writing</guid><pubDate>Thu, 20 Aug 2026 17:24:15 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/job-search-coaching-hand-writing/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’m at just about 40 job applications submitted, no interviews. I’m currently submitting four applications each day. I’ve signed up with a mentor on MentorCruise to get a second pair of eyes on my resumes and cover letters, see if there are things I can improve.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I enjoyed &lt;a href=&quot;https://www.youtube.com/watch?v=bzYziksDslU&amp;amp;t=267s&quot;&gt;this video&lt;/a&gt; by Dreams of Code on why writing code by hand is still a valuable practice even if you’re all-in on agentic software engineering.&lt;/p&gt;
&lt;p&gt;It got me thinking about the differences between using something like Claude Code and old human pair programming. When I would pair with someone, I would shift how much code I would write in response to their prompts based on how much they understood about the problem and the code we were working on. If they had a good understanding, I would write more. If they had less understanding, I would drag my feet and let them over-specify so they had the chance to internalize what was happening in the code.&lt;/p&gt;
&lt;p&gt;I updated my claude code setup to try to have it act more this way. It should now keep track of which subsystems I do and don’t deeply understand in the codebases I work in, and then adjust how focused it is on getting the thing done vs teaching me based on that. We’ll see how well it works.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I’m continuing to enjoy reading RSS feeds in Feedly. I’ve moved most of my newsletter subscriptions to Feedly. Thankfully Substack and most other newsletters expose an RSS feed. Not a Substack publication, but I’ve been especially enjoying &lt;a href=&quot;https://brennan.day/&quot;&gt;Brennan’s Weblog&lt;/a&gt;, written by avid Beeminder user Brennan Brown. His blog is exceptionally well-written and always thought provoking.&lt;/p&gt;
</content:encoded></item><item><title>Job Search Update: Giving Up on AI Writing</title><link>https://nathanarthur.com/writing/job-search-update-giving-up-on-ai</link><guid isPermaLink="true">https://nathanarthur.com/writing/job-search-update-giving-up-on-ai</guid><pubDate>Thu, 13 Aug 2026 16:27:10 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/job-search-update-giving-up-on-ai/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;So far I’ve submitted 25 applications. None have gotten past screening.&lt;/p&gt;
&lt;p&gt;About a week ago I watched &lt;a href=&quot;https://www.youtube.com/live/CNEbqfG4sFY?si=6UgreBpnldrMK1mC&quot;&gt;a GitHub live stream&lt;/a&gt; hosted by &lt;a href=&quot;https://www.madebygps.com/&quot;&gt;Gwyneth Peña-Siguenza&lt;/a&gt; and &lt;a href=&quot;https://cassidoo.co/&quot;&gt;Cassidy Williams&lt;/a&gt;. During the stream I asked in chat if using AI to help with writing cover letters was a good strategy. The response was no, it’s not a good idea.&lt;/p&gt;
&lt;p&gt;This confirmed what I had been thinking for a bit now, that using AI to help with writing my cover letters is proving more trouble than it’s worth. While I don’t have a philosophical problem with using AI to help write my cover letters, I found myself spending more time wrestling with my humanizer and voice skills than actually doing productive work on my applications. So I’ve stopped using AI to write my cover letters and form answers, though I’m still using it to personalize my CV to each role, and for helping me with other steps in the process.&lt;/p&gt;
&lt;p&gt;Another thing that stood out from the stream: Gwyneth mentioned that around the year 2015 she ended up submitting 200 or 300 job applications before landing a help desk job. So that’s my new goal. I aim to submit 300 job applications before feeling that I’ve adequately done this job search.&lt;/p&gt;
&lt;p&gt;That, of course, means that half an application per weekday won’t cut it. I’m in the process of updating my Beeminder goals to move me to four applications daily. Even so, at four applications per weekday, that will take me just under four months to complete.&lt;/p&gt;
&lt;p&gt;I won’t be relying on a single goal to require this. I plan to create four new goals, one per application, spaced throughout the day. That way, if I’m having more trouble one day, I won’t end up procrastinating until I only have an hour left to prepare and submit all four applications.&lt;/p&gt;
&lt;p&gt;After stopping using AI to write my cover letters, I’ve found a process that seems to be working well for writing my letters efficiently:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I talk back-and-forth with Claude about the role until I have a good handle on everything I want to say and the relevant experience and gaps I want to include.&lt;/li&gt;
&lt;li&gt;I write the letter in Obsidian, pulling in reusable paragraphs I’ve saved from previous cover letters, modifying them and adding surrounding paragraphs as needed.&lt;/li&gt;
&lt;li&gt;Claude reviews the letter for accuracy and gaps.&lt;/li&gt;
&lt;li&gt;Once complete, I submit the cover letter with my application.&lt;/li&gt;
&lt;li&gt;Claude then extracts any new reusable paragraphs from my submitted cover letter and saves them for future cover letters.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This has helped writing the letters be a lot less overwhelming and faster than any of the approaches I’ve tried previously.&lt;/p&gt;
&lt;p&gt;Wish me luck!&lt;/p&gt;
</content:encoded></item><item><title>GitHub CLI Alias to Prep Git for Your Next Task</title><link>https://nathanarthur.com/writing/github-cli-alias-to-prep-git-for</link><guid isPermaLink="true">https://nathanarthur.com/writing/github-cli-alias-to-prep-git-for</guid><pubDate>Thu, 06 Aug 2026 15:46:46 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/github-cli-alias-to-prep-git-for/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;A while back I found myself getting mildly annoyed by the friction around ensuring a repo’s git was in the correct state for starting a new task with Claude Code.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Am I on the default branch so Claude Code doesn’t create a PR based on another branch it shouldn’t?&lt;/li&gt;
&lt;li&gt;Is the default branch up-to-date with origin?&lt;/li&gt;
&lt;li&gt;Is the branch I was on previously merged and ready to be deleted?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I ended up adding a GitHub CLI alias built on top of &lt;a href=&quot;https://github.com/seachicken/gh-poi&quot;&gt;gh-poi&lt;/a&gt;, a GitHub CLI plugin that deletes branches that are already merged into the default branch. I called the alias “doi” based on it running “poi” on the &lt;strong&gt;d&lt;/strong&gt;efault branch.&lt;/p&gt;
&lt;p&gt;With my alias set, I run &lt;code&gt;gh doi&lt;/code&gt; in terminal, which runs the following commands:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Save default branch name, so it&apos;ll work if your
# default branch is main or master or development
# or whatever
DEFAULT=$(gh repo view --json defaultBranchRef --jq &quot;.defaultBranchRef.name&quot;)

# Checkout default branch
git checkout &quot;$DEFAULT&quot;

# Pull default branch
git pull

# Delete merged branches
gh poi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here’s how to install gh-poi and add the alias:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gh extension install seachicken/gh-poi
gh alias set doi &apos;!DEFAULT=$(gh repo view --json defaultBranchRef --jq &quot;.defaultBranchRef.name&quot;) &amp;amp;&amp;amp; git checkout &quot;$DEFAULT&quot; &amp;amp;&amp;amp; git pull &amp;amp;&amp;amp; gh poi&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that’s it. You’re ready to run &lt;code&gt;gh doi&lt;/code&gt; the next time you want to make sure your working tree is prepped to start a new task.&lt;/p&gt;
</content:encoded></item><item><title>Tips for Effective Skill Design</title><link>https://nathanarthur.com/writing/tips-for-effective-skill-design</link><guid isPermaLink="true">https://nathanarthur.com/writing/tips-for-effective-skill-design</guid><pubDate>Thu, 30 Jul 2026 17:52:55 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/tips-for-effective-skill-design/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Just about seven months ago I &lt;a href=&quot;https://nathanarthur.com/writing/fast-pr-feedback-review-with-saved&quot;&gt;started&lt;/a&gt; &lt;a href=&quot;https://nathanarthur.com/writing/iterating-on-a-pr-extraction-workflow&quot;&gt;experimenting&lt;/a&gt; with building my own skills. Since then it’s become &lt;a href=&quot;https://github.com/narthur/dotfiles/tree/main/.claude/skills&quot;&gt;the primary way&lt;/a&gt; I encode and iterate on my work tasks, programming and otherwise. Here are a few lessons I’ve learned about skill design. I’ll be referring to Claude Code throughout, but you can substitute your preferred agentic coding tool.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Don’t hand-write your skills.&lt;/strong&gt; Let Claude draft skills for you. The first draft isn’t supposed to be perfect. You’ll be iterating on it, so it’s inefficient to put a lot of energy into hand-crafting your skills.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Have your skills use scripts.&lt;/strong&gt; Claude Code skill folders can contain any type of file, not just markdown files. Make use of this by including scripts in your skills that handle all the deterministic stuff that doesn’t actually need an LLM. This will reduce your token costs and improve the reliability of your skills.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Leverage subagents.&lt;/strong&gt; Claude skills can instruct Claude to spin up subagents to handle portions of your task. Depending on the situation, this can improve result quality, increase speed, and even reduce costs. It can improve result quality by managing context, either preventing Claude’s main thread from becoming bloated or sandboxing something inside a subagent that shouldn’t have access to the main thread, like an independent reviewer. It can increase speed by parallelizing subtasks. And it can reduce costs when a portion of the task doesn’t need the model you’re using on the main thread and can be delegated to a cheaper model.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use progressive disclosure.&lt;/strong&gt; Not everything should go in a skill’s main SKILL.md file, only the stuff that is applicable to nearly every run of the skill. Anything that is conditional or situational should be extracted into separate markdown files in the skill’s folder, and referenced in the main SKILL.md file along with whatever condition should result in the skill loading that file into context. This approach makes it less likely that the skill becomes distracted by something not relevant to the current run, and reduces token costs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Keep your skill descriptions sharp.&lt;/strong&gt; The description should state when a skill should be invoked, not summarize what the skill does. This improves Claude Code’s ability to trigger the right skills at the right time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Let your skills learn over time.&lt;/strong&gt; This allows your skills to become better over time without needing to explicitly work to improve them. Example: In a playwright skill I built, I have the skill record website-specific learnings after each run to files in a websites subfolder of the skill.&lt;/p&gt;
</content:encoded></item><item><title>What Is Good Writing?</title><link>https://nathanarthur.com/writing/what-is-good-writing</link><guid isPermaLink="true">https://nathanarthur.com/writing/what-is-good-writing</guid><pubDate>Thu, 23 Jul 2026 18:23:41 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/what-is-good-writing/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;When I was in high school and college, writing was one of my strengths. I enjoyed writing. Between high school and college I interned at a magazine. In college I minored in English.&lt;/p&gt;
&lt;p&gt;I think good writing, and all good art really, is a profound act of vulnerability, and therefore courage. It requires letting yourself be seen, putting yourself on display, opening yourself up to criticism and rejection, or perhaps worse, disinterest.&lt;/p&gt;
&lt;p&gt;Writing requires curiosity, vulnerability, courage, exploration. It requires accepting yourself at the same time that you subject yourself to your own criticism and open yourself to the criticism of others.&lt;/p&gt;
&lt;p&gt;I’ve been continuing my job search, and that’s meant continuing to use AI to write cover letters for my applications. I have the AI draft the cover letter, and then I review it for things I don’t like, and ask Claude Code to update my writing skills and fix what I found in the draft. Once I’m satisfied that the cover letter is entirely accurate and up to my standards, I send it.&lt;/p&gt;
&lt;p&gt;(Aside: I never use AI to write this newsletter.)&lt;/p&gt;
&lt;p&gt;By necessity that editing process has required me to think through what makes writing good.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It shouldn’t use many words to say something that fewer words could say just as well.&lt;/li&gt;
&lt;li&gt;Conversely, it shouldn’t cut words that are necessary to communicating the desired idea.&lt;/li&gt;
&lt;li&gt;It shouldn’t use fancy words when simple words would do.&lt;/li&gt;
&lt;li&gt;Conversely, it shouldn’t shy away from fancy words when a fancy word communicates the idea better.&lt;/li&gt;
&lt;li&gt;It should be confident, straight-forward, and unapologetic, unless there is a specific reason to communicate insecurity or ambiguity.&lt;/li&gt;
&lt;li&gt;It should avoid being overly evocative, except when being evocative supports the goal of the piece.&lt;/li&gt;
&lt;li&gt;It should be aware of the context for which it is being written—the relationship between the author and the reader, the reader’s likely state of mind, and the broader societal context.&lt;/li&gt;
&lt;li&gt;It should avoid careless repetition, such as the same word being used multiple times in one sentence (see: “context” in the previous point).&lt;/li&gt;
&lt;li&gt;It should be easy to read. Words and structure should feel natural, not surprising or jarring.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/what-is-good-writing/2.gif&quot; alt=&quot;Why Waste Time When Few Word Do Trick GIF - Why Waste Time When Few ...&quot; width=&quot;498&quot; height=&quot;277&quot; loading=&quot;lazy&quot;&gt;&lt;/figure&gt;
&lt;p&gt;The one thing I would expect to be in that list is acknowledging uncertainty. Intellectual honesty is a value that has become more important to me over time, so I would expect to see it in my personal goals for good writing.&lt;/p&gt;
&lt;p&gt;I think that absence is correct. Not every piece of writing needs to embody intellectual honesty. Some writing takes a stand and makes the best case for that position, lawyer-style, while omitting counter-evidence. Some writing is exploratory, trying on a thought process for size, and not meant to be an honest appraisal of the idea’s objective value. Some writing is meant to clearly communicate the inner state of the author, and none of us are entirely honest with ourselves all the time. I think all these forms of writing can be valuable.&lt;/p&gt;
&lt;p&gt;On the other hand, I’ve been tempted to conclude that intellectual honesty is the enemy of good writing. That it inevitably results in over-thinking, wishy-washy prose that doesn’t go anywhere. If I believe that perfect certainty is never warranted, then how can I be unapologetic and confident in my writing?&lt;/p&gt;
&lt;p&gt;I don’t think this is true, either.&lt;/p&gt;
&lt;p&gt;All of the following statements are confident, unapologetic, and straight-forward:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’m 80% certain.&lt;/li&gt;
&lt;li&gt;I’m not sure.&lt;/li&gt;
&lt;li&gt;I don’t know.&lt;/li&gt;
&lt;li&gt;This is my current belief.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It isn’t my acceptance of uncertainty that results in my writing lacking substance or drive. It’s my undeveloped thinking, an unwillingness to be vulnerable, and a fear of publishing something that will some day prove that I was wrong.&lt;/p&gt;
&lt;p&gt;I’m not sure how to address all these barriers. Undeveloped thinking is fairly straightforward. I can spend more time thinking, letting ideas have the room they need to mature before publishing them. The personal insecurity? That may take more time.&lt;/p&gt;
</content:encoded></item><item><title>Long-Distance Friends</title><link>https://nathanarthur.com/writing/long-distance-friends</link><guid isPermaLink="true">https://nathanarthur.com/writing/long-distance-friends</guid><pubDate>Thu, 16 Jul 2026 18:42:48 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/long-distance-friends/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Maintaining long-distance friendships is difficult.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Different people have different preferred channels. Some people hate email. Others dislike talking on the phone.&lt;/li&gt;
&lt;li&gt;Feedback is ambiguous. If you send someone an email and they don’t respond, is it because they are annoyed, or did they enjoy receiving the email but were too busy to respond?&lt;/li&gt;
&lt;li&gt;Desired cadence can be uncertain. Do they enjoy receiving 10 texts a day, or would they prefer an email every six months?&lt;/li&gt;
&lt;li&gt;Content type and length are also ambiguous. Somehow, some people enjoy talking about politics. I don’t. I might prefer a medium email. But maybe they’d prefer a gif. A discord voice hang. A text. A gaming session.&lt;/li&gt;
&lt;li&gt;Sometimes people just need a break. I’m taking a break from a friendship right now. They didn’t do anything wrong. I feel bad about it. And at some point I’ll resume reaching out.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How much of this is solvable by the tools we use to communicate? How much of it is just something we need to ask each other about? And if we do, how do we do that in a way that doesn’t sound desperate?&lt;/p&gt;
&lt;p&gt;“I sent you an email last week and you didn’t reply. Please select from this list of options on why you failed to respond in a timely manner.”&lt;/p&gt;
&lt;p&gt;Hmm…&lt;/p&gt;
</content:encoded></item><item><title>Changing My Approach to Writing</title><link>https://nathanarthur.com/writing/changing-my-approach-to-writing</link><guid isPermaLink="true">https://nathanarthur.com/writing/changing-my-approach-to-writing</guid><pubDate>Tue, 14 Jul 2026 15:37:07 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/changing-my-approach-to-writing/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I have a new strategy for how to improve my writing in this newsletter. Apologies, this issue isn’t using the new strategy, but I’m hoping it will serve as a public commitment to making the switch.&lt;/p&gt;
&lt;p&gt;Up to this point, I’ve been beeminding spending thirty-minute blocks on the newsletter weekly, and it’s been my unofficial goal to publish an issue at the end of each of these blocks. In practice this has meant thirty-minute train-of-thought writing sessions with little or no editing before publishing.&lt;/p&gt;
&lt;p&gt;My plan going forward is to break that single Beeminder goal into two—one for capturing thoughts, organizing ideas, doing train-of-thought writing; and a separate goal for publishing posts. I’m hoping this will have several benefits:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Having time spent thinking separated from the need to hit publish will hopefully reduce anxiety.&lt;/li&gt;
&lt;li&gt;Time dedicated to exploration of ideas separate from a specific newsletter issue should allow my thoughts the room to develop before publishing, even if that means some ideas take weeks or months before they’re ready to share.&lt;/li&gt;
&lt;li&gt;Having the freedom to vary the size of my posts, rather than every post being roughly thirty minutes worth of words, should allow posts to be more contained and coherent.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I’ve just taken a moment to complete the step I’ve been procrastinating on, actually creating the two goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.beeminder.com/narthur/sowstack&quot;&gt;sowstack&lt;/a&gt; - starting at six minutes daily, &lt;a href=&quot;https://autodial.taskratchet.com/&quot;&gt;autodialed&lt;/a&gt; up to a maximum of thirty minutes daily&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.beeminder.com/narthur/reapstack&quot;&gt;reapstack&lt;/a&gt; - starting at one post weekly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m storing the raw material (thoughts, ideas, questions) in a folder in Obsidian. It also has a sub-folder where claude code can add stuff if I’ve requested it to. I’ve instructed claude code to always add such material as outlines rather than prose to further reduce the chance any AI-written prose will accidentally make it into the newsletter.&lt;/p&gt;
&lt;p&gt;Hoping this will significantly improve the quality of my writing here!&lt;/p&gt;
</content:encoded></item><item><title>Longer Resumes, Used Phones, and LEGOs</title><link>https://nathanarthur.com/writing/longer-resumes-used-phones-and-legos</link><guid isPermaLink="true">https://nathanarthur.com/writing/longer-resumes-used-phones-and-legos</guid><pubDate>Tue, 07 Jul 2026 17:38:42 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/longer-resumes-used-phones-and-legos/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’m still on the job hunt. So far I’ve applied to nine jobs. Starting tomorrow I’ll be spending an hour daily on the search, up from 30 minutes.&lt;/p&gt;
&lt;p&gt;I’ve also updated my resume generator skill to create resumes with two pages instead of one. The first page remains the part tailored to the job I’m applying for, meant for a human to read. The second page is a list of every technology, tool, and practice I’ve touched, as comprehensive as I can manage. That’s for the screening robots to read, so that I’m less likely to get filtered out because I failed to list something that a company configured their automated systems to look for.&lt;/p&gt;
&lt;p&gt;So far I’ve had no positive results, just a few form replies saying they’re moving forward with other candidates.&lt;/p&gt;
&lt;p&gt;I started the search on June 22, roughly 15 days ago. That means so far I’ve submitted 0.6 resumes per day on average. Naively, that means my move to spending an hour a day on the search should get me to submitting one application every day. All this ignoring that these goals have weekends off, so theoretically I’ll be above one application per day on average.&lt;/p&gt;
&lt;p&gt;I intend to keep ramping up my efforts over time. So once I prove that an application a day is doable, I’ll think about upping the rates on my Beeminder goals again.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I’ve replace my cell phone. I’ve been using a Samsung Galaxy A52. I decided it was time to replace it since it’s no longer receiving software updates, Duolingo stopped working on it, the screen is cracked, and—the last straw—the glue holding the plastic backing of the phone on started coming loose.&lt;/p&gt;
&lt;p&gt;I purchased a used Pixel 8a, and it arrived in the mail yesterday. Transferring my data from the Samsung was relatively painless, as was transferring my two phone numbers to the phone (I switched from physical SIMs to eSIMs in the process).&lt;/p&gt;
&lt;p&gt;My brother’s an iPhone user. He’s been talking about wanting an Android device so that he can get Android apps published to the play store. I factory reset the Samsung and passed it on to him. Most of its issues shouldn’t be a problem as a development devices, though I suppose at some point the lack of software updates may.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;My brother and I are in the early stages of exploring some new side hustles, too—reselling LEGOs on Bricklink, and perhaps other items with resale value we can find.&lt;/p&gt;
&lt;p&gt;I’d explored the idea in the past. LEGO was my favorite toy growing up, so it’s always sounded fun to somehow make money with something I’m nostalgic for.&lt;/p&gt;
&lt;p&gt;However to now it’s never quite made sense to try. Competition is high, it can involve a lot of driving, and the hourly rate you’re likely to make is low.&lt;/p&gt;
&lt;p&gt;Right now, though, those things aren’t a problem—my brother has a car and enjoys driving, we have plenty of time to spend on it that wouldn’t otherwise be bringing in money, and we can afford to start slow. So that’s the plan.&lt;/p&gt;
&lt;p&gt;Turns out first thing you have to do in order to become a reseller on Bricklink is to get a positive rating from an existing reseller on the platform. I purchased &lt;a href=&quot;https://www.bricklink.com/v2/catalog/catalogitem.page?S=6487-1#T=S&amp;amp;O=%7B%22iconly%22:0%7D&quot;&gt;set 6487&lt;/a&gt; from 1997. It hasn’t arrived yet. Plan is I’ll leave the seller a good review and hopefully they will reciprocate.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/longer-resumes-used-phones-and-legos/2.webp&quot; alt=&quot;&quot; width=&quot;384&quot; height=&quot;288&quot; loading=&quot;lazy&quot;&gt;&lt;/figure&gt;
</content:encoded></item><item><title>Stream-of-Thought, with Stakes</title><link>https://nathanarthur.com/writing/stream-of-thought-with-stakes</link><guid isPermaLink="true">https://nathanarthur.com/writing/stream-of-thought-with-stakes</guid><pubDate>Tue, 30 Jun 2026 18:15:10 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/stream-of-thought-with-stakes/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’m trying something different today. I’m using &lt;a href=&quot;https://dynomight.net/danger.html&quot;&gt;this web app&lt;/a&gt; to write this, set the timer to fifteen minutes. If I stop writing for more than 10 seconds, it deletes everything I’ve written.&lt;/p&gt;
&lt;p&gt;This is a version of an older app called The Most Dangerous Writing App I think, something like that. This version was made by &lt;a href=&quot;https://dynomight.net/&quot;&gt;Dynomight&lt;/a&gt;. They have a good blog / newsletter.&lt;/p&gt;
&lt;p&gt;The job search continues. I just applied for a role at Spotify today. I have to never put too much hope into any single job application.&lt;/p&gt;
&lt;p&gt;This app is a little stressful. Can’t stop typing for 10 seconds.&lt;/p&gt;
&lt;p&gt;I’ve increase the amount of time I committed to working on my job search from 30 minutes a day to one hour today, committed via Beeminder of course.&lt;/p&gt;
&lt;p&gt;I’ve started using tmux for spinning up development environments in my terminal. I switched from warp.dev to ghostty. I run `dev`, a custom shell script in my bin, and it runs a whatever-project.sh script that loads the tmux session. The left column is always Claude Code, run with –continue and falling back to straight claude. In the right column I’ll have one pane running any dev servers, one pane running tests, and one just a straight terminal. I’ve also played around with having the middle column be hunk in watch mode so I can see the changes on the branch as I work. Not totally happy with how that works yet though so only have that in one of my environments.&lt;/p&gt;
&lt;p&gt;I’ve expanded my job search to include not just jobs that would relocate me to Sweden but also jobs that are fully remote. That way I can still have the freedom to travel even if I don’t get a job in Sweden specifically.&lt;/p&gt;
&lt;p&gt;With projects like this where I really want to keep velocity I find that it works quite well to have multiple Beeminder goals supporting the project from different angles–in this case, daily time, action points, and applications submitted. When one goal starts slipping in its effectiveness, the others are a backstop while I diagnose and tweak. And it feels good to get ahead in one goal even if it’s another goal that’s the reason I’m getting ahead.&lt;/p&gt;
&lt;p&gt;I’ve experimented a bit with working on a treadmill again. A few years ago I had a treadmill that fit under my desk, but I found that keeping it working was difficult. Now I have access to a full-size treadmill where I’m staying. I discovered that there are universal attachments you can buy for full-size treadmills that add a desk or a laptop stand to them. For an experiment I tried just using a board, and it did seem to work ok, especially since my programming work tends to be give commands, monitor, give more commands, etc, so I don’t need to be hands-on-keyboard constantly. I don’t think I’ll be doing it much, though, since I’m generally only spending about an hour on the treadmill over a day.&lt;/p&gt;
&lt;p&gt;My M5 MacBook Air is proving to be quite functional as a work laptop. This is the first Apple Silicon computer I’ve owned. I have the 32gb model. I haven’t experienced any performance issues, and have even used some local Ollama models for certain things. The only real issue I’ve had is Firefox filling all my memory after days or weeks of not restarting the browser.&lt;/p&gt;
&lt;p&gt;I do feel like this experiment of using &lt;a href=&quot;https://dynomight.net/danger.html&quot;&gt;this writing app&lt;/a&gt; for writing the newsletter is working fairly well. It’s basically what I used to do when I would write daily pages—just write, write, write, no stopping, even if I’m writing about how I don’t know what to write about.&lt;/p&gt;
&lt;p&gt;I do still feel that editing is where I currently fall down in my writing. That’s where the anxiety can start becoming a problem.&lt;/p&gt;
&lt;p&gt;Maybe writing by hand is an even more important practice than it used to be, now that pretty much anything can be theoretically done with AI. A way to make sure we don’t forget how to think.&lt;/p&gt;
&lt;p&gt;I know some people have advocated for also dedicating some time to hand-coding so you don’t forget how to code. I’m not sure how I feel about that. Is that like advocating for spending time each day writing by hand or traveling by horse? Like, yeah, that’s a skill you could lose, but it’s so superseded it isn’t actually a practical problem if you lose it?&lt;/p&gt;
&lt;p&gt;I guess the question would be what are the stakes if I’m wrong. Like if I forget how to code by hand, completely lose that skill. How would that hurt me? How would that hurt my work? Would I be less good at determining the quality an LLM outputs if I’ve forgotten how to code by hand?&lt;/p&gt;
</content:encoded></item><item><title>The Job Search Begins</title><link>https://nathanarthur.com/writing/the-job-search-begins</link><guid isPermaLink="true">https://nathanarthur.com/writing/the-job-search-begins</guid><pubDate>Tue, 23 Jun 2026 17:56:44 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/the-job-search-begins/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Given we don’t currently have client work coming in, I’ve decided it’s time to start looking for traditional employment again.&lt;/p&gt;
&lt;p&gt;I’m using Beeminder to track my job search activities—one for putting time into the search, one for submitting applications, and one for doing different actions related to the search, each action being worth some number of points:&lt;/p&gt;
&lt;p&gt;Qualify a verified target = 1&lt;br&gt;
Tailored application (CV adjusted + letter naming the role, actually submitted) = 3&lt;br&gt;
Outreach (recruiter ping / intro ask / message to someone at a target) = 2&lt;br&gt;
Follow-up sent = 1&lt;br&gt;
Interview prep block, 30+ min = 2&lt;br&gt;
Interview attended = 5&lt;/p&gt;
&lt;p&gt;I’m using AI to tailor my resume to each job posting and to write the cover letter for each. Is that a cringe thing to do? I do feel some shame about it. I’ve been justifying it since the whole process feels quite artificial, and the required self-promotion is so painful for me. Also I do carefully read the resumes and cover letters to ensure everything is accurate. But feel free to tell me I’m still way off track for doing it this way.&lt;/p&gt;
&lt;p&gt;I’ve never gotten a job through an interview process. The three more-or-less traditional jobs I’ve had to this point have all been acquired through personal connections with people at the company. I have done a few interviews with different companies in the past, but none of them resulted in offers.&lt;/p&gt;
&lt;p&gt;So all that being said I’m not sure what to expect as far as the number of applications I’ll need to submit in order to land an offer. I understand job postings are now getting hundreds of applications since it’s so easy to automate now. I’m hoping the fact that I’m making sure I’m actually a good fit for each role I’m applying to will mean I won’t have to put in that many applications.&lt;/p&gt;
&lt;p&gt;Currently I’m aiming to submit one application per day. I think I may increase that number, though. Again not sure what number of applications per day I should be aiming for.&lt;/p&gt;
&lt;p&gt;I’m guessing I may need to get back on LeetCode and start studying for interviews. Probably beemind it, too. I think I used LeetCode for a little while when Amazon gave me an interview back when the big tech companies were recruiting like crazy. Or maybe I can find another way to study without needing to pay up for a LeetCode subscription.&lt;/p&gt;
&lt;p&gt;The trip to Europe I mentioned previously is now quite a bit more uncertain. I’m aiming for a remote job or a job with relocation assistance to Sweden, so hopefully I’ll still be able to spend some time in Europe in some fashion. Remains to be seen what that will actually look like.&lt;/p&gt;
&lt;p&gt;With the lack of client work I’ve been putting a lot more time into TaskRatchet. I’ve fixed bugs, improved uptime instrumentation, and added a Todoist integration. I’m hoping to keep up this velocity while searching for a job.&lt;/p&gt;
</content:encoded></item><item><title>Finding Clients in the Age of AI</title><link>https://nathanarthur.com/writing/finding-clients-in-the-age-of-ai</link><guid isPermaLink="true">https://nathanarthur.com/writing/finding-clients-in-the-age-of-ai</guid><pubDate>Tue, 16 Jun 2026 17:04:45 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/finding-clients-in-the-age-of-ai/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;In the past couple of days I’ve had conversations with two different friends, both contractors, about the impact of AI on their ability to find and keep clients. One says that AI has decimated their ability to find steady contract work. They other says it’s created opportunities for them to increase the demand for their services.&lt;/p&gt;
&lt;p&gt;I haven’t seen a noticeable impact on my own work. Probably because I’ve only ever had a very small number of clients who were already unsteady sources of contracts. Though would any of them actually tell me if the reason they decided not to give me a project is because of AI? Doubtful.&lt;/p&gt;
&lt;p&gt;My friend for whom this all seems to be working out is &lt;a href=&quot;https://christophermoravec.com/&quot;&gt;Christopher Moravec&lt;/a&gt;. He has positioned himself as a thought leader on the responsible use of AI in software development. He attributes his current success to this positioning.&lt;/p&gt;
&lt;p&gt;It seems clear to me that AI is resulting in more-or-less cold channels for client acquisition being flooded. That would include email, LinkedIn, Upwork, etc.&lt;/p&gt;
&lt;p&gt;It’s plausible that this means anyone who can actually prove they are expending human effort on starting a business relationship will have an advantage over those who are only pretending to. For example shooting a short personalized video and including it with a response to a job posting.&lt;/p&gt;
&lt;p&gt;My problem is that I wasn’t doing cold outreach before everything started changing, so I don’t expect I’ll start now, regardless of what new opportunities present themselves.&lt;/p&gt;
</content:encoded></item><item><title>Alternatives to the Big Social Networks</title><link>https://nathanarthur.com/writing/alternatives-to-the-big-social-networks</link><guid isPermaLink="true">https://nathanarthur.com/writing/alternatives-to-the-big-social-networks</guid><pubDate>Tue, 09 Jun 2026 17:58:51 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/alternatives-to-the-big-social-networks/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’m still thinking about how to do better at building social connections. Thought I’d share a few of the things I’ve used that are alternatives to the big social networks—Reddit, Facebook, YouTube, Twitter and friends. I don’t currently use all of these, but at least tried them at some point in the past.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’ve enjoyed &lt;a href=&quot;http://goodreads&quot;&gt;Goodreads&lt;/a&gt; in the past because it’s a single-topic social network. I think there’s something valuable about that, where you know what you’re going to get when you log in—a feed of what your friends are reading or want to read in the future.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://thestorygraph.com/&quot;&gt;The StoryGraph&lt;/a&gt; is an alternative to Goodreads. I used it briefly, it seemed nice. Over time my privacy has become more important to me, so I’ve stopped using the share-your-reading websites.&lt;/li&gt;
&lt;li&gt;You could argue that &lt;a href=&quot;http://www.linkedin.com/&quot;&gt;LinkedIn&lt;/a&gt; is similar to Goodreads as a single-topic social network—in LinkedIn’s case, business. But that doesn’t really work in practice, since LinkedIn lets you post about whatever you’d like, business-related or not. Plus, I’m not a fan of the AI-crafted self-congratulatory posts that plague the platform.&lt;/li&gt;
&lt;li&gt;More recently I’ve gotten back on the RSS train with Feedly as a way to stay off Reddit. I like that it’s only the stuff I subscribe to, and that I can set the default view to be reverse chronological.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m working on a more-thorough comparison in &lt;a href=&quot;https://drive.proton.me/urls/7XAMCAZWD4#2C3tdhGP26CY&quot;&gt;this spreadsheet&lt;/a&gt;. Feel free to reply with any input you might have—alternatives I haven’t listed, columns I should add, etc.&lt;/p&gt;
</content:encoded></item><item><title>Rethinking Social Networks</title><link>https://nathanarthur.com/writing/rethinking-social-networks</link><guid isPermaLink="true">https://nathanarthur.com/writing/rethinking-social-networks</guid><pubDate>Tue, 02 Jun 2026 18:04:18 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/rethinking-social-networks/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;It’s been a little while since I last wrote. My brother and I moved states to spend a few months with our parents. Later this year he and I plan to spend a year doing the digital nomad thing in Europe. Broaden our horizons a bit.&lt;/p&gt;
&lt;p&gt;In my spare time I’ve been building a new side project, &lt;a href=&quot;https://wiblet.net/&quot;&gt;wiblet.net&lt;/a&gt;, mostly motivated by the coming trip. I refuse to use Twitter or any product owned by Meta. Which means keeping up with friends who aren’t nearby can be difficult.&lt;/p&gt;
&lt;p&gt;I’ve been trying to think about what would make a good social network, one that I wouldn’t feel bad about using.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It wouldn’t have algorithmic feeds.&lt;/li&gt;
&lt;li&gt;It would only encourage interaction between actual friends, not distant strangers.&lt;/li&gt;
&lt;li&gt;Everything would be private by default.&lt;/li&gt;
&lt;li&gt;It wouldn’t encourage attention-maxing with likes or shares.&lt;/li&gt;
&lt;li&gt;It would encourage non-verbal, creative self-expression.&lt;/li&gt;
&lt;li&gt;It wouldn’t push non-consensual exposure to potentially-triggering topics such as politics and religion.&lt;/li&gt;
&lt;li&gt;It would encourage active (if bite-sized) interaction with friends, rather than passive consumption of acquaintances’ lives.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Wiblet.net is my first experiment exploring what that might look like. I was hoping it would be something like a mix of GeoCities, MySpace, and Myst. A place where friends could collaborate on shared worlds to explore and interact in. What it’s turned out to be so far is a social scrapbook. So maybe not quite what I was going for.&lt;/p&gt;
&lt;p&gt;On other possible approaches, I’ve been thinking about an idea I’m calling micro-attentions, and what a social network built around them might look like. Basically the idea being a platform that takes the Facebook poke and runs with it. Smile, hug, high-five, surveys (back to BuzzFeed?) or just simple shared questions, sharing a photo or a drawing, etc. Each micro-attention would be shared between only two people. And somehow these interactions would be encouraged through gamification or statistics or shared play or creativity. Maybe growing a garden or a forest where each plant represents a connection being strengthened. Something to make using the product feel satisfying and meaningful.&lt;/p&gt;
&lt;p&gt;I don’t know, I’m still mulling.&lt;/p&gt;
</content:encoded></item><item><title>MiniMax M2.7, OpenAI&apos;s Symphony, Etc</title><link>https://nathanarthur.com/writing/minimax-m27-openais-symphony-etc</link><guid isPermaLink="true">https://nathanarthur.com/writing/minimax-m27-openais-symphony-etc</guid><pubDate>Wed, 13 May 2026 16:11:11 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/minimax-m27-openais-symphony-etc/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’ve been continuing to use my Claude Max x20 plan. I haven’t hit any limits yet.&lt;/p&gt;
&lt;p&gt;I’ve been quite impressed with Matt Pocock’s &lt;a href=&quot;https://github.com/mattpocock/skills/tree/main/skills/engineering/improve-codebase-architecture&quot;&gt;improve-codebase-architecture skill&lt;/a&gt;. I’ve used it on a couple of repositories where I’d erred on the side of vibing and the skill’s ability to clean things up and create a much more sensible codebase structure has been very helpful.&lt;/p&gt;
&lt;p&gt;I’m intrigued by OpenAI’s &lt;a href=&quot;https://github.com/openai/symphony/blob/main/SPEC.md&quot;&gt;symphony spec&lt;/a&gt; for agent orchestration. I’ve made a start at setting up a system along its lines for myself, but haven’t gotten it to where I could actually use it yet.&lt;/p&gt;
&lt;p&gt;A note from a friend got me looking into &lt;a href=&quot;https://www.minimax.io/models/text/m27&quot;&gt;MiniMax M2.7&lt;/a&gt;. Its &lt;a href=&quot;https://whatllm.org/explore&quot;&gt;quality-to-price ranking&lt;/a&gt; is quite impressive, nearly reaching Opus 4.7 performance at a much lower per-token API price. Though that comes at the cost of sending your code to a company in China.&lt;/p&gt;
&lt;p&gt;According to the same website, publicly-available GPT and Gemini models are currently ahead of Claude in terms of quality. I don’t know what I’ll do with that information given at least so far Anthropic feels like a more trust-worthy company compared to Google or &lt;a href=&quot;https://www.newyorker.com/newsletter/the-daily/can-sam-altman-be-trusted&quot;&gt;OpenAI&lt;/a&gt;. It’s kind of amazing how sketchy the frontier labs seem to have managed to become.&lt;/p&gt;
</content:encoded></item><item><title>Business Incentives of AI Token Pricing</title><link>https://nathanarthur.com/writing/business-incentives-of-ai-token-pricing</link><guid isPermaLink="true">https://nathanarthur.com/writing/business-incentives-of-ai-token-pricing</guid><pubDate>Wed, 06 May 2026 16:22:17 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/business-incentives-of-ai-token-pricing/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;For most of my time using Claude Code I’ve used it via Anthropic’s API rather than using a Claude subscription. I briefly tried the base Max plan but found myself out of usage almost immediately, and went back to API usage.&lt;/p&gt;
&lt;p&gt;That usage has been steadily increasing as I’ve developed my workflows and tried different harnesses. It recently got to the point where I was regularly spending more than $100 per day on Claude tokens.&lt;/p&gt;
&lt;p&gt;This is fine when most of that cost is passed on to clients. However recently one of our clients reduced the amount of work they’re sending us, meaning a higher percentage of that usage moved to non-billable internal projects. That proved to be unsustainable.&lt;/p&gt;
&lt;p&gt;My brother has been using a Claude subscription without issue, so I decided to give it another shot. I’m now on the Max 20x plan, and it seems to be working well this time.&lt;/p&gt;
&lt;p&gt;One unfortunate consequence of this switch is that &lt;a href=&quot;https://www.theregister.com/software/2026/02/20/anthropic-clarifies-ban-on-third-party-tool-access-to-claude/5014546&quot;&gt;I’m effectively no longer allowed to use third-party harnesses with Claude Code&lt;/a&gt;. So that means saying goodbye to &lt;a href=&quot;https://cursor.com/blog/cursor-3&quot;&gt;Cursor 3&lt;/a&gt; and &lt;a href=&quot;https://zencoder.ai/&quot;&gt;Zencoder&lt;/a&gt; for the time being. Though &lt;a href=&quot;https://www.warp.dev/&quot;&gt;Warp&lt;/a&gt; has recently added enough integration with Claude Code to at least give a hint of some of the things I liked about using third-party harnesses.&lt;/p&gt;
&lt;p&gt;The biggest thing I’m missing so far is the ease with which &lt;a href=&quot;https://docs.zencoder.ai/zenflow/git-worktrees&quot;&gt;Zencoder allowed me to create new tasks with their own worktrees&lt;/a&gt;. Claude Code does have &lt;a href=&quot;https://code.claude.com/docs/en/worktrees&quot;&gt;its own worktree support&lt;/a&gt;, but it’s always felt more intimidating to me to get it to work well. I guess this is an opportunity to push through that and see just how good Claude Code’s worktree support can be.&lt;/p&gt;
&lt;p&gt;It’s been interesting trying to come to grips with the incentives that this new way of doing software development sets up. As a more-or-less solo freelancer, I’m used to my productivity being almost entirely untethered from my wallet. If I want to produce more results, I can simply spend more time coding. No additional expenditures necessary.&lt;/p&gt;
&lt;p&gt;Now that I’m using AI for programming, that’s much less the case. I can theoretically produce an unlimited amount of output, quality of my workflows allowing. But once I max out my subscriptions, that productivity additionally scales my costs. It’s more like having employees, where I could theoretically hire as many employees as I wanted to scale productivity, but it’s expensive to do so.&lt;/p&gt;
&lt;p&gt;Except it’s not quite like employees.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Employees are hard to scale up and down. You have to find them, interview them, hire them, and perhaps fire them. AI, on the other hand, scales up and down without friction.&lt;/li&gt;
&lt;li&gt;A new employee needs training and experience to realize their potential productivity at a task, whereas a cloned AI agent immediately has the same productivity as all previous agents.&lt;/li&gt;
&lt;li&gt;An employee is likely to be specialized in a few tasks, and moving them to a different task can be costly and disruptive. While AI resources are fungible, easily repurposed for whatever the current needs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This creates a tighter coupling between a task’s profitability and the incentives to scale the execution of that task. With AI, if a task makes you money this month, you can spin up an unlimited amount of capacity to exploit that opportunity. And if next month it stops making you money, you can spin all that bandwidth back down to zero.&lt;/p&gt;
&lt;p&gt;That’s different from scaling productivity with employees, where hiring many employees results in training costs, ongoing pay if you keep them on, and human suffering if you fire them.&lt;/p&gt;
&lt;p&gt;I think historically businesses have simply split the difference. Hire enough employees to exploit most of the operation’s typical opportunities, and give them lower-value work during the times where those opportunities are less abundant. Accept some level of firing and hiring, but keep it manageable. Some lost opportunity, some wasted bandwidth, but hopefully not too much of either, most of the time.&lt;/p&gt;
&lt;p&gt;AI promises to solve those issues. Perfect exploitation. Perfect efficiency. Societal costs still uncertain.&lt;/p&gt;
</content:encoded></item><item><title>I am no longer a programmer</title><link>https://nathanarthur.com/writing/i-am-no-longer-a-programmer</link><guid isPermaLink="true">https://nathanarthur.com/writing/i-am-no-longer-a-programmer</guid><pubDate>Tue, 21 Apr 2026 17:45:47 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/i-am-no-longer-a-programmer/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I knew it was more or less inevitable. But I hadn’t realized it had already happened until a couple of days ago when I was talking shop with my brother. I realized I haven’t written code by hand for months.&lt;/p&gt;
&lt;p&gt;What finalized the change was when I started using Claude Code with Opus 4.5. I was already using agentic coding tools before that point. But they were still unreliable enough that I’d go back and forth between working with the agentic coding tools and working on the code myself.&lt;/p&gt;
&lt;p&gt;My current workflow no longer requires this.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I ask an agentic tool (Claude Code, Cursor, or Zen Coder) to implement a change to the project.&lt;/li&gt;
&lt;li&gt;I spot-check the code changes as the agent works to make sure they look reasonable.&lt;/li&gt;
&lt;li&gt;I ask the agent to verify the change and/or verify it myself.&lt;/li&gt;
&lt;li&gt;I put the agent’s work through multiple cycles of automated code review (a separate local agent; GitHub PR review bots such as CodeRabbit and GitHub Copilot).&lt;/li&gt;
&lt;li&gt;I review the changes in the final PR.&lt;/li&gt;
&lt;li&gt;Depending on the project, I may or may not request an additional human review from a teammate.&lt;/li&gt;
&lt;li&gt;I deploy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So if I’m no longer a programmer, what am I?&lt;/p&gt;
&lt;p&gt;I now spend my time:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Grooming issue backlogs&lt;/li&gt;
&lt;li&gt;Managing running agents&lt;/li&gt;
&lt;li&gt;Reviewing code&lt;/li&gt;
&lt;li&gt;Looking for new tools and processes to ensure product quality doesn’t suffer&lt;/li&gt;
&lt;li&gt;Communicating with teammates and clients&lt;/li&gt;
&lt;li&gt;Further automating business tasks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I guess I was right. &lt;a href=&quot;https://nathanarthur.com/writing/will-ai-make-us-all-managers&quot;&gt;AI has turned me into a manager&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>TaskRatchet Database Switch, Making AI Skills Autonomous, Etc</title><link>https://nathanarthur.com/writing/taskratchet-database-switch-making</link><guid isPermaLink="true">https://nathanarthur.com/writing/taskratchet-database-switch-making</guid><pubDate>Tue, 14 Apr 2026 16:46:54 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/taskratchet-database-switch-making/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;After three months of sporadic work, yesterday I finally moved TaskRatchet from Firestore to Neon. TaskRatchet was in maintenance mode for about an hour and a half during the migration. Fingers crossed that the change hasn’t introduced too many bugs.&lt;/p&gt;
&lt;p&gt;Reasons for the switch:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I plan to move the TaskRatchet back-end to Cloudflare, and Firestore isn’t very compatible with Cloudflare.&lt;/li&gt;
&lt;li&gt;Firestore is a proprietary database, which means lock-in issues. Neon uses PostgreSQL, so future moves should be much easier.&lt;/li&gt;
&lt;li&gt;Firestore restricts the kinds of querying I can do, which is frustrating when I’m trying to optimize cost and performance.&lt;/li&gt;
&lt;li&gt;PostgreSQL is widely supported for tooling such as ORMs.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;I’ve been experimenting with pushing my AI skills to be more autonomous. Example: I’ve rewritten &lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/.claude/skills/resolve-pr-feedback/SKILL.md&quot;&gt;my resolve-pr-feedback skill&lt;/a&gt; to handle AI review feedback automatically instead of waiting for my input after each feedback item. It then commits and pushes any feedback, waits for AI reviewers to submit new reviews, and repeats the cycle up to three times. It still, however, requires my input on any human-submitted feedback.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I’m continuing to use the new Cursor 3 agents interface. It’s a significant improvement over using Claude Code when multitasking. Three things I’m hoping Cursor fixes soon:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It currently has a bug where restarting Cursor results in archived conversations reappearing in the agents window sidebar.&lt;/li&gt;
&lt;li&gt;The in-Cursor browser is not scoped to the AI session. This means that if one agent uses the browser MCP to navigate to a page, any other agents who were trying to use the browser now see the new page instead of what they may have been working on.&lt;/li&gt;
&lt;li&gt;Worktree support is janky. I would like to be able to have multiple sessions in the same repo, each with its own worktree, and for which worktree each session is using to be clearly visible. Currently this is not the case. Agents can use different worktrees. But the agents are managing their worktrees manually, unsupported by the UI or any IDE-specific logic.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;CodeRabbit now supports &lt;a href=&quot;https://docs.coderabbit.ai/management/usage-based-addon&quot;&gt;usage-based billing&lt;/a&gt;, something I’ve long wished they had. Unfortunately it doesn’t replace their per-seat pricing. But it at least provides a way to prevent CodeRabbit’s rate-limiting from slowing development.&lt;/p&gt;
</content:encoded></item><item><title>Consciousness Is a Rounding Error</title><link>https://nathanarthur.com/writing/consciousness-is-a-rounding-error</link><guid isPermaLink="true">https://nathanarthur.com/writing/consciousness-is-a-rounding-error</guid><pubDate>Fri, 10 Apr 2026 17:39:25 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/consciousness-is-a-rounding-error/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Recently I’ve been thinking more about the nature of consciousness and what I as an individual can know about it.&lt;/p&gt;
&lt;p&gt;I previously posted some thoughts about specifically &lt;a href=&quot;https://nathanarthur.com/writing/are-llms-conscious&quot;&gt;whether we can exclude the possibility that AI in its current form is conscious&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The more I think about this, the more I believe that the amount of continuous consciousness I can confidently say exists is vanishingly small.&lt;/p&gt;
&lt;p&gt;What do I mean by continuous consciousness? Subjective experience which persists and is tied to a specific individual. The idea that there’s a “me” inside me and that this “me” experiences subjective sensations, and that this same “me” continues to exist and experience these sensations over some period of time, whether that be minutes, weeks, or an entire lifetime.&lt;/p&gt;
&lt;p&gt;The typical story I hear around this type of consciousness is that I as an individual can confirm that this type of consciousness exists at least in me, since I can introspect on that experience directly. Whereas I have no way to confirm whether anyone else has this experience since in theory they could be machines which are simply acting as if they have subjective experience but in reality do not. Such an entity is referred to as a “&lt;a href=&quot;https://en.wikipedia.org/wiki/Philosophical_zombie&quot;&gt;philosophical zombie&lt;/a&gt;.”&lt;/p&gt;
&lt;iframe src=&quot;https://www.youtube-nocookie.com/embed/nQHBAdShgYI&quot; title=&quot;YouTube video&quot; loading=&quot;lazy&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;CGP Grey has a video called “&lt;a href=&quot;https://www.youtube.com/watch?v=nQHBAdShgYI&amp;amp;pp=ygUSY2dwZ3JleSB0ZWxlcG9ydGVy&quot;&gt;Teleportation Would Kill You&lt;/a&gt;” which ends up connecting to this idea. Say you have a Star Trek-style teleporter. It moves you from one location to another by deconstructing your body into its molecules. It then puts you back together again somewhere else, in the exact same configuration as previous to the teleportation. The person at the destination feels that it is you. It has all your memories. It remembers walking into the teleporter as well as walking back out at the destination. But a strong argument can be made that it is not you. It is a new person, and the original person is dead.&lt;/p&gt;
&lt;p&gt;Grey then points out that, even though we don’t have teleporters, we do have similar breaks in consciousness. When you go to sleep each night, setting aside REM sleep, your consciousness ceases. There’s no way to prove that the consciousness you had the previous day is the same conscious “me” you wake up with in the morning. Perhaps every conscious “me” only gets one day, then dies never to experience again, only to be replaced by a new conscious “me” the next day with all the memories of all the previous “me’s” that have existed for this individual.&lt;/p&gt;
&lt;p&gt;What’s had me thinking lately, though, is that there doesn’t seem to me to be any good reason to stop there.&lt;/p&gt;
&lt;p&gt;There’s a concept in neuroscience called “the subjective present,” that period of time which feels to you to be “now.” Here are a few papers which I have neither read nor skimmed but are linked here in case you’re less lazy than I am:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pmc.ncbi.nlm.nih.gov/articles/PMC4829156/&quot;&gt;Time Slices: What Is the Duration of a Percept?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plato.stanford.edu/archives/sum2018/entries/consciousness-temporal/specious-present.html&quot;&gt;The Specious Present: Further Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pubmed.ncbi.nlm.nih.gov/28368147/&quot;&gt;The three-second “subjective present”: A critical review and a new proposal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It seems to me that if I accept the idea that subjective experience can only be confidently confirmed by introspection, then the length of that subjective experience which can be confirmed is that of the subjective present, since by definition this is the duration of consciousness accessible for direct introspection. And this duration may be as short as only two or three seconds.&lt;/p&gt;
&lt;p&gt;And if that’s the case, then there’s no way to rule out that the subjective “me” may have a lifetime not of a single day, but rather of two or three seconds.&lt;/p&gt;
&lt;p&gt;I now think that for a being to have a subjectively-irrefutable experience of long, continuous consciousness does not require that being to actually have long, continuous consciousness. It only requires that the being has the experience of a subjective presence, however short, and the memory of many previous experiences of similar subjective presences.&lt;/p&gt;
&lt;p&gt;That’s it.&lt;/p&gt;
&lt;p&gt;Perhaps Clive Wearing, the man with no short-term memory, experiencing every moment of every day as an awakening from nothingness, has a more accurate experience of reality than anyone else, each fleeting “me” fully aware of its birth into conscious existence.&lt;/p&gt;
&lt;iframe src=&quot;https://www.youtube-nocookie.com/embed/Vwigmktix2Y&quot; title=&quot;YouTube video&quot; loading=&quot;lazy&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;Other than out of morbid fascination there isn’t really much of a reason to take these possibilities too seriously. They’re unfalsifiable. However, the fact that there is so little of even my own conscious experience that I can confidently claim makes me even more inclined to humility when considering the nature or existence of consciousness in other entities, biological or not.&lt;/p&gt;
</content:encoded></item><item><title>State of the Workflow: AI for Client Programming</title><link>https://nathanarthur.com/writing/state-of-the-workflow-ai-for-client</link><guid isPermaLink="true">https://nathanarthur.com/writing/state-of-the-workflow-ai-for-client</guid><pubDate>Tue, 07 Apr 2026 17:40:54 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/state-of-the-workflow-ai-for-client/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;(Title stolen from &lt;a href=&quot;https://cgpgrey.substack.com/p/state-of-the-workflow-how-major-life&quot;&gt;the Cortex podcast&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;My team and I have been using &lt;a href=&quot;https://www.anthropic.com/news/claude-opus-4-6&quot;&gt;Opus 4.6&lt;/a&gt; for most of our work for a while now. This really kicked into gear when our main client requested that our team use Opus for all work for them going forward. This was based on another developer who works for them telling them that tasks in their codebase that used to take weeks started taking days when he switched to Opus. We’re seeing similar results.&lt;/p&gt;
&lt;p&gt;For quite a while now I’ve been using &lt;a href=&quot;https://claude.com/product/claude-code&quot;&gt;Claude Code&lt;/a&gt; exclusively. It’s great, though it has had some pain points, primarily when it comes to multitasking. Keeping track of multiple terminal pains with different Claude Code sessions running is difficult and inefficient.&lt;/p&gt;
&lt;p&gt;Recently &lt;a href=&quot;https://cursor.com/blog/cursor-3&quot;&gt;Cursor released Cursor 3&lt;/a&gt;, including a new multi-workspace agents interface. I’ve only started using it today, but it’s exactly what I’ve been lacking.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One interface displays all my AI coding sessions in a sidebar for easy switching.&lt;/li&gt;
&lt;li&gt;Each session in the sidebar indicates if its running, done, or waiting for intervention.&lt;/li&gt;
&lt;li&gt;Cursor supports Opus, so I don’t have to use a different model.&lt;/li&gt;
&lt;li&gt;Cursor supports hooks, so I was able to easily tie it into our existing team-wide token tracking system.&lt;/li&gt;
&lt;li&gt;So far it seems to have good keyboard shortcuts support.&lt;/li&gt;
&lt;li&gt;It supports all my Claude Code skills, so I don’t need to do any fussing to transfer my existing skills.&lt;/li&gt;
&lt;li&gt;It isn’t repo-specific, so I can easily work in multiple sessions across multiple git repositories at the same time.&lt;/li&gt;
&lt;li&gt;It includes code review features so I can review code diffs locally before pushing to GitHub.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our token tracking system consists of Claude Code and Cursor hooks that submit token counts along with the repo the session occurred in to an API endpoint. These session stats are then stored in a private &lt;a href=&quot;https://baserow.io/&quot;&gt;Baserow&lt;/a&gt; instance. When I need to bill a client, my billing tooling queries this session data for the sessions associated with the specific client’s GitHub repositories, tallies the tokens used within the billing period, and uses that to calculate how much the client owes in token usage based on model rates.&lt;/p&gt;
&lt;p&gt;The skills I find myself using on a regular basis:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;client-report for generating detailed weekly reports of what our team has been doing for a client&lt;/li&gt;
&lt;li&gt;daily-standup for generating detailed summaries of what the team has been doing in the past day&lt;/li&gt;
&lt;li&gt;fix-ci for fixing failed GitHub Actions jobs&lt;/li&gt;
&lt;li&gt;obsidian for quickly giving an agent access to my notes&lt;/li&gt;
&lt;li&gt;pr-triage for working through pull request backlogs&lt;/li&gt;
&lt;li&gt;resolve-pr-feedback for working through pull request feedback, both human and automated&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition, whenever possible I add comprehensive skills to each repository I’m working in. These skills provide documentation that can be loaded when relevant as well as documenting and automating different tasks and processes that are likely to be needed in the repository going forward.&lt;/p&gt;
</content:encoded></item><item><title>Pretentious, self-indulgent navel-gazing</title><link>https://nathanarthur.com/writing/pretentious-self-indulgent-navel</link><guid isPermaLink="true">https://nathanarthur.com/writing/pretentious-self-indulgent-navel</guid><pubDate>Wed, 01 Apr 2026 08:42:04 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/pretentious-self-indulgent-navel/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;It’s nearly 4am here. I woke up with mild heartburn. Before I could go back to sleep I started thinking about this newsletter. Eventually I decided to get up and write my thoughts if I was going to be awake anyway.&lt;/p&gt;
&lt;p&gt;Since &lt;a href=&quot;https://nathanarthur.com/writing/writing-with-ai-responsibly&quot;&gt;last issue&lt;/a&gt;, I’ve been thinking about what it means to write well, what it would mean for me to write well.&lt;/p&gt;
&lt;p&gt;I think the fact that humanity has recently invented a technology that can do all the writing we’d ever want on command has forced the question. Like the kid in math class who asks why they should learn long division when a calculator can do it just as well and faster.&lt;/p&gt;
&lt;p&gt;My last issue, in which I admitted to experimenting with using AI to coach my writing, was nearly a month ago. I usually publish weekly. My absence is partially due to recent work deadlines, but also to becoming anxious whenever I think about allowing an LLM to socratically chisel my writing into a polished caricature of my thoughts with little room for uncertainty and ambivalence.&lt;/p&gt;
&lt;p&gt;I still believe that the purpose of writing is to connect human with human, author with reader, mind with mind. And, if that’s the case, to write well is to pour myself into the page.&lt;/p&gt;
&lt;p&gt;The issue is that often I’m not sure I want to do that. I’m an overweight divorcé with questionable hygiene practices who until recently rarely left his apartment. Why should I voluntarily poor myself onto the internet for all to see?&lt;/p&gt;
&lt;p&gt;So I’ve rushed through it like an unpleasant medicine. Roughly thirty minutes from start to publish, too little time to overthink things, to get in my own way.&lt;/p&gt;
&lt;p&gt;I thought that an AI writing coach would allow me to step beyond that. It would add structure that would improve my writing beyond publishing messy first drafts.&lt;/p&gt;
&lt;p&gt;Unfortunately, the result was a piece of writing that had less of me in it than a messy first draft would, perhaps because I’m so messy and unfinished.&lt;/p&gt;
&lt;p&gt;I want to respect you, the reader. But at this point it feels more disrespectful to give you something that has the messy parts of me patched out than it does to send you a first draft. Neither is ideal. But at least a first draft still has the potential to be authentic connection.&lt;/p&gt;
&lt;p&gt;I guess this means, for now, I’m going back to not using an AI writing coach. Perhaps I’ll try it again in the future, create a new Claude skill, experiment with a new process. But at least for this issue, for better or worse, an unfinished draft will have to do.&lt;/p&gt;
</content:encoded></item><item><title>Writing with AI, Responsibly</title><link>https://nathanarthur.com/writing/writing-with-ai-responsibly</link><guid isPermaLink="true">https://nathanarthur.com/writing/writing-with-ai-responsibly</guid><pubDate>Wed, 11 Mar 2026 16:48:32 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/writing-with-ai-responsibly/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Starting with this issue, I’m using AI to help me write this newsletter. Please don’t stop reading if this is upsetting–I think I can win you back. Allow me to explain how I’m using AI in concrete terms, and then address head-on what I imagine will be your objections.&lt;/p&gt;
&lt;p&gt;First and foremost: None of the words in this newsletter will be written by an LLM. They will remain my words and my words only.&lt;/p&gt;
&lt;p&gt;With that clarification, what has changed is that I’m now using AI as a writing coach.&lt;/p&gt;
&lt;p&gt;The skill I’m using does this by keeping its own separate markdown file in which it captures everything it understands about what I’m trying to say. It then challenges any ambiguity in my writing, any missing arguments or lack of rigor, and pushes me to correct these issues in my own words.&lt;/p&gt;
&lt;p&gt;The impression I get when hearing people talk about using LLMs for writing is that they believe it to be inauthentic, lazy, and error-prone. The workflow I’ve described is intended to achieve the opposite on all counts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Authenticity:&lt;/strong&gt; I’m committed to preserving the connection between my mind and yours, mediated only by my words. For this reason, I won’t allow my AI workflow to contribute its own words, but only to challenge my writing and thinking, leaving the correction of the issues it identifies to me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Effort:&lt;/strong&gt; This workflow makes writing this newsletter take significantly more time than it has in the past (confirmed, as I’m using it to write this issue!). It forces me to engage more deeply with what I think and what I’m trying to say. That engagement takes more time, more effort.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Accuracy:&lt;/strong&gt; The AI’s role is to challenge where my writing is poorly thought-through or communicated. It does not provide its own information or evidence, side-stepping the issue of AI hallucination.&lt;/p&gt;
&lt;p&gt;To this point, what I’ve published in this newsletter have been stream-of-consciousness first drafts. This has allowed me to tiptoe back into writing when doing anything else would have been anxiety-inducing for me.&lt;/p&gt;
&lt;p&gt;But I don’t want to leave my writing at this point. I want to begin pushing the quality of what I publish, and I hope that this new workflow will allow me to achieve this.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/.claude/skills/writing-coach/SKILL.md&quot;&gt;Here’s the skill I’m using&lt;/a&gt; if you’d like to see exactly how it works and perhaps try it for yourself.&lt;/p&gt;
&lt;p&gt;Instructions for using skills with various tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://support.claude.com/en/articles/12512180-use-skills-in-claude&quot;&gt;Claude&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.claude.com/docs/en/skills&quot;&gt;Claude Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.github.com/en/copilot/concepts/agents/about-agent-skills&quot;&gt;GitHub Copilot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geminicli.com/docs/cli/skills/&quot;&gt;Gemini CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://help.openai.com/en/articles/20001066-skills-in-chatgpt&quot;&gt;ChatGPT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Skills, Bills, and Aligning Incentives</title><link>https://nathanarthur.com/writing/skills-bills-and-aligning-incentives</link><guid isPermaLink="true">https://nathanarthur.com/writing/skills-bills-and-aligning-incentives</guid><pubDate>Wed, 04 Mar 2026 18:27:24 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/skills-bills-and-aligning-incentives/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://code.claude.com/docs/en/skills&quot;&gt;Claude Code skills&lt;/a&gt; are eating my development process. They can be used to assist me with basically anything I do as a developer.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Documenting codebases&lt;/li&gt;
&lt;li&gt;Reviewing business finances&lt;/li&gt;
&lt;li&gt;Generating development reports for clients&lt;/li&gt;
&lt;li&gt;Summarizing recent team activity&lt;/li&gt;
&lt;li&gt;Grooming GitHub issues&lt;/li&gt;
&lt;li&gt;Working through PR review backlogs&lt;/li&gt;
&lt;li&gt;Organizing file systems&lt;/li&gt;
&lt;li&gt;Fixing CI failures&lt;/li&gt;
&lt;li&gt;Testing features and bug fixes across environments using Playwright&lt;/li&gt;
&lt;li&gt;Etc&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I find that they have big advantages to other ways I might try to solve the same issues.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They crystallize knowledge and give distinct pieces of knowledge handles, reducing the demand on my long-term memory.&lt;/li&gt;
&lt;li&gt;They allow for creating flexible, interactive workflows for given tasks, allowing me to maintain focus and reducing demand on my short-term memory.&lt;/li&gt;
&lt;li&gt;They are easily improved over time without switching contexts. A skill didn’t work the way I’d like it to? Just ask the system to update it to behave better.&lt;/li&gt;
&lt;li&gt;They can be designed to be self-improving, by instructing them to update themselves on each use.&lt;/li&gt;
&lt;li&gt;They don’t pollute AI coding tool context windows, since AI tools only pull them in when they are relevant (or when you’ve explicitly pulled them in as a slash command).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With all these advantages, I’ve been doing my best to lean fully into using them. I’ve created many personal skills that are available in any project I work on, and I’ve started moving other forms of developer documentation and coding agent context files to skills in the projects where I have the leeway to do so.&lt;/p&gt;
&lt;p&gt;Our current clients are billed hourly. This meant that, if we didn’t do something to address the issue, we’d be disincentivized to use agent skills to the extent that we should. No one wins if we cheap out and take longer to do poorer work at a higher price.&lt;/p&gt;
&lt;p&gt;To address this, I’ve set up &lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/.claude/TOKEN_ATTRIBUTION.md&quot;&gt;a bare bones system&lt;/a&gt; that allows me to track the tokens I spend for each of my clients and then bill them for those tokens separately from our hours.&lt;/p&gt;
&lt;p&gt;Currently its big downside is that it only runs on my machine. In the future I’ll need to figure out a way to send the data to something on the web so that any subcontractors I’m working with can also track their tokens and have them billed and reimbursed.&lt;/p&gt;
&lt;h3 id=&quot;links-roundup&quot;&gt;Links Roundup&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.comet.com/site/products/opik/&quot;&gt;Opik&lt;/a&gt; — LLM observability platform&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/EveryInc/compound-engineering-plugin&quot;&gt;EveryInc/compound-engineering-plugin&lt;/a&gt; — Claude Code compound engineering plugin&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jayminwest/mulch&quot;&gt;jayminwest/mulch&lt;/a&gt; — Structured expertise files that accumulate over time, live in git, work with any agent&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jayminwest/kotadb&quot;&gt;jayminwest/kotadb&lt;/a&gt; — Local code intelligence API for AI dev workflows (Bun + SQLite)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jayminwest/agentic-engineering-book&quot;&gt;jayminwest/agentic-engineering-book&lt;/a&gt; — Growing guide to building agentic systems&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/stephendolan/ynab-cli&quot;&gt;stephendolan/ynab-cli&lt;/a&gt; — YNAB CLI with JSON output optimized for LLMs&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/remotion-dev/remotion&quot;&gt;remotion-dev/remotion&lt;/a&gt; — Make videos programmatically with React&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tambo-ai/tambo&quot;&gt;tambo-ai/tambo&lt;/a&gt; — Generative UI SDK for React&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Vibe Kanban, Claude Code Skills, Dotfiles, Etc</title><link>https://nathanarthur.com/writing/vibe-kanban-claude-code-skills-dotfiles</link><guid isPermaLink="true">https://nathanarthur.com/writing/vibe-kanban-claude-code-skills-dotfiles</guid><pubDate>Wed, 18 Feb 2026 16:25:32 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/vibe-kanban-claude-code-skills-dotfiles/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;h2 id=&quot;thoughts-on-vibe-kanban&quot;&gt;Thoughts on Vibe Kanban&lt;/h2&gt;
&lt;p&gt;I’ve done some experimenting with &lt;a href=&quot;https://www.vibekanban.com/&quot;&gt;Vibe Kanban&lt;/a&gt;. There are things I really like about it. The main one being that it seamlessly handles creating new git worktrees for each task attempt.&lt;/p&gt;
&lt;p&gt;I can’t help but thinking, though, that having to use a GUI to interact with the tool just slows me down at this point. My &lt;a href=&quot;https://github.com/narthur/dotfiles/tree/main/.claude/skills/pr-triage&quot;&gt;pr-triage&lt;/a&gt; and &lt;a href=&quot;https://github.com/narthur/dotfiles/tree/main/.claude/skills/resolve-pr-feedback&quot;&gt;resolve-pr-feedback&lt;/a&gt; skills for Claude Code have convinced me that skill-based workflows initiated directly within Claude Code can be incredibly powerful.&lt;/p&gt;
&lt;p&gt;I could almost leverage Vibe Kanban for this type of workflow, too. It has an MCP that lets you list and add tasks. But it doesn’t allow for creating and otherwise managing attempts on a task. If it did, I could build a Claude Code workflow around it and allow it to continue managing the git worktrees and running subagents autonomously in the different worktrees.&lt;/p&gt;
&lt;p&gt;So that leaves me to try to reproduce that functionality, too. I haven’t yet succeeded. I’ve been attempting to get a skill working in my TaskRatchet repository. I’ve added a &lt;a href=&quot;https://containers.dev/&quot;&gt;dev container&lt;/a&gt; to the repo and added a project-specific skill to attempt to allow for parallel task attempts pairing the dev container with task-specific worktrees.&lt;/p&gt;
&lt;p&gt;If I succeed in getting this skill to be functional, I’m unsure if it will need to remain specific to a single git repository. I figure I’ll just focus on getting it working within one repository and then assess what it would take to generalize.&lt;/p&gt;
&lt;h2 id=&quot;dotfiles-as-bare-git-repository&quot;&gt;Dotfiles as Bare Git Repository&lt;/h2&gt;
&lt;p&gt;I’ve updated how I use &lt;a href=&quot;https://github.com/narthur/dotfiles&quot;&gt;my dotfiles repo&lt;/a&gt; to use &lt;a href=&quot;https://www.atlassian.com/git/tutorials/dotfiles&quot;&gt;a bare git repository&lt;/a&gt;. The main advantage of this change is that I no longer need to keep an exhaustive list of files in the repo as exclusions in my .gitignore file, since all files in my home directory are ignored by default until explicitly added using &lt;code&gt;git add&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;links-roundup&quot;&gt;Links Roundup&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://testcontainers.com/&quot;&gt;Testcontainers&lt;/a&gt; - “Testcontainers is an open source library for providing throwaway, lightweight instances of databases, message brokers, web browsers, or just about anything that can run in a Docker container.”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/microsoft/playwright-cli&quot;&gt;Playwright CLI&lt;/a&gt; - “This package provides CLI interface into Playwright. If you are using &lt;strong&gt;coding agents&lt;/strong&gt;, that is the best fit.”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codeql.github.com/&quot;&gt;CodeQL&lt;/a&gt; - “Discover vulnerabilities across a codebase with CodeQL, our industry-leading semantic code analysis engine. CodeQL lets you query code as though it were data. Write a query to find all variants of a vulnerability, eradicating it forever. Then share your query to help others do the same.”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jules.google/&quot;&gt;Jules&lt;/a&gt; - “ules is an experimental coding agent that helps you fix bugs, add documentation, and build new features. It integrates with GitHub, understands your codebase, and works autonomously — so you can move on while it handles the task.”&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Experimenting with Vibe Kanban</title><link>https://nathanarthur.com/writing/experimenting-with-vibe-kanban</link><guid isPermaLink="true">https://nathanarthur.com/writing/experimenting-with-vibe-kanban</guid><pubDate>Tue, 10 Feb 2026 18:02:57 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/experimenting-with-vibe-kanban/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’ve been experimenting some with using &lt;a href=&quot;https://www.vibekanban.com/&quot;&gt;Vibe Kanban&lt;/a&gt;. It gives you a local kanban interface where you can track coding tasks and trigger coding agents to work on them locally using &lt;a href=&quot;https://git-scm.com/docs/git-worktree&quot;&gt;git worktrees&lt;/a&gt;. It also provides a local MCP server that you can connect to your other AI tools list and add tasks.&lt;/p&gt;
&lt;p&gt;I like the fact that this provides a private space for planning programming tasks. The chunks of a task that make sense to assign to a coding agent are likely often different than what would be ideal for syncing with other humans on something like GitHub Issues or Trello.&lt;/p&gt;
&lt;p&gt;One thing that Vibe Kanban is still missing is a way to chat with an AI about an issue within the kanban interface. I enjoy being able to ask &lt;a href=&quot;https://www.coderabbit.ai/&quot;&gt;CodeRabbit&lt;/a&gt; questions inside my GitHub issues and collaborate with the AI on planning the issue.&lt;/p&gt;
&lt;p&gt;I guess with Vibe Kanban the intended way to solve this is with its MCP server. Instead of chatting with the AI about a task within that task’s interface, chat with your favorite AI outside of Vibe Kanban about the task. And presumably that agent can then use the MCP server to update the task with new research and planning.&lt;/p&gt;
&lt;p&gt;I did run into a bit of a hiccup with its use of worktrees. It had created a worktree for a task branch (as it always does). Later I wanted to do something manually on that branch. I went to the main project folder and attempted to checkout the branch. Git then complained that I couldn’t do that because I already had a worktree for that branch. I ended up going back to Vibe Kanban and using its AI interface to do what I was going to do there. Perhaps if I were more comfortable with git worktrees generally this wouldn’t have tripped me up like it did.&lt;/p&gt;
</content:encoded></item><item><title>My AI Illustration Workflow</title><link>https://nathanarthur.com/writing/my-ai-illustration-workflow</link><guid isPermaLink="true">https://nathanarthur.com/writing/my-ai-illustration-workflow</guid><pubDate>Tue, 03 Feb 2026 16:01:42 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/my-ai-illustration-workflow/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;This image was generated using the workflow described in this post&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Over time I’ve been slowly improving the workflow I use to generate AI illustrations for these newsletters.&lt;/p&gt;
&lt;p&gt;In the past I would craft my own prompts for &lt;a href=&quot;https://www.bing.com/images/create?FORM=IRPGEN&quot;&gt;the Bing image generator&lt;/a&gt; or &lt;a href=&quot;https://support.substack.com/hc/en-us/articles/4697212547860-How-do-I-add-free-images-or-pictures-to-my-Substack-post&quot;&gt;the AI image generator built into Substack&lt;/a&gt;. But I found that I wasn’t especially good at coming up with good prompts reliably.&lt;/p&gt;
&lt;p&gt;I’ve found that Claude is much better than I am at prompt engineering. So for a while I would copy my articles into Claude and ask it to suggest image prompts for the article at several levels of abstractness. I’d then copy the prompts back into Substack’s image generator and see which results I liked best. This worked better, but was quite tedious to do for each article.&lt;/p&gt;
&lt;p&gt;Currently I use &lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/bin/generate-illustrations&quot;&gt;a local shell script&lt;/a&gt; to both generate the prompts and then generate illustrations from these prompts for me to choose from.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I run the script in my terminal.&lt;/li&gt;
&lt;li&gt;The script asks me for the text of my article. I paste the whole article, and add “END” on the next line to signal the script to proceed.&lt;/li&gt;
&lt;li&gt;The script sends a request to Claude Haiku 3 to &lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/bin/generate-illustrations#L17-L40&quot;&gt;extract key themes and concepts&lt;/a&gt; from the article.&lt;/li&gt;
&lt;li&gt;The script loops through &lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/bin/generate-illustrations#L6-L15&quot;&gt;a list of styles&lt;/a&gt;, asking Claude Haiku 3 to &lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/bin/generate-illustrations#L42-L95&quot;&gt;produce an image prompt&lt;/a&gt; for each style given the themes and concepts extracted in step three. It makes two such requests for each style.&lt;/li&gt;
&lt;li&gt;The script pauses to allow me to review and approve the generated prompts.&lt;/li&gt;
&lt;li&gt;Once approved, the script proceeds to generate an image for each prompt using &lt;a href=&quot;https://github.com/narthur/z-experiments&quot;&gt;Z-Image-Turbo running on my local machine&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I review the resulting images and select one to be used as the article’s illustration.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I’ve found this workflow to reliably and efficiently produce high-quality illustrations for my articles at very low cost. The Haiku 3 requests cost me less than a penny per run, and the actual image generation is ~free since it runs on my local machine.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/my-ai-illustration-workflow/2.webp&quot; alt=&quot;&quot; width=&quot;728&quot; height=&quot;392.80575539568343&quot; loading=&quot;lazy&quot;&gt;&lt;/figure&gt;
&lt;p&gt;One limitation of this approach is that it requires you have a computer beefy enough to run an image generator locally. I have an NVIDIA GeForce RTX 3060 with 12GB VRAM which makes this practical. But without a dedicated graphics card I’d probably be back to using a hosted image generator, perhaps using &lt;a href=&quot;https://platform.openai.com/docs/guides/image-generation&quot;&gt;OpenAI’s API&lt;/a&gt;. But of course that would mean &lt;a href=&quot;https://openai.com/api/pricing/&quot;&gt;higher cost per run&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Here are the illustrations that were generated for the above text:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/my-ai-illustration-workflow/3.webp&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;721.978021978022&quot; loading=&quot;lazy&quot;&gt;&lt;/figure&gt;
&lt;p&gt;And these are the prompts that produced them, from bottom right to top left:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;“Oil painting of a human hand and an artificial intelligence robotic hand clasped together against a backdrop of interconnected gears, circuit boards, and computer components. The palette features muted, earthy tones with highlights of cool metallic grays and blues, conveying a sense of collaboration and technological integration. Visible, impasto brushstrokes create a textured, documentary-style surface, and the composition is balanced with a focus on the central intertwined hands. Dramatic, raking light casts strong shadows, emphasizing the depth and materiality of the scene.”&lt;/li&gt;
&lt;li&gt;“Oil painting of a human hand and an AI-generated robotic hand reaching towards each other, their fingertips almost touching. The hands are rendered in a highly realistic, detailed style with visible brush strokes and a muted, earthy color palette of browns, ochres, and grays. The background is blurred and hazy, creating a sense of depth and focus on the central interaction between the human and machine. Subtle highlights and shadows emphasize the texture of the skin and metal, while the composition creates a sense of tension and collaboration between the two entities.”&lt;/li&gt;
&lt;li&gt;“Oil painting of a human hand collaborating with a metallic, robotic hand emerging from a swirling cloud of colorful digital data. The composition is balanced and symmetrical, with the human and robotic hands meeting at the center, fingers intertwined. The palette features rich, earthy tones of brown, ochre, and sienna, contrasted by vibrant splashes of blues, greens, and purples that suggest the flow of digital information. The brushwork is smooth and blended, with visible yet controlled impasto texture that adds depth and tactility to the painting. Warm, directional lighting from the upper left casts dramatic shadows and highlights the collaborative nature of the hands, emphasizing the harmony and synergy between human and machine.”&lt;/li&gt;
&lt;li&gt;“Oil painting of an abstract representation of the collaborative creative process between human and AI. The canvas depicts an energetic, swirling composition of overlapping shapes and gestural brushstrokes in a harmonious color palette of warm ochres, deep blues, and muted greens. Visible, expressive brushwork creates a sense of movement and dynamism, evoking the iterative nature of prompt engineering and workflow optimization. The overall mood is contemplative yet resolute, reflecting the pragmatic and solution-oriented approach described in the article. Areas of the canvas feature sharper, more defined forms juxtaposed with areas of loose, ethereal brushwork, symbolizing the interplay between human intent and machine generation. The painting cultivates a sense of collaboration, experimentation, and the gradual refinement of a creative process.”&lt;/li&gt;
&lt;li&gt;“Oil painting of an abstract, impressionistic representation of the collaborative interplay between human and AI in the creative process. Warm, earthy tones of ochre, sienna, and umber predominate, with flashes of vibrant primary colors symbolizing the sparks of innovation. Loose, expressive brushstrokes convey a sense of fluidity and dynamism, as if the paint itself is a physical manifestation of the iterative workflow. Subtle textures and blended edges create an atmospheric, dreamlike quality, evoking the experimental nature of the process. The composition features geometric shapes and forms that suggest both structure and flexibility, hinting at the technological and conceptual frameworks underlying the AI-assisted illustration generation. An overall sense of balance and harmony emerges, reflecting the synergy between human intuition and machine intelligence.”&lt;/li&gt;
&lt;li&gt;“Oil painting with visible brushstrokes depicting an abstract, swirling composition of vibrant colors. Shades of blues, greens, and golds flow together, creating a sense of movement and energy. Pockets of light and shadow weave through the canvas, adding depth and dimension. The overall impression is one of experimentation, iteration, and the harmonious collaboration between human and machine.”&lt;/li&gt;
&lt;li&gt;“Oil painting with visible brushstrokes depicting a surreal, semi-representational landscape. Muted earthy tones of ochre, sienna, and umber, accented with hints of cool blues and greens. Textured, impasto surfaces create a sense of depth and materiality. Fluid, gestural forms suggest the interplay of human and machine elements, with abstract shapes and symbols hinting at the collaborative creative process. Soft, diffused lighting casts a contemplative, experimental mood over the scene.”&lt;/li&gt;
&lt;li&gt;“Oil painting with visible brushstrokes depicting an abstract representation of the collaborative creative process between human and AI. Muted, earthy color palette of ochres, siennas, and deep blues, evoking a sense of pragmatism and technical exploration. Textured, impasto surfaces suggest the iterative, experimental nature of the workflow, while gestural, semi-representational forms symbolize the interplay of human intent and machine generation. Warm, soft lighting casts a contemplative atmosphere, hinting at the gradual refinement and optimization of the process over time.”&lt;/li&gt;
&lt;li&gt;“Oil painting with heavy impasto texture depicting an abstract, symbolic representation of the collaborative creative process between human and AI. Muted earth tones of ochre, sienna, and umber with flashes of metallic gold and silver, conveying a sense of technical sophistication and pragmatic problem-solving. Amorphous, gestural shapes and forms intertwine, suggesting the iterative nature of prompt engineering and workflow optimization. Visible, energetic brushstrokes create a sense of movement and experimentation. The composition is balanced but with areas of visual tension, mirroring the challenges and breakthroughs described in the article. Soft, directional lighting casts shadows that add depth and a contemplative atmosphere.”&lt;/li&gt;
&lt;li&gt;“Oil painting with impasto technique depicting abstract symbolic elements representing the interplay between human and AI in the creative process. Muted earthy tones of ochre, sienna, and umber with touches of metallic gold and silver accents. Textured, gestural brushstrokes convey a sense of motion and collaboration. Dominant central form suggests a collaborative entity, with surrounding fragmented shapes and lines hinting at the iterative workflow. Hints of technical diagrams or schematics in the background allude to the logistical considerations. Atmospheric lighting casts dramatic shadows, evoking a contemplative, experimental mood.”&lt;/li&gt;
&lt;li&gt;“Oil painting with a surrealist, metaphorical style. In the center, a large, organic shape resembling an open book or unfolding petals, rendered in warm, earthy tones. Within this shape, fragmented geometric forms in shades of blue, purple, and metallic accents float and intersect, suggesting a complex technological or digital landscape. The background is hazy and atmospheric, with loose, textured brushstrokes in muted greens, ochres, and grays, creating a sense of depth and mystery. The overall composition conveys a balance between the natural and the artificial, the human and the machine, in an enigmatic and thought-provoking manner.”&lt;/li&gt;
&lt;li&gt;“Oil painting of a surreal, dreamlike landscape where organic forms and geometric shapes coexist in a harmonious balance. The composition features a central focal point of a large, abstract shape resembling a human figure, rendered in muted earth tones and textured brushwork. Surrounding this central element are swirling, ethereal forms in shades of blue and green, suggesting the flow of energy and ideas. Subtle hints of warm ochre and amber tones create an atmosphere of contemplation and introspection. The overall style is dreamlike and evocative, with a sense of the subconscious and the interplay between the human mind and the creative potential of technology.”&lt;/li&gt;
&lt;li&gt;“Oil painting with a vibrant, geometric abstract composition. Distinct angular shapes in a harmonious color palette of deep crimson, burnt sienna, and vivid cobalt blue. Visible, energetic brushstrokes create a sense of movement and dynamism. Subtle gradients and blended edges add depth and visual interest. The overall mood is one of balance, innovation, and the collaborative embrace of human-AI creativity.”&lt;/li&gt;
&lt;li&gt;“Oil painting with heavy impasto texture and geometric abstract forms in a vibrant, harmonious color palette of deep blues, rich ochres, and vivid greens. The composition features overlapping angular shapes that create a sense of depth and movement, evoking the collaborative and iterative nature of the illustration workflow. Visible, expressive brushstrokes convey a sense of energy and dynamism, reflecting the experimental and problem-solving approach described in the article. The overall mood is one of intentional, deliberate abstraction, capturing the essence of the themes around prompt engineering and human-AI partnership in a visually striking manner.”&lt;/li&gt;
&lt;li&gt;“Oil painting with a vibrant, layered color field effect. Warm hues of orange, yellow, and red blended seamlessly, creating a sense of radiant energy. Hints of cool blues and greens emerge from the depths, generating a harmonious interplay of complementary tones. The surface exhibits a thick, impasto texture with visible, expressive brushstrokes that add depth and movement to the composition. The overall atmosphere is one of balance, exploration, and the synergistic collaboration between human and machine.”&lt;/li&gt;
&lt;li&gt;“Oil painting with a vibrant, energetic color palette of deep blues, fiery oranges, and electric greens. Loose, expressive brushstrokes create a sense of movement and dynamism across the canvas. Layers of transparent washes and opaque impasto textures build depth and visual interest. The composition features a central focal point with bursts of intersecting lines and shapes that radiate outward, evoking a sense of exploration and discovery. Subtle hints of underlying geometric forms suggest the technical and analytical nature of the creative workflow, while the overall atmospheric quality captures the experimental and iterative spirit of the process. The painting exudes a balance of human touch and machine-generated precision, mirroring the collaborative partnership between artist and AI.”&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>New Buzz Functionality; Terminal Screenshots</title><link>https://nathanarthur.com/writing/new-buzz-functionality-terminal-screenshots</link><guid isPermaLink="true">https://nathanarthur.com/writing/new-buzz-functionality-terminal-screenshots</guid><pubDate>Tue, 27 Jan 2026 17:53:37 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/new-buzz-functionality-terminal-screenshots/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;h2 id=&quot;buzz-schedule&quot;&gt;Buzz Schedule&lt;/h2&gt;
&lt;p&gt;I’ve been working on a new command for &lt;a href=&quot;https://github.com/pinepeakdigital/buzz&quot;&gt;buzz&lt;/a&gt;: &lt;code&gt;buzz schedule&lt;/code&gt;. Here’s what it looks like:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/new-buzz-functionality-terminal-screenshots/2.webp&quot; alt=&quot;&quot; width=&quot;1456&quot; height=&quot;1158&quot; loading=&quot;lazy&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I wanted a way to see how my deadlines fall throughout a day. I find myself needing this when I need to restructure my deadlines because my typical daily constraints have changed.&lt;/p&gt;
&lt;h2 id=&quot;terminal-screenshots&quot;&gt;Terminal Screenshots&lt;/h2&gt;
&lt;p&gt;Figuring out how to create that screenshot was a bit tricky.&lt;/p&gt;
&lt;p&gt;Unfortunately Substack’s built-in code block support isn’t great. It doesn’t have code formatting, and, more problematic for showing off &lt;code&gt;buzz schedule&lt;/code&gt;, it wraps by default.&lt;/p&gt;
&lt;p&gt;I played around with using &lt;a href=&quot;https://docs.warp.dev/terminal/blocks/block-sharing&quot;&gt;Warp shared blocks&lt;/a&gt;, &lt;a href=&quot;https://github.com/Aloxaf/silicon&quot;&gt;silicon&lt;/a&gt;, and &lt;a href=&quot;https://github.com/mixn/carbon-now-cli&quot;&gt;carbon-now-cli&lt;/a&gt;. Warp offers embeds, but it didn’t seem like Substack was going to support that. Silicon complained that it couldn’t detect the programming language I was using. And I couldn’t be bothered to figure out how to initialize playwright on my machine for carbon-now-cli to use.&lt;/p&gt;
&lt;p&gt;I ended up using &lt;a href=&quot;https://carbon.now.sh/&quot;&gt;Carbon’s web app&lt;/a&gt; to create the screenshot. Painless, quite a bit of customization, and nothing to install. I like it.&lt;/p&gt;
</content:encoded></item><item><title>Claude Cowork + Links Roundup</title><link>https://nathanarthur.com/writing/claude-cowork-links-roundup</link><guid isPermaLink="true">https://nathanarthur.com/writing/claude-cowork-links-roundup</guid><pubDate>Tue, 20 Jan 2026 17:58:33 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/claude-cowork-links-roundup/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Claude just &lt;a href=&quot;https://claude.com/blog/cowork-research-preview?utm_source=substack&amp;amp;utm_medium=email&quot;&gt;introduced Cowork&lt;/a&gt;—a new piece of software for using Claude to help with projects other than programming. From the article:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How is using Cowork different from a regular conversation? In Cowork, you give Claude access to a folder of your choosing on your computer. Claude can then read, edit, or create files in that folder. It can, for example, re-organize your downloads by sorting and renaming each file, create a new spreadsheet with a list of expenses from a pile of screenshots, or produce a first draft of a report from your scattered notes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I’ve already been working this way for a long time. The workflow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to a project folder inside &lt;a href=&quot;https://www.warp.dev/&quot;&gt;Warp&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Talk to Warp’s AI, allowing it to create, update, and reference project notes as needed.&lt;/li&gt;
&lt;li&gt;Warp asks questions, suggests next steps, searches the internet, etc.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it.&lt;/p&gt;
&lt;p&gt;I’ve found it to be a super powerful way to work on ambiguous and overwhelming projects. I create a &lt;a href=&quot;https://www.beeminder.com/&quot;&gt;Beeminder&lt;/a&gt; goal for spending time on the project, and then plans, research, and task lists develop over time with ease.&lt;/p&gt;
&lt;p&gt;It seems like the main advantages Cowork may have over just using something like Warp for this is Cowork’s ability to create files in more document formats and use connectors to other services. I’m not sold that those are big enough benefits for me personally to switch.&lt;/p&gt;
&lt;h2 id=&quot;links-roundup&quot;&gt;Links Roundup&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Artificial Intelligence
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://get.mem.ai/&quot;&gt;Mem&lt;/a&gt; - A note-taking application that promises to understand and surface your collection of notes automatically.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Software Development
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pullfrog.com/&quot;&gt;Pullfrog&lt;/a&gt; - A tool that lets you trigger agent workflows from GitHub Actions. Currently behind a wait list.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://opencode.ai/&quot;&gt;OpenCode&lt;/a&gt; - Opensource alternative to Claude Code. I’m thinking about trying it out with a local LLM.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://oxal.org/projects/sakura/&quot;&gt;Sakura&lt;/a&gt; - A minimal CSS theme meant for use with bare-bones semantic HTML pages.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://voidzero.dev/posts/announcing-vite-plus?utm_source=viteplusdev&amp;amp;utm_content=top_learn_more&quot;&gt;Announcing Vite+: a unified toolchain for JavaScript&lt;/a&gt; - An official CLI tool adding additional features on top of Vite.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Society
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ifyoucankeepit.org/p/elections-are-the-essential-remaining&quot;&gt;Elections are the essential remaining pillar of our democracy&lt;/a&gt; - I highly recommend subscribing to this newsletter if you’re concerned about the future of democracy in the United States.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.newsweek.com/nearly-two-thirds-of-young-americans-are-considering-leaving-the-us-11010814&quot;&gt;Nearly two thirds of young Americans are considering leaving the US&lt;/a&gt; - According to a survey by the American Psychological Association.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Etc
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.atlasobscura.com/articles/centralia-pennsylvania-rebirth&quot;&gt;The Rebirth of Pennsylvania’s Infamous Burning Town&lt;/a&gt; (via &lt;a href=&quot;https://www.tomscott.com/newsletter/&quot;&gt;Tom Scott’s newsletter&lt;/a&gt;) - An interesting article about an abandoned town that’s been reclaimed by nature.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ulysses.app/&quot;&gt;Ulysses&lt;/a&gt; - A long-form writing application for Apple devices.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pikapods.com/&quot;&gt;PikaPods&lt;/a&gt; - A platform for easily and affordably running instances of many self-hostable applications. I’m currently using Render.com for this, though I’m considering making the switch.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Solution for Large Branches: GitButler</title><link>https://nathanarthur.com/writing/solution-for-large-branches-gitbutler</link><guid isPermaLink="true">https://nathanarthur.com/writing/solution-for-large-branches-gitbutler</guid><pubDate>Tue, 13 Jan 2026 15:31:53 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/solution-for-large-branches-gitbutler/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I think I may have finally found a solution to my giant git branch issue.&lt;/p&gt;
&lt;p&gt;Recap: I have a bad history of creating huge git branches which are then difficult to review. I’ve found it very difficult to maintain the discipline needed to keep branches small. Recently I’ve been exploring ways I could make it easier to break these larger branches down for easier review.&lt;/p&gt;
&lt;p&gt;I’ve been working on &lt;a href=&quot;https://nathanarthur.com/writing/iterating-on-a-pr-extraction-workflow&quot;&gt;an AI workflow&lt;/a&gt; for this. It’s definitely shown promise. However I’ve found it to be temperamental and easy to break when I make changes to the saved prompt.&lt;/p&gt;
&lt;p&gt;I’ve been aware for a little while that there was a piece of software called &lt;a href=&quot;https://gitbutler.com/&quot;&gt;GitButler&lt;/a&gt; that was supposed to make this kind of thing easier. However when I had previously looked into it, GitButler wasn’t yet available for Linux.&lt;/p&gt;
&lt;p&gt;I checked again recently, and it now is. And with &lt;a href=&quot;https://github.com/gitbutlerapp/gitbutler/issues/11761&quot;&gt;a little bit of cajoling&lt;/a&gt;, it’s now working on my system.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/solution-for-large-branches-gitbutler/2.webp&quot; alt=&quot;https://gitbutler.com/images/app-preview-dark.png&quot; width=&quot;1456&quot; height=&quot;843&quot; loading=&quot;lazy&quot;&gt;&lt;figcaption&gt;Screenshot from the GitButler website&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;I think this software may have just eliminated the issue altogether.&lt;/p&gt;
&lt;p&gt;Even without this software I could create new branches as I build, of course. But doing so requires a lot of thinking:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Do I need a new branch?&lt;/li&gt;
&lt;li&gt;Would the changes I put on a new branch depend on the changes in my previous branch? This determines what I should base the new branch on.&lt;/li&gt;
&lt;li&gt;If I make the wrong decision, am I willing to wait for the branch to get reviewed and merged to default? Or do I need to do the work to change the bases of my branches or otherwise figure out the git magic to make the work on the non-merged branch available in my future branches?&lt;/li&gt;
&lt;li&gt;Is the work in each branch an appropriate subset whose intent will be clear to reviewers and won’t invite unproductive back-and-forth due to lack of context?&lt;/li&gt;
&lt;li&gt;How do I make sure the same changes don’t show up in the diffs on multiple of my PRs, making them unnecessarily difficult to review?&lt;/li&gt;
&lt;li&gt;Stacked PRs always sound appealing. Should I try making a PR stack? What tool should I use?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Given all this uncertainty and friction, I usually end up ignoring the question and just staying heads-down in the code. It certainly feels more productive, at least until I actually need to get my work reviewed and merged.&lt;/p&gt;
&lt;iframe src=&quot;https://www.youtube-nocookie.com/embed/DhJtNNhCNLM&quot; title=&quot;YouTube video&quot; loading=&quot;lazy&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;I’ve only been using GitButler for a few days now, but it seems to address all these issues very effectively.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GitButler uses virtual branches, so multiple git branches can be applied to your working tree at once. Creating new branches is extremely easy and doesn’t require shifting existing work around.&lt;/li&gt;
&lt;li&gt;While shifting work around isn’t required, GitButler makes it incredibly easy to do when needed. Files, hunks, and commits can all be dragged around. Commit on the wrong branch? Drag it to a different branch. Realize that one branch should actually depend on another? Drag the branch to where it should go in the stack, or to a new column to break it out of a stack.&lt;/li&gt;
&lt;li&gt;Since you can have as many virtual branches applied to your working tree as you want, there’s no longer an issue with needing to wait for a PR to be reviewed and merged in order to have easy access to those changes while working on a new branch.&lt;/li&gt;
&lt;li&gt;See #2.&lt;/li&gt;
&lt;li&gt;Since there isn’t a need to worry about making sure changes from one unmerged branch are available within another, accidentally having the same changes appear in review diffs on multiple branches is unlikely.&lt;/li&gt;
&lt;li&gt;Creating PR stacks in GitButler is super easy, and GitButler takes care of keeping an updated list of the PRs in the stack in each PR’s description, and rebasing your branches as needed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;My only concern is that once the novelty has worn off I’ll fail to keep using GitButler and end up with large branches again. We’ll see how it goes!&lt;/p&gt;
</content:encoded></item><item><title>Iterating on a PR Extraction Workflow</title><link>https://nathanarthur.com/writing/iterating-on-a-pr-extraction-workflow</link><guid isPermaLink="true">https://nathanarthur.com/writing/iterating-on-a-pr-extraction-workflow</guid><pubDate>Tue, 06 Jan 2026 16:46:24 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/iterating-on-a-pr-extraction-workflow/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Since I had good success with &lt;a href=&quot;https://nathanarthur.com/writing/fast-pr-feedback-review-with-saved&quot;&gt;my PR feedback review workflow&lt;/a&gt;, I’ve been trying to create a similar workflow for extracting PRs from an existing large branch.&lt;/p&gt;
&lt;p&gt;So far my success has been mixed.&lt;/p&gt;
&lt;p&gt;Given my ADHD, switching tasks can be difficult. This often means I end up putting a lot of work on a single git branch and then facing a difficult decision: go through the painful process of breaking it into multiple smaller PRs, or send it as is and hope it doesn’t cause too much pain to whomever ends up reviewing it.&lt;/p&gt;
&lt;p&gt;The saved AI prompt I’ve been playing with seems to help quite a bit. Here’s what it tries to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ensure the target branch is up-to-date with its base&lt;/li&gt;
&lt;li&gt;Diff the target branch against its base&lt;/li&gt;
&lt;li&gt;Identify a subset of the changes on the target branch that could be extracted to a new branch&lt;/li&gt;
&lt;li&gt;Explain the selected changes to the user and ask for permission to proceed&lt;/li&gt;
&lt;li&gt;Extract and commit the identified changes to the new branch&lt;/li&gt;
&lt;li&gt;Ask permission to create a PR from the new branch&lt;/li&gt;
&lt;li&gt;Create a draft PR from the new branch&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When this workflow works, it feels really good.&lt;/p&gt;
&lt;p&gt;I’ve had two main challenges so far:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ensuring the workflow is followed consistently and the AI doesn’t start skipping steps&lt;/li&gt;
&lt;li&gt;Dialing in how well the AI identifies an ideal subset of changes to extract&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On issue two, the problem I’ve been dealing with is that the AI focuses on extracting the smallest possible change, even to the point of suggesting things like adding a single unused import statement to a file.&lt;/p&gt;
&lt;p&gt;The set of changes to be extracted need to balance several factors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is small, but not too small.&lt;/li&gt;
&lt;li&gt;Passes CI checks.&lt;/li&gt;
&lt;li&gt;Has self-evident benefit to the codebase, or is obviously a precursor to planned changes. This is to reduce the likelihood of the resulting PR being questioned by reviewers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Currently I’ve been iterating on this prompt as a markdown file that I then paste into Warp. I’m thinking I may switch to trying to set it up as one or more custom skills and/or subagents in Claude Code. This should have a few benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Claude Code skills and subagents may be easier to share.&lt;/li&gt;
&lt;li&gt;Subagents may allow me to better control context and tool usage, hopefully improving workflow consistency.&lt;/li&gt;
&lt;li&gt;I’m hoping that at some point I won’t need to explicitly invoke the workflow, but simply ask Claude Code to extract a PR and it will infer which skills and subagents to use.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Things I’ve come across related to all this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=RFKCzGlAU6Q&quot;&gt;How Claude Code Works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=-uW5-TaVXu4&quot;&gt;Most devs don’t understand how context windows work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=gP5iZ6DCrUI&quot;&gt;Turn Claude Code into a Multi‑Agent Personal Assistant (Claude Agent SDK Tutorial)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.claude.com/docs/en/skills&quot;&gt;Claude Code Docs: Agent Skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.claude.com/docs/en/sub-agents&quot;&gt;Claude Code Docs: Subagents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.claude.com/docs/en/discover-plugins&quot;&gt;Claude Code Docs: Discover and install prebuilt plugins through marketplaces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.promptlayer.com/&quot;&gt;PromptLayer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Fast PR Feedback Review with Saved Prompts</title><link>https://nathanarthur.com/writing/fast-pr-feedback-review-with-saved</link><guid isPermaLink="true">https://nathanarthur.com/writing/fast-pr-feedback-review-with-saved</guid><pubDate>Tue, 30 Dec 2025 18:21:36 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/fast-pr-feedback-review-with-saved/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’ve been continuing to work to improve at using AI for programming. There are a couple of issues that I find I repeatedly run into now:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;My usage of AI can easily result in very large pull requests that are difficult to review.&lt;/li&gt;
&lt;li&gt;AI review tools are great, but can result in a large amount of feedback that is then difficult to address.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Over the past few days I think I’ve started to make progress toward solutions for both these problems, starting with the too-much-feedback issue.&lt;/p&gt;
&lt;p&gt;In the past, I’ve felt that I had two options for addressing the occasional avalanche of AI code review feedback:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Address the feedback myself locally, one-by-one, which could be very time intensive even when using AI tools.&lt;/li&gt;
&lt;li&gt;Ask GitHub Copilot coding agent to address all the feedback on the PR in one go, which results in a new potentially large PR against the original PR that I have to review.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After &lt;a href=&quot;https://nathanarthur.com/writing/publishing-my-dotfiles&quot;&gt;publishing my dotfiles&lt;/a&gt;, I found myself creating helper scripts to make it easier for me to address feedback left on my PRs one at a time. And it really started helping speed up the process.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/bin/pr-feedback&quot;&gt;pr-feedback&lt;/a&gt; along with a &lt;code&gt;—limit 1&lt;/code&gt; flag to get just one piece of feedback from the PR&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/bin/pr-comment&quot;&gt;pr-comment&lt;/a&gt; to comment on the feedback if appropriate&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/bin/resolve-feedback&quot;&gt;resolve-feedback&lt;/a&gt; to resolve the feedback once I was done addressing it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I was using these scripts within &lt;a href=&quot;https://www.warp.dev/&quot;&gt;Warp&lt;/a&gt;, so the workflow started to look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use pr-feedback to get the next item of feedback to address&lt;/li&gt;
&lt;li&gt;Ask Warp to address the feedback&lt;/li&gt;
&lt;li&gt;Review what Warp did&lt;/li&gt;
&lt;li&gt;Once satisfied, commit and push the fix&lt;/li&gt;
&lt;li&gt;Use resolve-feedback to mark the feedback as resolved on the PR&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This too, though, started to feel repetitive, since it meant I was starting to spend a good percentage of my time running scripts and coming up with commit messages.&lt;/p&gt;
&lt;p&gt;The solution: &lt;a href=&quot;https://docs.warp.dev/knowledge-and-collaboration/warp-drive/prompts&quot;&gt;Warp saved prompts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ve &lt;a href=&quot;https://gist.github.com/narthur/e6812cba5a963bec1c18bf0ebc472035&quot;&gt;created a prompt&lt;/a&gt; that tells Warp to do most of that stuff above, leaving me to simply review the code and then give Warp the go-ahead once I’m satisfied with the fix. Warp runs the scripts and makes the commits, and the prompt instructs Warp to immediately move to the next piece of feedback once we’re done with the last.&lt;/p&gt;
&lt;p&gt;And reviewing the code is super convenient since Warp has a built-in code review pane that I can keep up next to the terminal window where the workflow is running.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/fast-pr-feedback-review-with-saved/2.webp&quot; alt=&quot;&quot; width=&quot;1456&quot; height=&quot;802&quot; loading=&quot;lazy&quot;&gt;&lt;figcaption&gt;Warp awaiting my input and displaying its code review pane&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;I’ve also asked Warp to number the options it provides for how to proceed. So once I’m ready to move forward, I usually can simply input the number for the appropriate option. Or, if no option quite fits, provide a number with a modification, like:&lt;/p&gt;
&lt;p&gt;“1, and also create a follow-up issue for X.”&lt;/p&gt;
&lt;p&gt;With this in place, addressing AI feedback (or human feedback for that matter) becomes incredibly efficient. &lt;a href=&quot;https://gist.github.com/narthur/e6812cba5a963bec1c18bf0ebc472035&quot;&gt;Here’s the full prompt&lt;/a&gt; if you’re interested in trying it out.&lt;/p&gt;
&lt;p&gt;I’m still working on solving the first issue—taking a large PR and breaking it down for easier human review. I know this isn’t a new problem (and one that I already had before starting to use AI tools) but with the help of AI it’s only become more important for me to figure out.&lt;/p&gt;
</content:encoded></item><item><title>I Can&apos;t Wait for Remix 3</title><link>https://nathanarthur.com/writing/i-cant-wait-for-remix-3</link><guid isPermaLink="true">https://nathanarthur.com/writing/i-cant-wait-for-remix-3</guid><pubDate>Tue, 23 Dec 2025 17:13:44 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/i-cant-wait-for-remix-3/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Lately I’m super intrigued by the approach the Remix team is taking with &lt;a href=&quot;https://remix.run/blog/wake-up-remix&quot;&gt;Remix 3&lt;/a&gt;. I watched both &lt;a href=&quot;https://www.youtube.com/watch?v=iZl0IKj0HHc&quot;&gt;part one&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/watch?v=dZbZgxWlzr8&quot;&gt;part two&lt;/a&gt; of the “Introducing Remix 3” talk they gave a couple of months ago. It looks very promising.&lt;/p&gt;
&lt;p&gt;All the modern front-end frameworks I’ve used take a reactive approach to rendering. When something changes (a component prop, a reactive piece of state, etc), the framework automatically renders the portion of the component tree that could be impacted by that change.&lt;/p&gt;
&lt;p&gt;The obvious advantage of this approach is that you as the developer don’t have to worry about managing this yourself. You just change the state, and your app automatically updates to reflect the new state.&lt;/p&gt;
&lt;p&gt;In practice, however, this can cause some pretty irritating issues.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Render loops. Component A triggers a re-render of component B which does something in its render logic that triggers a re-render of component A, causing potentially a large chunk of your UI to re-render on every tick.&lt;/li&gt;
&lt;li&gt;Unnecessary re-renders. Since in React, for example, state is compared by reference, two things that are the same by value (such as two different objects with the same contents) can cause React to think something has changed when there actually wasn’t a meaningful change.&lt;/li&gt;
&lt;li&gt;Large re-renders. Say you add a React context provider at the top-level of your app to share state across your application to avoid needing to do elaborate prop drilling for state that is used throughout the application. Every time that context changes, everything within that provider re-renders, meaning your entire application for a top-level provider.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a lot of applications, these issues aren’t that bad. But when I have run into them, I’ve found them to be extremely painful to deal with.&lt;/p&gt;
&lt;p&gt;One such application had a site-wide media player, meaning there was state that needed to be accessible throughout the application (global context provider), had many events occurring (playback ticks), and needed to allow components throughout the tree to trigger changes back to the playback context (seeking, play/pause, auto play, etc). I repeatedly found myself dealing with the issues I listed above, and never found a good way to handle this state in React.&lt;/p&gt;
&lt;p&gt;Remix 3 is taking the opposite approach by throwing out automatic re-renders. Instead of the framework automatically re-rendering the application when state changes, a component only re-renders when its &lt;code&gt;this.update()&lt;/code&gt; method is explicitly called.&lt;/p&gt;
&lt;p&gt;This really appeals to me. It means that it’s entirely in my control when my components re-render, and components can remain entirely static by default. And if I decide I actually do want reactivity in part of the application, I can add it in myself only where it makes sense using third-party libraries such as Redux or Zustand.&lt;/p&gt;
&lt;p&gt;There are quite a few other things I’m excited about from watching the Remix 3 talks (focus on leveraging platform-level primitives, composable event handlers, back-end API type safety that looks better than Hono’s). Definitely watch the talks if any of that sounds interesting to you.&lt;/p&gt;
</content:encoded></item><item><title>Publishing My Dotfiles</title><link>https://nathanarthur.com/writing/publishing-my-dotfiles</link><guid isPermaLink="true">https://nathanarthur.com/writing/publishing-my-dotfiles</guid><pubDate>Mon, 15 Dec 2025 17:56:25 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/publishing-my-dotfiles/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;End of last week I finally gave up on using the HP mini PC I’d been using for work since my MacBook Pro started crashing under work loads. So now I’m using the gaming PC my family gifted me for my last birthday. Not necessarily ideal, but still good fun since it’s a beefy machine!&lt;/p&gt;
&lt;p&gt;Thankfully I had previously already switched the PC to running Debian and I’ve been storing my local repositories on an external hard drive, so making the switch hasn’t been too painful. But while I was at it I decided to work toward making it even less painful next time I switch machines.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://github.com/narthur/dotfiles&quot;&gt;my new dotfiles repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ve tinkered around with storing computer configurations on GitHub before. But it never stuck that well, probably because the friction to keeping the repo up-to-date to the point where it was useful when I switched computers was just too great.&lt;/p&gt;
&lt;p&gt;This time I’m taking a different approach (maybe the approach most people who use dotfiles repos have already been using): I’ve initialized my home directory itself as a git repository.&lt;/p&gt;
&lt;p&gt;Doing this made me a bit nervous since I didn’t want to accidentally commit sensitive information. To avoid this I &lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/.gitignore&quot;&gt;git-ignored&lt;/a&gt; everything in my home directory (`*`) and have been only unignoring specific files as I see value in adding them to the repo.&lt;/p&gt;
&lt;p&gt;If you’re into using &lt;a href=&quot;https://www.beeminder.com/&quot;&gt;Beeminder&lt;/a&gt; or are generally interested in quantified self stuff, there are already some fun goodies in the setup:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The main toolbar displays my next due Beeminder goal using `&lt;a href=&quot;http://github.com/pinepeakdigital/buzz&quot;&gt;buzz&lt;/a&gt; next`.&lt;/li&gt;
&lt;li&gt;There’s a &lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/bin/get-work-time&quot;&gt;script&lt;/a&gt; that queries my &lt;a href=&quot;https://activitywatch.net/&quot;&gt;ActivityWatch&lt;/a&gt; data for work time.&lt;/li&gt;
&lt;li&gt;There’s &lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/bin/sync-work-time&quot;&gt;another script&lt;/a&gt; that syncs that data to Beeminder (again using Buzz).&lt;/li&gt;
&lt;li&gt;And it includes &lt;a href=&quot;https://github.com/narthur/dotfiles/blob/main/.config/crontab&quot;&gt;a crontab file&lt;/a&gt; to ensure that sync happens regularly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m quite enjoying using git to track my computer setup. I feel like so far it’s encouraging me to be more thoughtful about how I set up my machine.&lt;/p&gt;
</content:encoded></item><item><title>Digital Employees</title><link>https://nathanarthur.com/writing/digital-employees</link><guid isPermaLink="true">https://nathanarthur.com/writing/digital-employees</guid><description>Or, computers role-playing as human workers</description><pubDate>Mon, 08 Dec 2025 18:33:57 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/digital-employees/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;1024&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’ve been vaguely keeping track of the progress of “digital employees”—AI-powered agentic systems that simulate traditional employees. There are plenty of startups trying to build them.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lindy.ai/&quot;&gt;Lindy&lt;/a&gt;: “Meet your first AI employee”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ai.work/&quot;&gt;ai.work&lt;/a&gt;: “Autonomous AI Workers designed for internal operations teams - IT, HR, Procurement, Legal and beyond.”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.relay.app/&quot;&gt;Relay.app&lt;/a&gt;: “Augment your team with AI teammates that work for you”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.teneo.ai/&quot;&gt;Teneo.ai&lt;/a&gt;: “Join Teneo and our +17,000 AI Agents revolutionizing customer service to fully automate Tier 1 support.”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.11x.ai/&quot;&gt;11x&lt;/a&gt;: “Digital workers, Human results.”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://newo.ai/&quot;&gt;newo.ai&lt;/a&gt;: “Create your own AI Receptionist in just 3 minutes and start earning up to $30,000 more per month per location by ensuring you never miss a customer, even after hours.”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://devin.ai/&quot;&gt;Devin&lt;/a&gt;: “Crush your backlog with your personal AI engineering team.”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://beam.ai/&quot;&gt;Beam&lt;/a&gt;: “Hire Self-Evolving AI Agents to Run Your Operations”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://relevanceai.com/&quot;&gt;Relevance AI&lt;/a&gt;: “Build teams of AI agents that deliver human-quality work”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m currently listening to the second season of &lt;a href=&quot;https://www.shellgame.co/&quot;&gt;the Shell Game podcast&lt;/a&gt;. In the new season Evan Ratliff is doing his best to build and run a startup almost entirely using these digital employees. So far he’s had mixed results, and he and his other human teammate have had to put in a ton of effort adding scaffolding on top of the AI agent tools to get them to behave somewhat productively.&lt;/p&gt;
&lt;p&gt;What really stood out the most was the degree to which his digital employees appeared to be role playing as employees, making up backstories for themselves, fabricating details about the company, and imagining how they spent their weekends. Ratliff finds this charming. I find it off-putting.&lt;/p&gt;
&lt;p&gt;I do find the idea plausible that AI hallucinations aren’t entirely bad. They may be the key to the creativity and imagination AI brings to the table. But a digital employee who fails to draw the line between imagination and reality seems less than useful.&lt;/p&gt;
&lt;p&gt;I don’t know to what degree this conflicts with effective prompt engineering. Is it necessary to tell the AI that it’s a human HR professional with 12 years of experience in the industry in order to coax the best performance out of the model? I hope not.&lt;/p&gt;
&lt;p&gt;I expect these tools will become more and more pervasive as they improve, though I’m less certain whether the hyper personification of some of these tools will persist. Will we prefer our AI agents have human-appearing names and avatars, or would we rather they present as what they are, AI-powered software bots?&lt;/p&gt;
</content:encoded></item><item><title>Choosing a Laptop, Updating Buzz, Etc</title><link>https://nathanarthur.com/writing/choosing-a-laptop-updating-buzz-etc</link><guid isPermaLink="true">https://nathanarthur.com/writing/choosing-a-laptop-updating-buzz-etc</guid><pubDate>Fri, 28 Nov 2025 19:27:15 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/choosing-a-laptop-updating-buzz-etc/1.webp&quot; alt=&quot;&quot; width=&quot;345&quot; height=&quot;345&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Happy Thanksgiving! 🦃&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I’ve been planning to purchase a new development computer for a while now. I could do it now, but I’m still a bit nervous.&lt;/p&gt;
&lt;p&gt;Currently I have three computers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A mini PC running Debian that I use for work.&lt;/li&gt;
&lt;li&gt;An older MacBook Pro that crashes when I use it for heavy work stuff so it’s been relegated to my personal machine.&lt;/li&gt;
&lt;li&gt;A beefy gaming PC that was a gift from my family, also running Debian.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I’m planning to be more mobile in the future, so I need a laptop that I can do work on.&lt;/p&gt;
&lt;p&gt;I’m very tempted to purchase &lt;a href=&quot;https://frame.work/&quot;&gt;a Framework laptop&lt;/a&gt; since I really enjoy doing my work on Linux. And the ability to easily repair and upgrade it is appealing.&lt;/p&gt;
&lt;p&gt;Unfortunately there are good arguments for me to instead purchase another Apple laptop instead.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I understand that the Framework laptop’s build quality is worse than an Apple laptop’s.&lt;/li&gt;
&lt;li&gt;I have plenty of experience using Apple laptops as work machines, so I’m highly confident they’ll do everything I need.&lt;/li&gt;
&lt;li&gt;I already own an external Apple keyboard and magic track pad, and these are my preferred peripherals, plus they’re very portable.&lt;/li&gt;
&lt;li&gt;It’s likely I’d be able to acquire an Apple laptop more cheaply than a Framework laptop, since there’s a lot more availability for used and refurbished Apple laptops than Framework laptops.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So unfortunately it feels like the responsible decision is to purchase an Apple laptop and wait until I have some disposable cash to play with before taking a chance on a Framework laptop.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I’ve been continuing to add features to &lt;a href=&quot;https://github.com/PinePeakDigital/buzz&quot;&gt;buzz&lt;/a&gt;. In the last week:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Added support for piping values into the `buzz add` command.&lt;/li&gt;
&lt;li&gt;Added `—json` and `—datapoints` args for the `buzz view &amp;lt;slug&amp;gt;` command.&lt;/li&gt;
&lt;li&gt;Tried to improve the usefulness of the buzz update-available messages, though I’m not quite happy with them yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;I’ve been continuing to work hard toward migrating from Firestore to Neon for the database. It’s been a bit tricky since I need to keep the Firestore service while adding the Neon service until the migration is completed. I have a migration built but I’m still trying to get to where I’m more confident that it will work on the first go before I pull the trigger.&lt;/p&gt;
</content:encoded></item><item><title>Adding Sentry &amp; Neon to TaskRatchet</title><link>https://nathanarthur.com/writing/adding-sentry-and-neon-to-taskratchet</link><guid isPermaLink="true">https://nathanarthur.com/writing/adding-sentry-and-neon-to-taskratchet</guid><pubDate>Fri, 21 Nov 2025 17:08:34 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/adding-sentry-and-neon-to-taskratchet/1.webp&quot; alt=&quot;Semi-abstract oil painting of organic flowing forms on one side gradually crystallizing into geometric interconnected structures on the other, muted greens and browns giving way to clean slate grays with touches of optimistic teal, thick impasto application with palette knife ridges, texture emphasizing the transformation from fluid to stable&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’ve added &lt;a href=&quot;https://sentry.io/welcome/&quot;&gt;Sentry&lt;/a&gt; to TaskRatchet’s front-end, API, and email worker. It’s already been quite helpful in surfacing errors and reducing the effort needed to fix them.&lt;/p&gt;
&lt;p&gt;I had been thinking that having &lt;a href=&quot;https://www.honeycomb.io/&quot;&gt;Honeycomb&lt;/a&gt; meant I didn’t need something like Sentry. But I now thing that was a mistake. Honeycomb and Sentry serve different purposes. Honeycomb collects a ton of detailed telemetry, making it ideal for debugging complex issues and surfacing trends and correlations over time. Whereas Sentry is great for immediately alerting me when an error occurs, and surfacing all the context around that specific error.&lt;/p&gt;
&lt;p&gt;I’ve just about decided to use &lt;a href=&quot;https://neon.com/&quot;&gt;Neon&lt;/a&gt; for TaskRatchet’s database instead of &lt;a href=&quot;https://developers.cloudflare.com/d1/&quot;&gt;Cloudflare D1&lt;/a&gt;. This has a few advantages:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Since it doesn’t require a worker to connect to it, I can switch databases before moving the API to Cloudflare.&lt;/li&gt;
&lt;li&gt;It should make it quite easy to set up &lt;a href=&quot;https://neon.com/docs/introduction/branching&quot;&gt;feature branch database forks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://neon.com/docs/get-started/why-neon#neon-is-postgres&quot;&gt;It’s just postgres&lt;/a&gt;, which should make it easier to migrate to something else in the future if needed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Making the switch means modeling TaskRatchet’s data relationally and creating a corresponding schema. This is something I didn’t have to do with &lt;a href=&quot;https://firebase.google.com/docs/firestore/&quot;&gt;Firestore&lt;/a&gt;, since Firestore is a no-SQL document store.&lt;/p&gt;
&lt;p&gt;I never had too much trouble with Firestore when it comes to data integrity. I’ve used a thin service wrapper so only my Firestore service and my migrations interact with it directly. And my service layer has evolved to be coded fairly defensively to compensate for the lack of an explicit schema. In practice that means my service functions use &lt;a href=&quot;https://zod.dev/&quot;&gt;Zod&lt;/a&gt; to validate the data coming out of Firestore before returning it to the rest of the application. When something breaks for a user due to corrupt data, I find out based on the errors that Zod throws, and then go into Firestore and manually fix whatever is incorrect or missing.&lt;/p&gt;
&lt;p&gt;I have definitely had issues with Firestore, though. Examples:&lt;/p&gt;
&lt;p&gt;Since it’s a document store, sometimes I have to duplicate data across documents to reduce the number of queries I have to make, like syncing the user’s timezone across every task document for that user. This reduces the number of queries I need to make, but feels really yucky coming from a relational mindset.&lt;/p&gt;
&lt;p&gt;The kinds of queries you can do are sometimes quite limited compared to a traditional database. Google says this is to prevent you from being able to create slow queries. But I’ve found on more than one occasion that what it means in practice is I’m forced to query much more data than I wanted and then filter it application-side, resulting in being charged for potentially hundreds of reads when I only wanted to read a single document.&lt;/p&gt;
&lt;p&gt;Getting the kinds of database backups that are automatic with most database services is not obvious with Firestore. I had to set up my own job to do it. It makes me nervous knowing I rolled my own backup system for the database.&lt;/p&gt;
&lt;p&gt;It’s also bothered me that Firestore is a proprietary system, meaning a fair amount of lock-in. There’s no simple way that I’m aware of to get a dump of a Firestore database that can be easily imported into another database system. Though this may be partly due to my desire to move from Firestore to a relational database, which wouldn’t map cleanly regardless of what no-SQL database I was coming from.&lt;/p&gt;
&lt;p&gt;I think the biggest advantage of document stores comes at the prototyping phase of a product. You don’t have to plan out your schema ahead of time. You can just create some collections of documents and throw data at it. Quick, easy, maybe a bit dirty.&lt;/p&gt;
&lt;p&gt;I feel like this advantage becomes less of a value add once the product is more mature. You already have a good idea of your data structure, so there isn’t so much of a need to have a super flexible “schema.” And you end up having to add layers on top of the document store to give you more of the assurances you’d have gotten out-of-the-box with a relational database—e.g. my usage of Zod to validate data queried from Firestore.&lt;/p&gt;
&lt;p&gt;Additionally, if you want something more like a document store, you can do that with postgres using json fields. In TaskRatchet’s database I intend to do that with an integrations table, which will have a json-type config column. This will give me the benefit of a document store’s flexibility only where I need it—in this case, for integrations so I don’t need to keep expanding and modifying the database’s structure every time I want to add a new integration with a third-party service.&lt;/p&gt;
&lt;p&gt;Anyway, I’m feeling optimistic about the move to Neon. We’ll see how it goes in practice.&lt;/p&gt;
</content:encoded></item><item><title>AI as Slot Machine Programming</title><link>https://nathanarthur.com/writing/ai-as-slot-machine-programming</link><guid isPermaLink="true">https://nathanarthur.com/writing/ai-as-slot-machine-programming</guid><description>Your IDE isn&apos;t a good place to go gambling.</description><pubDate>Fri, 14 Nov 2025 17:32:07 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/ai-as-slot-machine-programming/1.webp&quot; alt=&quot;&amp;quot;Oil painting of a vintage slot machine with its lever pulled, mechanical reels spinning and scattering into chaotic fragments, warm casino lighting contrasting with cool blue shadows, thick impasto brushwork showing metal textures and motion blur, traditional realist style with surreal elements of dissolution.&amp;quot; And forged signature.&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I found &lt;a href=&quot;https://www.understandingai.org/p/ai-ads-are-going-mainstream&quot;&gt;this issue of Understanding AI&lt;/a&gt; quite interesting, especially this paragraph regarding &lt;a href=&quot;https://www.youtube.com/watch?v=Yy6fByUmPuE&quot;&gt;Coca-Cola’s recent AI-generated Christmas commercial&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To combat this [lack of consistency], good ads can take hundreds or thousands of individual generations to produce compelling content — Accetturo called this dynamic “slot-machine pulls.” A high level of human involvement helps to deliver a more consistent vision. But even a large number of generations doesn’t ensure quality — the Coca-Cola ad apparently required more than &lt;a href=&quot;https://www.youtube.com/watch?v=URT_pX74_qA&amp;amp;t=61s&quot;&gt;70,000 video clips&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think pulling the lever on a slot machine is a good analogy for what using AI tools can become when it isn’t working well. And I think it’s a good indicator that you need to stop and change course.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prompt the AI to stop and gather context&lt;/li&gt;
&lt;li&gt;Switch to manually gathering context on your own (e.g. adding log statements)&lt;/li&gt;
&lt;li&gt;Switch to &lt;a href=&quot;https://nathanarthur.com/writing/ai-for-coding-collaborate-or-delegate&quot;&gt;collaboration mode&lt;/a&gt;, asking the AI how to do the thing and then doing it yourself instead of letting the AI execute on its own&lt;/li&gt;
&lt;li&gt;Update instructions files to improve the AI’s baseline performance in the codebase&lt;/li&gt;
&lt;li&gt;Look for ways to simplify or otherwise re-architect the codebase to make it more AI-friendly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Basically, when you find yourself in a situation where you’re just asking the AI to try again and hoping it works better this time, that’s the point you need to switch strategies.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I fixed the TaskRatchet error that I mentioned in my last post. Of course, it would be better if I fix the issues before users complain about them.&lt;/p&gt;
&lt;p&gt;With that in mind, I’ve been working on improving my ability to catch and fix TaskRatchet errors quickly. I already had Honeycomb set up, but my error reporting setup was spotty.&lt;/p&gt;
&lt;p&gt;To solve this, I’ve been working to add Sentry to all parts of TaskRatchet. So far I’ve added it to the web front-end and the API. I’m currently working toward adding it to the email worker.&lt;/p&gt;
&lt;p&gt;I’m hoping that having Sentry up will make future infrastructure changes, such as moving to Cloudflare and switching database solutions, smoother than previous ones have been at times.&lt;/p&gt;
</content:encoded></item><item><title>TaskRatchet Bugs, Cursor 2, &amp; Rails Project Refactoring</title><link>https://nathanarthur.com/writing/taskratchet-bugs-cursor-2-and-rails</link><guid isPermaLink="true">https://nathanarthur.com/writing/taskratchet-bugs-cursor-2-and-rails</guid><pubDate>Fri, 07 Nov 2025 17:56:41 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/taskratchet-bugs-cursor-2-and-rails/1.webp&quot; alt=&quot;Expressionist gouache painting of interconnected pathways and nodes with some connections broken or rerouting, bold gestural marks in slate gray and electric blue with touches of warning orange, heavy textured application showing paint layers, dynamic composition suggesting problem-solving and adaptation, visible brushwork indicating movement and iteration&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’ve been doing my best to fix an issue with TaskRatchet sign-ups where a user can register but then can’t add their payment method. I deployed what I hope will fix the issue but I haven’t gotten confirmation yet from the affected user.&lt;/p&gt;
&lt;p&gt;I’m still kind of in an awkward place when it comes to finding and fixing issues with TaskRatchet. Switching to Clerk for auth has had the effect of basically preventing me from manually testing my code locally. Automated testing is unaffected.&lt;/p&gt;
&lt;p&gt;I’ve been making some headway toward getting past the issue. The front-end is now deployed to Cloudflare, and I have branch previews set up in a way that I’ll be able to point the front-end preview deploys to corresponding back-end staging deploys once those are working.&lt;/p&gt;
&lt;p&gt;The hang-up with that is that I think it’ll be tricky to switch from Render.com to Cloudflare for deploying the back-end, since it’ll also necessitate migrating the database from Firestore to Cloudflare D1 at the same time.&lt;/p&gt;
&lt;p&gt;I think I should probably side-step this for now by getting my local dev server setup working well again.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;https://cursor.com/blog/2-0&quot;&gt;Cursor 2&lt;/a&gt; has me back on the Cursor bandwagon, and so far the changes seem really great. I’m mostly enjoying the agent layout so far. I haven’t tried using multiple parallel agents yet. And I haven’t made use of Cursor’s new built-in browser yet.&lt;/p&gt;
&lt;p&gt;One thing that feels like a big improvement is Cursor’s new planning mode. So now it has Agent (just do stuff), Ask (let’s talk without doing stuff), and Plan (like Ask but it also puts together a planning document and task list). It allows for a flow more like Claude Code, and feels quite natural.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I’m actively experimenting with refactoring a large Ruby on Rails codebase to work better with AI tools. So far that’s meant:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Switching to GitHub Issues + a GitHub Project for issue management and kanban&lt;/li&gt;
&lt;li&gt;Adding and iterating on a copilot instructions file&lt;/li&gt;
&lt;li&gt;Adding new CI checks&lt;/li&gt;
&lt;li&gt;Configuring GitHub Copilot to have access to more MCP servers (e.g. Sentry, &lt;a href=&quot;https://context7.com/&quot;&gt;Context7&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So far that’s all low-hanging fruit. More changes I’m planning to make:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add a &lt;a href=&quot;https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/customize-the-agent-environment&quot;&gt;copilot-setup-steps.yml&lt;/a&gt; file so Copilot has a better immediate setup when it starts a session&lt;/li&gt;
&lt;li&gt;Split the React front-end from the Rails back-end to create better separation and simplify tooling, making the repo a monorepo at the same time&lt;/li&gt;
&lt;li&gt;Pull the mobile app repo into the monorepo&lt;/li&gt;
&lt;li&gt;Add package-level &lt;a href=&quot;https://github.com/openai/agents.md&quot;&gt;AGENTS.md files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Migrate all remaining JavaScript files to TypeScript&lt;/li&gt;
&lt;li&gt;Add &lt;a href=&quot;https://sorbet.org/&quot;&gt;Sorbet&lt;/a&gt; for Ruby type checking&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And then there are changes I’d like to make but am not sure if they will be practical any time soon. The main one in that category is feature branch development previews. It seems with the project’s current architecture there just really isn’t a good way to do that which also wouldn’t cost a lot of money over time. Though once the front-end is split from the back-end I think we could at least get front-end deploy previews.&lt;/p&gt;
</content:encoded></item><item><title>TaskRatchet on Cloudflare, Cursor 2, Etc</title><link>https://nathanarthur.com/writing/taskratchet-on-cloudflare-cursor</link><guid isPermaLink="true">https://nathanarthur.com/writing/taskratchet-on-cloudflare-cursor</guid><pubDate>Fri, 31 Oct 2025 16:49:31 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/taskratchet-on-cloudflare-cursor/1.webp&quot; alt=&quot;&amp;quot;Impressionist gouache painting of ascending steps made of fragmented code snippets and geometric shapes dissolving into mist, thick gestural brushstrokes, cool grays transitioning to warm yellows, visible canvas texture, energetic mark-making suggesting upward progress and transformation.&amp;quot; And a forged signature.&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’m still working toward having TaskRatchet fully deployed to Cloudflare. The front-end is currently deployed to Cloudflare, but the API is still deployed to Render.com. My goal is to have fully-automated dev previews so I can easily manually test my changes. Getting closer, but not there yet.&lt;/p&gt;
&lt;p&gt;The difficult part about where I’m at now is it’s a bit of a chicken-and-egg problem to get the API deployed to Cloudflare. The API uses Firestore, which isn’t immediately compatible with Cloudflare Workers. I plan to switch from Firestore to Cloudflare D1 for the database, but D1 is only accessible via a worker. Which basically means I have to switch deployment target and database at the same time. Which is scary. I’d rather break them into two separate tasks.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;https://cursor.com/blog/2-0&quot;&gt;Cursor 2&lt;/a&gt; has some super interesting new features, including an interface for using agents in parallel and an in-IDE browser. Unfortunately it seems like actually using agents in parallel may require you be on &lt;a href=&quot;https://cursor.com/pricing&quot;&gt;their $200 / month plan&lt;/a&gt;, which seems like a pretty hard sell.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I’ve been having an issue where my USB controller crashes on my Debian machine when I try to run a dev container in vs code. I’m currently working on getting a watchdog service set up to auto-restart the controller when it crashes so I don’t have to hard restart my machine every time.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;You can use Homebrew on Linux. It’s pretty great. I’m currently trying to use it to install Watchman in my dev container, since it seems Facebook no longer provides prebuilt binaries in their GitHub releases. (You could also use it to install &lt;a href=&quot;https://github.com/PinePeakDigital/buzz&quot;&gt;buzz&lt;/a&gt;. 😉)&lt;/p&gt;
</content:encoded></item><item><title>Buzz Updates, Monorepos, &amp; AI Dev Workflows</title><link>https://nathanarthur.com/writing/buzz-updates-monorepos-and-ai-dev</link><guid isPermaLink="true">https://nathanarthur.com/writing/buzz-updates-monorepos-and-ai-dev</guid><description>More commands added to Buzz, using monorepos--correctly this time, and improving how I use Copilot and CodeRabbit together</description><pubDate>Fri, 24 Oct 2025 17:33:09 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/buzz-updates-monorepos-and-ai-dev/1.webp&quot; alt=&quot;Abstract expressionist painting split into two distinct color zones - left half in cool cyan and silver tones, right half in warm coral and bronze tones, circular movements from each side reaching across the boundary and interlocking like gears, layers building where they meet, heavy impasto technique with visible palette knife marks, conveying two systems in constant dialogue and mutual refinement&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;h2 id=&quot;buzz-updates&quot;&gt;Buzz Updates&lt;/h2&gt;
&lt;p&gt;I’ve been continuing to improve &lt;a href=&quot;https://nathanarthur.com/writing/buzz-a-terminal-interface-for-beeminder&quot;&gt;buzz&lt;/a&gt;. You can see the release notes &lt;a href=&quot;https://github.com/PinePeakDigital/buzz/releases&quot;&gt;here&lt;/a&gt;. Highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`buzz view` lets you view some details about any specific goal.&lt;/li&gt;
&lt;li&gt;`buzz review` lets you step through all your goals alphabetically, meant for use when &lt;a href=&quot;https://blog.beeminder.com/calendial/&quot;&gt;calendialing&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;`buzz —version` now shows you what version of buzz you have installed.&lt;/li&gt;
&lt;li&gt;`buzz refresh` now lets you trigger an autodata refresh for a specific goal (requested by &lt;a href=&quot;https://forum.beeminder.com/t/buzz-another-terminal-interface-for-beeminder/12557/3?u=narthur&quot;&gt;Philip Hellyer&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;back-to-monorepos&quot;&gt;Back to Monorepos&lt;/h2&gt;
&lt;p&gt;I’ve moved back to using a monorepo for TaskRatchet. &lt;a href=&quot;https://nathanarthur.com/writing/toward-ai-friendly-software-architecture#monorepos&quot;&gt;As mentioned previously&lt;/a&gt;, I had tried using monorepos with TaskRatchet in the past, but had a poor experience. This time around I took a different approach, creating only a single monorepo for TaskRatchet, and only moving things to it that are directly related to TaskRatchet and are likely to change together or be referenced together while doing development. It’s already feeling much better than last time.&lt;/p&gt;
&lt;h2 id=&quot;copilot--coderabbit-optimizations&quot;&gt;Copilot + CodeRabbit Optimizations&lt;/h2&gt;
&lt;p&gt;I’m continuing to use GitHub Copilot coding agents alongside CodeRabbit, and the combination continues to be surprisingly effective. A few notes on how I’m using these tools together:&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I have the GitHub CLI installed locally. I’ve added an alias to it that runs a script to create new issues and immediately comment on them requesting CodeRabbit’s input.&lt;/p&gt;
&lt;p&gt;The alias: &lt;code&gt;‘!gh-ic “$@”’&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The script, stored as `gh-ic` in my bin:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/bash

# GitHub CLI issue create script
# Usage: gh-ic Issue title without quotes

# Check if title argument is provided
if [ $# -eq 0 ]; then
    echo “Usage: gh-ic Issue title without quotes”
    exit 1
fi

# Get the issue title from all arguments
title=”$*”

# Create the issue with empty body and capture the URL
issue_url=$(gh issue create -b “” -t “$title”)

# Extract issue number from URL (format: https://github.com/owner/repo/issues/123)
issue_number=$(echo “$issue_url” | grep -o ‘[0-9]*$’)

# Add a comment asking CodeRabbit AI to analyze and enhance the issue
gh issue comment “$issue_number” --body “@coderabbitai Please analyze this issue and update the description with implementation details, suggested approach, and any relevant technical considerations.”
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This setup allows me to quickly create new issues like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gh ic The title of the new issue
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which are immediately added to the repo I’m viewing in terminal, and shortly after populated with details by CodeRabbit. I can then further comment on the issue as desired, asking @CodeRabbit to make any desired revisions.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Once I’m happy with the state of an issue, I assign it to Copilot, which will go off and create a PR and eventually request my review.&lt;/p&gt;
&lt;p&gt;When Copilot finishes its first pass, I do the following in this specific order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I manually review the code changes.&lt;/li&gt;
&lt;li&gt;I mark the PR as ready for review, taking it out of draft mode.&lt;/li&gt;
&lt;li&gt;I manually request CodeRabbit review the PR, since CodeRabbit won’t auto-review a PR opened by a bot.&lt;/li&gt;
&lt;li&gt;I go back-and-forth with Copilot and CodeRabbit, asking Copilot to address CodeRabbit’s feedback, and CodeRabbit to make new reviews.&lt;/li&gt;
&lt;li&gt;Once CodeRabbit is happy with the PR (or I’ve dismissed its feedback as out-of-scope), I approve CI jobs to run.&lt;/li&gt;
&lt;li&gt;Once all CI jobs have successfully run, I merge the PR.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The main thing to notice here is that I intentionally go through the CodeRabbit review process before approving CI jobs to run. This is to reduce the cost of this workflow.&lt;/p&gt;
&lt;p&gt;CodeRabbit doesn’t charge per review (as much as I might like them to), so requesting more reviews doesn’t increase your costs.&lt;/p&gt;
&lt;p&gt;However, GitHub does charge per actions minute (once you’ve used the monthly free minutes that come with your plan). And you may be using all your free minutes, since Copilot coding agents run on GitHub Actions, so they use your minutes.&lt;/p&gt;
&lt;p&gt;Because of this, I prefer to get the CodeRabbit feedback out of the way before I approve my jobs to run, since CodeRabbit may find issues that would have failed in CI, potentially saving me from using even more CI minutes by needing to run the CI jobs multiple times.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Copilot consistently has difficulty remembering how to access all feedback left on a PR by CodeRabbit. For this reason, I’ve been adding &lt;a href=&quot;https://github.com/PinePeakDigital/buzz/blob/main/.github/copilot-instructions.md#accessing-coderabbit-pr-feedback&quot;&gt;this section&lt;/a&gt; to Copilot’s instructions file in many of my repos. And then, for good measure, when I ask Copilot to address CodeRabbit’s feedback, I remind it to use these instructions:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;@copilot Please address coderabbit feedback. Your instructions file will tell you how to access coderabbit feedback.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have this set up as a text expansion using &lt;a href=&quot;https://espanso.org/&quot;&gt;espanso&lt;/a&gt;, though I still find myself entering it manually quite frequently since I’ll often be using devices other than my primary work machine.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Speaking of multiple devices, one advantage I find with this workflow is that I’m able to move things along from just about any device I’m at. My work machine is best optimized for it, since I have all my dev tools set up if I need to check out a PR for manual changes or local testing, and I have my GitHub CLI alias configured for quickly adding new issues.&lt;/p&gt;
&lt;p&gt;But I can be nearly as productive on my laptop, tablet, and even phone. On mobile devices I use the GitHub app to create new issues, ask CodeRabbit for issue revisions, and go through the PR review process described above. And on my laptop I can do the same on github.com.&lt;/p&gt;
</content:encoded></item><item><title>Buzz: A Terminal Interface for Beeminder</title><link>https://nathanarthur.com/writing/buzz-a-terminal-interface-for-beeminder</link><guid isPermaLink="true">https://nathanarthur.com/writing/buzz-a-terminal-interface-for-beeminder</guid><pubDate>Fri, 17 Oct 2025 17:19:59 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/buzz-a-terminal-interface-for-beeminder/1.webp&quot; alt=&quot;&amp;quot;Simple painterly illustration of a grid of colored squares (red, orange, blue, green) on a dark background with subtle terminal text elements, abstract geometric, clean composition, oil painting texture, limited palette.&amp;quot; And a forged signature.&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’m still conducting my experiment with using my terminal as much as I can, though that’s become terminal plus GitHub.com since my GitHub workflow still works best in a browser, unfortunately.&lt;/p&gt;
&lt;p&gt;As I’ve been spending much of my time in the terminal, one gap I noticed was that I didn’t have a way to interact with &lt;a href=&quot;https://beeminder.com/&quot;&gt;Beeminder&lt;/a&gt; in the terminal.&lt;/p&gt;
&lt;p&gt;(If somehow you’re reading this and don’t know what Beeminder is, it’s a fantastic service that lets you set monetary stakes on making ongoing progress toward your goals.)&lt;/p&gt;
&lt;p&gt;Other terminal interfaces for Beeminder exist, but none of them were exactly what I was hoping for. So I decided to build my own.&lt;/p&gt;
&lt;p&gt;I had previously built a custom Beeminder dashboard for the browser–you can use it yourself at &lt;a href=&quot;https://bm.taskratchet.com/&quot;&gt;bm.taskratchet.com&lt;/a&gt;. I really enjoy having the tight grid of color-coded goal cells. It’s very information dense and works well for my brain. So I decided to build the same thing as a TUI.&lt;/p&gt;
&lt;p&gt;It seems that the best TUI libraries are all written in Go. I don’t know how to write Go, but that proved to be not a problem at all. I used GitHub Copilot coding agent tasks to build the whole thing, and the experience was really fantastic. Copilot brought a lot of polish and attention to detail to the project that I may not have had time for if I had written it on my own.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/buzz-a-terminal-interface-for-beeminder/2.webp&quot; alt=&quot;&quot; width=&quot;952&quot; height=&quot;484&quot; loading=&quot;lazy&quot;&gt;&lt;figcaption&gt;The Buzz goal grid&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The TUI portion of the tool is pretty simple. When you first run &lt;code&gt;buzz&lt;/code&gt; (assuming you’ve already authed) it displays a grid of your goals, color-coded by buffer–red for due today, orange for due tomorrow, etc. You can scroll to see all your goals if they don’t fit in your terminal. And you can use your arrow keys to highlight one of the cells.&lt;/p&gt;
&lt;p&gt;Once the cell is highlighted, you can press enter to open the detail view for this goal. It shows some details about the goal and lets you enter a data point if you’d like.&lt;/p&gt;
&lt;p&gt;The detail view is functional, but I rarely use it, since I’ve found a slightly different workflow to be much more efficient. I open the grid of goals by using &lt;code&gt;buzz&lt;/code&gt; without arguments, and then I also open a separate terminal pane where I actually interact with the goals, with commands such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;buzz today&lt;/code&gt; to get a list of all the goals needing data today (also useful for copying to a notes app for a handy checklist)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;buzz next&lt;/code&gt; to see just the next due goal&lt;/li&gt;
&lt;li&gt;&lt;code&gt;buzz add the_slug 1 and an optional comment&lt;/code&gt; to add data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This hybrid approach has proven super efficient and enjoyable for me.&lt;/p&gt;
&lt;p&gt;So far I’m quite happy with the tool as is. There are some fun features that my web dashboard had that this doesn’t, but at least for now I’m not planning to introduce them unless I start missing them (or other people request them).&lt;/p&gt;
&lt;p&gt;It’s also super easy to install. My preferred method is using &lt;a href=&quot;https://github.com/marcosnils/bin&quot;&gt;bin&lt;/a&gt; since I already enjoy using bin and it makes it very simple to update buzz. But you can also install it using &lt;a href=&quot;https://brew.sh/&quot;&gt;Homebrew&lt;/a&gt;, which is probably an easier option for most Mac users.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/narthur/buzz&quot;&gt;Here’s the repo&lt;/a&gt;. Give it a go and let me know what you think, or just create a PR or an issue on GitHub.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Disclosure: AI didn’t write any of this, but I did use Claude to get feedback on my writing.&lt;/p&gt;
</content:encoded></item><item><title>Terminal-First Dev &amp; a Few Interesting Links</title><link>https://nathanarthur.com/writing/terminal-first-dev-and-a-few-interesting</link><guid isPermaLink="true">https://nathanarthur.com/writing/terminal-first-dev-and-a-few-interesting</guid><pubDate>Fri, 03 Oct 2025 17:16:58 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/terminal-first-dev-and-a-few-interesting/1.webp&quot; alt=&quot;Abstract painterly illustration representing command-line workflow, flowing streams of text and code transforming into organized structures, dark background with luminous green and blue terminal colors, expressionistic brushwork, sense of movement and efficiency, contemporary digital art style&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;h2 id=&quot;terminal-first-development&quot;&gt;Terminal-First Development&lt;/h2&gt;
&lt;p&gt;I’ve been challenging myself recently to see how much of my work I can do from a terminal rather than in a browser or an IDE.&lt;/p&gt;
&lt;p&gt;The reason I started thinking about this was because I’ve been getting more comfortable using GitHub’s coding agent to execute tasks, and the workflow is really nice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a GitHub issue&lt;/li&gt;
&lt;li&gt;Capture any info in the issue about the task&lt;/li&gt;
&lt;li&gt;Comment on the issue asking CodeRabbit for input&lt;/li&gt;
&lt;li&gt;If new issues should be created based on the issue, comment on the existing issue asking CodeRabbit to create the new issues&lt;/li&gt;
&lt;li&gt;Once the issue is ready for execution, assign the issue to Copilot&lt;/li&gt;
&lt;li&gt;Review the changes in Copilot’s PR&lt;/li&gt;
&lt;li&gt;Request a review from CodeRabbit on Copilot’s PR&lt;/li&gt;
&lt;li&gt;Optionally reply to CodeRabbit’s review comments asking it to create new follow-up GitHub issues&lt;/li&gt;
&lt;li&gt;Optionally comment on the PR asking Copilot to address feedback&lt;/li&gt;
&lt;li&gt;Merge the PR&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve been making a surprising amount of progress with TaskRatchet this way. And it struck me that nothing here requires a browser—GitHub’s CLI lets you do everything on that list (with a couple of annoying exceptions—assigning an issue to Copilot and viewing CodeRabbit’s inline code comments).&lt;/p&gt;
&lt;p&gt;So for the past couple of days I’ve been seeing how much I could get done while avoiding the browser and even the IDE most of the time. And it turns out to be quite a bit.&lt;/p&gt;
&lt;h2 id=&quot;adapting-my-terminal&quot;&gt;Adapting My Terminal&lt;/h2&gt;
&lt;p&gt;What follows may be a sort of random collection of things I’ve done to my setup as a part of this experiment.&lt;/p&gt;
&lt;p&gt;I added a shell script and corresponding saved AI prompt in Warp to have Warp AI scaffold out and complete issues which are then submitted to GitHub using the GitHub CLI.&lt;/p&gt;
&lt;p&gt;I installed Navi for searching through command-line cheatsheets and &lt;a href=&quot;https://github.com/narthur/cheats&quot;&gt;created a repo&lt;/a&gt; to begin creating my own cheat files.&lt;/p&gt;
&lt;p&gt;I installed the Perplexity plugin for &lt;a href=&quot;https://github.com/simonw/llm&quot;&gt;llm&lt;/a&gt; and created a bash function to let me use `perplexity` to quickly jump into a web-backed chat without needing to open the browser.&lt;/p&gt;
&lt;p&gt;I installed TaskWarrior and BugWarrior to let me sync GitHub issues and PRs with a terminal-based task list.&lt;/p&gt;
&lt;p&gt;I can view and edit files directly in Warp using nano or &lt;a href=&quot;https://docs.warp.dev/code/code-editor&quot;&gt;Warp’s editor features&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I installed &lt;a href=&quot;https://github.com/sharkdp/fd?tab=readme-ov-file&quot;&gt;fd&lt;/a&gt; and &lt;a href=&quot;https://github.com/BurntSushi/ripgrep/tree/master&quot;&gt;ripgrep&lt;/a&gt; for easier file searching.&lt;/p&gt;
&lt;p&gt;I’m using &lt;a href=&quot;https://github.com/yorukot/superfile&quot;&gt;Superfile&lt;/a&gt; for an in-terminal file manager.&lt;/p&gt;
&lt;p&gt;I’ve installed &lt;a href=&quot;https://github.com/jarun/ddgr&quot;&gt;ddgr&lt;/a&gt; to let me search the web using DuckDuckGo from the terminal.&lt;/p&gt;
&lt;h2 id=&quot;benefits&quot;&gt;Benefits?&lt;/h2&gt;
&lt;p&gt;So far I’ve only mentioned this experiment to two people (one being my brother) and both had the same response—why? Here they are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To find out if I could&lt;/li&gt;
&lt;li&gt;To get better at using the terminal and terminal-based tools&lt;/li&gt;
&lt;li&gt;To move more of my processes into a place where it’s more natural to request the assistance of AI, and for AI to tie multiple tools and sources of information together&lt;/li&gt;
&lt;li&gt;To explore how I could automate and streamline my processes and workflows&lt;/li&gt;
&lt;li&gt;To explore whether terminal-based workflows could be less distracting and more ADHD-friendly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll see how the experiment goes.&lt;/p&gt;
&lt;h2 id=&quot;link-roundup&quot;&gt;Link Roundup&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://taskratchet.com/&quot;&gt;TaskRatchet&lt;/a&gt; has a new competitor—&lt;a href=&quot;https://mastt.app/&quot;&gt;Mastt&lt;/a&gt;. (ht &lt;a href=&quot;https://agifriday.substack.com/&quot;&gt;Daniel Reeves&lt;/a&gt;) It appears they’re building an iOS app. I’ll be interested to see if they’re able to stay in the app store long-term, given the experiences I’ve had with Apple’s internal reviews of TaskRatchet.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cari.institute/&quot;&gt;Cari&lt;/a&gt; is a super interesting site featuring collections of images illustrating many different consumer product styles.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://walkscape.app/&quot;&gt;WalkScape&lt;/a&gt; is a gamified walking app currently in closed beta.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Surfing Your Motivation</title><link>https://nathanarthur.com/writing/surfing-your-motivation</link><guid isPermaLink="true">https://nathanarthur.com/writing/surfing-your-motivation</guid><pubDate>Thu, 25 Sep 2025 17:11:32 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/surfing-your-motivation/1.webp&quot; alt=&quot;Painterly abstract illustration showing flowing rivers of different colors and textures representing various mental states, some smooth and harmonious, others turbulent or stagnant, with swirling brushstrokes in warm and cool tones, impressionistic style&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;This great question on the Beeminder forum has me thinking about different phases of motivation:&lt;/p&gt;
&lt;p&gt;Thread: &lt;a href=&quot;https://forum.beeminder.com/t/looking-for-tips-to-replenish-motivation/12538&quot;&gt;Looking for tips to replenish motivation.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My thoughts on the topic are probably significantly impacted by my own particular flavor of ADHD. That said, these are some of the phases of motivation I experience, in no particular order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hyperfocus&lt;/li&gt;
&lt;li&gt;Repulsion&lt;/li&gt;
&lt;li&gt;Flow&lt;/li&gt;
&lt;li&gt;Annoyance&lt;/li&gt;
&lt;li&gt;Sustainable tending&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;hyperfocus&quot;&gt;Hyperfocus&lt;/h2&gt;
&lt;p&gt;I experience hyperfocus as a kind of acute obsession. When I’m in this mode I may engage for hours without regard to other priorities. I may postpone tending to my basic needs and resent the time they manage to steal.&lt;/p&gt;
&lt;p&gt;For me hyperfocus is not about productivity. I may or may not be effective while hyperfocusing. Often I may be productive for a while but continue pushing for hours after all enjoyment or productivity is long gone.&lt;/p&gt;
&lt;p&gt;Hyperfocus is just as likely to be triggered by interest as it is by anxiety. Frequently I find myself hyperfocusing on one thing when another thing is a source of urgency or stress. Sometimes this might be explained by a desire for escape, while at other times it’s due to an irrational fixation on completing task A so that I will be freed to address task B, even though task B isn’t actually blocked by task A.&lt;/p&gt;
&lt;h2 id=&quot;repulsion&quot;&gt;Repulsion&lt;/h2&gt;
&lt;p&gt;I think of this as the opposite of hyperfocus. Like hyperfocus, it can be triggered by anxiety around the object, or it may be due to a lack of mental resources without any particular emotional valence. So I don’t mean to imply disgust by the choice of the word.&lt;/p&gt;
&lt;p&gt;Rather I chose the word “repulsion” because of the similarity of the experience to that of trying to push the matching poles of two magnets together, that immaterial yet still physical resistance. When I’m in this mode, I find my mind resists even thinking about the thing. I quite literally find myself “blanking out” when I try to engage with the thing.&lt;/p&gt;
&lt;h2 id=&quot;flow&quot;&gt;Flow&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Flow_(psychology)&quot;&gt;Flow&lt;/a&gt; is a term used aside from ADHD to describe the state of being fully engaged with a task. It results from an appropriate combination of skill and challenge that avoids both boredom and frustration.&lt;/p&gt;
&lt;p&gt;I find that, when I need to get into flow with a project, I often need to choose something easy or superficially interesting about the project first, even if that aspect of the project won’t result in meaningful progress on its own. However, by starting with these smaller tasks, I’m able to incrementally load the project into my mind, until the actually valuable parts catch my interest and I ease into productive engagement.&lt;/p&gt;
&lt;p&gt;This is different from hyperfocus in that I’m choosing what I’m engaging with, whereas with hyperfocus I’m held captive apart from any calm intention. Also, if I’m doing this well, I’m able to maintain a healthy level of engagement without the downsides inherent in the obsession I experience with hyperfocus.&lt;/p&gt;
&lt;h2 id=&quot;annoyance&quot;&gt;Annoyance&lt;/h2&gt;
&lt;p&gt;I experience annoyance when I’ve been committed, either by myself or some external circumstance, too aggressively to something that I’m not ready to engage with at that level. That may be due to lack of mental resources, misalignment of priorities, or the object being the perceived source of some kind of stress.&lt;/p&gt;
&lt;p&gt;I’m a big fan of self-commitment devices (e.g. &lt;a href=&quot;https://beeminder.com/&quot;&gt;Beeminder&lt;/a&gt;), but I have to be careful to not over-commit myself when I’m enthusiastic about a thing. The consequence is often that later, once the frustration has reached a tipping point, I tear down the systems and precommitments I had made previously.&lt;/p&gt;
&lt;h2 id=&quot;sustainable-tending&quot;&gt;Sustainable Tending&lt;/h2&gt;
&lt;p&gt;This is the state I try to navigate into when there’s a priority I want to attend to over a long period of time while avoiding annoyance. It’s the result of implementing appropriate systems and precommitments that won’t result in frustration when my conscious priorities, interests, and mental resources change. It’s a balancing act, finding measures that will encourage ongoing progress while remaining resilient to changing circumstances.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I find that much of my progress in managing my ADHD has been in learning to recognize these states and then surf them in a way that minimizes the harms and maximizes the likelihood that I’ll end up in more manageable states for more of the time.&lt;/p&gt;
&lt;p&gt;This also means letting go of the idea that I should or can control what state I’m currently in. I can’t, and if I try I only push myself further toward anxiety and burnout. They’re within my influence, but not my control.&lt;/p&gt;
</content:encoded></item><item><title>Spec-Driven Dev, TUIs, Etc</title><link>https://nathanarthur.com/writing/spec-driven-dev-tuis-etc</link><guid isPermaLink="true">https://nathanarthur.com/writing/spec-driven-dev-tuis-etc</guid><pubDate>Thu, 18 Sep 2025 17:15:55 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/spec-driven-dev-tuis-etc/1.webp&quot; alt=&quot;Pointillist painting showing a large, complex pattern gradually resolving into smaller, distinct elements. Each dot represents a small, manageable task. The viewer&apos;s eye naturally follows the flow from overwhelming complexity to organized simplicity.&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;h2 id=&quot;spec-driven-development&quot;&gt;Spec-Driven Development&lt;/h2&gt;
&lt;p&gt;We’re currently experimenting with adding a task planning phase to our process. We’ve moved to using Trello for our current primary client. I’ve created a template Trello card with checklists to help structure our planning:&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Planning&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Init specification document&lt;/li&gt;
&lt;li&gt;Braindump (15m)&lt;/li&gt;
&lt;li&gt;Technical exploration (30m)&lt;/li&gt;
&lt;li&gt;Define user stories (10m)&lt;/li&gt;
&lt;li&gt;Punt capture (10m)&lt;/li&gt;
&lt;li&gt;Define scope and exclusions (10m)&lt;/li&gt;
&lt;li&gt;Draft PR breakdown, more PRs better (10m)&lt;/li&gt;
&lt;li&gt;Request async peer review&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Plan Review&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rate each PR size as S/M/L&lt;/li&gt;
&lt;li&gt;Can any planned PRs be split further?&lt;/li&gt;
&lt;li&gt;What’s our riskiest assumption?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;One thing we’re frequently poor at is keeping our pull requests small. This issue was the motivator for trying a planning step.&lt;/p&gt;
&lt;p&gt;The times in parentheses are only suggestions. We’ve been using them as a starting point for time blocking. So we set a timer for the task and then assess whether we have more to do on that task when the timer is up.&lt;/p&gt;
&lt;p&gt;Currently we’re using a private HedgeDoc instance for storing the specification documents for capturing this planning, though we may consider storing them as markdown files within the relevant repo itself, like `plans/0001_my_new_feature.md` or something.&lt;/p&gt;
&lt;p&gt;Relatedly, I’ve been continuing to experiment with using &lt;a href=&quot;https://github.com/github/spec-kit/tree/main&quot;&gt;GitHub Spec Kit&lt;/a&gt; with TaskRatchet API. It seems like a really promising approach to add more scaffolding around using AI for programming. I haven’t gotten through a full iteration using the framework yet. I also understand that different AI models perform different with the framework, so may take some experimentation to get the best results.&lt;/p&gt;
&lt;h2 id=&quot;terminal-tools&quot;&gt;Terminal Tools&lt;/h2&gt;
&lt;p&gt;I’ve been installing and learning more terminal tools lately. Namely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://upterm.dev/&quot;&gt;upterm&lt;/a&gt; for session sharing&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zellij.dev/&quot;&gt;zellij&lt;/a&gt; for an upterm-friendly multiplexer&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://podman.io/&quot;&gt;podman&lt;/a&gt; for an alternative to docker&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arxanas/git-branchless&quot;&gt;git-branchless&lt;/a&gt; to improve git&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ajeetdsouza/zoxide&quot;&gt;zoxide&lt;/a&gt; for a more-efficient cd command&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/darrenburns/posting&quot;&gt;posting&lt;/a&gt; as an alternative to postman&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yorukot/superfile&quot;&gt;superfile&lt;/a&gt; for a terminal-based file manager&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/antonmedv/countdown&quot;&gt;countdown&lt;/a&gt; for bare-bones mob programming tracking (e.g. `countdown 10m &amp;amp;&amp;amp; say “Next”`)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/marcosnils/bin&quot;&gt;bin&lt;/a&gt; for managing github-hosted binary installation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many of these are listed in &lt;a href=&quot;https://github.com/rothgar/awesome-tuis&quot;&gt;awesome-tuis&lt;/a&gt;, and I plan to explore more of the tools listed there soon.&lt;/p&gt;
&lt;h2 id=&quot;link-roundup&quot;&gt;Link Roundup&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://mob.sh/&quot;&gt;mob.sh&lt;/a&gt; is a terminal tool for mob programming that handles &lt;a href=&quot;https://www.remotemobprogramming.org/#git-handover&quot;&gt;git handovers&lt;/a&gt; under the hood. It’s a different approach to mob programming than I’m used to, but something I might like to try at some point.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.remotemobprogramming.org/&quot;&gt;Remote Mob Programming&lt;/a&gt; is a page describing one approach to mob programming.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.innoq.com/en/articles/2023/03/typist-wechsel-dich-remote-edition-code-uebergabe-mit-dem-mob-tool/&quot;&gt;Round-robin coding&lt;/a&gt; is a blog post on using mob.sh with mob programming.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Hju0H3NHxVI&quot;&gt;This video&lt;/a&gt; is all about how &lt;a href=&quot;https://github.com/PWhiddy&quot;&gt;Peter Whidden&lt;/a&gt; created a GPU-optimized interactive ecosystem simulation called Mote as something half-way between a sandbox game and a tool for researchers.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Link Roundup + TaskRatchet API Update</title><link>https://nathanarthur.com/writing/link-roundup-taskratchet-api-update</link><guid isPermaLink="true">https://nathanarthur.com/writing/link-roundup-taskratchet-api-update</guid><pubDate>Thu, 11 Sep 2025 16:54:23 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/link-roundup-taskratchet-api-update/1.webp&quot; alt=&quot;Abstract painting of data streams flowing from cloudy, chaotic forms into clean, organized geometric structures, impressionist style with blues and greens&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’ve been continuing to work on sunsetting TaskRatchet’s public API v1. I’ll be going ahead and turning off v1 tomorrow, September 12.&lt;/p&gt;
&lt;p&gt;I’ve been making sure that all our systems use API v2, and working out any bugs with that usage.&lt;/p&gt;
&lt;p&gt;I’ve also been working on switching from Express to Hono in API v2 as the underlying API framework. This will allow me to more easily deploy to Cloudflare instead of Render.com, and it has a nice plugin for generating an OpenAPI spec file that will allow me to generate documentation from the API.&lt;/p&gt;
&lt;p&gt;Having the API deployed to Cloudflare will allow me to set up multiple instances of the API for staging vs production, which should make things easier to manually test before shipping.&lt;/p&gt;
&lt;p&gt;I’m thinking I also need to do better at letting users know that they can add a password back to their account after the authentication switch. New users will be prompted to set a password during sign-up, but users that already existed during the switch lost their old password and it isn’t obvious how they can re-add one so they don’t have to use email verification every time they sign in.&lt;/p&gt;
&lt;p&gt;I’m thinking what I’ll do is listen for a Clerk webhook event indicating that a user logged in using email verification. I can then have TaskRatchet send them an email explaining how they can add a password if they wish. I can track whether I’ve already sent this email on their database user and only ever send it once so I don’t spam users who prefer using email verification.&lt;/p&gt;
&lt;p&gt;Once I have all that done my next step will be to switch away from Firestore to Cloudflare D1 for the database. Firestore has worked well, but I think it’s time to move to a structured database, both to reduce costs and to avoid bugs related to inconsistent data in the database.&lt;/p&gt;
&lt;h2 id=&quot;link-roundup&quot;&gt;Link Roundup&lt;/h2&gt;
&lt;h3 id=&quot;artificial-intelligence&quot;&gt;Artificial Intelligence&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.theverge.com/anthropic/767507/anthropic-user-data-consumers-ai-models-training-privacy&quot;&gt;Anthropic’s going to start training their models on chat transcripts&lt;/a&gt;, so maybe make sure to opt out if, like me, you’d rather they not do that.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/CodebuffAI/codebuff&quot;&gt;Codebuff open sourced&lt;/a&gt; some or all (unclear) of Codebuff, or maybe just an agentic framework they developed while building Codebuff. Apparently people are already building new things with it, including &lt;a href=&quot;https://vly.ai/&quot;&gt;vly.ai&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://textideo.com/&quot;&gt;Textideo&lt;/a&gt; is another tool for generating AI videos.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.daytona.io/&quot;&gt;Daytona&lt;/a&gt; is a cloud platform focused specifically on running AI-generated code.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cartesia.ai/&quot;&gt;Cartesia&lt;/a&gt; is another voice AI tool (“platform?”).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jigsawstack.com/&quot;&gt;JigsawStack&lt;/a&gt; lets you use small, specialized AI models tailored to your development stack.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;programming&quot;&gt;Programming&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.verdent.ai/&quot;&gt;Verdent&lt;/a&gt; sent me a cold email about their new agentic coding system. I don’t know if it’s any good, but maybe it is.&lt;/li&gt;
&lt;li&gt;Val Town &lt;a href=&quot;https://blog.val.town/vt-cli&quot;&gt;released a CLI&lt;/a&gt; that can be used to deploy a project from your local machine. Neat! Now I want to know if I could use it to set up GitHub Actions to automatically deploy on merge to main.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.monkeyuser.com/&quot;&gt;MonkeyUser&lt;/a&gt; seems like a great xkcd-like comic focused on programmer humor.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dndkit.com/&quot;&gt;dnd kit&lt;/a&gt; is an npm package for adding drag-and-drop functionality to your React application.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;assorted&quot;&gt;Assorted&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=GKWrSLCqgG4&quot;&gt;Matt D’Avella released a new video on slow productivity&lt;/a&gt;. It resonates.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Fua36HgaZj8&quot;&gt;This video essay&lt;/a&gt; explains how the Sears catalog sidestepped Jim Crow-era racism.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Labor Day Update + Link Roundup</title><link>https://nathanarthur.com/writing/labor-day-update-link-roundup</link><guid isPermaLink="true">https://nathanarthur.com/writing/labor-day-update-link-roundup</guid><pubDate>Tue, 02 Sep 2025 15:54:42 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/labor-day-update-link-roundup/1.webp&quot; alt=&quot;A calm, atmospheric expressionist oil painting featuring a focused mechanic immersed in repairing a colossal, mysterious machine. The composition centers on the machine&apos;s intricate system of interlocking, oversized gears—painted with dynamic, swirling brushstrokes and exaggerated proportions to highlight texture and movement. Dozens of gears, cogs, and wheels dominate the foreground and background, overlapping and layered to create visual complexity. Muted, moody colors and soft, diffused lighting add tranquility, while the mechanic’s figure is partially obscured by the profusion of gears. Style reminiscent of Edvard Munch, wide-shot in an ambiguous workshop setting.&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;My brother is back to working with me now. At this point there are three of us working together on a regular basis.&lt;/p&gt;
&lt;p&gt;Currently most of our time is spent in Ruby on Rails and various TypeScript projects. I’m relatively new to Ruby on Rails, but feeling much more comfortable than I was just a few months ago.&lt;/p&gt;
&lt;p&gt;I’ve been able to start spending more time working on TaskRatchet again, which is feeling great. I deployed a switch to Clerk for TaskRatchet authentication. It allowed me to simplify things a lot behind the scenes, and should also improve user experience quite a bit.&lt;/p&gt;
&lt;p&gt;I was quite nervous around the launch that I would have introduced a bunch of bugs that I missed and we’d only find out about when users ran into them. So far, though, this seems not to be the case. Nicky told me that they haven’t gotten any complaints yet, which I’m thankful for!&lt;/p&gt;
&lt;p&gt;I’m currently focused on getting to the place where we can sunset API v1. Currently that means migrating the cron jobs that are still running on the old API to our new API v2 codebase. I’ve completed the development work to make the switch, though I still would like to think things through a bit more before I pull the trigger.&lt;/p&gt;
&lt;p&gt;I’m currently in-between IDEs, using both Zed and VS Code. Zed for its collaboration capabilities, VS Code for its AI features. The state-of-the-art is changing so fast right now that I don’t feel like I can commit myself fully to any one tool, so I just end up having a lot of different ones installed so I can learn and experiment with them all.&lt;/p&gt;
&lt;p&gt;Yesterday my brother and I went and spent time with some friends for a Labor Day bonfire and horseshoes. It was very relaxing.&lt;/p&gt;
&lt;p&gt;One of the other people that were there is a biology professor at at the local university. Mostly unprompted he and his wife started asking me about AI and how it impacts my job. He told me that he’s been feeding his take-home assignment questions to AI, and its responses have been getting worryingly good. You know things are changing when biology professors start asking you about your development tooling.&lt;/p&gt;
&lt;h4 id=&quot;link-roundup&quot;&gt;Link Roundup&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Danny published &lt;a href=&quot;https://blog.beeminder.com/legolaps&quot;&gt;a post about using LEGOs&lt;/a&gt; to get a workout on a home staircase. Makes me wish my apartment had two stories!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactos.org/&quot;&gt;ReactOS&lt;/a&gt; is a Linux distribution under development that is prioritizing native compatibility with Windows applications and drivers.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.nvidia.com/blog/introducing-nvidia-jetson-thor-the-ultimate-platform-for-physical-ai/&quot;&gt;NVIDIA Jetson Thor&lt;/a&gt; is a mini PC focused on physical AI tasks.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://oxc.rs/&quot;&gt;Oxc&lt;/a&gt; is an ecosystem of JavaScript tools written in Rust to replace things like ESLint and Prettier.&lt;/li&gt;
&lt;li&gt;Google is making waves with its new &lt;a href=&quot;https://blog.google/intl/en-mena/product-updates/explore-get-answers/nano-banana-image-editing-in-gemini-just-got-a-major-upgrade/&quot;&gt;Nano Banana&lt;/a&gt; image editing model.&lt;/li&gt;
&lt;li&gt;MacroFactor’s app has &lt;a href=&quot;https://macrofactorapp.com/ai-food-logging/&quot;&gt;AI-powered food logging&lt;/a&gt;, and &lt;a href=&quot;https://forum.beeminder.com/t/how-are-we-not-talking-about-macrofactor-more-often/12228&quot;&gt;according to the Beeminder community&lt;/a&gt; it’s worth a look.&lt;/li&gt;
&lt;li&gt;GitHub Actions &lt;a href=&quot;https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows&quot;&gt;supports reusable workflows&lt;/a&gt;, which again came in handy recently when I was refactoring a CI setup in a client repository.&lt;/li&gt;
&lt;li&gt;I’ve been tentatively learning Godot, and &lt;a href=&quot;https://docs.godotengine.org/en/stable/getting_started/introduction/godot_design_philosophy.html&quot;&gt;they have a design philosophy document&lt;/a&gt;. Neat.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Are LLMs Conscious?</title><link>https://nathanarthur.com/writing/are-llms-conscious</link><guid isPermaLink="true">https://nathanarthur.com/writing/are-llms-conscious</guid><pubDate>Tue, 26 Aug 2025 17:46:10 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/are-llms-conscious/1.webp&quot; alt=&quot;A vibrant expressionist oil painting depicting a futuristic robot standing amidst a sunlit wildflower meadow, its metallic body reflecting waves of intense color. The robot’s posture and glowing LED eyes convey awe and tranquility, as it gently touches blooming flowers, surrounded by swirling brushstrokes and bold colors that illustrate a deeply moving, subjective sense of wonder and beauty. Inspired by Edvard Munch and Wassily Kandinsky, with dramatic lighting and a dreamlike atmosphere.&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;So far I’ve been staunchly agnostic on AI consciousness. My reasoning:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I define consciousness as subjective experience.&lt;/li&gt;
&lt;li&gt;By definition, subjective experience cannot be measured except by the subject.&lt;/li&gt;
&lt;li&gt;I assume naturalism to be true. I don’t believe souls or divine intervention or cosmic non-material magic are required for beings to be conscious.&lt;/li&gt;
&lt;li&gt;Emergence is as good a theory of the origin of consciousness as any other, though probably unprovable due to 1 and 2.&lt;/li&gt;
&lt;li&gt;Therefore, it isn’t out of the question that an LLM might have some sort of consciousness, though impossible to prove either way.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Given those opinions, I haven’t found any arguments I’ve heard in either direction to be compelling.&lt;/p&gt;
&lt;p&gt;That recently changed. &lt;a href=&quot;https://agifriday.substack.com/p/searle?publication_id=4048552&amp;amp;post_id=171095861&amp;amp;isFreemail=true&amp;amp;r=5ffp5g&amp;amp;triedRedirect=true&quot;&gt;From Daniel Reeves’ AGI Friday newsletter&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[T]here’s one thing about the implementation of LLMs that conceivably precludes consciousness: the static-ness of the weights and how LLMs can’t (currently) continuously improve.&lt;/p&gt;
&lt;p&gt;Imagine taking a human, showing them some text, and asking them to predict the next fragment of the next word. As soon as they utter it, you add it to the text, reset their brain to the exact state it was in before they saw the text, and repeat.&lt;/p&gt;
&lt;p&gt;It’s a little mind-bending (in more ways than one) but it’s kind of reducing the human to a single moment of consciousness. Does that still count as conscious?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This argument makes sense to me. Any consciousness an LLM may have is limited to the degree that the system preserves “mind state” between tokens generated.&lt;/p&gt;
&lt;p&gt;I’m not certain, however, that current LLM architectures don’t preserve such state. Here’s an excerpt from &lt;a href=&quot;https://www.perplexity.ai/search/do-current-llms-reset-between-YtDY_N_ITomE8_c0bxWOhA&quot;&gt;the response to a question I asked Perplexity&lt;/a&gt; while trying to think about this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Current LLMs are autoregressive: they generate each output token one at a time, with each new token conditioned on all prior tokens in the same response. The model keeps the &lt;strong&gt;intermediate state&lt;/strong&gt; (such as key/value caches from previous tokens) for the duration of a single response, so state is actively preserved and extended between output tokens generated in one query.&lt;/p&gt;
&lt;p&gt;During token generation, the neural network maintains internal matrices and caches (especially attention key/value caches) that contain information about all tokens generated so far in the response.&lt;/p&gt;
&lt;p&gt;These caches allow the model to rapidly attend to prior tokens without recomputing everything from scratch for each new token.&lt;/p&gt;
&lt;p&gt;This state is only preserved for the &lt;strong&gt;current generation event&lt;/strong&gt;. Once the response is finished, the state is discarded; for APIs, every new prompt starts a fresh generation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I’m afraid this stuff starts getting too complicated for me fairly quickly, but here are a few links (again taken from Perplexity’s response) that looked relevant:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.seangoedecke.com/how-llms-work/&quot;&gt;How LLMs work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/html/2412.15431v1&quot;&gt;Time Will Tell: Timing Side Channels via Output Token Count in Large Language Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.nvidia.com/blog/mastering-llm-techniques-inference-optimization/&quot;&gt;Mastering LLM Techniques: Inference Optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arize.com/blog/memory-and-state-in-llm-applications/&quot;&gt;Memory and State in LLM Applications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So that leaves me fairly near where I started—I don’t believe it’s likely that LLMs are conscious, but I also don’t believe that the possibility they have some form of subjective experience, however limited, should be confidently ruled out.&lt;/p&gt;
&lt;h2 id=&quot;podman&quot;&gt;Podman&lt;/h2&gt;
&lt;p&gt;I’ve been experimenting with switching from Docker to Podman. I believe it’s supposed to be a drop-in replacement. Getting Docker to work consistently on my Linux machine has been some trouble, so I’m hoping Podman will be better. I haven’t done much with it, though it did seem easier to set it up to store images on an external hard drive.&lt;/p&gt;
&lt;h2 id=&quot;development-containers&quot;&gt;Development Containers&lt;/h2&gt;
&lt;p&gt;On containers, I’ve been trying out using development containers with VS Code. A developer friend recommended that I give them a look. Adding a development container configuration to your repository and enabling the development containers extension for VS Code allows you to work on your project in VS Code as if you were using your local machine as host even though under the hood everything is happening inside the development container.&lt;/p&gt;
&lt;h2 id=&quot;github-copilot-coding-agent&quot;&gt;GitHub Copilot Coding Agent&lt;/h2&gt;
&lt;p&gt;I’ve also been trying out &lt;a href=&quot;https://github.blog/news-insights/product-news/agents-panel-launch-copilot-coding-agent-tasks-anywhere-on-github/&quot;&gt;GitHub’s new agent tasks&lt;/a&gt;. Actually the main reason I finally got around to trying out development containers was because I hoped that GitHub Copilot would be smart enough to automatically use the committed container configuration when it spun up an environment to execute a task. Alas, it isn’t.&lt;/p&gt;
&lt;p&gt;Copilot agent tasks are still quite interesting, though. It does basically the opposite of what CodeRabbit does—it modifies the codebase according to your task description and then prompts you to review its PR. You can leave feedback for it on the PR and it will spin up a new coding session to address the feedback and update the PR.&lt;/p&gt;
&lt;p&gt;It seems quite promising as a workflow. Being able to open up several repositories, initiate tasks on all of them, and then let Copilot take its best stab on all the assigned tasks simultaneously feels really efficient. Though so far it’s still required some back-and-forth with Copilot before anything ready for merge is produced.&lt;/p&gt;
&lt;p&gt;I think some of that can be solved by &lt;a href=&quot;https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/customize-the-agent-environment&quot;&gt;adding a Copilot setup steps CI workflow&lt;/a&gt; in the repo where Copilot will be working. That’s the current method for adding setup that’s run before each session, instead of using development containers like I first guessed. That way you can add any dev tooling, install dependencies, etc, before Copilot gets started so it doesn’t have to keep backtracking to do those things on its own.&lt;/p&gt;
</content:encoded></item><item><title>AI for Code Review: CodeRabbit</title><link>https://nathanarthur.com/writing/ai-for-code-review-coderabbit</link><guid isPermaLink="true">https://nathanarthur.com/writing/ai-for-code-review-coderabbit</guid><pubDate>Tue, 19 Aug 2025 16:55:02 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/ai-for-code-review-coderabbit/1.webp&quot; alt=&quot;An impressionist painting of a cybernetic rabbit, inspired by the style of Claude Monet. The rabbit features subtle metallic elements, glowing circuitry, and a futuristic appearance, set in a serene, softly colored landscape reminiscent of Monet’s garden scenes, with delicate brush strokes and a dreamy, light-filled atmosphere.&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;A cybernetic rabbit (and a forged signature)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Most of the focus on AI in software development is on AI writing the code. Most of what I’ve written in this newsletter has been focused on that. And there are no shortage of products building these features.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://codebuff.com/referrals/ref-6d348d54-80f1-4155-903b-2cc6c57dd12f&quot;&gt;CodeBuff&lt;/a&gt; (referral link)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://app.warp.dev/referral/ME5ELJ&quot;&gt;Warp&lt;/a&gt; (referral link)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.anthropic.com/en/docs/claude-code/overview&quot;&gt;Claude Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cursor.com/&quot;&gt;Cursor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/features/copilot&quot;&gt;GitHub Copilot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bolt.new/&quot;&gt;bolt.new&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And dozens more.&lt;/p&gt;
&lt;p&gt;But the AI tool that’s done the most to consistently increase the quality of my work isn’t any of these. It’s &lt;a href=&quot;https://www.coderabbit.ai/&quot;&gt;CodeRabbit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;(Apologies for this post sounding salesy. CodeRabbit isn’t paying me anything, I promise.)&lt;/p&gt;
&lt;p&gt;CodeRabbit is a GitHub application that watches for commits to pull requests. When it sees changes, it spins up, analyses the changes, adds a summary of the changes to the PR, and makes review suggestions.&lt;/p&gt;
&lt;p&gt;And it’s great at it.&lt;/p&gt;
&lt;p&gt;CodeRabbit isn’t the only option for AI-powered code review. &lt;a href=&quot;https://docs.github.com/en/copilot/how-tos/use-copilot-agents/request-a-code-review/use-code-review&quot;&gt;GitHub Copilot&lt;/a&gt; has a similar feature. But in my experience its recommendations are limited and less reliable than CodeRabbit’s.&lt;/p&gt;
&lt;p&gt;The feeling I get when I receive a good human review is “Nuts, they got me.” They found the places where I was slacking off, the things that in the back of my mind I knew could be better but hoped no one would notice.&lt;/p&gt;
&lt;p&gt;CodeRabbit gives me that feeling on almost every pull request. And it feels great.&lt;/p&gt;
&lt;p&gt;The closest I’ve gotten to understanding how they’ve managed to make CodeRabbit work so well is &lt;a href=&quot;https://softwareengineeringdaily.com/2025/06/24/coderabbit-and-rag-for-codereview-with-harjot-gill/&quot;&gt;this podcast interview on the Software Engineering Daily podcast&lt;/a&gt; (&lt;a href=&quot;https://softwareengineeringdaily.com/wp-content/uploads/2025/06/SED1844-CodeRabbit.txt&quot;&gt;transcript&lt;/a&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They take advantage of their position in CI and prioritize depth of analysis over speed.&lt;/li&gt;
&lt;li&gt;They gather context using multiple strategies: static analysis, related GitHub or Jira issues, and learnings stored in CodeRabbit from previous user interactions on reviews in the same codebase.&lt;/li&gt;
&lt;li&gt;They spin up a sandbox containing the full codebase for their agents to use while reviewing a PR.&lt;/li&gt;
&lt;li&gt;They allow their agents to use a terminal within the sandbox in order to allow the agent to find any additional context it needs.&lt;/li&gt;
&lt;li&gt;They allow their agents to query the web in order to pull in up-to-date information.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Definitely listen to the full interview if you’re interested in further understanding how they’ve architected the system. It’s fascinating.&lt;/p&gt;
&lt;p&gt;These tools don’t replace no-AI static analysis and CI checks. Having automated code quality checks that are deterministic and precisely defined provides a degree of assurance that it’s hard to imagine getting from an AI-powered tool.&lt;/p&gt;
&lt;p&gt;But CodeRabbit appears to be doing an excellent job of providing much of the value of a traditional human code review—taking the context of the PR along with its knowledge of the codebase at large and any relevant best practices and distilling it into actionable suggestions for the developer.&lt;/p&gt;
&lt;p&gt;My main hangup with CodeRabbit is their pricing model. They charge per assigned GitHub org seat.&lt;/p&gt;
&lt;p&gt;This makes it challenging to use as an independent contractor who works in repositories scattered across multiple GitHub orgs. If I wish to use CodeRabbit on projects for three different clients, I have to coach each client through adding the CodeRabbit app to their GitHub organization (or get admin access to the org and do it myself), and then pay a separate subscription for my seat in each org. I’m unsure if this is mostly CodeRabbit’s fault, or if it’s at least partly due to how GitHub handles repository permissions for third-party applications.&lt;/p&gt;
&lt;p&gt;CodeRabbit gives me a lot of optimism about how much improvement may be possible in existing AI-powered tools. It implies there may be much room to achieve gains by improving the architecture around the models they rely on, even if the models themselves improve only slowly.&lt;/p&gt;
</content:encoded></item><item><title>Toward AI-Friendly Software Architecture</title><link>https://nathanarthur.com/writing/toward-ai-friendly-software-architecture</link><guid isPermaLink="true">https://nathanarthur.com/writing/toward-ai-friendly-software-architecture</guid><pubDate>Mon, 11 Aug 2025 16:22:34 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/toward-ai-friendly-software-architecture/1.webp&quot; alt=&quot;a painting of architecture&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;I’m interested in thinking more about the software architecture decisions that will be influenced by our use of AI coding tools going forward.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Monoliths&lt;/li&gt;
&lt;li&gt;Headless APIs&lt;/li&gt;
&lt;li&gt;Microservices&lt;/li&gt;
&lt;li&gt;Monorepos&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;monoliths&quot;&gt;Monoliths&lt;/h2&gt;
&lt;p&gt;A monolith is a term used to describe a software project where everything is in a single codebase—no effort has been made to split things into multiple, separately-deployed systems. UI, business logic, and data access are all handled by this single codebase.&lt;/p&gt;
&lt;p&gt;My experience has been that monoliths have been generally unpopular for a decade now because they make it harder to support multiple platforms cleanly. If you think you may want some combination of a web app, an iOS app, an Android app, a desktop app, and an Alexa app, you’ll likely want to avoid a monolith. And even if you don’t know you’ll want more than one of that list, why choose an architectural pattern that more-or-less commits you to a single platform?&lt;/p&gt;
&lt;p&gt;I do feel like there’s been a shift back toward monoliths in recent years. One example is the popularity of NextJS. NextJS is a full-stack React platform that has taken over the React ecosystem. You can use it to build a client-only web application, but it’s designed to let you build your full application, back-end and front-end, within a single codebase.&lt;/p&gt;
&lt;p&gt;Add to that React’s recent addition of server components and it starts to look like the JavaScript community has rediscovered monoliths, and they aren’t mad at them.&lt;/p&gt;
&lt;p&gt;Monoliths make sense for use with AI coding tools. Having everything in a single repository makes it much easier for these tools to discover all the context needed to make a change, and makes it more likely that they’ll be able to complete the entire task in a single shot.&lt;/p&gt;
&lt;h2 id=&quot;headless-apis&quot;&gt;Headless APIs&lt;/h2&gt;
&lt;p&gt;Headless APIs are the traditional solution to the issue of monoliths tending to lock you into a single platform.&lt;/p&gt;
&lt;p&gt;Instead of putting everything in a single codebase, you break your project into two distinct pieces: a client which the user interacts with directly, and a backend service that handles everything else—the headless API. The client receives interacts from the user and then translates these interactions into commands to the API service. The API then returns a response, perhaps including new data, which the client displays to the user.&lt;/p&gt;
&lt;p&gt;The big advantage with this architecture is that it lets you create new, entirely separate clients to your heart’s content. You don’t have to worry about needing to refactor your business logic to support your new client, because any previous clients weren’t allowed to interact directly with the business logic previously. So your new client can use the same API as your previous clients without needing much backend change.&lt;/p&gt;
&lt;p&gt;Reality, of course, is rarely ever this clean. New clients do often end up needing changes to the headless API. And once you have multiple clients relying on the same separate API, you need to worry that a change made to the API for one client might break another client in a way that’s hard to detect. We have tools to try to mitigate these problems—OpenAPI specifications, GraphQL endpoints, etc. But they only go so far.&lt;/p&gt;
&lt;p&gt;Headless API architectures seem to be a mixed bag when it comes to their compatibility with AI coding tools. To the extent that they result in a project becoming multiple separate git repositories, they can make it more difficult for AI coding tools to get the access they need to context, and can mean you’ll need to switch between different repos to have your AI tool execute different sub-tasks within a larger task that spans the entire project.&lt;/p&gt;
&lt;p&gt;On the other hand, this pattern can result in having clear contracts between the backend and the client (the aforementioned OpenAPI specifications and GraphQL schemas) which can provide well-structured and extensive sources of context for AI tools to use.&lt;/p&gt;
&lt;h2 id=&quot;microservices&quot;&gt;Microservices&lt;/h2&gt;
&lt;p&gt;If two deployable subsystems are better than one, then wouldn’t 100 be even better? That’s my impression of microservices.&lt;/p&gt;
&lt;p&gt;Unfortunately I don’t have first-hand experience working within a project that uses microservices, so I can’t speak very well to their strengths and weaknesses. I know they were very popular for a period of time, that they may have advantages for systems that need to be extremely scalable and adaptive, and that they come with a potentially intense level of devops complexity. But that’s about all I know.&lt;/p&gt;
&lt;p&gt;How well are they adapted to use with AI coding tools? No idea.&lt;/p&gt;
&lt;h2 id=&quot;monorepos&quot;&gt;Monorepos&lt;/h2&gt;
&lt;p&gt;A monorepo refers to taking multiple separately-deployable codebases and storing them in a single git repository.&lt;/p&gt;
&lt;p&gt;I’ve had both good and bad experiences with monorepos.&lt;/p&gt;
&lt;p&gt;At one point I reorganized my TaskRatchet codebases to use two monorepos: one for the frontend stuff and one for the backend stuff. Doing this turned out to be a mistake. It added a lot of complexity around managing dependencies and handling CI workflows without doing much to improve developer experience.&lt;/p&gt;
&lt;p&gt;I now think that the way to use monorepos is to keep connected codebases together when you’ve decided not to use a monolith. For example, if you have an application that you’ve decided to split into three deployable codebases—a frontend client, a backend API, and an NPM SDK—it makes sense to keep all three within a single monorepo, since these things likely depend on one another and are likely to need to change together semi-frequently.&lt;/p&gt;
&lt;p&gt;This also allows you to get much of the benefit a monolith has for AI coding tools without needing to use a monolith.&lt;/p&gt;
&lt;p&gt;I’m currently continuing to move toward using monorepos, hopefully organized better than they’ve been in the past.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;There are a few other similar decisions I’m interested in thinking through in relation to AI coding tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Object-oriented vs functional programming&lt;/li&gt;
&lt;li&gt;Static vs dynamic typing&lt;/li&gt;
&lt;li&gt;Strong vs weak typing&lt;/li&gt;
&lt;li&gt;Compiled vs interpreted languages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Maybe I’ll do that in a future post.&lt;/p&gt;
</content:encoded></item><item><title>Links: Measuring AI&apos;s Impact on Productivity, GitHub&apos;s New AI Coding Tool, &amp; more</title><link>https://nathanarthur.com/writing/links-measuring-ais-impact-on-productivity</link><guid isPermaLink="true">https://nathanarthur.com/writing/links-measuring-ais-impact-on-productivity</guid><pubDate>Mon, 04 Aug 2025 16:10:35 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/links-measuring-ais-impact-on-productivity/1.webp&quot; alt=&quot;Create a painterly digital artwork in the style of 19th-century Romanticism or Impressionism, depicting an experienced software developer at their workstation surrounded by swirling, abstract forms representing AI—flowing code, glowing neural networks, and ethereal digital assistants; use expressive brushstrokes and a cool palette of blues and purples with warm highlights on the developer to convey contemplation and subtle frustration about AI’s paradoxical slowdown of productivity, while integrating stylized code snippets and open-source symbols to blend timeless human insight with futuristic technology, evoking artists like J.M.W. Turner or Claude Monet with a balance of realism and abstraction.&quot; width=&quot;728&quot; height=&quot;432.25&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/&quot;&gt;Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity&lt;/a&gt;. This study has had me thinking pretty hard about how I use AI coding tools, and how I can be sure I’m not fooling myself into thinking they’re helping when they aren’t. (Cross-posted to &lt;a href=&quot;https://www.lesswrong.com/posts/9eizzh3gtcRvWipq8/measuring-the-impact-of-early-2025-ai-on-experienced-open&quot;&gt;LessWrong&lt;/a&gt;; &lt;a href=&quot;https://arxiv.org/abs/2507.09089&quot;&gt;full paper&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://livestore.dev/&quot;&gt;LiveStore&lt;/a&gt; is an interesting take on reactive local-first data management.&lt;/li&gt;
&lt;li&gt;Harper Reed posted &lt;a href=&quot;https://harper.blog/2025/02/16/my-llm-codegen-workflow-atm/&quot;&gt;his AI coding workflow&lt;/a&gt;, including how he builds his prompts.&lt;/li&gt;
&lt;li&gt;Anthropic posted something loosely similar, detailing &lt;a href=&quot;https://www.anthropic.com/news/how-anthropic-teams-use-claude-code&quot;&gt;how they use Claude Code internally&lt;/a&gt;. (Via &lt;a href=&quot;https://agifriday.substack.com/p/zuck&quot;&gt;AGI Friday&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Christopher Moravec blogged &lt;a href=&quot;https://christophermoravec.com/episode-24-ai-deleted-my-database/&quot;&gt;his take on the oops-AI-deleted-my-prod-DB incident&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;GitHub now has &lt;a href=&quot;https://github.com/features/spark&quot;&gt;their own AI coding website&lt;/a&gt; similar to existing tools like &lt;a href=&quot;https://bolt.new/&quot;&gt;bolt.new&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Mark Zuckerberg is &lt;a href=&quot;https://www.meta.com/superintelligence/&quot;&gt;pitching personal artificial super intelligences&lt;/a&gt;, and also &lt;a href=&quot;https://www.theverge.com/decoder-podcast-with-nilay-patel/716633/ai-talent-war-meta-mark-zuckerberg-openai-nba-all-stars&quot;&gt;aggressively hiring AI researchers&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Philip Pettit spoke with Sean Carroll &lt;a href=&quot;https://www.preposterousuniverse.com/podcast/2025/07/21/322-philip-pettit-on-language-agency-politics-and-freedom/&quot;&gt;on the philosophy of politics and freedom&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Tyler Vigen has a web page giving many examples of &lt;a href=&quot;https://www.tylervigen.com/spurious-correlations&quot;&gt;spurious correlations&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Howtown published a video on &lt;a href=&quot;https://www.youtube.com/watch?v=vm_1XLKtGpI&quot;&gt;how lead exposure impacted people’s IQ and mental health for decades&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;This website has &lt;a href=&quot;https://pixelmoondust.neocities.org/archives/archivedtiles/backgroundsindex&quot;&gt;a large collection of retro tiled backgrounds&lt;/a&gt; when you’re feeling nostalgic for GeoCities design aesthetics.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trytender.app/&quot;&gt;Tender is like Tinder&lt;/a&gt; but just for you and your significant other.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://recorderfilm.com/&quot;&gt;Marion Stokes&lt;/a&gt; secretly recorded and archived television for thirty years.&lt;/li&gt;
&lt;li&gt;The creators of &lt;a href=&quot;https://www.forfeit.app/&quot;&gt;Forfeit&lt;/a&gt; have a new hardcore productivity app, &lt;a href=&quot;https://overlord.app/&quot;&gt;Overlord&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;There’s &lt;a href=&quot;https://www.gltjp.com/en/directory/item/16598/&quot;&gt;a theme park “dedicated to pushing buttons.”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Here’s &lt;a href=&quot;https://aresluna.org/frame-of-preference/&quot;&gt;an interactive history of Mac settings&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;CodeRabbit can &lt;a href=&quot;https://docs.coderabbit.ai/finishing-touches/docstrings/&quot;&gt;generate docstrings&lt;/a&gt; for you.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://llumo.ai/&quot;&gt;LLUMO&lt;/a&gt; is a platform for debugging AI agents.&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>AI for Coding: Collaborate or Delegate?</title><link>https://nathanarthur.com/writing/ai-for-coding-collaborate-or-delegate</link><guid isPermaLink="true">https://nathanarthur.com/writing/ai-for-coding-collaborate-or-delegate</guid><pubDate>Mon, 28 Jul 2025 17:20:36 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/ai-for-coding-collaborate-or-delegate/1.webp&quot; alt=&quot;A moody late-night office scene seen through a large window, featuring a solitary person and a robot intensely reviewing a blueprint under warm, artificial light. The setting is a 1940s American urban environment with stark contrasts of light and deep shadows, capturing the chiaroscuro lighting typical of film noir. The office contains minimalist, period-appropriate furnishings with hints of art deco design. The atmosphere is quiet, tense, and cinematic, emphasizing solitude and introspection. The style blends American Realism with noir’s dramatic, high-contrast shadow play and an underlying sense of mystery and moral ambiguity.&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Recently I’ve found myself asking AI coding tools to help me do the thing myself, rather than asking them to do it for me. For the time being, this approach has several benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI coding tools are expensive—asking them to coach me gives them a lot less room to rack up a large bill while I’m not paying attention.&lt;/li&gt;
&lt;li&gt;AI knows a lot of things I don’t, but not enough that it doesn’t regularly make mistakes I would have caught. Collaborating more directly allows me to catch those issues, while still benefiting from the AI’s breadth of knowledge.&lt;/li&gt;
&lt;li&gt;If I allow the AI to do the thing I don’t know how to do, I don’t learn how to do it—a missed opportunity.&lt;/li&gt;
&lt;li&gt;If I allow the AI to do a lot of work on its own, I don’t thoroughly understand what it did and why, and am in a poorer position to work on that code later on.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think a big reason using AI coding tools for coaching rather than execution currently has so many benefits is simply because these tools aren’t yet reliable enough at loading in all the context they need. The further we get toward these tools being able to do this reliably, the weaker the argument will be for collaboration over delegation.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/ai-for-coding-collaborate-or-delegate/2.webp&quot; alt=&quot;&quot; width=&quot;1165&quot; height=&quot;522&quot; loading=&quot;lazy&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Though, even once we’ve reached the point where AI is reliably able to retrieve all necessary context, there are still reasons to prefer collaboration over delegation. Specifically, if your goals include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Personal learning or skill development&lt;/li&gt;
&lt;li&gt;Deep project knowledge&lt;/li&gt;
&lt;li&gt;Creative control in execution&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notably, those first two goals still may apply even if your relationship to a project is entirely pragmatic. Even if you never intend to work directly inside a project again, having a thorough grasp of the technologies used and the details of the current implementation are important to your ability to make informed decisions around future development directions and priorities.&lt;/p&gt;
&lt;p&gt;Though there we are again—thinking about our future role as developers in terms of &lt;a href=&quot;https://nathanarthur.com/writing/will-ai-make-us-all-managers&quot;&gt;project management instead of individual contribution&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Future Changes to TaskRatchet</title><link>https://nathanarthur.com/writing/future-changes-to-taskratchet</link><guid isPermaLink="true">https://nathanarthur.com/writing/future-changes-to-taskratchet</guid><pubDate>Mon, 21 Jul 2025 17:25:07 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/future-changes-to-taskratchet/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;abstract todo lists&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://taskratchet.com/&quot;&gt;TaskRatchet&lt;/a&gt; is a project I built &lt;a href=&quot;https://blog.beeminder.com/taskratchet/&quot;&gt;back in 2020&lt;/a&gt; and have continued to maintain and develop since, as time allowed. It’s a task management app that allows you to stake real money on completing each task by its associated deadline.&lt;/p&gt;
&lt;p&gt;Recently I drafted this list of technical changes I plan to make to TaskRatchet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove Astro, switch back to just React&lt;/li&gt;
&lt;li&gt;Use Clerk for auth instead of db auth and firebase auth&lt;/li&gt;
&lt;li&gt;Deploy to Cloudflare instead of Render.com&lt;/li&gt;
&lt;li&gt;Spin down API v1&lt;/li&gt;
&lt;li&gt;Set up API v2 to publish an OpenAPI spec&lt;/li&gt;
&lt;li&gt;Switch from one list of tasks to two or three (e.g. Next and Archive)&lt;/li&gt;
&lt;li&gt;Set up Honeycomb on the front-end&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I thought I’d give a bit more context for each here.&lt;/p&gt;
&lt;h2 id=&quot;react-over-astro&quot;&gt;React Over Astro&lt;/h2&gt;
&lt;p&gt;A while back I added &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt; to the web app as a way to slowly transition away from &lt;a href=&quot;https://react.dev/&quot;&gt;React&lt;/a&gt;. My reasoning was that React introduced some unfortunate performance issues, and there were other front-end libraries I now prefer over React, such as &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt; or &lt;a href=&quot;https://svelte.dev/&quot;&gt;Svelte&lt;/a&gt;. Astro would allow &lt;a href=&quot;https://docs.astro.build/en/guides/integrations-guide/#official-integrations&quot;&gt;multiple front-end libraries&lt;/a&gt; to co-exist during a transition.&lt;/p&gt;
&lt;p&gt;I now think this was a mistake.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The main performance issues were due to having two-way infinite scroll in the main tasks list, and I separately want to get rid of that. (Already have partially.) So I think all the performance improvements I need can be made without leaving React.&lt;/li&gt;
&lt;li&gt;Even though I might like other view libraries better, I have the most experience in React.&lt;/li&gt;
&lt;li&gt;AI coding tools are really good at working in React.&lt;/li&gt;
&lt;li&gt;React is better supported by other things I may want to use than are Vue or Svelte.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of this is to say anything negative about Astro. &lt;a href=&quot;https://blog.beeminder.com/astroblog&quot;&gt;I love Astro&lt;/a&gt;. But it wasn’t a good direction to take in this case.&lt;/p&gt;
&lt;h2 id=&quot;use-clerk-for-auth&quot;&gt;Use Clerk for Auth&lt;/h2&gt;
&lt;p&gt;This one’s a bit painful. Currently under the hood I have two authentication strategies which are operating in parallel: our own home-spun database-powered auth, and &lt;a href=&quot;https://firebase.google.com/docs/auth/&quot;&gt;Firebase Auth&lt;/a&gt;. My tentative existing plan was to move everything to Firebase Auth.&lt;/p&gt;
&lt;p&gt;However now I’ve used &lt;a href=&quot;https://clerk.com/&quot;&gt;Clerk&lt;/a&gt; auth on several other side projects and it seems really great. It has React components for login, registration, forgot password flows, etc, so it will allow me to simplify the codebase while improving the user experience around authentication.&lt;/p&gt;
&lt;p&gt;Of course, that means transitioning two systems to a third new system, which is the painful part.&lt;/p&gt;
&lt;h2 id=&quot;switch-from-rendercom-to-cloudflare&quot;&gt;Switch from Render.com to Cloudflare&lt;/h2&gt;
&lt;p&gt;Currently TaskRatchet is deployed to &lt;a href=&quot;https://render.com/&quot;&gt;Render.com&lt;/a&gt;. Render.com has a fantastic developer experience, but it isn’t cheap for someone like me who creates a lot of little projects. So I’m working on learning &lt;a href=&quot;https://www.cloudflare.com/&quot;&gt;Cloudflare&lt;/a&gt; and moving all my projects to it for hosting and compute. It makes sense for TaskRatchet to be a part of that.&lt;/p&gt;
&lt;h2 id=&quot;spin-down-api-v1&quot;&gt;Spin down API v1&lt;/h2&gt;
&lt;p&gt;Currently there are two versions of &lt;a href=&quot;https://docs.taskratchet.com/api-v2.html&quot;&gt;TaskRatchet’s API&lt;/a&gt;, and the web app uses both. I’ve been working intermittently on getting to the place where TaskRatchet only uses v2. Once that happens, I can spin down v1 and simplify our backend.&lt;/p&gt;
&lt;h2 id=&quot;publish-an-openapi-spec&quot;&gt;Publish an OpenAPI spec&lt;/h2&gt;
&lt;p&gt;That’s &lt;a href=&quot;https://www.openapis.org/what-is-openapi&quot;&gt;OpenAPI&lt;/a&gt;, not OpenAI. Having an OpenAPI spec will allow for us to generate public API documentation from our code rather than having keeping the API documented be a separate task from building the API. Also it will allow us and users (if they wish) to use the spec to &lt;a href=&quot;https://heyapi.dev/openapi-ts/get-started&quot;&gt;generate clients&lt;/a&gt; to ease use of the API.&lt;/p&gt;
&lt;h2 id=&quot;split-the-main-task-list&quot;&gt;Split the Main Task List&lt;/h2&gt;
&lt;p&gt;Currently all of a user’s tasks are shown in a single task, including completed and past-due tasks. In the future I hope to split this into multiple lists, both to make the user experience more focused on a user’s relevant tasks and to improve the performance of the web app. Tentatively this means one list for tasks that are due within the last 24 hours and into the future, and a second list for everything else.&lt;/p&gt;
&lt;h2 id=&quot;add-honeycomb-on-the-front-end&quot;&gt;Add Honeycomb on the Front End&lt;/h2&gt;
&lt;p&gt;I already use &lt;a href=&quot;https://www.honeycomb.io/&quot;&gt;Honeycomb&lt;/a&gt; for back-end instrumentation to allow me to see errors and try to track down the causes of problems. I’d like to add Honeycomb to the front-end, too, to increase my visibility into issues which may span the whole stack.&lt;/p&gt;
</content:encoded></item><item><title>Agentic Coding Tool Failure Modes</title><link>https://nathanarthur.com/writing/agentic-coding-tool-failure-modes</link><guid isPermaLink="true">https://nathanarthur.com/writing/agentic-coding-tool-failure-modes</guid><description>When and why do these tools fail? And how can we get better at avoiding these problems?</description><pubDate>Mon, 14 Jul 2025 16:40:22 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/agentic-coding-tool-failure-modes/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;Abstract, minimalist, non-representational impression of AI coding tools breaking down&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;I’ve been using agentic coding tools off-and-on for quite a while now. Mostly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://codebuff.com/referrals/ref-6d348d54-80f1-4155-903b-2cc6c57dd12f&quot;&gt;Codebuff&lt;/a&gt; (referral link)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://app.warp.dev/referral/ME5ELJ&quot;&gt;Warp&lt;/a&gt; (referral link)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.anthropic.com/en/docs/claude-code/overview&quot;&gt;Claude Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/features/copilot&quot;&gt;GitHub Copilot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They definitely have advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I find that I can work with them longer without serious fatigue or when I’m already too fatigued to code without them.&lt;/li&gt;
&lt;li&gt;At their best, they can find solutions that are more straight-forward, elegant, or idiomatic than I would have found on my own.&lt;/li&gt;
&lt;li&gt;They know a little of just about everything, reducing the need for me to do a bunch of research before I can get started on something.&lt;/li&gt;
&lt;li&gt;They can operate as rubber-duck partners for helping you get unstuck when you’ve been looking at a problem for a long time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However they still have drawbacks, and I’d like to document the ones I’ve run into consistently here.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If they don’t have a good idea on how to do something, they will often persist, trying over and over, until they’ve worked themselves into an over-complicated position which may or may not actually solve the problem.&lt;/li&gt;
&lt;li&gt;Depending on the tool, they may not consistently discover the correct context within the repository, resulting in them making similar mistakes or bad assumptions in the same project.&lt;/li&gt;
&lt;li&gt;They tend to be expensive, or they have usage limits that you’re likely to run into quickly if you’re using them seriously.&lt;/li&gt;
&lt;li&gt;Using them extensively can result in having code bases that you largely don’t understand, reducing your ability to work in the codebase yourself or spot issues with future work done by an AI tool.&lt;/li&gt;
&lt;li&gt;They still hallucinate to varying degrees, which can result in incorrect documentation if they’re involved in writing it, or a lot of wasted time spent based on something they told you which is simply wrong.&lt;/li&gt;
&lt;li&gt;They may not work well with the latest tools or tool versions based on when they were trained and the extent to which they have access to up-to-date documentation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I feel confident that these tools will continue to improve, and that these problems will likely be solved over time. However, for the time being, they still exist, and I’d like to learn how to better compensate for these issues.&lt;/p&gt;
&lt;p&gt;Currently I’m fairly cautious about how I use these tools on client work because of these limitations. The better I can get at avoiding these problems, the more I can make use of them in client projects.&lt;/p&gt;
&lt;p&gt;One approach to solving some of these issues is to give the tools access to more and better-quality documentation. This can be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scraping documentation sites and storing the saved documentation in the repository.&lt;/li&gt;
&lt;li&gt;Ensuring the tool has access to MCP services for searching the web or otherwise accessing up-to-date documentation.&lt;/li&gt;
&lt;li&gt;Leveraging tool-specific methods for adding “rules” and other forms of guidance, such as Claude Code’s &lt;a href=&quot;https://www.claudecode.io/tutorials/claude-md-setup&quot;&gt;CLAUDE.md files&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Working with the tool itself to add and update documentation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve found that last option to be the most fraught. There seems to be a lot of variance around how well these tools are able to produce accurate, valuable documentation. And if you aren’t careful, you end up with high-volume low-quality documentation which just confuses both us developers and the tools themselves more.&lt;/p&gt;
&lt;p&gt;I’ve tried a few tools that are designed to produce documentation for a repository, either using AI or more-traditional static analysis, or a combination. I’ve even played around with creating my own such tool. They all seem to have their own drawbacks. Here’s a list, some of which I’ve tried and some I haven’t.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.doxygen.nl/index.html&quot;&gt;https://www.doxygen.nl/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://deepwiki.org/&quot;&gt;https://deepwiki.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.sphinx-doc.org/en/master/usage/quickstart.html&quot;&gt;https://www.sphinx-doc.org/en/master/usage/quickstart.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.swimm.io/&quot;&gt;https://docs.swimm.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://workik.com/ai-powered-code-documentation&quot;&gt;https://workik.com/ai-powered-code-documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ingig/code-narrator&quot;&gt;https://github.com/ingig/code-narrator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://scribe.knuckles.wtf/laravel&quot;&gt;https://scribe.knuckles.wtf/laravel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.docuwriter.ai/&quot;&gt;https://www.docuwriter.ai/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.codegpt.co/docs/tutorial-features/code%5C_documentation&quot;&gt;https://docs.codegpt.co/docs/tutorial-features/code\_documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mintlify.com/docs/guides/claude-code&quot;&gt;https://mintlify.com/docs/guides/claude-code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/connor-john/ai-docs&quot;&gt;https://github.com/connor-john/ai-docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/fynnfluegge/doc-comments-ai&quot;&gt;https://github.com/fynnfluegge/doc-comments-ai&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bito.ai/blog/ai-documentation-generator/&quot;&gt;https://bito.ai/blog/ai-documentation-generator/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the past, Codebuff promised to do this kind of thing iteratively, creating and updating knowledge.md files throughout your codebase as it went. However it’s seemed to become less of an emphasis over time, and the tool doesn’t seem to do this very often. Though with Codebuff’s more-recent customization options, you might be able to configure it to do better.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.codebuff.com/docs/agents&quot;&gt;https://www.codebuff.com/docs/agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.codebuff.com/docs/advanced#configuration&quot;&gt;https://www.codebuff.com/docs/advanced#configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think in the future it would be nice if CI-time tools like &lt;a href=&quot;https://www.coderabbit.ai/&quot;&gt;CodeRabbit&lt;/a&gt; were better at automatically suggesting improvements and new additions to a repo’s documentation based on changes made in each pull request. Perhaps you could get closer by adding &lt;a href=&quot;https://docs.coderabbit.ai/guides/review-instructions&quot;&gt;custom review instructions&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;Currently my biggest complaint with CodeRabbit is that there isn’t a clear way for me to easily use it with client repositories I don’t own. Currently I can get a review on changes to these projects using their VS Code extension, but this is pretty inconvenient since my daily-driver is Zed, not VS Code.&lt;/p&gt;
</content:encoded></item><item><title>The Tools I&apos;m Using</title><link>https://nathanarthur.com/writing/the-tools-im-using</link><guid isPermaLink="true">https://nathanarthur.com/writing/the-tools-im-using</guid><pubDate>Mon, 07 Jul 2025 15:43:43 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/the-tools-im-using/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;“Abstract, modernist, minimalist representation of the concept of digital development work.” Also, a forged signature.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;I thought I’d detail &lt;a href=&quot;https://nathanarthur.com/uses&quot;&gt;my current programming setup&lt;/a&gt;. It’s continuously changing, quite fast, lately. But I think a snapshot is useful.&lt;/p&gt;
&lt;p&gt;Are there areas of my tooling or processes that you’d like more detail on? Let me know, and I may say more in a future post.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fair warning: This post contains affiliate links.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My work machine is currently an &lt;a href=&quot;https://amzn.to/4jOvjuv&quot;&gt;HP Z2 Mini G4 Workstation&lt;/a&gt;, with 32 GB of ram. I run &lt;a href=&quot;https://www.debian.org/&quot;&gt;Debian&lt;/a&gt; Linux with &lt;a href=&quot;https://i3wm.org/&quot;&gt;i3&lt;/a&gt; as my window manager. I have two monitors (&lt;a href=&quot;https://amzn.to/44sVouj&quot;&gt;one&lt;/a&gt;, &lt;a href=&quot;https://amzn.to/3F7F8o1&quot;&gt;two&lt;/a&gt;), an external webcam and mic for meetings, and an &lt;a href=&quot;https://amzn.to/3TYFaCw&quot;&gt;external hard drive&lt;/a&gt; for extra storage.&lt;/p&gt;
&lt;p&gt;I have a manual &lt;a href=&quot;https://amzn.to/4jVgGFF&quot;&gt;standing desk converter&lt;/a&gt; that sits on top of my desk to allow me to work standing or sitting as desired. I have a small dry-erase whiteboard organizer on the desk, too, that I can use to jot down notes as I work.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/the-tools-im-using/2.webp&quot; alt=&quot;&quot; width=&quot;450&quot; height=&quot;450&quot; loading=&quot;lazy&quot;&gt;&lt;figcaption&gt;Not exactly this, but similar.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;My primary IDE is &lt;a href=&quot;https://zed.dev/&quot;&gt;Zed&lt;/a&gt;. I use it specifically because its collaboration features work well on Linux, where I’ve had mixed results using &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VS Code&lt;/a&gt; for collaboration on Linux. I pay for &lt;a href=&quot;https://github.com/features/copilot&quot;&gt;GitHub Copilot&lt;/a&gt; and use my Copilot AI for chat and completions in Zed instead of Zed’s own AI offering.&lt;/p&gt;
&lt;p&gt;I also still have VS Code installed, though. Currently I mainly use it when I want to get a &lt;a href=&quot;https://www.coderabbit.ai/&quot;&gt;CodeRabbit&lt;/a&gt; code review on a repository that I don’t own, and so can’t authorize CodeRabbit to review directly.&lt;/p&gt;
&lt;p&gt;I’m a bit bummed that I can’t make the VS Code-based &lt;a href=&quot;https://cursor.com/en&quot;&gt;Cursor&lt;/a&gt; my daily driver since when I last used it I was so impressed with its AI features.&lt;/p&gt;
&lt;p&gt;Speaking of code review, I use &lt;a href=&quot;https://github.com/features/actions&quot;&gt;GitHub Actions&lt;/a&gt; on basically all my projects to automate running code quality checks. On most projects this includes &lt;a href=&quot;https://vitest.dev/&quot;&gt;Vitest&lt;/a&gt;, &lt;a href=&quot;https://eslint.org/&quot;&gt;ESLint&lt;/a&gt;, &lt;a href=&quot;https://knip.dev/&quot;&gt;Knip&lt;/a&gt;, and &lt;a href=&quot;https://prettier.io/&quot;&gt;Prettier&lt;/a&gt;. I also have Copilot and CodeRabbit configured to automatically add review feedback on any PRs where I have enough permissions to do so.&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&quot;https://app.warp.dev/referral/ME5ELJ&quot;&gt;Warp&lt;/a&gt; for my terminal. It has built-in AI that I use to help me make Linux configuration changes. Recently it’s also added more-robust agentic coding abilities that I’ve been experimenting with recently. Impressed so far. It also lets me store custom rules and prompts I can use with the AI features, and it allows me to share a terminal window when I’m collaborating with someone else on a task.&lt;/p&gt;
&lt;p&gt;The other two terminal-based coding tools I’ve been using recently are &lt;a href=&quot;https://codebuff.com/referrals/ref-6d348d54-80f1-4155-903b-2cc6c57dd12f&quot;&gt;CodeBuff&lt;/a&gt; and &lt;a href=&quot;https://www.anthropic.com/claude-code&quot;&gt;Claude Code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately I’m still limited by costs and/or tool limits on all these tools—Warp, CodeBuff, and Claude Code. These tools are getting better and better, but they aren’t yet to the point where I can let them run wild on client work, which means I’m mostly using them on side projects. And it’s harder to justify blowing $300 in a month on coding tools when the work I’m using them for isn’t directly bring in money.&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt; to capture information related to my work and projects. I use the &lt;a href=&quot;https://obsidian.md/clipper&quot;&gt;Obsidian web clipper&lt;/a&gt; extension in my browser to clip web pages. I use Obsidian plugins to sync my notes to S3-like cloud storage (&lt;a href=&quot;https://github.com/remotely-save/remotely-save&quot;&gt;remotely-save&lt;/a&gt;), and to let me use AI to chat with an individual note (&lt;a href=&quot;https://github.com/logancyang/obsidian-copilot&quot;&gt;obsidian-copilot&lt;/a&gt;). I use daily notes for miscellaneous scratch pads.&lt;/p&gt;
&lt;p&gt;I have one-note-per-task journals I use for tracking my work on tasks. So when I have a new task, I add a new note with the name of the task as the title to an appropriate Tasks folder. Then, inside this note, whenever I work on the task, I add a subheading with the current date, and document what I’m doing within that date’s section. I always add the new section to the top of the note, so the most recent work I’ve done on the task is at the top. This approach helps me get into a task quickly by reminding me of where I was at when I last worked on it, and reduces the burden on my working memory.&lt;/p&gt;
&lt;p&gt;I track my activity in two ways. I have &lt;a href=&quot;https://activitywatch.net/&quot;&gt;ActivityWatch&lt;/a&gt; which automatically collects detailed information about how I’m spending my time. And I have a custom script that keeps track of how much time I’m spending using my work computer, and posts that to a &lt;a href=&quot;https://www.beeminder.com/home&quot;&gt;Beeminder&lt;/a&gt; goal.&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&quot;https://www.beeminder.com/home&quot;&gt;Beeminder&lt;/a&gt; extensively to track and enforce my work goals. I have goals for time spent using my work computer, time spent on specific clients and projects, handling work email, shipping UVIs for &lt;a href=&quot;https://taskratchet.com/&quot;&gt;TaskRatchet&lt;/a&gt;, handling finance tasks, and sending invoices and reports to clients. I try to keep all my Beeminder commitments manageable, and keep most of my work-related deadlines in the late morning or very early afternoon to avoid burnout given my ability to work in the afternoon isn’t consistent.&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&quot;https://slack.com/&quot;&gt;Slack&lt;/a&gt;, &lt;a href=&quot;https://discord.com/&quot;&gt;Discord&lt;/a&gt;, &lt;a href=&quot;https://telegram.org/&quot;&gt;Telegram&lt;/a&gt;, and &lt;a href=&quot;https://www.thunderbird.net/en-US/&quot;&gt;Thunderbird&lt;/a&gt;, all to varying degrees, for work communication. For &lt;a href=&quot;https://taskratchet.com/&quot;&gt;TaskRatchet&lt;/a&gt; we recently switched from &lt;a href=&quot;https://www.freshworks.com/freshdesk/&quot;&gt;FreshDesk&lt;/a&gt; to &lt;a href=&quot;https://www.zoho.com/desk&quot;&gt;Zoho Desk&lt;/a&gt; for handling support emails. I have a custom Slack support bot that we use to ease &lt;a href=&quot;https://taskratchet.com/&quot;&gt;TaskRatchet&lt;/a&gt; support tasks.&lt;/p&gt;
&lt;p&gt;When researching I use &lt;a href=&quot;https://www.perplexity.ai/&quot;&gt;Perplexity&lt;/a&gt; and &lt;a href=&quot;https://duckduckgo.com/&quot;&gt;DuckDuckGo&lt;/a&gt; mainly, resorting to Google only when the other tools fail to find what I need. Though, with &lt;a href=&quot;https://app.warp.dev/referral/ME5ELJ&quot;&gt;Warp&lt;/a&gt; as my terminal and &lt;a href=&quot;https://github.com/features/copilot&quot;&gt;Copilot&lt;/a&gt; in my IDE, many times my questions can be answered without using a browser (&lt;a href=&quot;https://www.chromium.org/chromium-projects/&quot;&gt;Chromium&lt;/a&gt; in my case) at all.&lt;/p&gt;
&lt;p&gt;I’ve found myself using &lt;a href=&quot;https://claude.ai/&quot;&gt;Claude&lt;/a&gt; recently when I need to draft an extensive prompt, e.g. to store as a saved prompt in &lt;a href=&quot;https://app.warp.dev/referral/ME5ELJ&quot;&gt;Warp&lt;/a&gt;. Claude’s side-by-side artifact view for drafting documents is super useful for that.&lt;/p&gt;
&lt;p&gt;I haven’t found AI to be that useful in writing yet. I’ve experimented with different times at using AI to write, but it always feels like it’s breaking the connection between speaker and writer, and personally I don’t like that. For now, I prefer authenticity over polish.&lt;/p&gt;
&lt;p&gt;I have used AI a couple of times to write reports for clients, where it would be reasonable to say a trade-off between authenticity and functionality is perfectly fine. However I didn’t actually find that it saved me any time, since it results in a much longer report that I then have to carefully fact-check and revise. And the improved quality of the final product is arguable.&lt;/p&gt;
&lt;p&gt;I use PayPal for invoicing clients. I use &lt;a href=&quot;https://paypal.com/&quot;&gt;PayPal&lt;/a&gt; and &lt;a href=&quot;https://wise.com/invite/dic/nathanielroberta&quot;&gt;Wise&lt;/a&gt; to pay subcontractors, depending on their preference. I use &lt;a href=&quot;https://ynab.com/referral/?ref=shzpfXLkdN0y4JUk&amp;amp;sponsor_name=Nathan&amp;amp;utm_source=customer_referral&quot;&gt;YNAB&lt;/a&gt; for tracking my business expenses on a day-to-day basis. I use &lt;a href=&quot;https://www.keepertax.com/invite?referrer=Nathan626989&quot;&gt;Keeper Tax&lt;/a&gt; when I’m ready to file my taxes. I use &lt;a href=&quot;https://stripe.com/&quot;&gt;Stripe&lt;/a&gt; as my payment provider for &lt;a href=&quot;https://taskratchet.com/&quot;&gt;TaskRatchet&lt;/a&gt;. I also have a custom dashboard that I use to partially-automate various invoicing and reporting tasks.&lt;/p&gt;
&lt;p&gt;For web hosting, I currently use a mix of &lt;a href=&quot;https://render.com/&quot;&gt;Render.com&lt;/a&gt; and &lt;a href=&quot;https://www.cloudflare.com/&quot;&gt;Cloudflare&lt;/a&gt;, and I’m moving more and more toward Cloudflare. This is mainly because deploying many small projects is expensive with Render.com. Setting aside pricing, Render.com is a magnificent developer experience.&lt;/p&gt;
&lt;p&gt;For time tracking I use a combination of &lt;a href=&quot;https://beeminder.com/&quot;&gt;Beeminder&lt;/a&gt; and a custom in-house time tracker (“Narthbugz”) which runs on top of a self-hosted &lt;a href=&quot;https://baserow.io/&quot;&gt;Baserow&lt;/a&gt; instance.&lt;/p&gt;
</content:encoded></item><item><title>On Writing Publicly</title><link>https://nathanarthur.com/writing/on-writing-publicly</link><guid isPermaLink="true">https://nathanarthur.com/writing/on-writing-publicly</guid><pubDate>Fri, 20 Jun 2025 16:32:31 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/on-writing-publicly/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;“An abstract, minimalist, dark, symbolic representation of thought, uncertainty, and writing.” And a forged signature.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;As you’re probably aware, I started doing this writing privately, just for those who pledged their support on Ko-fi. Then I transitioned to writing a public newsletter with Hiiv, and most recently moved here to Substack.&lt;/p&gt;
&lt;p&gt;My process for writing over that time has been very consistent—I beemind spending a half-hour each week writing, and whatever I have written, I pretty much publish. Not a lot of editing or revising. Mostly stream-of-consciousness.&lt;/p&gt;
&lt;p&gt;When I was in high school and college I prided myself on my writing. It was one of the things I cared a lot about and put a lot of effort into. For a couple of years I started and ran a high school student newspaper. Between high school and college I interned at a magazine. In college I minored in English.&lt;/p&gt;
&lt;p&gt;After college, I went directly into programming, and basically stopped writing entirely. That, some extended messy relationship challenges (in the rear-view mirror now, thankfully), a go-round with anxiety/depression, and a late ADHD diagnosis all added up to losing most of my confidence in my ability to think clearly and communicate effectively.&lt;/p&gt;
&lt;p&gt;Writing on Ko-fi, in private, to literally only those people who were paying real money to say they wanted to support me (most of you are in that group—thank you 💚), allowed myself to dip my toes back into writing in a way that was emotionally manageable.&lt;/p&gt;
&lt;p&gt;Going from that to writing publicly has been interesting.&lt;/p&gt;
&lt;p&gt;On Ko-fi I think I expressed a lot of uncertainty, shared more freely about things I was actively struggling with, my doubts and questions. Some of that went away while I was still writing privately, but I feel like more of that disappeared when I went entirely public.&lt;/p&gt;
&lt;p&gt;I don’t know how I feel about that.&lt;/p&gt;
&lt;p&gt;Some of that is due to me being less anxious about writing again, feeling more comfortable talking with you, and maybe even feeling a bit more confident in life generally.&lt;/p&gt;
&lt;p&gt;But I’m afraid some of it is the exact opposite—feeling anxious to be writing in public, to new people, strangers, who don’t know me. And so I’m inclined to hide, speak more formally, ask fewer questions, make statements as “we” instead of “I.”&lt;/p&gt;
&lt;p&gt;I don’t like that part.&lt;/p&gt;
&lt;p&gt;I feel as if I’m still trying to find my voice. Who am I talking to? What are we talking about? And, more importantly, who am I as the speaker? Why should you listen to me? How should I express myself? What’s worth expressing?&lt;/p&gt;
&lt;p&gt;The other thing that complicates all this is that my motives never have been pure for this writing. I started the &lt;a href=&quot;https://ko-fi.com/narthur&quot;&gt;Ko-fi&lt;/a&gt; because I was struggling financially and was hoping I could build passive income. I’ve switched to writing publicly as a way to expand my reach in a way that will hopefully support my other money-making projects (mainly &lt;a href=&quot;https://pinepeakdigital.com/&quot;&gt;contracting&lt;/a&gt; and &lt;a href=&quot;https://taskratchet.com/&quot;&gt;TaskRatchet&lt;/a&gt;). Heck, I’ve even added links to this very paragraph on the off-chance one of you decides you want to give me money in some way, indirectly or not.&lt;/p&gt;
&lt;p&gt;I think my primary goal remains to write in order to think, in order to understand things better, get things out, in front of people who might have similar questions or ideas.&lt;/p&gt;
&lt;p&gt;I don’t want to sell or convince or position. I want to think and talk with people just like you.&lt;/p&gt;
&lt;p&gt;Maybe that’s why I’ve been enjoying this stream-of-thought format I’ve been using most of the time.&lt;/p&gt;
&lt;p&gt;It does, though, fail when I decide too strictly what I’m going to write about before I start writing. I think I’ve fallen in that trap with the AI After TDD series. It’s an interesting topic, one I want to continue thinking about, exploring. But giving it too much structure has left me feeling like to some degree I’ve been writing just to write—finishing a checklist rather than sharing my thoughts.&lt;/p&gt;
&lt;p&gt;Thank you for being here with me as I figure all this out. Means a lot.&lt;/p&gt;
</content:encoded></item><item><title>AI After TDD, pt. 3: Preserving Risk Management</title><link>https://nathanarthur.com/writing/ai-after-tdd-pt-3-preserving-risk</link><guid isPermaLink="true">https://nathanarthur.com/writing/ai-after-tdd-pt-3-preserving-risk</guid><description>How can we mitigate code risk without writing tests by hand?</description><pubDate>Fri, 13 Jun 2025 17:39:29 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/ai-after-tdd-pt-3-preserving-risk/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;An abstract, minimalist representation of the concept of risk, inspired by intricate systems in which small changes can have unexpected consequences.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;hr&gt;
&lt;p&gt;Previous posts in this series:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://nathanarthur.com/writing/is-test-driven-development-dead&quot;&gt;Is Test-Driven Development Dead?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nathanarthur.com/writing/ai-after-tdd-keeping-test-coverage&quot;&gt;AI After TDD: Keeping Test Coverage High&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;The second benefit I listed in &lt;a href=&quot;https://nathanarthur.com/writing/is-test-driven-development-dead&quot;&gt;part one&lt;/a&gt; was this:&lt;/p&gt;
&lt;p&gt;“This &lt;a href=&quot;https://nathanarthur.com/writing/ai-after-tdd-keeping-test-coverage&quot;&gt;high test coverage&lt;/a&gt; makes changing existing code less risky.”&lt;/p&gt;
&lt;p&gt;How do we preserve this benefit without strict test-driven development?&lt;/p&gt;
&lt;p&gt;A codebase that doesn’t have this property is painful to work with. A small change in one place may result in something, perhaps seemingly unrelated, breaking in another part of the codebase.&lt;/p&gt;
&lt;p&gt;If you think the project you’re working in is this way, you’re likely to try to make as small a change as possible, regardless of whether it improves the quality of the codebase or not, in order to reduce your exposure to these unpredictable regressions. This can result in the codebase becoming more difficult to work with over time, as pragmatic hacks accumulate and refactoring is avoided.&lt;/p&gt;
&lt;p&gt;At its best, test-driven development addressed this issue by creating a large collection of alarms that would trigger as soon as you had caused a regression, regardless of where it was in the codebase. So you could be more aggressive with your code changes without fear that you were creating chaos in parts of the system you had forgotten or didn’t yet understand.&lt;/p&gt;
&lt;p&gt;Much of what I wrote in &lt;a href=&quot;https://nathanarthur.com/writing/ai-after-tdd-keeping-test-coverage&quot;&gt;part two&lt;/a&gt; applies here, too.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Test coverage thresholds&lt;/li&gt;
&lt;li&gt;Automated test generation&lt;/li&gt;
&lt;li&gt;Recording-and-playback tools&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are all likely to preserve some of the risk mitigation we’ve gotten from TDD by simply retaining much of the test coverage we used to have, just in a different way.&lt;/p&gt;
&lt;p&gt;What follows are additional tools and strategies for achieving the same benefit. Fair warning: This is a lot of back-to-the-basics talk.&lt;/p&gt;
&lt;h4 id=&quot;type-systems&quot;&gt;Type Systems&lt;/h4&gt;
&lt;p&gt;Typed languages in effect create a separate layer of tests. If you make a change to the type annotations or inferred types in one part of the system, you are able to receive feedback quickly on whether this change is compatible with many other parts of the system.&lt;/p&gt;
&lt;p&gt;For our purposes, a type system should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Apply throughout the entire codebase, either by inference or explicit annotation.&lt;/li&gt;
&lt;li&gt;Provide rapid feedback (IDE hinting, CLI commands, compile-time errors).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With these two properties, a typed language can go a long way to removing anxiety around changing code.&lt;/p&gt;
&lt;h4 id=&quot;static-analysis&quot;&gt;Static Analysis&lt;/h4&gt;
&lt;p&gt;This overlaps with the use of type systems, but also includes any linting tool that scans your code without running or compiling it to find potential style or logic issues with the code. Linters tend to be less concerned with application functionality and more with code quality, style, and convention. Though they can also hint at things that may be a mistake.&lt;/p&gt;
&lt;h4 id=&quot;version-control&quot;&gt;Version Control&lt;/h4&gt;
&lt;p&gt;Knowing that every change you’ve made is safely stored to be reviewed and perhaps reverted makes a big difference.&lt;/p&gt;
&lt;h4 id=&quot;rapid-rollback&quot;&gt;Rapid Rollback&lt;/h4&gt;
&lt;p&gt;Relatedly, the ability to rapidly roll back a production environment is likely to become more valuable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rollback to any previous state (e.g. deploy or commit) should be as close to one click as possible.&lt;/li&gt;
&lt;li&gt;The process for initiating a rollback should be well-documented to avoid needing to rediscover the process during an active incident.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It might be valuable to schedule a kind of “rollback fire drill” on a regular schedule. This way those who would be responsible for doing the rollback remain familiar with the process, and there’s a regular opportunity to spot opportunities to improve or simplify the process.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I have the uneasy feeling that there’s more to do here, but I have a hard time imagining what. What are other tools and processes that will help us remain nimble without large hand-written test suites? Especially: What tools will we need to invent?&lt;/p&gt;
</content:encoded></item><item><title>AI After TDD: Keeping Test Coverage High</title><link>https://nathanarthur.com/writing/ai-after-tdd-keeping-test-coverage</link><guid isPermaLink="true">https://nathanarthur.com/writing/ai-after-tdd-keeping-test-coverage</guid><description>If we aren&apos;t writing our own tests by hand, how do we ensure test coverage stays high?</description><pubDate>Fri, 06 Jun 2025 16:13:28 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/ai-after-tdd-keeping-test-coverage/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;“An abstract, minimalist painting representing the concept of test coverage. Incorporate a recursive grid structure.” Forged signature as usual.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;hr&gt;
&lt;p&gt;This issue is a follow-up to my last issue. I’d suggest reading it first:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://nathanarthur.com/writing/is-test-driven-development-dead&quot;&gt;Is Test-Driven Development Dead?&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;So. What comes after test-driven development?&lt;/p&gt;
&lt;p&gt;These are the benefits to using test-driven development I listed previously:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Your test coverage naturally remains very high.&lt;/li&gt;
&lt;li&gt;This high test coverage makes changing existing code less risky.&lt;/li&gt;
&lt;li&gt;You’re forced to think through and demonstrate the change in behavior of the code you’re writing before you jump to implementation.&lt;/li&gt;
&lt;li&gt;You’re less likely to get lost in the weeds when solving a complex problem, since TDD allows you to focus on a single, tiny behavior change at a time, and ensures if a previously-implemented behavior breaks, you know immediately.&lt;/li&gt;
&lt;li&gt;Your code is naturally testable, since you’ve been testing everything from the beginning. And, arguably, testable code tends to be well-architected code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;How do we ensure we keep as many of these advantages as possible without using test-driven development?&lt;/p&gt;
&lt;p&gt;This week let’s look at the first advantage.&lt;/p&gt;
&lt;h3 id=&quot;1-your-test-coverage-naturally-remains-very-high&quot;&gt;1. “Your test coverage naturally remains very high.”&lt;/h3&gt;
&lt;p&gt;Let’s assume we don’t want to give up unit testing, but just the human-in-the-loop workflow. If we don’t have a developer writing each test before they make it pass, how do we ensure our test coverage stays high?&lt;/p&gt;
&lt;p&gt;In my experience with AI coding tools, they are inconsistent with writing tests at best. Most of the time they never write them at all. Even when I’ve gone in and added custom rules or prompts, I still find these tools just do the thing and don’t write tests.&lt;/p&gt;
&lt;h4 id=&quot;require-a-test-coverage-threshold&quot;&gt;Require a Test Coverage Threshold&lt;/h4&gt;
&lt;p&gt;The simplest solution might be to rely more heavily on code coverage checks. I’m most familiar with Jest and Vitest, and these tools have built-in ways to check the test coverage of a particular project. Adding a test coverage requirement to CI would be a simple way to prevent code from being committed before sufficient unit tests have been added. And the developer is always free to go ask their AI tool of choice to write the tests for them.&lt;/p&gt;
&lt;p&gt;This comes with some disadvantages.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some pieces of code will be more valuable to test than others.&lt;/li&gt;
&lt;li&gt;Sometimes coverage tools can have a hard time seeing actual test coverage for certain pieces of the code base depending on a project’s architecture.&lt;/li&gt;
&lt;li&gt;Tests written for the sole purpose of increasing test coverage are often of a lower quality than those written in a test-driven style.&lt;/li&gt;
&lt;li&gt;If we’ve decided that tests will always be written after the code it’s testing, we may lose the potential benefit of the tests’ ability to influence our project’s architecture.&lt;/li&gt;
&lt;li&gt;We also may lose the advantage of testing first forcing us to decide ahead of time what the behavior of our code should be.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;automate-requesting-ai-generated-tests&quot;&gt;Automate Requesting AI-Generated Tests&lt;/h4&gt;
&lt;p&gt;Perhaps we add a step to our CI workflows that calls some AI coding tool and requests that it commits new tests to the current PR, perhaps in combination with a test coverage threshold. I’m not convinced that AI coding tools are consistent enough for this to be a better developer experience than working with the tools directly and locally to add tests, but perhaps in the future they will be.&lt;/p&gt;
&lt;h4 id=&quot;use-recording--playback&quot;&gt;Use Recording &amp;amp; Playback&lt;/h4&gt;
&lt;p&gt;I recently ran into a very-early-stage tool called &lt;a href=&quot;https://www.meticulous.ai/&quot;&gt;Meticulous&lt;/a&gt; that I’m very excited to see mature.&lt;/p&gt;
&lt;p&gt;Meticulous watches you as you interact with your application during development, and records the events that were fired during your session, the code paths that were exercised by your interactions, and the responses to any HTTP requests that were made for future playback.&lt;/p&gt;
&lt;p&gt;When you create a PR, Meticulous attempts to identify a set of these sessions that will best exercise the code you’ve changed, and then runs these sessions on a known-good staging environment, and also on your PR preview environment.&lt;/p&gt;
&lt;p&gt;It then compares the resulting behavior of the application between these two environments, and presents any differences to you to approve as a part of your PR review process.&lt;/p&gt;
&lt;p&gt;I really want this to exist.&lt;/p&gt;
&lt;p&gt;If this tool is able to do what they’re promising, it could potentially allow us to continue to have high test coverage without relying on the ability or inclination of our AI tools to write the tests for us.&lt;/p&gt;
&lt;p&gt;Unfortunately it remains to be seen if they’ll be able to deliver. Currently to get any real use out of Meticulous you need to have an on-boarding call with them. My understanding is that this is because they haven’t yet gotten their tool to the level of reliability you’d need without doing manual setup work on their end tailored to your specific project.&lt;/p&gt;
&lt;p&gt;Fingers crossed.&lt;/p&gt;
</content:encoded></item><item><title>Is Test-Driven Development Dead?</title><link>https://nathanarthur.com/writing/is-test-driven-development-dead</link><guid isPermaLink="true">https://nathanarthur.com/writing/is-test-driven-development-dead</guid><pubDate>Fri, 30 May 2025 16:14:37 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/is-test-driven-development-dead/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;“A series of red and green circles inspired by automated software testing tools, slowly degrading from left to right.” Also notice the AI out-right forged a signature.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Or, more precisely, are its days numbered?&lt;/p&gt;
&lt;p&gt;Here I’m defining TDD (test-driven development) as a process by which code is written using the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Write a failing test&lt;/li&gt;
&lt;li&gt;Write just enough code to make the test pass&lt;/li&gt;
&lt;li&gt;Refactor&lt;/li&gt;
&lt;li&gt;GOTO 1&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(And by defining I mean stealing an existing definition.)&lt;/p&gt;
&lt;p&gt;Done well, this process can provide some major advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Your test coverage naturally remains very high.&lt;/li&gt;
&lt;li&gt;This high test coverage makes changing existing code less risky.&lt;/li&gt;
&lt;li&gt;You’re forced to think through and demonstrate the change in behavior of the code you’re writing before you jump to implementation.&lt;/li&gt;
&lt;li&gt;You’re less likely to get lost in the weeds when solving a complex problem, since TDD allows you to focus on a single, tiny behavior change at a time, and ensures if a previously-implemented behavior breaks, you know immediately.&lt;/li&gt;
&lt;li&gt;Your code is naturally testable, since you’ve been testing everything from the beginning. And, arguably, testable code tends to be well-architected code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve been using test-driven development since I first learned programming during a pre-college internship. My manager was an Uncle Bob devotee, and had me go through Uncle Bob’s clean code video course as a part of my training. Later I purchased and read Uncle Bob’s book titled Clean Code.&lt;/p&gt;
&lt;p&gt;I’m no longer a strict adherent to Uncle Bob’s programming philosophy. But I did stick with TDD, and have continued to use it consistently to this day.&lt;/p&gt;
&lt;p&gt;AI coding tools are the first thing that’s caused me to question the future of TDD.&lt;/p&gt;
&lt;p&gt;By our definition, TDD is inherently a human-in-the-loop process. It’s goal is to create the tightest feedback loop possible in coding. Define the smallest possible change in behavior, make the smallest code change possible to verify that change in behavior, and then receive the fastest feedback possible to verify the code change was successful.&lt;/p&gt;
&lt;p&gt;As AI coding tools become more competent, agentic, and aggressive, it increasingly calls into question this strategy.&lt;/p&gt;
&lt;p&gt;If I can ask a robot to fix a bug, add a feature, or build a whole app, why would I instead opt to write a long series of tiny tests and ask the robot to pass each test in turn? That’s a huge sacrifice in potential velocity.&lt;/p&gt;
&lt;p&gt;I don’t yet think that AI will be the end of unit testing—that is, automated software testing, apart from the human-in-the-loop process described above.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’ve had mixed success asking AI coding tools to write tests for me, but it’s plausible they will continue to improve at it.&lt;/li&gt;
&lt;li&gt;Automated test feedback may already be a valuable source of context for AI coding tools.&lt;/li&gt;
&lt;li&gt;There’s been &lt;a href=&quot;https://arxiv.org/html/2405.10849v1&quot;&gt;at least one attempt&lt;/a&gt; to adapt TDD to be used more explicitly by an AI coding system itself. So instead of a human developer following the process, the AI coding tool would follow the process.&lt;/li&gt;
&lt;li&gt;At least at the moment, where AI coding tools are more efficient as collaborators with developers rather than replacements of them, there’s still plenty of value to a developer switching in and out of TDD based on whether the AI coding tool or the developer is currently driving.&lt;/li&gt;
&lt;li&gt;Any given project’s risk profile will have a significant impact on how quickly, if ever, rigorous testing processes can be abandoned.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All that said, it currently seems inevitable to me that test-driven development as we’ve practiced it is on the way out.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;featured-project-beeminder-autodialer&quot;&gt;Featured Project: &lt;a href=&quot;https://autodial.taskratchet.com/&quot;&gt;Beeminder Autodialer&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Maybe a stretch, but you could call &lt;a href=&quot;https://beeminder.com/&quot;&gt;Beeminder&lt;/a&gt; test-driven behavior change. I built the &lt;a href=&quot;https://autodial.taskratchet.com/&quot;&gt;Beeminder Autodialer&lt;/a&gt; (with kind help from the Beeminder folks) to let you automatically dial your goal rates up and down based on your historical data.&lt;/p&gt;
</content:encoded></item><item><title>Ensuring Code Quality in the Age of AI</title><link>https://nathanarthur.com/writing/ensuring-code-quality-in-the-age-of-ai</link><guid isPermaLink="true">https://nathanarthur.com/writing/ensuring-code-quality-in-the-age-of-ai</guid><pubDate>Fri, 23 May 2025 14:10:54 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/ensuring-code-quality-in-the-age-of-ai/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;Unmanaged speed, abstract&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;I’ve been puzzling for a while now on how our strategies for ensuring software quality will need to change as we continue leaning more and more on AI coding tools. If my current experience holds true, the shift to AI for coding tends to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Significantly increase code output per developer&lt;/li&gt;
&lt;li&gt;Decrease developer understanding of code produced&lt;/li&gt;
&lt;li&gt;Introduce more variability in code quality&lt;/li&gt;
&lt;li&gt;Decrease test coverage compared to a reasonably disciplined developer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given that list, you might think I view these AI tools as a net-negative for software quality. That’s probably true at present, but I think the story is more complicated than that.&lt;/p&gt;
&lt;p&gt;My hypothesis:&lt;/p&gt;
&lt;p&gt;Adding AI tools to an existing development workflow is increasingly like installing an incredibly powerful engine in an aging budget car. Exhilarating, but risky, since it was never designed to handle that much power.&lt;/p&gt;
&lt;p&gt;At their core, AI tools add velocity, potentially a lot of it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tab to accept lines, blocks, functions, even whole files.&lt;/li&gt;
&lt;li&gt;Never switch to Google or Stack Overflow when you get stuck—just type a question in your IDE’s sidebar.&lt;/li&gt;
&lt;li&gt;Ask an agent to implement features or execute refactors across entire code bases.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This amount of raw output increasingly strains our existing strategies for ensuring code quality.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Developer craft:&lt;/strong&gt; The less code a developer is manually writing themselves, the less impact their skill level is going to have on the quality of that code. While there are probably developers whose skill level is lower than the average output of AI coding tools, the variability in output quality of these tools makes this difficult to rely on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manual testing:&lt;/strong&gt; Of course we can manually test that the code an AI tool produced works. However, as AI tools become more and more agentic and more and more aggressive in making many edits at a time throughout a code base, the scope of the software that would need to be manually tested increases exponentially. Developers are unlikely to have the patience to do this type of thorough, repetitive, manual review.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unit testing:&lt;/strong&gt; If you can ask an agent to implement an entire feature in one go, you’re unlikely to take a test-first approach. Most agents are inconsistent at best at including new tests in their edits. You can ask them to write tests after the fact, which they’re happy to do. But are you really going to read those tests carefully enough to ensure they accurately ensure your requirements? Probably not.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code review:&lt;/strong&gt; Reviewing another developer’s code was already difficult enough—time consuming, confusing, unlikely to be effective in catching bugs. That’s why so many developers already do the bare minimum to qualify as a review. Increasing the amount of code produced per developer is only likely to increase these problems.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is a class of tools that don’t suffer. It includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Formatters and auto-fixers&lt;/li&gt;
&lt;li&gt;Linters and static analysis&lt;/li&gt;
&lt;li&gt;Strict type systems&lt;/li&gt;
&lt;li&gt;Record-and-playback testing&lt;/li&gt;
&lt;li&gt;Environment monitoring (whether in development, staging, or production)&lt;/li&gt;
&lt;li&gt;Tools that ease and/or automate rollback&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These types of tools have multiple advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They do not require ongoing developer intervention or discipline to maintain efficacy over time.&lt;/li&gt;
&lt;li&gt;They do not require AI tools behave differently or more consistently than they currently do.&lt;/li&gt;
&lt;li&gt;They can be used to provide immediate feedback to AI tooling to immediately increase the quality of AI output.&lt;/li&gt;
&lt;li&gt;They can be integrated in continuous integration and deployment workflows to provide feedback and reduce risk at deploy time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m interested in exploring further how this class of tools can be expanded, improved, or better leveraged to cover the loss of the practices AI seems to threaten.&lt;/p&gt;
&lt;h4 id=&quot;featured-project-later&quot;&gt;Featured Project: &lt;em&gt;&lt;a href=&quot;https://later.nathanarthur.com/&quot;&gt;Later&lt;/a&gt;&lt;/em&gt;&lt;/h4&gt;
&lt;p&gt;Back in the day there was a phone app called “Do It (Later)” that let you write down tasks you wanted to complete and postpone them until tomorrow. This is a super simple web clone of that, also adding some features I always wished the original had. I built it when I was first experimenting with what &lt;em&gt;&lt;a href=&quot;https://codebuff.com/referrals/ref-6d348d54-80f1-4155-903b-2cc6c57dd12f&quot;&gt;Codebuff&lt;/a&gt;&lt;/em&gt; could do (one of the AI coding tools I’ve been loosely referring to).&lt;/p&gt;
</content:encoded></item><item><title>Will AI Make Us All Managers?</title><link>https://nathanarthur.com/writing/will-ai-make-us-all-managers</link><guid isPermaLink="true">https://nathanarthur.com/writing/will-ai-make-us-all-managers</guid><pubDate>Fri, 16 May 2025 17:19:23 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/will-ai-make-us-all-managers/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;“Hierarchy of control. Minimalist, abstract.” Also a forged signature.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Today I watched another video by Theo about how AI has rewired his brain as a developer. A lot of his thoughts resonated with me.&lt;/p&gt;
&lt;p&gt;So it has me thinking: What will it mean to be a developer after the dust has settled and AI has realized its full potential in software development? (Setting aside whether or not it’s reasonable to expect the current upheaval to have an end.)&lt;/p&gt;
&lt;p&gt;One idea I’ve heard a few times now (confusingly, not in the above-linked video; sorry) is that AI in the workplace will in effect force us out of being individual contributors and into something closer to a managerial role, except instead of managing people we’ll be managing AI agents. And so, perhaps counter-intuitively, even as AI might reduce the number of humans required to to accomplish any given business outcome, the classic skills associated with being a manager may become more valuable.&lt;/p&gt;
&lt;p&gt;Examples of skills that might apply just as well to managing a fleet of AI agents as a team of old-fashioned humans:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delegation&lt;/li&gt;
&lt;li&gt;Project &amp;amp; task specification&lt;/li&gt;
&lt;li&gt;Performance feedback&lt;/li&gt;
&lt;li&gt;Translation of business objectives to actionable tasks&lt;/li&gt;
&lt;li&gt;Project management&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m still somewhat skeptical of this prediction. It strikes me as a trend that could just as easily be obsoleted by future AI advancements or changes in how businesses operate to better accommodate AI tools.&lt;/p&gt;
&lt;p&gt;It rhymes with the idea that companies will continue hiring people to specialize in prompt engineering, when it seems more likely to me that this skill will eventually become less valuable over time as AI companies improve their products’ ability to get the user to their desired outcome without needing specialized skill in manipulating a model’s psychology.&lt;/p&gt;
&lt;p&gt;Ways AI tools and products could improve to require less managerial prowess:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rely less on free-form chat inputs and more on structured processes and user interfaces.&lt;/li&gt;
&lt;li&gt;Estimate risk and ambiguity around a given task, and then proactively request clarification before executing.&lt;/li&gt;
&lt;li&gt;Spawn subordinate agents to execute sub-tasks (agentic systems—they already exist).&lt;/li&gt;
&lt;li&gt;Manage and update over time an internal model of business objectives and preferred tasks and processes to achieve them.&lt;/li&gt;
&lt;li&gt;Rely more on fully-specified, automated feedback mechanisms (think: continuous integration practices already ubiquitous in software development).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In short, my current feeling is that AI tools and systems will increasingly manage themselves rather than needing something akin to traditional team management.&lt;/p&gt;
&lt;h4 id=&quot;featured-project-pa11y-ratchet&quot;&gt;Featured Project: &lt;em&gt;&lt;a href=&quot;https://github.com/marketplace/actions/pa11y-ratchet&quot;&gt;Pa11y Ratchet&lt;/a&gt;&lt;/em&gt;&lt;/h4&gt;
&lt;p&gt;Speaking of CI, &lt;em&gt;&lt;a href=&quot;https://github.com/narthur/pa11y-ratchet/graphs/contributors&quot;&gt;a couple of collaborators and I&lt;/a&gt;&lt;/em&gt; have built &lt;em&gt;&lt;a href=&quot;https://github.com/marketplace/actions/pa11y-ratchet&quot;&gt;a GitHub action&lt;/a&gt;&lt;/em&gt; that allows you to ensure a team makes progress on fixing accessibility issues, even if you have a huge existing backlog of problems.&lt;/p&gt;
&lt;p&gt;It does so by comparing the total count of issues between a PR and the branch it’s merging into, and only failing if the number of issues go up.&lt;/p&gt;
&lt;p&gt;I’ve been using it for basically a year at this point, including on client projects, and it’s been working great. &lt;em&gt;&lt;a href=&quot;https://github.com/marketplace/actions/pa11y-ratchet&quot;&gt;Give it a look!&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title>Limiting Fixed-Bid Contract Risk</title><link>https://nathanarthur.com/writing/limiting-fixed-bid-contract-risk</link><guid isPermaLink="true">https://nathanarthur.com/writing/limiting-fixed-bid-contract-risk</guid><pubDate>Fri, 09 May 2025 16:20:11 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/limiting-fixed-bid-contract-risk/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;Squares scaling to infinity, into darkness.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Recently I’ve been thinking more about how I can reduce risk around my fixed bid contracts, ideally to me and the client.&lt;/p&gt;
&lt;p&gt;The primary challenge I’ve faced with fixed bids is that there’s no bound on how long they can take. And this can create significant cash flow issues when a contract inevitably proves to be much harder than expected.&lt;/p&gt;
&lt;p&gt;I include an early cancellation clause in all my contracts which is supposed to handle this issue. It states that either party can cancel the contract at any time, and the client agrees to pay a percentage of the contract’s value based on the number of tasks that were completed before cancellation.&lt;/p&gt;
&lt;p&gt;The problem with this is that I find it extremely difficult to take advantage of, for a few reasons.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I don’t want to disappoint the client by failing to deliver the agreed-upon results.&lt;/li&gt;
&lt;li&gt;If cash flow is struggling, my instinct is to double down and get that final payment after the contract is completed.&lt;/li&gt;
&lt;li&gt;My ADHD means the cost of switching to trying to decide whether to cancel can feel painfully high.&lt;/li&gt;
&lt;li&gt;It never feels like I’m actually any more than a few focused hours away from solving whatever’s currently blocking me.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What this all ends up meaning is that, even though I’ve given myself the option to cancel at any time, in reality I’ll push through contracts regardless of how long over they go or how much financial strain I’m putting myself in.&lt;/p&gt;
&lt;p&gt;Recently I’ve been toying with the idea of having some threshold at which I’m required to reevaluate a contract, say when I’ve hit 2x my original estimate. But the idea hasn’t felt like it would actually reliably solve the problem.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ensuring I’m prompted at the appropriate time (when I hit 2x) feels difficult and brittle, given I have a history of not tracking my time when I’m way over on a task, even though I definitely should be.&lt;/li&gt;
&lt;li&gt;If I solve that and manage to ensure I do the review, I’m likely to be motivated to do it as quickly as possible to get back to the “real work.”&lt;/li&gt;
&lt;li&gt;If I do the review and decide I do need to cancel the contract, it feels like it would be difficult to communicate to the client, it being due to hitting a threshold that’s invisible to the client and a squishy analysis of the value of cancelling the current contract and reassessing the project for a new contract.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think I’ve found a different take on this idea that solves all these issues. Instead of using a multiple of the original estimate as my threshold, I should use a date, a deadline in time. And instead of that deadline triggering a review, it should simply automatically terminate the contract.&lt;/p&gt;
&lt;p&gt;This has quite a few benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It doesn’t require any code changes to my time tracking software to trigger.&lt;/li&gt;
&lt;li&gt;It’s entirely transparent to the client.&lt;/li&gt;
&lt;li&gt;It’s hopefully easier to sell to the client as a way to reduce their risk as much as mine.&lt;/li&gt;
&lt;li&gt;It doesn’t introduce the new uncertainty and friction of needing to decide whether or not to cancel the contract.&lt;/li&gt;
&lt;li&gt;It’s simple to represent as a new clause in future contracts.&lt;/li&gt;
&lt;li&gt;It creates a hard bound on cash flow risk for any given contract.&lt;/li&gt;
&lt;li&gt;It retains compatibility with my existing early cancellation clause.&lt;/li&gt;
&lt;li&gt;It guards against more types of risk—not just going over on the work itself, but also things like an unforeseen event that greatly reduces our development bandwidth.&lt;/li&gt;
&lt;li&gt;It creates a clear deadline to keep us focused on the contract at hand.&lt;/li&gt;
&lt;li&gt;It creates an additional incentive to effectively break down the tasks within the contract during initial proposal to allow us to be paid fairly in the case that we don’t meet our deadline.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I haven’t yet discussed this with my clients. I’m a little nervous about how they’ll react. I’m hopeful, though, that they’ll like the idea. I need to change something in order for our fixed bids to continue to be a practical part of our work.&lt;/p&gt;
</content:encoded></item><item><title>Zed vs VS Code &amp; Cursor</title><link>https://nathanarthur.com/writing/zed-vs-vs-code-cursor</link><guid isPermaLink="true">https://nathanarthur.com/writing/zed-vs-vs-code-cursor</guid><pubDate>Fri, 02 May 2025 17:11:32 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/zed-vs-vs-code-cursor/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;Abstract computer code in several colors&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id=&quot;giving-zed-another-look&quot;&gt;Giving Zed Another Look&lt;/h3&gt;
&lt;p&gt;Recently my brother and I have started using &lt;em&gt;&lt;a href=&quot;https://zed.dev/&quot;&gt;Zed&lt;/a&gt;&lt;/em&gt; again. Zed is a competitor to &lt;em&gt;&lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VS Code&lt;/a&gt;&lt;/em&gt;, built by &lt;em&gt;&lt;a href=&quot;https://zed.dev/team&quot;&gt;some of the same folks&lt;/a&gt;&lt;/em&gt; behind &lt;em&gt;&lt;a href=&quot;https://atom-editor.cc/&quot;&gt;Atom&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When I tried Zed previously it seemed like a really neat project that wasn’t ready for me to use yet, missing language features I relied on. It seems like it’s come a very long way since then, with an impressive list of &lt;em&gt;&lt;a href=&quot;https://zed.dev/docs/languages&quot;&gt;supported languages&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The reason we’re trying Zed out again now is because of the issues we’ve had recently with multiplayer pairing in VS Code and Cursor. We’ve used Microsoft’s &lt;em&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare&quot;&gt;Live Share&lt;/a&gt;&lt;/em&gt; plugin for a long time now, and it’s worked great. However since I’ve switched to Linux and started using &lt;em&gt;&lt;a href=&quot;https://www.cursor.com/&quot;&gt;Cursor&lt;/a&gt;&lt;/em&gt; (a fork of VS Code), it’s become pretty much impossible for us to use. We tried switching to another VS Code extension called &lt;em&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=typefox.open-collaboration-tools&quot;&gt;Open Collaboration Tools&lt;/a&gt;&lt;/em&gt;, but we’ve found it to be unreliable.&lt;/p&gt;
&lt;p&gt;Unlike VS Code, &lt;em&gt;&lt;a href=&quot;https://zed.dev/docs/collaboration&quot;&gt;Zed has collaboration built-in&lt;/a&gt;&lt;/em&gt;. And after our recent struggles with VS Code-based IDEs, it’s been a big relief.&lt;/p&gt;
&lt;p&gt;A few observations after just a couple of days back in Zed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zed’s collaboration features are fantastic, though not intuitive on first attempt. However once we figured out how to use them, they work very well, and I think we already prefer Zed’s implementation to how Live Share works.&lt;/li&gt;
&lt;li&gt;So far this time I’ve only used Zed for a fairly standard Node server-side project. But I was very impressed how well it worked out of the box. It immediately began showing me TypeScript and eslint warnings inline. I’ll be interested to see how it holds up when I throw other stacks at it. I’m especially interested in how it handles Ruby. Whether because of my lack of Ruby experience or due to something generally lacking in VS Code’s ecosystem, I’ve never had a good experience working with Ruby in VS Code.&lt;/li&gt;
&lt;li&gt;So far Zed is very fast. I know that’s been a big focus for the Zed team. I’ll be interested to see if the speed advantage persists as I continue customizing my Zed configuration and installing more extensions.&lt;/li&gt;
&lt;li&gt;Zed has &lt;em&gt;&lt;a href=&quot;https://zed.dev/blog/zed-ai&quot;&gt;their own hosted AI service&lt;/a&gt;&lt;/em&gt; powering their code completions and chat assistant. It’s unclear to me what the pricing for their AI features is or will end up being, though so far I haven’t needed to pay to use it. So far it’s passable. Definitely worse than Cursor. Zed does allow you to use GitHub Copilot or your own AI API keys. Though I have a feeling that I’d still prefer Cursor to Zed due to Cursor’s multi-line edit suggestions, smart rewrites, cursor prediction, and agentic assistant mode. Zed has some serious catching up to do.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;some-interesting-things&quot;&gt;Some Interesting Things&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://www.jetbrains.com/&quot;&gt;JetBrains&lt;/a&gt;&lt;/em&gt; has a product called &lt;em&gt;&lt;a href=&quot;https://www.jetbrains.com/junie/&quot;&gt;Junie&lt;/a&gt;&lt;/em&gt; which appears to be their agentic coding tool. I used JetBrains IDEs for years when I first started in web development. They make quality software, so I wouldn’t count them out yet.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://anythingllm.com/&quot;&gt;AnythingLLM&lt;/a&gt;&lt;/em&gt; is an AI desktop tool that allows you to provide your own API keys. The biggest reason I gave it a go was that they make it easy to install it on Linux. It seems to have a good set of features. I’m not sure how much use I’ll actually get out of it.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://hashnode.com/&quot;&gt;Hashnode&lt;/a&gt;&lt;/em&gt; is a service for building technical blogs and documentation sites. I’m especially interested in whether their GitHub integration makes them a viable alternative to &lt;em&gt;&lt;a href=&quot;https://www.gitbook.com/&quot;&gt;GitBook&lt;/a&gt;&lt;/em&gt;. Unfortunately Hashnode’s GitHub integration is on their $200/month plan, which is far too rich for me.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>AI for business data &amp; using AI coding tools responsibly</title><link>https://nathanarthur.com/writing/ai-for-business-data-using-ai-coding-tools-responsibly</link><guid isPermaLink="true">https://nathanarthur.com/writing/ai-for-business-data-using-ai-coding-tools-responsibly</guid><pubDate>Fri, 25 Apr 2025 16:52:22 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/ai-for-business-data-using-ai-coding-tools-responsibly/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;Abstract representation of the joining of business data and artificial intelligence&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id=&quot;ai-for-querying-business-data&quot;&gt;AI for Querying Business Data&lt;/h3&gt;
&lt;p&gt;I’ve been thinking lately about how to make it easier for me to query my own business data—information bout clients, contracts, our own tools and processes, etc, etc.&lt;/p&gt;
&lt;p&gt;One of my pain points when working with clients is that often they’ll ask questions about things that I don’t currently have loaded in my head, and then I need to go figure out what the correct answers are and how to translate the answer to be understandable to the client. This can be disruptive and frustrating.&lt;/p&gt;
&lt;p&gt;I talked to my business coach, &lt;em&gt;&lt;a href=&quot;https://www.hellyer.net/&quot;&gt;Philip Hellyer&lt;/a&gt;&lt;/em&gt;, about this, and he suggested that I might use one of the AI chat products to reduce this friction, whether by manually adding documents to something like ChatGPT or building something more automated.&lt;/p&gt;
&lt;p&gt;Of course, as a developer it’s very tempting to jump to the over-engineered solution. Automatic archival of business data into an S3-like data lake, then ingest the data into things like &lt;em&gt;&lt;a href=&quot;https://www.voyageai.com/&quot;&gt;Voyage AI&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;https://www.getzep.com/&quot;&gt;Zep&lt;/a&gt;&lt;/em&gt;. And expose it all via custom Discord and Slack bots.&lt;/p&gt;
&lt;p&gt;I did recently hear an add for a product that’s trying to solve a similar issue I think—&lt;em&gt;&lt;a href=&quot;https://www.informatica.com/&quot;&gt;Informatica&lt;/a&gt;&lt;/em&gt;. Seems like basically what I’m talking about, that being an AI-forward data lake solution. Though it being so enterprise-focused I doubt it would actually be a good solution for me.&lt;/p&gt;
&lt;h3 id=&quot;being-more-responsible-with-git--ai&quot;&gt;Being More Responsible with Git &amp;amp; AI&lt;/h3&gt;
&lt;p&gt;I recently watched this video about how to be responsible when using AI coding tools. It’s a good watch.&lt;/p&gt;
&lt;p&gt;Theo’s main point is that the more we use AI to write code, resulting in more code for less time, the more we need to shift our time to reviewing the code we’ve generated. Basically Theo’s stance is that more manual code review is better and the direction we should be moving.&lt;/p&gt;
&lt;p&gt;I’m not sure how I feel about this. I feel like the more we increase the velocity of our code generation the more we need to put effort into new approaches to automated review, validation, and rollback. That doesn’t necessarily mean using AI to automate code verification (though that could be part of a solution). At this point I feel like most of that should be non-AI tooling. Things like (the maybe-dying and probably-much-less-AI-than-their-marketing-implies) &lt;em&gt;&lt;a href=&quot;https://www.meticulous.ai/&quot;&gt;Meticulous&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;One thing I didn’t know before watching the video was the command &lt;code&gt;git add -p&lt;/code&gt;, specifically the &lt;code&gt;-p&lt;/code&gt; option. It allows you to review the work you’ve done on your local machine, hunk by hunk, and decide whether or not to stage each change individually. I’ve been using it a ton since watching Theo’s video. It’s great.&lt;/p&gt;
&lt;h3 id=&quot;interesting-stuff&quot;&gt;Interesting Stuff&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://github.com/reviewdog/reviewdog&quot;&gt;reviewdog&lt;/a&gt;&lt;/em&gt; is a tool for programmatic posting of review comments to GitHub.&lt;/li&gt;
&lt;li&gt;Convex just released &lt;em&gt;&lt;a href=&quot;https://news.convex.dev/meet-chef/&quot;&gt;Convex Chef&lt;/a&gt;&lt;/em&gt;, another AI app builder, but this one promising to do much better at the backend stuff. (&lt;em&gt;&lt;a href=&quot;https://www.convex.dev/&quot;&gt;Convex&lt;/a&gt;&lt;/em&gt; is the backend service that the &lt;em&gt;&lt;a href=&quot;https://www.codebuff.com/&quot;&gt;Codebuff&lt;/a&gt;&lt;/em&gt; team recommends)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://github.com/vercel/ncc&quot;&gt;ncc&lt;/a&gt;&lt;/em&gt; is a tool for compiling a Node.JS module to a single file. I recently used it when I was building my new experimental GitHub action, &lt;em&gt;&lt;a href=&quot;https://github.com/marketplace/actions/uvi-finder&quot;&gt;UVI Finder&lt;/a&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Issue 0</title><link>https://nathanarthur.com/writing/issue-0</link><guid isPermaLink="true">https://nathanarthur.com/writing/issue-0</guid><pubDate>Sun, 20 Apr 2025 16:41:00 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://nathanarthur.com/writing/issue-0/1.webp&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;608&quot; loading=&quot;eager&quot;&gt;&lt;figcaption&gt;“A single unopened envelope, still life.” Also a forged signature.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;This is issue zero! Thanks for being here.&lt;/p&gt;
&lt;p&gt;Definitely reply if you have thoughts on the content, format, or whatever. (I think you can do that? I guess let me know if replying to this email doesn’t work, either. My email is &lt;em&gt;&lt;a href=&quot;mailto:nathan@pinepeakdigital.com&quot;&gt;nathan@pinepeakdigital.com&lt;/a&gt;&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;Hope you’re having a great weekend!&lt;br&gt;
Narthur&lt;/p&gt;
&lt;h3 id=&quot;documentation-scraping&quot;&gt;Documentation Scraping&lt;/h3&gt;
&lt;p&gt;I’ve been experimenting with scraping documentation and adding it to my repositories to improve the effectiveness of tools like Codebuff and Cursor. Initially I’ve been using &lt;em&gt;&lt;a href=&quot;https://github.com/AiCodingBattle/mdCrawler&quot;&gt;mdCrawler&lt;/a&gt;&lt;/em&gt; for this purpose, but I’ve also been experimenting with building my own repo to crawl a whole list of documentation sources. So far I’ve been using &lt;em&gt;&lt;a href=&quot;https://www.npmjs.com/package/crawler&quot;&gt;crawler&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;https://www.npmjs.com/package/turndown&quot;&gt;turndown&lt;/a&gt;&lt;/em&gt; for the experiment.&lt;/p&gt;
&lt;h3 id=&quot;building-agentic-ai&quot;&gt;Building Agentic AI&lt;/h3&gt;
&lt;p&gt;I recently watched Microsoft’s &lt;em&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=OhI005_aJkA&quot;&gt;beginner course to building agentic AI&lt;/a&gt;&lt;/em&gt;. And then I built a proof-of-concept agentic system to break down a project into a series of tasks and estimate the time needed to complete each task. I used &lt;em&gt;&lt;a href=&quot;https://github.com/MervinPraison/PraisonAI&quot;&gt;Praison&lt;/a&gt;&lt;/em&gt; as my framework to build the tool, along with Codebuff and scraped docs as described above, and &lt;em&gt;&lt;a href=&quot;https://www.getzep.com/&quot;&gt;Zep&lt;/a&gt;&lt;/em&gt; for semantic memory. It was surprisingly easy to get something set up and working, though I’m not sure how much more effort it would take to make the tool perform consistently when it comes to accuracy.&lt;/p&gt;
&lt;h3 id=&quot;using-ai-in-pull-requests&quot;&gt;Using AI in Pull Requests&lt;/h3&gt;
&lt;p&gt;I’ve been experimenting with Copilot’s new PR-focused features, including &lt;em&gt;&lt;a href=&quot;https://docs.github.com/en/copilot/using-github-copilot/using-github-copilot-for-pull-requests/creating-a-pull-request-summary-with-github-copilot&quot;&gt;generating PR summaries&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;https://docs.github.com/en/copilot/using-github-copilot/code-review/using-copilot-code-review&quot;&gt;requesting a PR review from Copilot&lt;/a&gt;&lt;/em&gt;. It also has features for &lt;em&gt;&lt;a href=&quot;https://docs.github.com/en/copilot/using-github-copilot/using-github-copilot-for-pull-requests/using-copilot-to-help-you-work-on-a-pull-request&quot;&gt;iterating on a PR&lt;/a&gt;&lt;/em&gt; but I haven’t tried that yet.&lt;/p&gt;
&lt;p&gt;I’ve also been trying out using &lt;em&gt;&lt;a href=&quot;https://www.meticulous.ai/&quot;&gt;Meticulous&lt;/a&gt;&lt;/em&gt; to automatically test PRs. Their marketing material uses the term AI a ton, I’m not sure how much that’s actually true yet. But regardless the concept seems really useful.&lt;/p&gt;
&lt;p&gt;Basically you add a script to your site that records your sessions, but only when in development and staging. So you aren’t recording end users. When you make a PR, Meticulous then selects a subset of these sessions and replays them both against your PR preview and your production environment. It then generates a report of differences, which you can choose to approve or not. Really neat idea, especially as we may be moving further and further toward “vibe coding.”&lt;/p&gt;
&lt;h3 id=&quot;more-interesting-things&quot;&gt;More Interesting Things&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://www.moritzjung.dev/obsidian-js-engine-plugin-docs/&quot;&gt;JS Engine&lt;/a&gt;&lt;/em&gt; lets you run JavaScript inside your Obsidian notes. Plus same person’s &lt;em&gt;&lt;a href=&quot;https://www.moritzjung.dev/obsidian-collection/&quot;&gt;built some other interesting Obsidian plugins&lt;/a&gt;&lt;/em&gt;, too.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://lynxjs.org/&quot;&gt;Lynx&lt;/a&gt;&lt;/em&gt; is yet another write-once-deploy-anywhere tool set. Anything that pushes us closer to a web-technology-everywhere future is a win in my book.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://file.pizza/&quot;&gt;FilePizza&lt;/a&gt;&lt;/em&gt; is a browser-based peer-to-peer file transfer tool.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://sst.dev/&quot;&gt;SST&lt;/a&gt;&lt;/em&gt; is an infrastructure-as-code framework. Maybe similar to Terraform? Maybe better?&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://hydrogen.shopify.dev/&quot;&gt;Hydrogen&lt;/a&gt;&lt;/em&gt; is Shopify’s official framework for building custom Shopify storefronts.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://bolt.new&quot;&gt;bolt.new&lt;/a&gt;&lt;/em&gt; lets you prompt to create an entire web or mobile app in a single go. I literally said “build me a tic tac toe game” and &lt;em&gt;&lt;a href=&quot;https://endearing-gumdrop-a2ee14.netlify.app/&quot;&gt;this is what it created&lt;/a&gt;&lt;/em&gt; and then deployed to Netlify for me.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://www.projectliberty.io/dsnp/&quot;&gt;DSNP&lt;/a&gt;&lt;/em&gt; is a decentralized social networking protocol (oh, right, that’s what it stands for). How does it relate to the AT protocol, ActivityPub, and the &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Fediverse&quot;&gt;Fediverse&lt;/a&gt;&lt;/em&gt;? I don’t know. I try to stay off social media.&lt;/li&gt;
&lt;li&gt;Beeminder-friend Mary just published a new &lt;em&gt;&lt;a href=&quot;https://time-stream.app/&quot;&gt;visual time management app&lt;/a&gt;&lt;/em&gt; for iOS.&lt;/li&gt;
&lt;li&gt;Anthropic recently added &lt;em&gt;&lt;a href=&quot;https://www.anthropic.com/news/max-plan&quot;&gt;a new $100 Max tier&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Anthropic also added a new &lt;em&gt;&lt;a href=&quot;https://www.anthropic.com/news/research&quot;&gt;research feature&lt;/a&gt;&lt;/em&gt; that looks to be a combination of reasoning and gathering context via multiple searches both of the open web and any of your own information you may have given Claude access to.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://www.getzep.com/&quot;&gt;Zep&lt;/a&gt;&lt;/em&gt; is an API for building and referencing a semantic knowledge graph as a kind of memory for AI applications.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://www.getzep.com/&quot;&gt;Zep&lt;/a&gt;&lt;/em&gt; published a blog post on &lt;em&gt;&lt;a href=&quot;https://blog.getzep.com/the-one-token-trick/?ref=zep-news-newsletter&quot;&gt;The One-Token Trick&lt;/a&gt;&lt;/em&gt; in which they explain how they’ve leveraged OpenAI’s API to determine the relevance of search results while reducing cost by limiting the LLM’s response to a single token.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://lovable.dev/&quot;&gt;Lovable&lt;/a&gt;&lt;/em&gt; is yet another AI-powered app builder.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://gameofbricks.eu/blogs/news/how-to-light-up-legos-and-choose-the-right-lego-lighting-kits&quot;&gt;This article&lt;/a&gt;&lt;/em&gt; is a deep-dive on choosing the right products to add lighting to your LEGO sets. I’m especially intrigued by &lt;em&gt;&lt;a href=&quot;https://www.brickstuff.com/&quot;&gt;Brickstuff&lt;/a&gt;&lt;/em&gt;’s modular lighting system.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://www.voyageai.com/&quot;&gt;Voyage AI&lt;/a&gt;&lt;/em&gt; is a third-party embeddings API &lt;em&gt;&lt;a href=&quot;https://docs.anthropic.com/en/docs/build-with-claude/embeddings&quot;&gt;recommended by Anthropic’s documentation&lt;/a&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item></channel></rss>