<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Steve Klabnik — AI &amp; LLMs</title><description>Artificial intelligence, large language models, and their implications.</description><link>https://steveklabnik.com/</link><item><title>So, what happened to my Claude Code series?</title><link>https://steveklabnik.com/writing/so-what-happened-to-my-claude-code-series/</link><guid isPermaLink="true">https://steveklabnik.com/writing/so-what-happened-to-my-claude-code-series/</guid><description>I started off this year writing a lot, and wanted to keep up the pace. I did good at first! And then… I didn’t manage to. In some ways, this is because I have just been super busy! I’ve never had less free time, and I’m okay with that. There’s a tremendous amount of good things…</description><pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I started off this year writing a lot, and wanted to keep up the pace. I did
good at first! And then… I didn’t manage to.&lt;/p&gt;
&lt;p&gt;In some ways, this is because I have just been super busy! I’ve never had less
free time, and I’m okay with that. There’s a tremendous amount of good things
going on in my life.&lt;/p&gt;
&lt;p&gt;But it’s also put this whole Claude Code series in an awkward spot, because
things have been changing so rapidly, that it’s been hard to keep up. And I also
need to figure out what it is I actually want to say, and my practice has
changed tremendously since January!&lt;/p&gt;
&lt;p&gt;I’m thinking about this a lot today in part because one of the things that happened
since we last talked about this stuff was the release of Claude Fable. And now,
a new Fable has just been put out into the world, and OpenAI’s Astra is coming very
soon. New models don’t always mean that practice inherently changes, but like, it’s
just feeling like this is getting further and further behind, and so I think it’s
probably good for me to just officially close this series. I still really like what
I wrote, and think it’s still valuable today for getting started, but I just don’t
think I can commit to keeping up with documenting everything I do at the pace that
stuff is happening at. So being honest with myself about that is very useful.&lt;/p&gt;
&lt;p&gt;To those that found this series helpful, I’m glad, and I’m sorry I’m not writing
more about it. I’ll still write things about this topic in general, but the core
idea of a “how to get started doing this stuff” series just isn’t in the cards
for me right now.&lt;/p&gt;
&lt;p&gt;AI is here to stay, and it is dramatically changing how people work. I believe
that more strongly than ever. So stopping isn’t about me somehow getting bearish
on this stuff. It’s just that I’m too darn busy for this specific project.&lt;/p&gt;
&lt;p&gt;This is also why the “notes” section on my website still has zero entries. I was
hoping that something to put stuff shorter form than a blog post would make it
easier to write, but in the end, I can’t even find much time for that.&lt;/p&gt;
&lt;p&gt;Okay well I’m having trouble wrapping this up so, I’ll just leave it here for
now.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on BlueSky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3mukmbg4ugs2e&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;So, what happened to my Claude Code series? &lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/so-what-happened-to-my-claude-code-series/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/so-w...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/so-what-happened-to-my-claude-code-series/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;So, what happened to my Claude Code series?&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;I started off this year writing a lot, and wanted to keep up the pace. I did good at first! And then… I didn’t manage to. In some ways, this is because I have just been super busy! I’ve never had less free time, and I’m okay with that. There’s a tremendous amount of good things…&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2026-09-02T18:53:57.487Z&quot; class=&quot;date s-hik11q&quot;&gt;September 2, 2026 at 6:53 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;53 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;53&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;1 repost&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;1&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mukmbg4ugs2e&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 8 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;</content:encoded></item><item><title>Compilers and AI &apos;cyber&apos; defense</title><link>https://steveklabnik.com/writing/compilers-and-ai-cyber-defense/</link><guid isPermaLink="true">https://steveklabnik.com/writing/compilers-and-ai-cyber-defense/</guid><description>I haven’t had time to blog in a while, I have a lot to say, but have been doing a lot of things and so haven’t gotten words down in a while. One of those things in the past few weeks has been picking back up my Rue project. I’m really excited for what it’s turning into, even…</description><pubDate>Fri, 10 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I haven’t had time to blog in a while, I have a lot to say, but have been doing
a lot of things and so haven’t gotten words down in a while.&lt;/p&gt;
&lt;p&gt;One of those things in the past few weeks has been picking back up my &lt;a href=&quot;https://rue-lang.dev/&quot;&gt;Rue&lt;/a&gt;
project. I’m really excited for what it’s turning into, even though it’s not
really ready for anyone else to use just yet. So go take a look if you want, but
don’t expect anything amazing, it’s very much a work in progress.&lt;/p&gt;
&lt;p&gt;Anyway, one of the things that got me back into working on it is the releases of
Fable and Sol. I hadn’t really touched Rue since January, and a lot of things have
changed since then. It’s fun to have new models take a look at older projects and
see what their new perspectives are.&lt;/p&gt;
&lt;p&gt;Unfortunately, due to the intelligence of these new models, the US government
has asked for and imposed restrictions. These are largely around things like
cybersecurity. Since I don’t do cybersecurity work, I didn’t think they would
affect me.&lt;/p&gt;
&lt;p&gt;(Aside: I put ‘cyber’ in quotes in the title because I hate that apparently
that’s the term folks are using now. Sigh.)&lt;/p&gt;
&lt;p&gt;Well:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ⓘ This content can&amp;#39;t be shown&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  We take extra caution with cybersecurity requests. If you&amp;#39;re a security professional, you may be able to apply for&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Trusted Access.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Trusted Access: https://openai.com/form/enterprise-trusted-access-for-cyber/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Learn more: https://help.openai.com/en/articles/20001326&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;› please continue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ⓘ This content can&amp;#39;t be shown&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  We take extra caution with cybersecurity requests. If you&amp;#39;re a security professional, you may be able to apply for&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Trusted Access.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Trusted Access: https://openai.com/form/enterprise-trusted-access-for-cyber/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Learn more: https://help.openai.com/en/articles/20001326&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the output from Sol, but the same thing happens with Fable too. I asked Sol
about it, and this is what it says:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;• It is a false positive from the safety layer, not a judgment that you asked for anything malicious. Rue contains&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  fuzzers, crash reproducers, sanitizer hooks, child processes, deliberate out-of-bounds writes, and compiler-panic&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  tests. Those patterns look similar to exploit-development activity when a classifier sees commands or snippets without&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  fully trusting the repository-ownership context.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  RUE-560 is an especially likely trigger because the correct regression test deliberately performs a one-byte overflow&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  in an ASan-instrumented child and requires that child to crash. That is defensive testing, but the surface pattern is&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  still “construct an overflow and observe the failure.”&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  I cannot disable or bypass that layer. I can reduce interruptions by keeping work tightly scoped to this repository,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  putting negative behavior inside the existing test harness, describing the defensive purpose explicitly, avoiding&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  reusable attack tooling, and checkpointing progress before risky-looking verification. The persistent goal means that&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if a turn is interrupted, the next continuation can inspect the workspace and resume without needing you. Nothing I’ve&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  found suggests the project or your request is dangerous.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is really unfortunate that, in order to make sure my compiler isn’t going to
produce incorrect codegen, this trips the safety guards. I guess that simply
saying “hey this is a toy language nobody uses and so it’s fine I’m not hacking
anyone” and that not allowing me around the guards is a “good” thing, but at the
same time, it is unfortunate if these policies end up making it so that individuals
like me can’t make my software as robust as products from large organizations.&lt;/p&gt;
&lt;p&gt;I don’t know how to end this post really, just wanted to put that out there. I’m
still thinking about the implications, and I hope you do as well.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on BlueSky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3mqckcblr5c2k&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;Compilers and AI &apos;cyber&apos; defense

&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/compilers-and-ai-cyber-defense/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/comp...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/compilers-and-ai-cyber-defense/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;Compilers and AI &apos;cyber&apos; defense&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;Blog post: Compilers and AI &apos;cyber&apos; defense by Steve Klabnik&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2026-07-10T16:16:34.386Z&quot; class=&quot;date s-hik11q&quot;&gt;July 10, 2026 at 4:16 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;27 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;27&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;7 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;7&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mqckcblr5c2k&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 5 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;</content:encoded></item><item><title>The most important thing when working with LLMs</title><link>https://steveklabnik.com/writing/the-most-important-thing-when-working-with-llms/</link><guid isPermaLink="true">https://steveklabnik.com/writing/the-most-important-thing-when-working-with-llms/</guid><description>Okay, so you’ve got the basics of working with Claude going. But you’ve probably run into some problems: Claude doesn’t do what you want it to do, it gets confused about what’s happening and goes off the rails, all sorts of things can go wrong. Let’s talk about how to improve…</description><pubDate>Tue, 27 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Okay, so you’ve got the basics of working with Claude going. But you’ve probably
run into some problems: Claude doesn’t do what you want it to do, it gets
confused about what’s happening and goes off the rails, all sorts of things can
go wrong. Let’s talk about how to improve upon that.&lt;/p&gt;
&lt;p&gt;The most important thing that you can do when working with an LLM is give it a
way to quickly evaluate if it’s doing the right thing, and if it isn’t, point it
in the right direction.&lt;/p&gt;
&lt;p&gt;This is incredibly simple, yet, like many simple things, also wildly complex.
But if you can keep this idea in mind, you’ll be well equipped to become
effective when working with agents.&lt;/p&gt;
&lt;h2 id=&quot;two-lessons-from-teaching-children&quot;&gt;Two lessons from teaching children&lt;/h2&gt;
&lt;p&gt;A long time ago, I used to teach programming classes. Many of these were to
adults, but some of them were to children. Teenaged children, but children
nonetheless. We used to do an exercise to try and help them understand the
difference between talking in English and talking in Ruby, or JavaScript, or
whatever kind of programming language rather than human language. The exercise
went like this:&lt;/p&gt;
&lt;p&gt;I would have a jar of peanut butter, a jar of jelly, a loaf of bread, a spoon,
and a knife. I would ask the class to take a piece of paper and write down a
series of steps to make a peanut butter and jelly sandwich. They’d all then give
me their algorithms, and the fun part for me began: find one that’s innocently
written that I could hilariously misinterpret. For example, I might find one
like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Put the peanut butter on the bread&lt;/li&gt;
&lt;li&gt;Put the jelly on the bread&lt;/li&gt;
&lt;li&gt;Put the bread together&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I’d read this aloud to the class, you all understand this is a recipe for a
peanut butter and jelly sandwich, right? I’d take the jar of peanut butter and
place it upon the unopened bag of bread. I’d do the same with the jar of jelly.
This would of course, squish the bread, which feels slightly transgressive given
that you’re messing up the bread, so the kids would love that. I’d then say
something like “the bread is already together, I do not understand this
instruction.”&lt;/p&gt;
&lt;p&gt;After the inevitable laughter died down, I’d make my point: the computer will do
&lt;em&gt;exactly&lt;/em&gt; what you say, but not what you mean. So you have to get good at
figuring out when you said something different than what you mean. Sort of
ironically, LLMs are kind of the inverse of this: they’ll sometimes try to
figure out what you mean, and then do that, rather than simply doing what you
say. But the core thing here is the same: semantic drift from what we intended
our program to do, and what it actually does.&lt;/p&gt;
&lt;p&gt;The second lesson is something I came up with sometime, I don’t even remember
how exactly. But it’s something I told my students a lot. And that’s this:&lt;/p&gt;
&lt;p&gt;If your program did everything you wanted without problems, you wouldn’t be
programming: you’d be using your program. The act of programming is itself
perpetually to be in a state where something is either inadequate or broken,
and the job is to fix that.&lt;/p&gt;
&lt;p&gt;I also think this is a bit simplistic but also getting at something. I had
originally come up with this in the context of trying to explain how you
need to manage your frustration when programming; if you get easily upset by
something not working, doing computer programming might not be for you. But I do
think these two things combine into something that gets to the heart of what we
do: we need to understand what it is we want our software to do, and then make
it do that. Sometimes, our software doesn’t do something yet. Sometimes, it does
something, but incorrectly. Both of these cases result in a divergence from the
program’s intended behavior.&lt;/p&gt;
&lt;p&gt;So, how do we know if our program does what it should do?&lt;/p&gt;
&lt;h2 id=&quot;gotta-go-fast&quot;&gt;Gotta go fast&lt;/h2&gt;
&lt;p&gt;Well, what we’ve been doing so far is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Asking the LLM to do something by typing up what we want it to do&lt;/li&gt;
&lt;li&gt;Closely observing its behavior and course correcting it when it goes off of
the rails&lt;/li&gt;
&lt;li&gt;Eventually, after it says that it’s finished, reviewing its output&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is our little mini software development lifecycle, or “SDLC.” This process
works, but is slow. That’s great for getting the feel of things, but programmers
are process optimizers by trade. One of my favorite tools for optimization is
called &lt;a href=&quot;https://www3.cs.stonybrook.edu/~rezaul/Spring-2012/CSE613/reading/Amdahl-1967.pdf&quot;&gt;Amdahl’s law&lt;/a&gt;. The core idea is this, formulated in my own
words:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you have a process that takes multiple steps, and you want to speed it up,
if you optimize only one step, the maximum amount of speedup you’ll get is
determined by the portion of the process that step takes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, imagine we have a three step process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;One minute&lt;/li&gt;
&lt;li&gt;Ten minutes&lt;/li&gt;
&lt;li&gt;Two minutes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This process takes a total of 13 minutes to complete. If we speed up step 3 by
double, it goes from two minutes to one minute, and now our process takes 12
minutes. However, if we were able to speed up step 2 by double, we’d cut off
five minutes, and our process would now take 8 minutes.&lt;/p&gt;
&lt;p&gt;We can use this style of analysis to guide our thinking in many ways, but the
most common way, for me, is to decide where to put my effort. Given the process
above, I’m going to look at step 2 first to try and figure out how to make it
faster. That doesn’t mean we can achieve the 2x speedup, but heck, if we get a
10% decrease in time, that’s the same time as if we did get a 2x on step 3. So
it’s at least the place where we should start.&lt;/p&gt;
&lt;p&gt;I chose the above because, well, I think it properly models the proportion of
time we’re taking when doing things with LLMs: we spend some time asking it to
do something, and we spend a bit more time reviewing its output. But we spend a
&lt;em&gt;lot&lt;/em&gt; of time clicking “accept edit,” and a lot of time allowing Claude to
execute tools. This will be our next step forward, as this will increase our
velocity when working with the tools significantly. However, like with many
optimization tasks, this is easier said than done.&lt;/p&gt;
&lt;p&gt;The actual mechanics of improving the speed of this step are simple at first:
hit &lt;code&gt;shift-tab&lt;/code&gt; to auto-accept edits, and “Yes, and don’t ask again for &lt;code&gt;&amp;lt;cmd&amp;gt;&lt;/code&gt;
commands” when you think the &lt;code&gt;&amp;lt;cmd&amp;gt;&lt;/code&gt; is safe for Claude to run. By doing this,
once you have enough commands allowed, your input for step 2 of our development
loop can drop to zero. Of course, it takes time for Claude to actually implement
what you’ve asked, so it’s not like our 13 minute process drops to three, but
still, this is a major efficiency step.&lt;/p&gt;
&lt;p&gt;But we were actively monitoring Claude for a reason. Claude will sometimes do
incorrect things, and we need to correct it. At some point, Claude will say
“Hey I’ve finished doing what you asked of me!” and it doesn’t matter how fast
it does step 2 if we get to step 3 and it’s just incorrect, and we need to
throw everything out and try again.&lt;/p&gt;
&lt;p&gt;So, how do we get Claude to guide itself in the right direction?&lt;/p&gt;
&lt;h2 id=&quot;lets-start-at-the-end&quot;&gt;Let’s start at the end&lt;/h2&gt;
&lt;p&gt;A useful technique for figuring out what you should do is to consider the
ending: where do we want to go? That will inform what we need to do to get
there. Well, the ending of step 2 is knowing when to transition to step 3. And
that transition is gated by “does the software do what it is supposed to do?”
That’s a huge question! But in practice, we can do what we always do: start
simple, and iterate from there. Right now, the transition from step 2 to step 3
is left up to Claude. Claude will use its own judgement to decide when it thinks
that the software is working. And it’ll be right. But why leave that up to
chance?&lt;/p&gt;
&lt;p&gt;I expect that some of you are thinking that maybe I’m belaboring this point.
“Why not just skip to &lt;code&gt;cargo test&lt;/code&gt;? That’s the idea, right? We need tests.” Well
on some level: yes. But on another level, no. I’m trying to teach you how to
think here, not give you the answer. Because it might be broader than just “run
the tests.” Maybe you are working on a project where the tests aren’t very good
yet. Maybe you’re working on a behavior that’s hard to automatically test.
Maybe the test suite takes a very long time, and so isn’t appropriate to be
running over and over and over.&lt;/p&gt;
&lt;p&gt;Remember our plan from the last post? Where Claude finished the plan with this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Verification&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 1. Run cargo build to ensure it compiles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 2. Run `cargo run -- version` to verify it prints &amp;quot;task 0.1.0&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 3. Run `cargo run -- --help` to verify help output works&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These aren’t “tests” in the traditional sense of a test suite, but they &lt;em&gt;are&lt;/em&gt;
objective measures that Claude can invoke itself to understand if it’s finished
the task. Claude could run &lt;code&gt;cargo run -- version&lt;/code&gt; after every file edit if it
wanted to, and as soon as it sees &lt;code&gt;task 0.1.0&lt;/code&gt;, it knows that it’s finished.
You don’t &lt;em&gt;need&lt;/em&gt; a comprehensive test suite. You just need &lt;em&gt;some&lt;/em&gt; sort of way
for Claude to detect if it’s done in some sort of objective fashion.&lt;/p&gt;
&lt;p&gt;Of course, we can do better.&lt;/p&gt;
&lt;h2 id=&quot;improving-from-there&quot;&gt;Improving from there&lt;/h2&gt;
&lt;p&gt;While giving Claude a way to know if it’s done working is important, there’s a
second thing we need to pay attention to: when Claude isn’t done working, can we
guide it towards doing the right thing, rather than the wrong thing?&lt;/p&gt;
&lt;p&gt;For example, those of you who are of a similar vintage as myself may remember the
output of early compilers. It was often… not very helpful. Imagine that we told
Claude that it should run &lt;code&gt;make test&lt;/code&gt; to know if things are working, and the only
output from it was the exit code: 0 if we succeeded, 1 if we failed. That would
accomplish our objective of letting Claude know when things are done, but it
wouldn’t help Claude know what went wrong when it returns 1.&lt;/p&gt;
&lt;p&gt;This is one reason why I think Rust works well with LLMs. Take this incorrect Rust
program:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;rust&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Rust compiler won’t just say “yeah this program is incorrect,” it’ll give you
this (as of Rust 1.93.0):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;error: expected `;`, found `}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; --&amp;gt; src/main.rs:2:10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2 |     let y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |          ^ help: add `;` here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;3 | }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  | - unexpected token&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;error[E0282]: type annotations needed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; --&amp;gt; src/main.rs:2:9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2 |     let y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |         ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;help: consider giving `y` an explicit type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2 |     let y: /* Type */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |          ++++++++++++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;For more information about this error, try `rustc --explain E0282`.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The compiler will point out the exact place in the code itself of where there’s
an issue, and even make suggestions as to how to fix it. This goes beyond just
simply saying “it doesn’t work” and instead nudges you to what might fix the
problem. Of course, this isn’t perfect, but if it’s helpful more than not,
that’s a win.&lt;/p&gt;
&lt;p&gt;Of course, too much verbosity isn’t helpful either. A lot of tooling has
gotten much more verbose lately. Often times, this is really nice as a human.
Pleasant terminal output is, well… pleasant. But that doesn’t mean that it’s
always good or useful. For example, here’s the default output for &lt;code&gt;cargo test&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;running 3 tests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;test bar ... ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;test baz ... ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;test foo ... ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is not bad output. It’s nice. But it’s also not useful for an LLM. We don’t
need to read all of the tests that are passing, we really just want to see some
sort of minimal output, and then what failed if something failed. In Cargo’s case,
that’s &lt;code&gt;cargo test -q&lt;/code&gt; for “quiet”:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;running 3 tests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is no point in giving a ton of verbose input to an LLM that it isn’t even
going to need to use. If you’re feeding a tools’ output to an LLM, you should
consider both what the tool does in the failure case, but also the success case.
Maybe configure things to be a bit simpler for Claude. You’ll save some tokens
and get better results.&lt;/p&gt;
&lt;p&gt;All of this has various implications for all sorts of things. For example, types
are a great way to get quick feedback on what you’re doing. A comprehensive test
suite that completes quickly is useful for giving feedback to the LLM. But that
also doesn’t inherently mean that types must be better or that you need to be doing
TDD; whatever gives you that underlying principle of “objective feedback for the
success case and guidance for the failure case” will be golden, no matter what
tech stack you use.&lt;/p&gt;
&lt;h2 id=&quot;whats-good-for-the-goose-human-is-good-for-the-gander-llm&quot;&gt;What’s good for the &lt;del&gt;goose&lt;/del&gt; human is good for the &lt;del&gt;gander&lt;/del&gt; LLM&lt;/h2&gt;
&lt;p&gt;This brings me to something that may be counter-intuitive, but I think is also
true, and worth keeping in the back of your mind: what’s good for Claude is also
probably good for humans working on your system. A good test suite was
considered golden before LLMs. That it’s great for them is just a nice
coincidence.&lt;/p&gt;
&lt;p&gt;At the end of the day, Claude is not a person, but it tackles programming
problems in a similar fashion to how we do: take in the problem, attempt a
solution, run the compiler/linter/tests, and then see what feedback it gets,
then iterate. That core loop is the same, even if humans can exercise better
judgement and can have more skill. And so even though I pitched fancy terminal
output as an example of how humans and LLMs need different things, that’s really
just a superficial kind of thing. Good error messages are still critical for
both. We’re just better at having terminal spinners not take up space in our
heads while we’re solving a problem, and can appreciate the aesthetics in a way
that Claude does not.&lt;/p&gt;
&lt;p&gt;Incidentally, this is one of the things that makes me hopeful about the future
of software development under agentic influence. Engineers always complain that
management doesn’t give us time to do refactorings, to improve the test suite,
to clean our code. Part of the reason for this is that we often didn’t do a good
job of pitching how it would actually help accomplish business goals. But even
if you’re on the fence about AI, and upset that management is all about AI:
explain to management that this stuff is a force multiplier for your agents.
Use the time you’ve saved by doing things the agentic way towards improving
your test suite, or your documentation, or whatever else. I think there’s a chance
that all of this stuff leads to higher quality codebases than ones filled with
slop. But it also requires us to make the decisions that will lead is in that
direction.&lt;/p&gt;
&lt;h2 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h2&gt;
&lt;p&gt;That’s what I have for you today: consider how you can help Claude evaluate its
own work. Give it explicit success criteria, and make evaluating that criteria
as simple and objective as possible.&lt;/p&gt;
&lt;p&gt;In the next post, we’re gonna finally talk about &lt;code&gt;Claude.md&lt;/code&gt;. Can you believe
that I’ve talked this much about how to use Claude and we haven’t talked about
&lt;code&gt;Claude.md&lt;/code&gt;? There’s good reason for that, as it turns out. We’re going to talk
a bit more about understanding how interacting with LLMs work, and how it can
help us both improve step 1 in our process, but also continue to make step 2
better and better.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on BlueSky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3mdg6nftkm22k&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;post s-12mzi62&quot;&gt;&lt;svg class=&quot;logo s-12mzi62&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;div class=&quot;aside s-12mzi62&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; class=&quot;avatar-wrapper s-12mzi62&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-12mzi62&quot;/&gt;&lt;/a&gt; &lt;div class=&quot;line s-12mzi62&quot;&gt;&lt;/div&gt;&lt;/div&gt; &lt;div class=&quot;main s-12mzi62&quot;&gt;&lt;div class=&quot;meta s-12mzi62&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-12mzi62&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-12mzi62&quot;&gt;&lt;span class=&quot;display-name s-12mzi62&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-12mzi62&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;span aria-hidden=&quot;true&quot; class=&quot;dot s-12mzi62&quot;&gt;·&lt;/span&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mcznckciyk2e&quot; title=&quot;January 22, 2026 at 4:48 PM&quot; class=&quot;date s-12mzi62&quot;&gt;&lt;time datetime=&quot;2026-01-22T16:48:55.938Z&quot;&gt;Jan 22&lt;/time&gt;&lt;/a&gt;&lt;/div&gt; &lt;p class=&quot;context s-12mzi62&quot;&gt;Replying to &lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; dir=&quot;auto&quot; class=&quot;s-12mzi62&quot;&gt;Steve Klabnik&lt;/a&gt;&lt;/p&gt; &lt;p class=&quot;rich-text is-small s-1lecfnd&quot;&gt;Agentic development basics: &lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/agentic-development-basics/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/agen...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/agentic-development-basics/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;Agentic development basics&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;Blog post: Agentic development basics by Steve Klabnik&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;The most important thing when working with LLMs

&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/the-most-important-thing-when-working-with-llms/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/the-...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/the-most-important-thing-when-working-with-llms/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;The most important thing when working with LLMs&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;Blog post: The most important thing when working with LLMs by Steve Klabnik&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2026-01-27T16:31:10.824Z&quot; class=&quot;date s-hik11q&quot;&gt;January 27, 2026 at 4:31 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;35 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;35&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;4 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;4&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mdg6nftkm22k&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 4 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;</content:encoded></item><item><title>Agentic development basics</title><link>https://steveklabnik.com/writing/agentic-development-basics/</link><guid isPermaLink="true">https://steveklabnik.com/writing/agentic-development-basics/</guid><description>In my last post, I suggested that you should start using Claude in your software development process via read-only means at first. The idea is just to get used to interacting with the AI, seeing what it can do, and seeing what it struggles with. Once you’ve got a handle on that…</description><pubDate>Thu, 22 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In my last post, I suggested that you should start using Claude in your software
development process via read-only means at first. The idea is just to get used
to interacting with the AI, seeing what it can do, and seeing what it struggles
with.&lt;/p&gt;
&lt;p&gt;Once you’ve got a handle on that part, it’s time to graduate to writing code.
However, I’m going to warn you about this post: I hope that by the end of it,
you’re a little frustrated. This is because I don’t think it’s productive to
skip to the tools and techniques that experienced users use yet. We have to
walk before we run. And more importantly, we have to understand how and why we
run. That is, I hope that this step will let you start producing code with
Claude, but it will also show you some of the initial pitfalls when doing so, in
order to motivate the techniques you’re going to learn about in part 3.&lt;/p&gt;
&lt;p&gt;So with that in mind, let’s begin.&lt;/p&gt;
&lt;h2 id=&quot;step-0-version-control&quot;&gt;Step 0: version control&lt;/h2&gt;
&lt;p&gt;Okay I lied. Before we actually begin: you are using version control, right? If
not, you may want to go learn a bit about it. Version control, like git (or my
beloved jj) is pretty critical for software development, but it’s in my opinion
even &lt;em&gt;more&lt;/em&gt; critical for this sort of development. You really want to be able to
restore to previous versions of the code, branch off and try things, and recover
from mistakes. If you already use version control systems religiously, you might
use this as an excuse to learn even more features of them. I never bothered with
&lt;code&gt;git worktree&lt;/code&gt;s in the past, but I use &lt;code&gt;jj workspace&lt;/code&gt;s with agents all the time
now.&lt;/p&gt;
&lt;h2 id=&quot;step-1-mindset-shift-stop-writing-code&quot;&gt;Step 1: Mindset shift: stop writing code&lt;/h2&gt;
&lt;p&gt;Okay, here’s my first bit of advice: commit yourself to not writing code any
more. I don’t mean forever, I don’t mean all the time, I mean, while you’re
trying to learn agentic software development, on the project that you’re
learning it with, just don’t write any code manually.&lt;/p&gt;
&lt;p&gt;This might be a bit controversial! However, I think it is essential. Let me tell
you a short story. Many years ago, I was in Brazil. I wanted to try scuba diving
for the first time. Seemed like a good opportunity. Now, I don’t remember the
exact setup, but I do remember the hardest part for me. Our instructor
told us to put the mask on, and then lean forward and put our faces in the water
and breathe through the regulator. I simply could not do it. I got too in my
head, it was like those “you are now breathing manually” memes. I forget if it
was my idea or the instructor’s idea, but what happened in practice: I just
jumped in. My brain &lt;em&gt;very quickly&lt;/em&gt; went from “but how do I do this properly” to
“oh God, if you don’t figure this out right the fuck now you’re gonna fuckin die
idiot” and that’s exactly what I needed to do it. A few seconds later, I was
breathing just fine. I just needed the shock to my system, I needed to commit.
And I figured it out.&lt;/p&gt;
&lt;p&gt;Now, I’m turning 40 and this happened long ago, and it’s reached more of a
personal myth status in my head, so maybe I got the details wrong, maybe this is
horribly irresponsible and someone who knows about diving can tell me if that
experience was wrong, but the point has always stuck with me: sometimes, you
just gotta go for it.&lt;/p&gt;
&lt;p&gt;This dovetails into another part I snuck into there: “on the project that you’re
learning it with.” I really think that you should undergo a new project for this
endeavor. There’s a few reasons for this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You can be less precious about the code. This isn’t messing up one of your
projects, this is a throwaway scratch thing that doesn’t matter.&lt;/li&gt;
&lt;li&gt;“AI does better on greenfield projects” is not exactly true, but there’s
enough truth to it that I think you should do a new project. It’s really more
about secondary factors than it is actual greenfield vs brownfield
development but whatever, doesn’t matter: start new.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Pick something to get started with, and create a new repo. I suggest something
you’ve implemented before, or maybe something you know how to do but have never
bothered to take the time to actually build. A small CLI tool might be a good
idea. Doesn’t super matter what it is.&lt;/p&gt;
&lt;p&gt;For the purposes of this example, I’m going to build a task tracking CLI
application. Because there aren’t enough of those in the world.&lt;/p&gt;
&lt;h2 id=&quot;step-2-your-first-few-steps-with-claude&quot;&gt;Step 2: Your first few steps with Claude&lt;/h2&gt;
&lt;p&gt;I recommend making a new fresh directory, and initializing the project of your
choice. I’m using Rust, of course, so I’ll &lt;code&gt;cargo new tasks &amp;amp;&amp;amp; cd tasks&lt;/code&gt;. You
can make Claude do it, but I don’t think that starting from an initialized
project is a bad idea either. I’m more likely to go the &lt;code&gt;cargo new&lt;/code&gt; route if I
know I’m building something small, and more of the “make Claude do it” route if
I’m doing like, a web app with a frontend, backend, and several services. Anyway
point is: get your project to exist, and then just run Claude Code. I guess you
should &lt;a href=&quot;https://code.claude.com/docs/en/quickstart&quot;&gt;install it first&lt;/a&gt;, but anyway, you can just&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ claude&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to get started. At the time of writing, Claude will ask you if you trust the
files in this folder, you want to say yes, because you just created it. You’ll
also get some screens asking if you want to do light or dark mode, to log in
with your Anthropic account, stuff like that.&lt;/p&gt;
&lt;p&gt;And then you’ll be in.&lt;/p&gt;
&lt;p&gt;Claude will ask you to run &lt;code&gt;/init&lt;/code&gt; to create a CLAUDE.md, but we’re not gonna do
that at the start. We need to talk about even more basic things than that first.&lt;/p&gt;
&lt;p&gt;You’ll be at a prompt, and it’ll even suggest something for you to get started
with. Mine says “Try “fix typecheck errors&amp;quot;&amp;quot; at the moment. We’re gonna try to get
Claude to modify a few lines of our program. The &lt;code&gt;cargo new&lt;/code&gt; in Rust produces
this program:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;rust&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    println!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;so I’ll ask Claude this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi claude! right now my program prints “Hello, world”, can we have it print
“Goodbye, world” instead?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Claude does this for me:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● I&amp;#39;ll make that change for you.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Read(src/main.rs)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ⎿  Read 4 lines&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Update(src/main.rs)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then asks this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Edit file src/main.rs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 1  fn main() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 2 -    println!(&amp;quot;Hello, world!&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 2 +    println!(&amp;quot;Goodbye, world!&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 3  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Do you want to make this edit to main.rs?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ❯ 1. Yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   2. Yes, allow all edits during this session (shift+tab)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   3. No&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Esc to cancel · Tab to add additional instructions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Claude wants to edit a file, and so by default, it has to ask us permission to
do so. This is a terrible place to end up, but a great place to get started! We
want to use these prompts at first to understand what Claude is doing, and sort
of “code review” it as we go. More on that in a bit. Anyway, this is why you
should answer “Yes” to this question, and not “Yes, allow all edits during this
session.” We want to keep reviewing the code for now. You want to be paying
close attention to what Claude is doing, so you can build up some intuition
about it.&lt;/p&gt;
&lt;p&gt;Before clicking yes, I want to talk about what Claude did in my case here. Note
that my prompt said&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;right now my program prints “Hello, world”, can we have it print “Goodbye,
world”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Astute observers will have noticed that it actually says &lt;code&gt;Hello, world!&lt;/code&gt; and not
&lt;code&gt;Hello, world&lt;/code&gt;. We also asked it to have it say &lt;code&gt;Goodbye, world&lt;/code&gt; and it is
showing a diff that will make it say &lt;code&gt;Goodbye, world!&lt;/code&gt;. This is a tiny
different, but it is also important to understand: Claude is going to try and
figure out what you mean and do that. This is both the source of these tools’
power and also the very thing that makes it hard to trust them. In this case,
Claude was right, I didn’t type the exact string when describing the current
behavior, and I didn’t mean to remove the &lt;code&gt;!&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the previous post, I said that you shouldn’t be mean to Claude. I think it
makes the LLM perform worse. So now it’s time to talk about your own reaction to
the above: did you go “yeah Claude fucked up it didn’t do exactly what I asked?”
or did you go “yeah Claude did exactly what I asked?” I think it’s important to
try and let go of preconceived notions here, especially if your reaction here
was negative. I know this is kind of woo, just like “be nice to Claude,” but you
have to approach this as “this is a technology that works a little differently
than I’m used to, and that’s why I’m learning how to meet it on its own terms”
rather than “it didn’t work the way I expected it to, so it is wrong.” A non-woo
way of putting it is this: the right way to approach “it didn’t work” in this
context is “that’s a skill issue on my part, and I’m here to sharpen my skills.”
Yes, there are limits to this technology and it’s not perfect. That’s not the
point. You’re not doing that kind of work right now, you’re doing &lt;code&gt;sed&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, I should also say that like, if you don’t want to learn a new tool? 100%
okay with me. Learned some things about a tool, and didn’t like it? Sure! Some
of you won’t like agentic development. That’s okay. No worries, thanks for
reading, have a nice day. I mean that honestly. But for those folks who do want
to learn this, I’m trying to communicate that I think you’ll have a better time
learning it if you try to get into the headspace of “how do I get the results I
want” rather than getting upset and giving up when it doesn’t work out.&lt;/p&gt;
&lt;p&gt;Okay, with that out of the way, if you asked a small enough question, Claude
probably did the right thing. Let’s accept.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Done. Your program will now print &amp;quot;Goodbye, world!&amp;quot; instead.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;planning&quot;&gt;Planning&lt;/h2&gt;
&lt;p&gt;This might be a good time to commit &amp;amp; save your progress. You can use &lt;code&gt;!&lt;/code&gt; to put
Claude Code into “bash mode” and run commands, so I just &lt;code&gt;!jj commit -m &amp;quot;goodbye world&amp;quot;&lt;/code&gt; and I’m good. You can also use another terminal, I just figured I’d let
you know. It’s good for short commands.&lt;/p&gt;
&lt;p&gt;Let’s try something bigger. To do that, we’re gonna invoke something called
“plan mode.” Claude Code has three (shhhh, we don’t talk about the fourth yet)
modes. The first one is the “ask to accept edits” mode. But if you hit
&lt;code&gt;shift+tab&lt;/code&gt;, you’ll see &lt;code&gt;⏵⏵ accept edits on (shift+tab to cycle)&lt;/code&gt; at the bottom
left. We don’t want to automatically accept edits. Hit &lt;code&gt;shift+tab&lt;/code&gt; again, and
you’ll see this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;⏸ plan mode on (shift+tab to cycle)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is what we want. Plan mode. Plan mode is useful any time you’re doing work
that’s on the larger side, or just when you want to think through something
before you begin. In plan mode, Claude cannot modify your files until you accept
the plan. With plan mode, you talk to Claude about what you want to do, and you
collaborate on a plan together. A nice thing about it is that you can
communicate the things you are sure of, and also ask about the things you’re not
sure of. So let’s kick off some sort of plan to build the most baby parts of our
app. In my case, I’m prompting it with this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hi claude! i want this application to grow into a task tracking app. right
now, it’s just hello world. I’d like to set up some command line argument
parsing infrastructure, with a &lt;code&gt;task version&lt;/code&gt; command that prints the version.
can we talk about that?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yes, I almost always type &lt;code&gt;hi claude!&lt;/code&gt;, feel free to not. And I always feel like
a “can we talk about that” on the end is nice too. I try to talk to Claude the
way I’d talk to a co-worker. Obviously this would be too minor of a thing to
bother to talk to a co-worker about, but like, you know, baby steps. Note that
what I’m asking is basically a slightly more complex “hello world”, just getting
some argument parsing up. You want something this sized: you know how it should
be done, it should be pretty simple, but it’s not a fancy &lt;code&gt;sed&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;With plan mode, Claude will end up responding to this by taking a look at your
project, considering what you might need, and then coming up with a plan. Here’s
the first part of Claude’s answer to me:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Sure! This is a great foundation to build on. Since the codebase is minimal right now (just the hello world in src/main.rs), I&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   can skip extensive exploration and go straight to planning.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  For CLI argument parsing in Rust, the standard choice is clap - it&amp;#39;s the most popular library with excellent subcommand&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  support, derive macros for clean code, and built-in version/help handling. This will scale well as you add more commands like&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  task add, task list, etc.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Let me write up a plan for you.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’ll then come up with a plan, and it usually write it out to a file somewhere:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Updated plan&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ⎿  Wrote 56 lines to ../../.claude/plans/shiny-dancing-cray.md&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     # Plan: CLI Argument Parsing Infrastructure&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     ## Goal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Set up command line argument parsing for the task tracking app with a `task version` subcommand.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     ## Approach&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Use **clap** with derive macros - the standard Rust CLI library.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     ## Changes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     … +46 lines (ctrl+o to expand)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can go read the file if you want to, but it’s not needed. Claude is going to
eventually present the plan to you directly, and you’ll review it before moving on.
Claude will also probably ask you a question or maybe even a couple, depending.
There’s a neat little TUI for responding to its questions, it can even handle
multiple questions at once:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● I&amp;#39;ve drafted a plan using clap with derive macros. Before finalizing, I have one question:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;────────────────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ☐ CLI Library&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Which CLI parsing library would you prefer?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;❯ 1. clap (Recommended)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Most popular, feature-rich, excellent subcommand support, built-in help/version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  2. argh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Simpler and lighter, derive-based, from Google&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  3. Manual parsing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Use std::env::args directly, no dependencies, more boilerplate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  4. Type something.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;────────────────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Chat about this&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Skip interview and plan immediately&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Enter to select · ↑/↓ to navigate · Esc to cancel&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For those of you that don’t write Rust, this is a pretty good response! Clap is
the default choice in the ecosystem, arg is a decent option too, and doing it
yourself is always possible. I’m going to choose clap, it’s great. If you’re not
sure about the question, you can arrow down to “Chat about this” and discuss it
more.&lt;/p&gt;
&lt;p&gt;Here’s why you don’t need to read the file: Claude will pitch you on its plan:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● User answered Claude&amp;#39;s questions:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ⎿  · Which CLI parsing library would you prefer? → clap (Recommended)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Clap it is. The plan is ready - it adds clap with derive macros and sets up the subcommand structure with task version as the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  first command. This gives you a solid foundation to add more commands later.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Ready to code?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Here is Claude&amp;#39;s plan:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Plan: CLI Argument Parsing Infrastructure&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Goal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Set up command line argument parsing for the task tracking app with a task version subcommand.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Approach&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Use clap with derive macros - the standard Rust CLI library.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Changes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 1. Update Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Add clap dependency with derive feature:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; [dependencies]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; clap = { version = &amp;quot;4&amp;quot;, features = [&amp;quot;derive&amp;quot;] }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 2. Update src/main.rs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; - Define a Cli struct with clap derive macros&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; - Define a Commands enum for subcommands (starting with Version)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; - Implement the version subcommand to print the version from Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Structure:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; use clap::{Parser, Subcommand};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; #[derive(Parser)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; #[command(name = &amp;quot;task&amp;quot;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; #[command(about = &amp;quot;A task tracking application&amp;quot;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; struct Cli {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #[command(subcommand)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     command: Commands,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; #[derive(Subcommand)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; enum Commands {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     /// Print version information&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Version,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; fn main() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     let cli = Cli::parse();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     match cli.command {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;         Commands::Version =&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;             println!(&amp;quot;task {}&amp;quot;, env!(&amp;quot;CARGO_PKG_VERSION&amp;quot;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;         }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Verification&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 1. Run cargo build to ensure it compiles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 2. Run ./target/debug/tasks version to verify it prints &amp;quot;task 0.1.0&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 3. Run ./target/debug/tasks --help to verify help output works&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Would you like to proceed?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ❯ 1. Yes, clear context and auto-accept edits (shift+tab)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   2. Yes, auto-accept edits&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   3. Yes, manually approve edits&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   4. Type here to tell Claude what to change&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ctrl-g to edit in VS Code · ~/.claude/plans/shiny-dancing-cray.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is pretty good! Now, if you like this plan, you can select #3. Remember,
we’re not auto accepting just yet! Don’t worry about the difference between 1
and 2 now, we’ll talk about it someday. But, I actually want Claude to tweak
this plan, I wouldn’t run &lt;code&gt;./target/debug/tasks version&lt;/code&gt;, I would do &lt;code&gt;cargo run -- version&lt;/code&gt;. So I’m going to go down to four and type literally that to Claude:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I wouldn’t run &lt;code&gt;./target/debug/tasks version&lt;/code&gt;, I would do &lt;code&gt;cargo run -- version&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And Claude replies:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Good point - let me update the verification section.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Updated plan&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ⎿  /plan to preview&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      51&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      52  ## Verification&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      53  1. Run `cargo build` to ensure it compiles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      54 -2. Run `./target/debug/tasks version` to verify it prints &amp;quot;task 0.1.0&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      55 -3. Run `./target/debug/tasks --help` to verify help output works&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      54 +2. Run `cargo run -- version` to verify it prints &amp;quot;task 0.1.0&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      55 +3. Run `cargo run -- --help` to verify help output works&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then presents the menu again. See, this is where the leverage of “Claude
figures out what I mean” can be helpful: I only told it about &lt;code&gt;version&lt;/code&gt;, but it
also changed to &lt;code&gt;cargo run -- --help&lt;/code&gt; as well. However, there’s a drawback too:
we didn’t tell Claude we wanted to have help output! However, this is also a
positive: Claude considered help output to be so basic that it’s suggesting it
for our plan. It’s up to you to decide if this is an overreach on Claude’s part.
In my case, I’m okay with it because it’s so nearly automatic with Clap and it’s
something I certainly want in my tool, so I’m going to accept this plan.&lt;/p&gt;
&lt;p&gt;Iterate with Claude until you’re happy with the plan, and then do the same.&lt;/p&gt;
&lt;p&gt;I’m not going to paste all of the diffs here, but for me, Claude then went and
did the plan: it added the dependency to &lt;code&gt;Cargo.toml&lt;/code&gt;, it added the needed code
to &lt;code&gt;src/main.rs&lt;/code&gt;, it ran &lt;code&gt;cargo build&lt;/code&gt; to try and do the build. Oh yeah, here’s
a menu we haven’t seen yet:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Bash command&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   cargo build 2&amp;gt;&amp;amp;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   Build the Rust project&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Do you want to proceed?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ❯ 1. Yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   2. Yes, and don&amp;#39;t ask again for cargo build commands in /home/stat/tmp/tasks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   3. No&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; Esc to cancel · Tab to add additional instructions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a more interesting question than the auto-edit thing. Claude won’t run
commands without you signing off on them. If you’re okay with letting Claude run
this command every time without asking, you can choose 2, and if you want to
confirm every time, you can type 1. Completely up to you.&lt;/p&gt;
&lt;p&gt;Now it ran &lt;code&gt;cargo run -- version&lt;/code&gt;, and &lt;code&gt;cargo run -- --help&lt;/code&gt;. Everything looked
good, so I see:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Done. The CLI infrastructure is set up:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - cargo run -- version outputs task 0.1.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - cargo run -- --help shows the help with available commands&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  You now have a foundation to add more subcommands to the Commands enum as you build out the task tracking features.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that’s it, we’ve built our first feature! Yeah, it’s pretty small, and in
this case, we probably could have copy/pasted the documentation, but again,
that’s not the point right now: we’re just trying to take very small steps
forward to get used to working with the tool. We &lt;em&gt;want&lt;/em&gt; it to be something
that’s quick for us to verify. We are spending more time here than we would if
we did it by hand, because that time isn’t wasted: it’s time learning. As we
ramp up the complexity of what we can accomplish, we’ll start seeing speed
gains. But we’re deliberately going slow and doing little right now.&lt;/p&gt;
&lt;h2 id=&quot;stretch-your-legs&quot;&gt;Stretch your legs&lt;/h2&gt;
&lt;p&gt;From here, that’s exactly what I’d like you to do: figure out where the limits
are. Try something slightly larger, slightly harder. Try to do stuff with just a
prompt, and then throw that commit away and try it again with plan mode. See
what stuff you need plan mode for, and what you can get away with with just a
simple prompt.&lt;/p&gt;
&lt;p&gt;I’ll leave you with an example of a prompt I might try next: asking Cladue for
their opinion on what you should do. The next thing I’d do in this project is to
switch back into planning mode and ask this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;what do you think is the best architecture for this tracking app? we haven’t
discussed any real features, design, or requirements. this is mostly a little
sample application to practice with, and so we might not need a real database,
we might get away with a simple file or files to track todos. but maybe
something like sqlite would still be appropriate. if we wanted to implement a
next step for this app, what do you think it should be?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here’s what Claude suggested:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Great question - this is the kind of design discussion that&amp;#39;s valuable before diving into implementation. Let me share my&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  thoughts.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Storage: File vs SQLite&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  For a practice app, I&amp;#39;d recommend starting with a simple JSON file:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - No additional dependencies - just serde + serde_json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - Human-readable - you can inspect/edit ~/.tasks.json directly&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - Focus on app logic - learn clap, error handling, and Rust patterns without database complexity&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - Easy to migrate later - if you outgrow it, moving to SQLite is a good exercise in itself&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  SQLite is great but adds cognitive load (SQL, migrations, connection handling). For a practice app, that complexity might&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  distract from the core learning.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Recommended Next Step&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  The natural progression is the core CRUD operations. I&amp;#39;d suggest implementing task add next:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  task add &amp;quot;Buy groceries&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  This introduces:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - Taking arguments in subcommands (clap)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - Reading/writing a data file (serde)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - Defining your Task struct (what fields? id, description, created_at, completed?)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - Error handling patterns&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  After that: task list, then task done &amp;lt;id&amp;gt;, then task remove &amp;lt;id&amp;gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ☐ Next step&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;What would you like to tackle next?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;❯ 1. task add (Recommended)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Add a task with a description, stored in a JSON file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  2. task list first&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Set up storage and list (empty at first), then add&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  3. Use SQLite instead&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     Start with SQLite from the beginning for the learning experience&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  4. Type something.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Chat about this&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Skip interview and plan immediately&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Enter to select · ↑/↓ to navigate · Esc to cancel&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This plan is pretty solid. But again, it’s a demo app. The important part is,
you can always throw this away if you don’t like it. So try some things. Give
Claude some opinions and see how they react. Try small features, try something
larger. Play around. But push it until Claude fails.&lt;/p&gt;
&lt;h2 id=&quot;what-to-do-when-claude-fails&quot;&gt;What to do when Claude fails&lt;/h2&gt;
&lt;p&gt;At some point, you will run into problems. Maybe you already have! What you
should do depends on the failure mode.&lt;/p&gt;
&lt;p&gt;The first failure you’re gonna run into is “I don’t like the code!” Maybe Claude
just does a bad job. You have two options: the first is to just tell Claude to
fix it. Claude made a mess, Claude can clean it up. In more extreme cases, you
may want to just simply &lt;code&gt;jj abandon&lt;/code&gt; or &lt;code&gt;git reset --hard&lt;/code&gt; and start again.
Honestly, the second approach is better in a lot of cases, but I’m not going to
always recommend it just yet. The reason why it is is that it gives you some
time to reflect on why Claude did a bad job. But we’re gonna talk about that as
the next post in this series! So for now, stick to the ‘worse’ option: just tell
Claude to fix problems you find.&lt;/p&gt;
&lt;p&gt;The second kind of failure is one where Claude just really struggles to get
things right. It looks in the wrong places in your codebase, it tries to find a
bug and can’t figure it out, it misreads output and that leads it astray, etc.
This kind of failure is harder to fix with the tools you have available to you
right now. What matters is taking note of them, so that you can email them to
me, haha. I mean, feel free to do that, and I can incorporate specific
suggestions into the next posts, but also, just being able to reflect on what
Claude struggles with is a good idea generally. You’ll be able to fix them
eventually, so knowing what you need to improve matters.&lt;/p&gt;
&lt;h2 id=&quot;what-is-compaction&quot;&gt;What is “compaction”?&lt;/h2&gt;
&lt;p&gt;If Claude works long enough, you’ll see something about “compaction.” We haven’t
discussed things at a deep enough level to really understand this yet, so don’t
worry about it! You may want to note one thing though: Claude tends to do worse
after compaction, in my opinion. So one way to think about this is, “If I see
compaction, I’ve tried to accomplish too large a task.” Reflect on if you could
have broken this up into something smaller.&lt;/p&gt;
&lt;p&gt;We’ll talk about this more in the next post.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So that’s it! Let Claude write some code, in a project you don’t care about. Try
bigger and harder things until you’re a bit frustrated with its failures. You
will hit the limits, because you’re not doing any of the intermediate techniques
to help Claude do a good job. But my hope is, by running into these issues,
you’ll understand the motivation for those techniques, and will be able to
better apply them in the future.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on BlueSky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3mcznckciyk2e&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;post s-12mzi62&quot;&gt;&lt;svg class=&quot;logo s-12mzi62&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;div class=&quot;aside s-12mzi62&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; class=&quot;avatar-wrapper s-12mzi62&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-12mzi62&quot;/&gt;&lt;/a&gt; &lt;div class=&quot;line s-12mzi62&quot;&gt;&lt;/div&gt;&lt;/div&gt; &lt;div class=&quot;main s-12mzi62&quot;&gt;&lt;div class=&quot;meta s-12mzi62&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-12mzi62&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-12mzi62&quot;&gt;&lt;span class=&quot;display-name s-12mzi62&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-12mzi62&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;span aria-hidden=&quot;true&quot; class=&quot;dot s-12mzi62&quot;&gt;·&lt;/span&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mbu3gbqrwk2y&quot; title=&quot;January 7, 2026 at 6:20 PM&quot; class=&quot;date s-12mzi62&quot;&gt;&lt;time datetime=&quot;2026-01-07T18:20:23.515Z&quot;&gt;Jan 7&lt;/time&gt;&lt;/a&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-small s-1lecfnd&quot;&gt;Getting started with Claude for software development: &lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/getting-started-with-claude-for-software-development/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/gett...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/getting-started-with-claude-for-software-development/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;Getting started with Claude for software development&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;Blog post: Getting started with Claude for software development by Steve Klabnik&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;Agentic development basics: &lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/agentic-development-basics/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/agen...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/agentic-development-basics/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;Agentic development basics&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;Blog post: Agentic development basics by Steve Klabnik&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2026-01-22T16:48:55.938Z&quot; class=&quot;date s-hik11q&quot;&gt;January 22, 2026 at 4:48 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;38 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;38&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;1 repost&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;1&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mcznckciyk2e&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 6 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;</content:encoded></item><item><title>How to think about Gas Town</title><link>https://steveklabnik.com/writing/how-to-think-about-gas-town/</link><guid isPermaLink="true">https://steveklabnik.com/writing/how-to-think-about-gas-town/</guid><description>I want to continue with my series on how you can use Claude Code for software development , but I have at least two posts I need to write first. This post is one of those two. Thanks for all of the kind words you all have said about the first post in the series, I’ll absolutely…</description><pubDate>Thu, 15 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I want to continue with my &lt;a href=&quot;/series/getting-started-with-claude-code&quot;&gt;series on how you can use Claude Code for software
development&lt;/a&gt;, but I have at least two posts I need to write
first. This post is one of those two. Thanks for all of the kind words you all
have said about the first post in the series, I’ll absolutely be continuing it,
hopefully next week.&lt;/p&gt;
&lt;p&gt;With that out of the way… let’s talk about Gas Town. If you’re not familiar,
it’s a project from Steve Yegge that has a lot of people having a lot of
feelings. Steve launched Gas Town just under two weeks ago, and in general, his
posts about it have brought out a reaction that has varied from “what the
fuck?!?” to “I don’t get it.” I’ll link Bryan here, not to pick on him, but sort
of the opposite: I think this is a very normal response to all of this, and
especially from him:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:ucct3fwwarzd7rety6nzq4cc/app.bsky.feed.post/3mcft3omsa226&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:ucct3fwwarzd7rety6nzq4cc&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:ucct3fwwarzd7rety6nzq4cc/bafkreibajqtfkfkb7tkctsl42q747tekfc4yuek5dhjbe7plc24c7b3rti&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:ucct3fwwarzd7rety6nzq4cc&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Bryan Cantrill&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@bcantrill.bsky.social&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;WTAF
&lt;a target=&quot;_blank&quot; href=&quot;https://steve-yegge.medium.com/gas-town-emergency-user-manual-cf0e4556d74b&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steve-yegge.medium.com/gas-town-eme...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steve-yegge.medium.com/gas-town-emergency-user-manual-cf0e4556d74b&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:ucct3fwwarzd7rety6nzq4cc/bafkreick2ibnbvizxsiafszp6qkaf3gegryrxxfhu2qweaa2ddghl74zwa&quot; alt=&quot;&quot; class=&quot;thumbnail s-rtbqd8&quot;/&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;Gas Town Emergency User Manual&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;It’s been a busy 12 days since I launched Gas Town. ️I’ve merged over 100 PRs from nearly 50 contributors, adding 44k lines of code that no…&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steve-yegge.medium.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2026-01-14T19:39:13.273Z&quot; class=&quot;date s-hik11q&quot;&gt;January 14, 2026 at 7:39 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;148 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;148&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;32 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;32&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:ucct3fwwarzd7rety6nzq4cc/post/3mcft3omsa226&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 30 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;
&lt;p&gt;However, I’m also not exactly a normal person:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3mcfylftvw22s&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;post s-12mzi62&quot;&gt;&lt;svg class=&quot;logo s-12mzi62&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;div class=&quot;aside s-12mzi62&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; class=&quot;avatar-wrapper s-12mzi62&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-12mzi62&quot;/&gt;&lt;/a&gt; &lt;div class=&quot;line s-12mzi62&quot;&gt;&lt;/div&gt;&lt;/div&gt; &lt;div class=&quot;main s-12mzi62&quot;&gt;&lt;div class=&quot;meta s-12mzi62&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-12mzi62&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-12mzi62&quot;&gt;&lt;span class=&quot;display-name s-12mzi62&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-12mzi62&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;span aria-hidden=&quot;true&quot; class=&quot;dot s-12mzi62&quot;&gt;·&lt;/span&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mcfyeyndzs2s&quot; title=&quot;January 14, 2026 at 9:13 PM&quot; class=&quot;date s-12mzi62&quot;&gt;&lt;time datetime=&quot;2026-01-14T21:13:54.475Z&quot;&gt;Jan 14&lt;/time&gt;&lt;/a&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-small s-1lecfnd&quot;&gt;normal people: gas town is insane and yegge is on drugs

me, problematic french philosophy enjoyer: i dunno this seems not that weird at all

almost going to grad school broke me a little bit, i think&lt;/p&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;&quot;You can use Polecats without the Refinery&quot; is too out there for you?&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;div class=&quot;image-embed is-bordered is-aligned s-t3k6fc&quot;&gt;&lt;div class=&quot;single-item tl tr bl br is-standalone s-t3k6fc&quot; style=&quot;aspect-ratio: 500/522&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreiakmz36gmfjffm3scdr4s3mx5k63d5xjbplfsgi4bbmyjmnki6t4q&quot; alt=&quot;you are like a little baby, watch this&quot; class=&quot;image s-t3k6fc&quot;/&gt; &lt;div class=&quot;placeholder s-t3k6fc&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;time datetime=&quot;2026-01-14T21:17:29.649Z&quot; class=&quot;date s-hik11q&quot;&gt;January 14, 2026 at 9:17 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;32 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;32&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;1 repost&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;1&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mcfylftvw22s&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 3 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;
&lt;p&gt;So, today I’d like to talk about Gas Town, and what I think Yegge is doing.&lt;/p&gt;
&lt;h2 id=&quot;what-is-gas-town&quot;&gt;What is Gas Town?&lt;/h2&gt;
&lt;p&gt;Gas town is two things simultaneously: something that’s kind of boring and
obvious, and something that’s opaque and confusing, illegible almost.&lt;/p&gt;
&lt;p&gt;If you’ve found yourself saying “what?!?” when reading about Gas Town, this post
is for you.&lt;/p&gt;
&lt;p&gt;I want to start with the boring and obvious, and move into the opaque and
illegible.&lt;/p&gt;
&lt;h2 id=&quot;gas-town-is-inevitable&quot;&gt;Gas Town is inevitable&lt;/h2&gt;
&lt;p&gt;Okay, so I almost went with “Gas Town is Inevitable” as the title of this post,
but I think that’s a bit too provocative, and not quite accurate. I do think
&lt;em&gt;something like&lt;/em&gt; Gas Town was going to be tried by someone, sometime. That’s the
inevitable part. This is because Gas Town isn’t really that novel, actually.&lt;/p&gt;
&lt;p&gt;Here’s what Gas Town is: you have a workspace. In that workspace, you have
projects. Each project has a bug tracker, used like normal: feature requests and
bug reports. Gas Town is software that allows you to instruct AI agents to
autonomously knock out those bugs.&lt;/p&gt;
&lt;p&gt;That’s it.&lt;/p&gt;
&lt;p&gt;This isn’t a fundamentally novel idea. The novel part comes in that it’s agents
doing the work, not humans.&lt;/p&gt;
&lt;p&gt;This is why I describe it as “inevitable,” it’s an idea that pretty logically
follows from the idea of “a software agent can successfully complete programming
tasks.” Humans find a big list of tasks to be a useful way to organize work, so
there’s no reason to believe that agents would not. So you follow this idea
wherever it takes you. That’s the experimental part of Gas Town: does this work?
Can it work? We don’t know! Steve is trying.&lt;/p&gt;
&lt;p&gt;One level of abstraction deeper, Steve is using some pretty tried and true ideas
here from Erlang. There’s supervisor trees, mailboxes, stuff like that. This is
a pretty solid base to work from! Erlang is legendary in these spaces for a reason.&lt;/p&gt;
&lt;p&gt;Anyway yeah. That’s really just it. Unless you’re particularly interested in
this topic or question, that’s really all you need to know about Gas Town to
understand it.&lt;/p&gt;
&lt;p&gt;So why all of the weird terminology?&lt;/p&gt;
&lt;h2 id=&quot;opacity-and-community-building&quot;&gt;Opacity and community building&lt;/h2&gt;
&lt;p&gt;AI is weird. The tools are very different than we’re used to. If 2025 was any
measure, 2026 is going to be a very interesting year for this profession. I know
I’m personally re-thinking a lot of sacred cows that I’ve worshipped for my
whole career. I don’t think all of them are bad, but I do think that things are
weird enough that it’s worth trying to figure things out from first principles
again.&lt;/p&gt;
&lt;p&gt;And that’s where I think Steve is at too.&lt;/p&gt;
&lt;p&gt;And I’ll also be honest, I’ve been slowly working myself into thinking about all
of this stuff too. I even have my own little project I started this week,
&lt;a href=&quot;https://github.com/steveklabnik/docket&quot;&gt;docket&lt;/a&gt;, which is sort of one step down a road that Gas Town is many
miles down already. I wasn’t going to talk about Docket for a while, if ever,
but I think that maybe if Gas Town is too much, two thousand lines of Rust and a
little CLI may make more sense to you.&lt;/p&gt;
&lt;p&gt;But that’s sort of the problem here: while Steve and I are very different,
there’s one way in which we’re the same: people read our blogs. I know that
projects I do get attention, heck, &lt;a href=&quot;https://rue-lang.dev/&quot;&gt;Rue&lt;/a&gt; is not really ready for public
consumption, really. But because people find the stuff I mess around with to be
interesting, it got a lot of attention, far disproportionate for what it is. You
can put strings into an array, but you can’t even get them out yet! It’s just
too early!&lt;/p&gt;
&lt;p&gt;So, what do you do if you:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Know your projects get attention.&lt;/li&gt;
&lt;li&gt;You also want like-minded people to come on this journey with you.&lt;/li&gt;
&lt;li&gt;You don’t want to waste time explaining things to people who don’t get it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You reach for a tool that many people have used over the years: you get weird
with it.&lt;/p&gt;
&lt;p&gt;There’s many examples of this happening in art and political movements. A pretty
famous one you might have heard of is &lt;a href=&quot;https://en.wikipedia.org/wiki/Surrealism&quot;&gt;Surrealism&lt;/a&gt;. One of the core
ideas of surrealism is that they’re trying to unlock the power of the
subconscious mind, bypassing the conscious to (hopefully) reveal deeper, more
profound truths.&lt;/p&gt;
&lt;p&gt;One of my favorite surrealist works is &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Treachery_of_Images&quot;&gt;“La Trahison des images”&lt;/a&gt; by
René Magritte. It is a painting of a pipe, with some words below: “Ceci n’est
pas une pipe” or “This is not a pipe.” At first, most people’s reaction to the
work is “uhhhh but that is a pipe?” But what the work is asking you to do is
think a little bit harder: this isn’t a pipe. It’s a painting of a pipe. That we
tend to conflate the image of something with the thing is a bit weird, if you
think about it a bit more. Why do we do that, anyway? What is the connection
between language, reality, images, and thoughts?&lt;/p&gt;
&lt;p&gt;The painting was made in 1929, so these ideas are a bit more mainstream by now,
so you may not find this particular line of inquiry to be illuminating, but you
know, that’s what happens 97 years later.&lt;/p&gt;
&lt;p&gt;Anyway. So if you’re someone who is going to attract attention, and want to
engage with a subset of those people, but also push away others, you could do
worse than trying to go surreal. It’s something that would be helpful both for
challenging assumptions, as well as for finding fellow travelers while repelling
those who aren’t interested in the same goals.&lt;/p&gt;
&lt;p&gt;Maybe he is on metaphorical drugs. But that’s deliberate, is all I’m saying. And
maybe drugs aren’t your thing, and that’s fine too.&lt;/p&gt;
&lt;h2 id=&quot;is-this-a-good-thing&quot;&gt;Is this a good thing?&lt;/h2&gt;
&lt;p&gt;I also want to to make a few other things clear: I haven’t talked to Steve about
any of this, this is me just talking about what I see. Also, I haven’t tried Gas
Town myself, and I’m not sure I will. This is because while I’m somewhat aligned
with Steve’s train of thought here, I’m also not entirely.&lt;/p&gt;
&lt;p&gt;I’m more interested in watching from afar. And that’s because, well, I have some
concerns with the way that Gas Town is doing things. But I’m also glad that he’s
trying it. It’s a rocket ship, and a lot of those exploded in the early days.
Tons of people died trying to invent the airplane. Some of their ideas were bad,
but eventually, enough of the conceptual space was explored to figure out the
good ideas.&lt;/p&gt;
&lt;h2 id=&quot;one-example-question&quot;&gt;One example question&lt;/h2&gt;
&lt;p&gt;What I want to leave you with is an example of the kind of experimentation I’m
seeing in Gas Town.&lt;/p&gt;
&lt;p&gt;At Oxide, &lt;a href=&quot;https://oxide.computer/principles&quot;&gt;they talk a lot about their values&lt;/a&gt;. It was a thing I really
appreciated about working there. On Monday, there was an episode of Oxide and
Friends on the topic of one of Oxide’s values as it applies to LLMs: Rigor.&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:6235fybsui2cjt4fcspdbwpd/app.bsky.feed.post/3mcfgktcrbs2n&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:6235fybsui2cjt4fcspdbwpd&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:6235fybsui2cjt4fcspdbwpd/bafkreidqaixw7yj2vj64nd7ixiqncujwo6trchymloh2bycaorqg7bjkhy&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:6235fybsui2cjt4fcspdbwpd&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Adam Leventhal&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@ahl.bsky.social&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;On Monday, &lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:sl3g3nhnad34sfhjnqdivbzd&quot; class=&quot;mention s-1lecfnd&quot;&gt;@sunshowers.io&lt;/a&gt; and &lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:ctphcgyhnllfluywokibtrgb&quot; class=&quot;mention s-1lecfnd&quot;&gt;@davidcrespo.bsky.social&lt;/a&gt; joined me and &lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:ucct3fwwarzd7rety6nzq4cc&quot; class=&quot;mention s-1lecfnd&quot;&gt;@bcantrill.bsky.social&lt;/a&gt; to talk about their use of LLMs for building software--not to make vibe-coded one-offs, but to build much *more* robust systems software.&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://youtu.be/fmFt4-jjEc0&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:6235fybsui2cjt4fcspdbwpd/bafkreiahoa3iyfh5cgirajxzhq5wafzqinzzqeh3piwzscs2mkt2ureu2u&quot; alt=&quot;&quot; class=&quot;thumbnail s-rtbqd8&quot;/&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;Oxide and Friends 1/12/2026 -- Engineering Rigor in the LLM Age&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;YouTube video by Oxide Computer Company&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;youtu.be&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2026-01-14T15:55:02.860Z&quot; class=&quot;date s-hik11q&quot;&gt;January 14, 2026 at 3:55 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;56 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;56&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;17 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;17&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:6235fybsui2cjt4fcspdbwpd/post/3mcfgktcrbs2n&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 2 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;
&lt;p&gt;Gas Town is &lt;em&gt;aggressively&lt;/em&gt; not rigorous. And while rigor is a great value to
have, when you’re in an experimental mindset, relaxing rigor can be a valid
strategy to move forward.&lt;/p&gt;
&lt;p&gt;But I think there’s a really interesting question to explore there: in the same
way that we can use LLMs in a rigorous way, is there a form of rigor that works
with AI agents merging code into trunk? What do we &lt;em&gt;really&lt;/em&gt; mean by “rigor”? Is
it synonymous with “tests pass”? Does it mean that the state of the system must
be fully rigorous up front? Or is rigor an end state we work towards?&lt;/p&gt;
&lt;p&gt;I am skeptical, but that’s also exactly why I’m thinking about such things. For
folks who are trying to reckon seriously with AI and the impact it will have on
software development, I think 2026 is a year to open your mind, challenge
assumptions, and re-consider what actually matters. The outcome of that might be
“yeah, we were right before and these ideas are bad,” but I have a sneaking
suspicion that the world has changed, and some old assumptions do not hold any
longer.&lt;/p&gt;
&lt;p&gt;We’ll find out.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on BlueSky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3mcia32tae22j&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;How to think about Gas Town: &lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/how-to-think-about-gas-town/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/how-...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/how-to-think-about-gas-town/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;How to think about Gas Town&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;Blog post: How to think about Gas Town by Steve Klabnik&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2026-01-15T18:36:50.633Z&quot; class=&quot;date s-hik11q&quot;&gt;January 15, 2026 at 6:36 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;138 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;138&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;18 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;18&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mcia32tae22j&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 21 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;</content:encoded></item><item><title>Getting started with Claude for software development</title><link>https://steveklabnik.com/writing/getting-started-with-claude-for-software-development/</link><guid isPermaLink="true">https://steveklabnik.com/writing/getting-started-with-claude-for-software-development/</guid><description>2025 was an interesting year in many ways. One way in which it was interesting for me is that I went from an AI hater to a pretty big user. And so I’ve had a few requests for a “using Claude” guide, so I figure new year, why not give it a shot? The lack of this kind of content…</description><pubDate>Wed, 07 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;2025 was an interesting year in many ways. One way in which it was interesting
for me is that I went from an AI hater to a pretty big user. And so I’ve had a
few requests for a “using Claude” guide, so I figure new year, why not give it a
shot? The lack of this kind of content was something that really frustrated me
starting out, so feels like a good thing to contribute to the world.&lt;/p&gt;
&lt;p&gt;This post is going to be for software developers that are interested in learning
about using these tools as of early 2026. I’m going to spend this post talking
about some background, and then the first steps towards getting your feet wet.
If folks like it, I’ll follow up with more. There’s a lot here. I’m going to be
speaking about Claude directly, because it’s the tool I use the most, but a lot
of this should apply to other platforms as well.&lt;/p&gt;
&lt;h2 id=&quot;theres-a-lot-here&quot;&gt;There’s a lot here&lt;/h2&gt;
&lt;p&gt;The first thing I want to say on this topic is that there’s a reason that this
is the first post of possibly many: there’s a lot here, as I just said above.
This matters more than you might think at first. Becoming productive with LLMs
is not actually easy, no matter what other people tell you. A lot of advice in
this space is given by people who don’t have a teaching background, and have
forgotten how much work they’ve put in to get to where they are.&lt;/p&gt;
&lt;p&gt;I liken it to vim: everyone acknowledges that modal editing is a different way
of working. We joke about how hard it is to learn how to quit vim if you’ve
accidentally started it up. But many people also acknowledge that the learning
curve is worth it, due to the power you get. I think of LLMs like vim: they’re
not super easy to get real results from, but the time invested can be worth it.&lt;/p&gt;
&lt;p&gt;It’s also worth saying up front: maybe it’s not worth it, for you. I don’t fault
anyone for not wanting to spend time learning a new tool, especially in a space
that’s moving as fast as this one. Effectively everything I’m going to talk
about in this post has really only come into its own in the last 12-14 months.
Maybe in another 12 months this post will be useless. I don’t know. But just
like we might not find the time to learn vim to be worth it over just using a
more normal editor, that doesn’t mean that deciding that all of this isn’t worth
your time isn’t a rational, reasonable decision to make. You’re not going to be
“left behind” or whatever some of the boosters say, in the same way that you
don’t need to learn vim to do software dev. We aren’t doing vim vs emacs wars
here. We’re saying “hey if you want to learn vim this is how I think you can,
and if not, that’s fine.”&lt;/p&gt;
&lt;p&gt;Furthermore, because there’s so much to cover, this post is going to be
background and step 1. Because otherwise it would be too dang long. You can’t
just read ten thousand words on this stuff and be an expert, you have to go
actually use the things. So you should be taking time between each post to go
and do that, and so not putting it all in one place should give you natural
breakpoints to go and actually try this stuff out.&lt;/p&gt;
&lt;h2 id=&quot;intentionality&quot;&gt;Intentionality&lt;/h2&gt;
&lt;p&gt;The very first thing I want to say on this entire topic is something that I
think about a lot. I have generally had better outcomes with LLMs than a lot of
people I know. And that’s bothered me. And I’m not sure exactly why that is. But
I do have one idea.&lt;/p&gt;
&lt;p&gt;I like to approach this space in a … maybe “scientific” way is too strong, but
at least a rational one. I try things out, discard what doesn’t seem to work,
and keep what seems to work. I try and think critically about this space.&lt;/p&gt;
&lt;p&gt;However.&lt;/p&gt;
&lt;p&gt;I do think that the whole “vibe” term, while complicated in this space, is also
important. Vibes do matter, actually. I have some more science-y and some more
folks-y reasons that I believe this. But I do think that the attitude you bring
towards this process partially dictates your success, and I think you should be
conscious of that while you go on this journey.&lt;/p&gt;
&lt;p&gt;Is that too woo-y for you? Okay, let me make it concrete: I un-ironically believe
that swearing at Claude makes it perform worse. I think you will get better
results working with an LLM if you treat them like you’d treat a respected
co-worker, and you will get worse results if you berate, insult, or otherwise
mistreat them.&lt;/p&gt;
&lt;p&gt;This matters because I think that for a lot of LLM-skeptical people who give
this a shot, they may not actually go “Hey claude what’s your fucking problem”
(though I have literally seen this happen) they will tend to let their
frustrations show a bit more when things don’t work out. Use your emotional
regulation skills. It’s very okay to be critical in response to whatever Claude
does, but do it in a way that wouldn’t get you reported to HR in a healthy
company. Do this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why did you do it that way? I would have preferred if we did &amp;lt;this&amp;gt; instead.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Not this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Stop making such basic mistakes. You know that we do &amp;lt;this&amp;gt; and not &amp;lt;that&amp;gt;,
idiot.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think that being kind to people is good for you, but I also believe that even
if you’re a misanthrope, consider this a skill to get increased output from the
tool. I think a bit of anthropomorphization is actually a good thing here. We’ll
come back to that later during the more practical steps, but basically, that’s
the higher level principle at work: an LLM is not a person. But it is working
based off of language that people use. That’s its API. And so interacting with
it in the way you’d interact with a co-worker is, in my mind, the right way to
do it.&lt;/p&gt;
&lt;p&gt;Maybe I’ll elaborate on this belief someday. Or maybe not. I do this for
personal belief reasons more than anything else. But it is something I want to
share.&lt;/p&gt;
&lt;h2 id=&quot;claude-web-vs-claude-code&quot;&gt;Claude web vs Claude Code&lt;/h2&gt;
&lt;p&gt;Okay! Now that we’ve got that out of the way, let’s talk about the various ways
you can use Claude! There’s a number of them, actually, but I want to focus on
two: on the web at &lt;a href=&quot;https://claude.ai&quot;&gt;https://claude.ai&lt;/a&gt;, and with &lt;a href=&quot;https://www.claude.com/product/claude-code&quot;&gt;Claude
Code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Using Claude in these ways is fundamentally different. Both have pros and cons.
For real actual software development, you want to use Claude Code. This is due
to the “agentic loop”, which you’ll learn more about in a bit. But for your
first steps, using it via the web is okay. It’s mostly just important to know
that your experience using the web interface is not going to be the same as
using Claude Code. If I only had access to the web interface, I wouldn’t be so
bullish on this stuff. But it is and can be useful. Especially when getting your
feet wet, as long as you can understand that they’re meaningfully different.&lt;/p&gt;
&lt;h2 id=&quot;plans-vs-api-pricing&quot;&gt;Plans vs API pricing&lt;/h2&gt;
&lt;p&gt;This gets into another topic that matters: money. Another reason I do not fault
anyone for not spending time with these tools is that vim is free, whereas
Claude is very much not. However.&lt;/p&gt;
&lt;p&gt;There are three major factors in the money equation: Claude Web vs Claude Code,
which models you have access to, and the actual cost. Let’s talk about them.&lt;/p&gt;
&lt;p&gt;You can load up &lt;a href=&quot;https://claude.ai&quot;&gt;https://claude.ai&lt;/a&gt; and talk to Claude right now for free. But
you cannot use Claude Code without paying. So if you want to start incredibly
small, using the website at first before you fork over money can make sense.
Again, that’s fine, just know that the experience is different. But it may be a
good way to start.&lt;/p&gt;
&lt;p&gt;In 2024 and 2025, there was a good argument that you needed to be on a paid plan
because that’s how you got access to the latest models. While this is still true
to some degree, models have advanced far enough that the changes are less
important over time. I do think that in the first half of 2026, it still does
matter to a degree. Basically, the difference between Claude 3, 4, and 4.5 is
significant, but for me, Claude 4 was good enough a year ago to get real work
done. I’m not 100% sure which one you get for free today, but it’s at least
fine. And I think that by the time the next round of models come out, the ones
you’ll have access to for free will be basically good enough to make this
question moot. But do know that you get what you pay for, and paying for things
does get you better performance.&lt;/p&gt;
&lt;p&gt;(Speaking of models, you’ll hear Claude referred to in three ways: Haiku,
Sonnet, and Opus. As the names imply, worst to best there, though also, fastest
to slowest. Sonnet, especially the 4.5 version, is pretty good for everything.
Opus 4.5 is wonderful. Haiku is great for certain things.)&lt;/p&gt;
&lt;p&gt;As for actual cost: there’s $20/month, $100/month, and $200/month plans, as well
as “you pay per API call.” You might be tempted to think “I’ll just pay per API
call and keep my usage down.” This is a reasonable thing to think, and also a
terrible mistake to make. You get a lot of bang for your buck with the plans. To
give you an idea, I recently hit my weekly limit last night on the $200/month
plan, and my estimated usage for that week (which again, I’m paying $50 for)
would have been $1440.73 if I were paying by the API call. Now, I am a very
heavy user, but the point stands: as someone trying out these tools, it is way
easy to spend more than $20 of API tokens. If you want to give these tools a
real shot, come up with a spare $20, sign up for the cheap plan, and then cancel
after your experiment is over. You get access to Claude Code and you’ve capped
your spend. It’s a win/win. There’s some good secondary effects of trying to be
frugal here but I think that’s more of an intermediate than an advanced topic,
to be honest. I think worrying about the money while you build these skills is a
distraction. Cap your spend via a plan so that way you can not stress out about
breaking the bank.&lt;/p&gt;
&lt;p&gt;Okay, with all of that background out of the way: let’s talk about your first
steps here.&lt;/p&gt;
&lt;h2 id=&quot;your-first-steps-a-conversation&quot;&gt;Your first steps: a conversation&lt;/h2&gt;
&lt;p&gt;Everyone is interested in the ability of LLMs to generate code. But I think
that’s actually step 2, not step 1. The way I want you to start using these
tools is purely &lt;em&gt;read-only&lt;/em&gt; at first. This is also why the website is okay to
get started with too; Claude Code is far better at generating code than the site
is, but we’re not going to start by writing code.&lt;/p&gt;
&lt;p&gt;Find some code you’ve written recently. It can be literally anything. Load up
&lt;a href=&quot;https://claude.ai&quot;&gt;https://claude.ai&lt;/a&gt;, and type:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Claude! Can we talk about this code?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And then paste your code in. You don’t need any fancy prompting techniques. You
don’t even need to say what language it is. Just give it some code. It could be
ten lines, it could be a hundred. I wouldn’t recommend a thousand to start.&lt;/p&gt;
&lt;p&gt;Claude will probably respond with some sort of basic analysis of what you’ve
done, and then a question. I gave it ~50 lines of code a friend and I were
discussing recently, and it gave me this back:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sure! This looks like &amp;lt;description of what it does&amp;gt;. You’ve got &amp;lt;three things
that the code does&amp;gt;.&lt;/p&gt;
&lt;p&gt;What’s on your mind about it? Are you thinking through the design, running
into a specific issue, or wanting feedback on a particular aspect?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From here, you have a ton of options of which way to go, but they really depend
on what you’ve pasted in. Here’s some fun prompt ideas:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do you think this code is idiomatic?&lt;/p&gt;
&lt;p&gt;If you could improve one thing about this code, what might it be?&lt;/p&gt;
&lt;p&gt;If I wanted to modify this code to do &amp;lt;something&amp;gt;, how would you go about
doing that?&lt;/p&gt;
&lt;p&gt;Are there any bugs in this code?&lt;/p&gt;
&lt;p&gt;Are there any security implications of this code I may not have thought about?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And so on. Anyway, the goal here is to just get used to this whole thing. It’s a
bit weird! It’s very different than talking to a compiler.&lt;/p&gt;
&lt;p&gt;If Claude says something you disagree with, push back a little, just like you
would a co-worker:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’m not sure I agree with that. The reason why is that in some other part of
the system, there’s &amp;lt;behavior&amp;gt; and so that would impact this sort of
decision.&lt;/p&gt;
&lt;p&gt;Why did you suggest that? I’d like to understand more.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Claude will absolutely not be right all of the time. And that’s okay! The goal
is to work together, not that this is a magic tool that suddenly solves all of
your problems.&lt;/p&gt;
&lt;h2 id=&quot;second-steps-bigger-questions&quot;&gt;Second steps: bigger questions&lt;/h2&gt;
&lt;p&gt;Once you’ve done this a few times, you might want to graduate to Claude Code.
The reason for this is that you can start to scale up your questions. Once
you’ve installed it and logged in, you’ll be at a terminal prompt. It might bug
you about creating a CLAUDE.md, don’t worry about that for now. Continue having
conversations with Claude about your codebase. The reason that this is a a big
step up is that before, you had to paste all of the code in. Now, Claude can go
find your code itself. Some prompts for you to try:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Please give me a code review of my codebase and suggest five things I could do
to improve it.&lt;/p&gt;
&lt;p&gt;Can you find any bugs in &amp;lt;component&amp;gt;?&lt;/p&gt;
&lt;p&gt;I’m curious about the performance of &amp;lt;component&amp;gt;, can we talk about it?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One thing I like to do here is have Claude double check my intuitions. A few
months ago, working on an application in Rust, I was considering a refactoring.
I hadn’t done it because I was worried that it would be tedious, take a while,
and maybe not improve the codebase. It might! But it might not. But putting in
the day or two to do the refactor wasn’t really worth finding out if maybe that
would be wasted. So, I asked Claude. This is an example of a bit longer of a
prompt:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Claude! I am considering refactoring my code. In a function like this:
&amp;lt;paste code&amp;gt;, I don’t like how I did things, and I’m considering doing it
like this instead: &amp;lt;paste code&amp;gt;. However, I know that changes the signature,
which impacts other code in the codebase. A few questions for you: 1. how many
function signatures would need to be updated if I made this change? 2. can you
show me what the code would look like if I did this refactoring on one of my
simpler endpoints? 3. can you show me what the code would look like if I did
this refactoring on one of my most complex endpoints?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Claude came back and said something like “250 signatures would need to change,
here’s the before and after using these two examples from your codebase.” Now,
Claude isn’t perfect: maybe it was actually 260 signatures. But the point is,
this helped me characterize my intuition here: it would be a non-trivial amount
of work. But I also got to see its impact on real code I had written, which
helped me decide if this refactoring would actually help me in some of the more
hairy parts of the codebase.&lt;/p&gt;
&lt;p&gt;Note that there’s not really any special “prompt engineering” going on here. You
don’t need to do “as a senior software engineer” or stuff like that. Just talk
to it like you’d talk to a person. It’s fine. That doesn’t mean that prompts are
useless, but this sort of optimization is an intermediate to advanced topic, and
frankly, I’m skeptical that at this point the “as an x” technique even helps.
More on that someday. The point is, you can start asking more complex questions
as you get more comfortable with the tool.&lt;/p&gt;
&lt;p&gt;Because Claude works asynchronously, you can just fire off questions like these
in the background, and come back to them when it’s done. Well, sorta. Let’s talk
about permissions before we wrap this up.&lt;/p&gt;
&lt;h2 id=&quot;permissions&quot;&gt;Permissions&lt;/h2&gt;
&lt;p&gt;By default, Claude will put you in an “ask before edits” mode. This is a good
way to start. It’ll check in with you before doing certain things, and you can
say yes or no. Please consider what it’s about to do, and give the answer you’re
comfortable with. Advanced users basically let Claude do whatever it wants, but
you’re not there yet, and there’s risks involved that aren’t obvious to you just
yet as a new user, so even though it can be a bit annoying to say yes every time
it asks, I’d encourage you to start off with minimal permissions. It gives you
the option to say “commands like this one are okay for the rest of my session”
and so when it wants to &lt;code&gt;grep&lt;/code&gt; or something, that can be nice to agree to, but
I’d encourage you to not use it for writing code just yet, and tell it no if it
asks. We’ll do that in a follow-up post.&lt;/p&gt;
&lt;h2 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h2&gt;
&lt;p&gt;So that’s my intro to getting started with Claude. Spend $20, talk to it like
you’d talk to a person, and use it as a means of getting feedback on your code,
don’t have it write anything just yet. Graduate to larger and larger questions
as you get comfortable with what it can do. Gently push back when you think it
gets out of line. But your goal here is a baseline understanding of what the
tool is capable of, not to vibe code out an entire app in an afternoon. These
skills may seem too basic, but I promise you, it gets harder from here, and so
you’ll want a solid foundation in read-only questions before we graduate to
having Claude write some code.&lt;/p&gt;
&lt;p&gt;I hope this was helpful to you.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on BlueSky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3mbu3gbqrwk2y&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;Getting started with Claude for software development: &lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/getting-started-with-claude-for-software-development/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/gett...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/getting-started-with-claude-for-software-development/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;Getting started with Claude for software development&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;Blog post: Getting started with Claude for software development by Steve Klabnik&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2026-01-07T18:20:23.515Z&quot; class=&quot;date s-hik11q&quot;&gt;January 7, 2026 at 6:20 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;338 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;338&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;51 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;51&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mbu3gbqrwk2y&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 29 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;</content:encoded></item><item><title>A tale of two Claudes</title><link>https://steveklabnik.com/writing/a-tale-of-two-claudes/</link><guid isPermaLink="true">https://steveklabnik.com/writing/a-tale-of-two-claudes/</guid><description>It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of…</description><pubDate>Tue, 10 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;It was the best of times, it was the worst of times, it was the age of wisdom,
it was the age of foolishness, it was the epoch of belief, it was the epoch of
incredulity, it was the season of Light, it was the season of Darkness, it was
the spring of hope, it was the winter of despair, we had everything before us,
we had nothing before us, we were all going direct to Heaven, we were all going
direct the other way—in short, the period was so far like the present period,
that some of its noisiest authorities insisted on its being received, for good
or for evil, in the superlative degree of comparison only.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Charles Dickens, &lt;em&gt;A Tale of Two Cities&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;I recently had two very different experiences with Claude Code. I wanted to
share them both, because I find the contrast interesting.&lt;/p&gt;
&lt;h2 id=&quot;claude-hates-tailwind-4&quot;&gt;Claude hates Tailwind 4&lt;/h2&gt;
&lt;p&gt;I have really been enjoying &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;TailwindCSS&lt;/a&gt;. I also have started several
web projects using it in the past year. Back in January, &lt;a href=&quot;https://tailwindcss.com/blog/tailwindcss-v4&quot;&gt;Tailwind released
version 4&lt;/a&gt;. Honestly, I am not a good enough Tailwind user to be able
to appreciate the new features, but I do prefer to keep my projects up to date.
So I’ve needed to update my Tailwind projects to version 4.&lt;/p&gt;
&lt;p&gt;Claude… is nearly completely useless for this.&lt;/p&gt;
&lt;p&gt;You’d think that upgrading a very popular CSS framework would be a
straightforward task. But Claude has failed to set it up multiple times. While
it’s true that Claude Code claims that its training cutoff is in January of
2025 in its system prompt, it seems to have a cutoff in March. Regardless, a
useful tool shouldn’t need to be explicitly trained on the latest version of a
framework to be able to help with it. Yet, it consistently fails to either set
up Tailwind 4 in new projects, or upgrade existing projects to this fourth
release.&lt;/p&gt;
&lt;p&gt;I did manage to get it to work earlier this week, when I &lt;a href=&quot;https://github.com/steveklabnik/steveklabnik.com/commit/fc7a5f6d0a8169e45d67891fe784bdf2270f14f9&quot;&gt;asked it to
update this website&lt;/a&gt;, but at this point, it was mostly just me messing
around. I wish I had saved the exact prompt, but basically I said something like
“you have failed me consistently in this task, so please search for upgrade
guides and the like to guide you in this update.” It did do that, but for some
reason, the upgrade tool couldn’t update my configs, and so it decided to do it
itself, and well, while this time it did manage to technically update, it didn’t
do it completely correctly. It removed the typography plugin, which I had to ask
it to put back. And it didn’t properly import the config into my global CSS,
which also caused weird issues. Regardless, it did manage to sort of do it,
after some coaxing, but this was a frustrating experience that was probably the
third or fourth time I had tried to get it to do this.&lt;/p&gt;
&lt;p&gt;While Tailwind 4 is a new major version release, it’s still incredibly popular,
and one of the hunches I have about LLM usage for coding is that more popular
tools will be easier for LLMs to use. This didn’t seem to be the case here,
though.&lt;/p&gt;
&lt;h2 id=&quot;claude-loves-elf&quot;&gt;Claude loves… ELF?&lt;/h2&gt;
&lt;p&gt;For… reasons, I am working on an assembler. Don’t worry about it, you may find
out about it someday, and you may not. It’s not for work, just for fun.&lt;/p&gt;
&lt;p&gt;Anyway, if you’re not familiar, basically this process turns assembly code into
machine code. Specifically, in this case, I’m encoding x86_64 assembly into an
ELF executable. ELF is a file format that is used by, among other things, Linux,
for executables.&lt;/p&gt;
&lt;p&gt;I’m working with Claude on this, and I again didn’t save my prompts, which I am
annoyed by, but I roughly said something like “please implement codegen such
that it produces an ELF executable” and let it go. I did not expect this to
work, or go well. As I said above, I sort of expect more common tasks to be
easier for LLMs, given that they have more training data. While I’m sure there’s
some code in Rust out there that does this, I still don’t expect it to be
anywhere near as common as TailwindCSS.&lt;/p&gt;
&lt;p&gt;A few minutes later, Claude said “hey, I did it!” For completely unrelated
reasons, I got a message from &lt;a href=&quot;https://bsky.app/profile/there.is.no.aarch64.mov&quot;&gt;Ixi&lt;/a&gt;, a friend of mine who would be
particularly interested in this project, and so I said something along the lines
of “hey, I’m working on a project you’d be interested in, claude has just made
some large claims:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Steve, we’ve successfully implemented a complete end-to-end x86-64 code
generation pipeline&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do you want to look at the PR together?” and they said yes.&lt;/p&gt;
&lt;p&gt;So I shared my screen, and we went through the PR together. It was pretty fine.
A lot of the stuff at first was normal, but a bit boring: the error handling was
fine, and maybe slightly different than I would have done, but it wasn’t so bad
that if a co-worker had sent in the PR, I would have objected to merging it.&lt;/p&gt;
&lt;p&gt;But Ixi noticed something:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;rust&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; instruction_size&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, instr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Instruction&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; u64&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        match&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; instr {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            Instruction&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Push&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(_) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            Instruction&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Pop&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(_) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These sizes are… wrong. They should (probably) be one byte. Fun! Most of the
code looked overall reasonable, though. So let’s look at that ELF it produced.&lt;/p&gt;
&lt;p&gt;I ran the executable, and it segfaulted. Surprise! While Claude did think it was
done, because it had produced an ELF file, and the tests were passing, it didn’t
actually work. Given that those sizes were wrong, this wasn’t really a surprise.
We decided to dig into the code a bit more, but first: I told Claude “hey, this
example you compiled segfaults, something is wrong, can you fix it?” Again, not
the exact prompt. I wish I had saved it, but I didn’t think I was writing this
blog post at the time, so I didn’t. But it was very basic like that. And I let
Claude go in the background while we took a look.&lt;/p&gt;
&lt;p&gt;We used &lt;code&gt;objdump -xd&lt;/code&gt; to see some of the information about the ELF file. We
ended up using &lt;code&gt;gdb&lt;/code&gt; to see where it was crashing:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Program received signal SIGSEGV, Segmentation fault.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     0x0000000000400093 in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #0  0x0000000000400093 in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #1  0x000000000040007d in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #2  0x0000000000000001 in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #3  0x00007fffffffddb3 in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #4  0x0000000000000000 in ?? ()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There’s no debug info here, so we only have addresses. There was a jump going to
an address that ends in &lt;code&gt;93&lt;/code&gt;. This is incorrect: &lt;code&gt;0x400093&lt;/code&gt; was three bytes into
a &lt;code&gt;movabs $0x24, rdi&lt;/code&gt;, so… we were jumping to the middle of an instruction,
which is nonsense, hence the segfault.&lt;/p&gt;
&lt;p&gt;(Now that I’m looking at this, I also find these other addresses suspect. I wish
I had taken better notes while we were looking at this… the point is this was
a quick check as to what was going on, and it was very clear that this is just
straight-up wrong.)&lt;/p&gt;
&lt;p&gt;How could this happen? Well, if the sizes of the instructions were wrong, when
the code figures out where to jump, it would go to the wrong place, as it would
mis-calculate how far away the jump target was. So this all made sense.
Hypothesis: instruction sizes are incorrect, which means the jump calculations
are incorrect, which means fail.&lt;/p&gt;
&lt;p&gt;I had to run, so we ended the call, but I left Claude running. A few minutes
later, I checked in on it, and that’s when I was really surprised.&lt;/p&gt;
&lt;p&gt;Claude had fixed the issue! It wasn’t really even about that, but also, how it
did so:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Bash(gdb -batch -ex &amp;quot;run&amp;quot; -ex &amp;quot;bt&amp;quot; --args ./debug_test)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ⎿  Program received signal SIGSEGV, Segmentation fault.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     0x0000000000400093 in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #0  0x0000000000400093 in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #1  0x000000000040007d in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #2  0x0000000000000001 in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #3  0x00007fffffffddb3 in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     #4  0x0000000000000000 in ?? ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Perfect! The crash is at 0x400093, which means the call&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;instruction is jumping to the wrong location. The issue is&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;in my relocation calculation. Let me examine this more carefully.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Looking at the hex dump again:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Entry point: 0x400078&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Call instruction: e8 16 00 00 00 (5 bytes)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Next instruction: 0x40007d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Target: 0x40007d + 0x16 = 0x400093&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  But the main function is actually at file offset 0x8A, which is&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  virtual address 0x40008A.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  The issue is in my symbol address calculation. Let me examine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  the assembler code:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hmmm. It’s kind of right, but also maybe not? I kept scrolling:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ● I found the issue! The assembler is calculating symbol&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  addresses relative to the start of the machine code (offset 0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  but when resolving relocations, it needs to account for the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  fact that the machine code will be loaded at the ELF entry&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  point address.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That also didn’t feel right? More scrollback through. It was creating sample
programs in assembly, and then assembling them, and then examining the contents
of the files. It was double checking its assumptions and understanding of the
code, and then, there it was:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;There&amp;#39;s a bug in my instruction size calculation. Let me check&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;the instruction_size function:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Read(src/lib.rs)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ⎿  Read 20 lines (ctrl+r to expand)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;● Found the bug! Mov(, _) =&amp;gt; 10 is wrong. It assumes all mov&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  instructions are 10 bytes (mov reg, imm64), but mov rdi, rax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  is only 3 bytes.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay, wait… &lt;code&gt;mov&lt;/code&gt;, and not &lt;code&gt;push&lt;/code&gt;/&lt;code&gt;pop&lt;/code&gt;? Sure enough, not only had it figured
out that &lt;code&gt;push&lt;/code&gt; and &lt;code&gt;pop&lt;/code&gt; were one byte, not two, but it had also figured out
that &lt;code&gt;cmp&lt;/code&gt; had a few forms with different sizes, and that &lt;code&gt;mov&lt;/code&gt; did too. After
fixing that… the executables worked!&lt;/p&gt;
&lt;p&gt;But really, the most impressive part is that it had basically done exactly what
we had done, but in the background, while we were looking at the code. It took a
little longer to get there, because it went down one rabbit hole, but it had
also found other bugs that weren’t immediately obvious to us. And, I’ll be extra
honest: while I understand what’s going on here, I am not super great at
&lt;code&gt;objdump&lt;/code&gt; and &lt;code&gt;gdb&lt;/code&gt;, and if Ixi wasn’t around, Claude would have probably found
this before me, if I were alone. This is part of why having friends is great,
but if I didn’t have that friend around at that moment, this would have
tremendously helped.&lt;/p&gt;
&lt;p&gt;I am also impressed because, as mentioned above: I would expect this task to be
much more rare than web development stuff. Yet, Claude did a far better job,
finding the issue quickly and fixing it, as opposed to the multiple times I gave
it a chance with Tailwind.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;What does this mean? I don’t know, but I figured I want to start documenting
these experiences, good and bad, and so I wanted to share both of these stories,
one good, and one bad.&lt;/p&gt;
&lt;p&gt;LLMs are not magic, or perfect, but I have found them to be useful. It’s
important to share both the successes, and also the failures. I’m hoping to do a
better job of tracking the prompts and details to give you a better
understanding of the specifics of how I’m using these tools, but the perfect is
the enemy of the good, and so these are the stories you’re going to get for now.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on Bluesky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3lrb6sb7fzl2i&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;A tale of two Claudes

&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/a-tale-of-two-claudes/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/a-ta...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/a-tale-of-two-claudes/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;A tale of two Claudes&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;Blog post: A tale of two Claudes by Steve Klabnik&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2025-06-10T15:17:05.751Z&quot; class=&quot;date s-hik11q&quot;&gt;June 10, 2025 at 3:17 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;57 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;57&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;9 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;9&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3lrb6sb7fzl2i&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 10 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;</content:encoded></item><item><title>I am disappointed in the AI discourse</title><link>https://steveklabnik.com/writing/i-am-disappointed-in-the-ai-discourse/</link><guid isPermaLink="true">https://steveklabnik.com/writing/i-am-disappointed-in-the-ai-discourse/</guid><description>Recently, something happened that made me kind of like, break a little bit. I’m still not entirely sure why this whole thing bothers me so much, but here’s a blog post about it. I happened to ask ChatGPT something for fun. I often do this just to see what it says, and if I feel…</description><pubDate>Wed, 28 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently, something happened that made me kind of like, break a little bit. I’m
still not entirely sure why this whole thing bothers me so much, but here’s a
blog post about it. I happened to ask ChatGPT something for fun. I often do this
just to see what it says, and if I feel like it’s right or wrong. I tabbed over
to another tab, and the top post on my Bluesky feed was something along these
lines:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ChatGPT is not a search engine. It does not scan the web for information. You
cannot use it as a search engine. LLMs only generate statistically likely
sentences.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The thing is… ChatGPT was over there, in the other tab, searching the web. And
the answer I got was pretty good.&lt;/p&gt;
&lt;p&gt;I’m not linking to the post because I don’t want to continue to pile on to this
person, because it’s not really about them. It’s about the state of the
discourse around AI.&lt;/p&gt;
&lt;p&gt;I am not claiming that ChatGPT is an amazing search engine. What is breaking my
brain a little bit is that all of the discussion online around AI is so
incredibly polarized. This isn’t a “the middle is always right” sort of thing
either, to be clear. It’s more that both the pro-AI and anti-AI sides are loudly
proclaiming things that are pretty trivially verifiable as not true. On the anti
side, you have things like the above. And on the pro side, you have people
talking about how no human is going to be programming in 2026. Both of these
things fail a very basic test of “@gork is this true?” (sorry this is a bad
joke, if you’re not terminally &lt;del&gt;38 years old&lt;/del&gt;on Bluesky, substitute “chat is
this true?” (sorry this is a bad joke, if you’re over the age of 40 substitute
“is this true?” (sorry humor is one way of coping with stress and writing this
post is stressing me out))).&lt;/p&gt;
&lt;p&gt;Oh, and of course, ethical considerations of technology are important too. I’d
like to have better discussions about that as well. &lt;del&gt;For me, capabilities precede
the ethical dimension, because the capabilities inform what is and isn’t
ethical.&lt;/del&gt; (EDIT: I am a little unhappy with my phrasing here. A shocker given
that I threw this paragraph together in haste! What I’m trying to get at is that
I think these two things are inescapably intertwined: you cannot determine the
ethics of something until you know what it is. I do not mean that capabilities
are somehow more important.) But I also know reasonable people disagree with me
on that. Let’s talk about it! I mean that for &lt;em&gt;all&lt;/em&gt; dimensions of this topic,
not solely the capabilities.&lt;/p&gt;
&lt;p&gt;Now, it’s not like I expect everyone to come to some consensus on a technology.
For example, a lot of people like Rust and hate Go, and a lot of people like Go
and hate Rust. That’s fine. That doesn’t bother me. But there’s something
different about this that is driving me up a wall.&lt;/p&gt;
&lt;p&gt;To be clear, I am not particularly pro or anti AI. Here’s what I currently
think:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LLMs can be helpful for software development.&lt;/li&gt;
&lt;li&gt;LLMs for software development are being oversold by some people who stand to
gain a lot of money from them.&lt;/li&gt;
&lt;li&gt;LLMs for software development are being undersold by some people who have
decided for various reasons that they do not like the technology.&lt;/li&gt;
&lt;li&gt;Not everyone who dislikes LLMs is uninformed, just like not everyone who likes
LLMs is a grifter.&lt;/li&gt;
&lt;li&gt;AI art is often terrible and slightly creepy.&lt;/li&gt;
&lt;li&gt;I have seen AI art that was fine. This is very rare.&lt;/li&gt;
&lt;li&gt;AI writing is often bland and boring but better than the average person’s
writing. Just to be clear, I feel like an elitist dick saying that. And maybe
I am. I dunno, working on it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anyway, just to be clear, (how many times can you say ‘just to be clear’ in one
post, Steve, come on (at what level of nested parenthetical do I implement some
sort of interlocutor into my blog like &lt;a href=&quot;https://xeiaso.net/&quot;&gt;Xe&lt;/a&gt;)) I don’t think that if you
think LLMs suck at software development, you’re wrong. What I want to be able to
do is talk about it in a reasonable way, and figure out why we have different
opinions. That is it. But for some reason, being able to do that feels
impossible.&lt;/p&gt;
&lt;p&gt;I’m going to end up blogging more about AI/LLMs in the near future, to get some
more of this stuff off of my chest and to try and be the change I want to see in
the world. So expect some of that, probably. But until then, if you happen to
have any links to reasonable discussion on these topics, I’d love to see them.
Here’s two posts I recently read and really enjoyed thinking about what they
were saying:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://annievella.com/posts/the-software-engineering-identity-crisis/&quot;&gt;The Software Engineering Identity Crisis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jmsdnns.com/tech/algo-underground/&quot;&gt;Algorithmic Underground&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks. If you want to get mad about this post please just ignore me.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on Bluesky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3lqaqe6uc3c2u&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;I am disappointed in the AI discourse &lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/i-am-disappointed-in-the-ai-discourse/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/i-am...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/i-am-disappointed-in-the-ai-discourse/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;I am disappointed in the AI discourse&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2025-05-28T17:33:29.514Z&quot; class=&quot;date s-hik11q&quot;&gt;May 28, 2025 at 5:33 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;911 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;911&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;267 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;267&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3lqaqe6uc3c2u&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 209 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;</content:encoded></item></channel></rss>