<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://antonkuzmenko.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://antonkuzmenko.dev/" rel="alternate" type="text/html" /><updated>2025-11-21T07:49:06+00:00</updated><id>https://antonkuzmenko.dev/feed.xml</id><title type="html">Anton Kuzmenko</title><subtitle>TIL and other stuff</subtitle><author><name>Anton Kuzmenko</name></author><entry><title type="html">I Turned My Idle PC into a Linux Gaming Console</title><link href="https://antonkuzmenko.dev/2025/11/19/i-turned-my-idle-pc-into-linux-gaming-console/" rel="alternate" type="text/html" title="I Turned My Idle PC into a Linux Gaming Console" /><published>2025-11-19T00:00:00+00:00</published><updated>2025-11-19T00:00:00+00:00</updated><id>https://antonkuzmenko.dev/2025/11/19/i-turned-my-idle-pc-into-linux-gaming-console</id><content type="html" xml:base="https://antonkuzmenko.dev/2025/11/19/i-turned-my-idle-pc-into-linux-gaming-console/"><![CDATA[<p>When Valve announced the new Steam Machine, I was genuinely excited. I’m not an avid gamer myself. I built a solid PC thinking I would get back into gaming, but after playing through <a href="https://www.thewitcher.com/us/en/witcher3">The Witcher 3</a> and <a href="https://www.focus-entmt.com/en/games/warhammer-40000-space-marine-2">Space Marine 2</a>, life happened, priorities changed, and the machine sat silent. But I have a son who is just old enough that we can start playing games together on a console.</p>

<p>The catch? I don’t own a console. But I <em>do</em> have that idle PC collecting dust.</p>

<p>I immediately thought: maybe I can just install <a href="https://store.steampowered.com/steamos">SteamOS</a> on it, like what powers the <a href="https://store.steampowered.com/steamdeck/">Steam Deck</a> and the future <a href="https://store.steampowered.com/sale/steammachine">Steam Machine</a>. After a little digging, I found out the official SteamOS isn’t something they make publicly available for installation on arbitrary hardware.</p>

<h3 id="the-need-for-console-simplicity">The Need for Console Simplicity</h3>

<p>The good news is that any Linux distribution can benefit from the kernel optimizations Valve baked into SteamOS. But that wasn’t the point.</p>

<p>As someone who runs two Linux servers in my home lab, I actively did <strong>not</strong> want to deal with the inherent complexity of Linux when it comes to gaming, especially in the living room.</p>

<p>The goal was simple:</p>

<p><em>I needed a distribution that functioned exactly like SteamOS.</em></p>

<p>I wanted a PC that would boot directly into the full-screen Steam interface, requiring no password (I know, bad security, but it’s dedicated to gaming in my living room, so I don’t care), and requiring zero terminal interaction. I just wanted to turn it on and play.</p>

<h3 id="the-search-bazzite-chimeraos-and-the-ugly-website-winner">The Search: Bazzite, ChimeraOS, and the “Ugly Website” Winner</h3>

<p>I started researching. It turns out there are a few interesting solutions out there. The two primary ones that stood out were <strong>Bazzite</strong> and <strong>ChimeraOS</strong>.</p>

<ul>
  <li><a href="https://chimeraos.org/">ChimeraOS</a> aims to turn any PC into a gaming console. However, I found the website wasn’t particularly useful, and their wiki is hosted on GitHub, which I find harder to navigate compared to standard documentation sites.</li>
  <li><a href="https://bazzite.gg/">Bazzite</a> is a custom Fedora Atomic image optimized for smooth gaming on desktops and handhelds. It features a specific <code class="language-plaintext highlighter-rouge">bazzite-deck</code> variant for a console-like experience and receives frequent updates from upstream Fedora.</li>
</ul>

<p>Bazzite, in particular, has a beautiful, stunning website. But frankly, the “immutable OS” approach felt like overkill for my needs. I haven’t had much experience with atomic distributions, and I wasn’t looking to learn a new paradigm. If something goes wrong on a gaming rig, I can just reinstall it in 20 minutes. I’m well-versed in standard Fedora, so sticking to a mutable, familiar base felt safer.</p>

<p>I also tend to be wary when a project feels <em>too</em> polished or tries to appeal to everyone. I often prefer software driven by a handful of opinionated maintainers who build exactly what they want to use.</p>

<p>Then there was <strong><a href="https://nobaraproject.org/">Nobara</a></strong>.</p>

<p>The Nobara Project is an unofficial Fedora spin maintained by <a href="https://github.com/GloriousEggroll">GloriousEggroll</a> (the developer behind <a href="https://github.com/GloriousEggroll/proton-ge-custom">Proton-GE</a>). It comes pre-loaded with essential gaming tools like Steam, Lutris, OBS, and WINE dependencies, along with specific gaming optimizations baked right in. It even ships with NVIDIA drivers pre-configured if you choose the correct ISO.</p>

<p>Nobara stood out as probably the best option. The <a href="https://wiki.nobaraproject.org/">wiki</a> was easy to read and navigable, which gave me confidence that if things broke, I could fix them.</p>

<p>The main website, however, looked honestly utilitarian - definitely made by engineers rather than designers. But to me, that’s often a good sign. It suggests a project built by a true Linux user who cares more about the code than the marketing. The main point was a large, visible download button, a clear project overview, and the promise that it fixes most issues to offer a better gaming experience out of the box.</p>

<p>It is a solo project (one maintainer), which suggests a singular, focused vision. And based on the description, it did everything I ever wanted: <strong>It basically turns your PC into a Linux gaming console</strong>.</p>

<h3 id="the-installation">The Installation</h3>

<p>My setup is fairly modern but modest: it has an AMD Ryzen 5 5600 CPU, 16 GB of RAM, and an NVIDIA RTX 4060 GPU. It’s perfect for 1080p gaming, which is good enough for playing with my son on the TV.</p>

<p>The installation process was incredibly simple and quick.</p>

<ul>
  <li>I downloaded <a href="https://nobaraproject.org/download-nobara/">the ISO</a>.</li>
  <li>I used <a href="https://etcher.balena.io/">Balena Etcher</a> to burn it to a USB.</li>
  <li>I reinstalled it onto my PC.</li>
</ul>

<p>The whole process probably took me 20 minutes.</p>

<p><img src="/img/2025-11-20/nobara-grub-menu.png" alt="Nobara GRUB menu" /></p>

<h3 id="the-console-experience">The Console Experience</h3>

<p>Once it booted, I was immediately greeted with the Steam interface. Fantastic.</p>

<p>I logged in. This was the only non-console part of the experience: I painfully entered my long Steam password using the controller. (In retrospect, I should have just connected a keyboard, but hey, I was trying to fully immerse myself in the controller experience).</p>

<p>After logging into Steam, all my games were immediately playable. Out of my modest library of seven games, six worked right away: <em>The Witcher 3</em>, the <em>Portal</em> games (1 and 2), and <em>Warhammer 40,000: Space Marine 2</em>. <em>GTA 5</em> was the only exception, but honestly, I don’t care about that game anymore.</p>

<p><img src="/img/2025-11-20/htpc-steam-library.jpg" alt="Steam Library in Game Mode" /></p>

<p>I cannot express how shocked I was. Seven or eight years ago, trying to play games on Linux was impossible - nothing worked. Now, the experience is smooth and simple, and it just works.</p>

<p>We immediately installed <a href="https://store.steampowered.com/app/212480/Sonic__AllStars_Racing_Transformed_Collection/">Sonic Racing</a> and <a href="https://store.steampowered.com/app/996770/Moving_Out/">Moving Out</a>, which were tons of fun. I’m now waiting for Black Friday to buy more games, including the <a href="https://goose.game/">Untitled Goose Game</a>.</p>

<h3 id="the-one-glitch-and-the-upside-of-low-res-4k">The One Glitch and the Upside of Low-Res 4K</h3>

<p>Like any good piece of tech, it wasn’t <em>entirely</em> flawless, but the issues were minor. I had one issue with Nobara: an extremely annoying, jumping, flickering interface <em>within</em> the Steam UI. The moment I turned on a game, the flickering stopped.</p>

<p><img src="/img/2025-11-20/htpc-steam-flickering.gif" alt="Flickering Steam UI" /></p>

<p>After some searching, I discovered the real issue was the interface scaling. I dialed it down a notch, and it stopped.</p>

<p><img src="/img/2025-11-20/htpc-display-scaling-flicker-fix.jpg" alt="Steam display scaling settings" /></p>

<p>The only other technical curiosity I had revolved around the display setup:</p>

<ul>
  <li>My PC case is a chunky black tower that doesn’t exactly blend with the living room decor, but my wife accepted it solely because it lacks flashy RGB lights.</li>
  <li>I play on a 4K TV.</li>
  <li>For some reason, the only resolution Nobara offered was 1080p.</li>
</ul>

<p>I initially planned to spend time figuring out how to force at least 1440p resolution, because 1080p felt like “not enough” on a 4K screen. But then I started playing games, and sitting four or five feet away on the couch, <strong>I couldn’t even tell the difference</strong>. The quality is perfect, and I see absolutely no problems playing in 1080p on a 4K TV.</p>

<p>Why should I care if it already looks good?</p>

<h3 id="life-in-the-linux-console-era">Life in the Linux Console Era</h3>

<p>The overall experience still feels surreal to me.</p>

<p>As a techie, the lack of a password at boot bothers me slightly, but I’m getting used to it since this machine is purely dedicated to Steam and games.</p>

<p>Upgrades are handled directly in the SteamOS interface, which is amazing - I don’t need to do anything, I just hit “update” and it works. Since it’s technically Fedora Linux underneath, I can occasionally switch to the desktop experience, connect a mouse and keyboard, and manually upgrade the system dependencies and packages. This doesn’t sound awful to me at all.</p>

<p><img src="/img/2025-11-20/htpc-living-room.jpg" alt="My HTPC setup in the living room" /></p>

<p>Honestly, this feels like the beginning of the end for Windows for personal use.</p>

<p>If you have an old gaming rig that you aren’t using and you don’t have a console, <strong>it’s pretty easy. Just go do it</strong>.</p>

<p>Good luck and have fun!</p>]]></content><author><name>Anton Kuzmenko</name></author><category term="linux" /><category term="gaming" /><category term="steamos" /><summary type="html"><![CDATA[When Valve announced the new Steam Machine, I was genuinely excited. I’m not an avid gamer myself. I built a solid PC thinking I would get back into gaming, but after playing through The Witcher 3 and Space Marine 2, life happened, priorities changed, and the machine sat silent. But I have a son who is just old enough that we can start playing games together on a console.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://antonkuzmenko.dev/img/2025-11-20-i-turned-my-idle-pc-into-linux-gaming-console.jpg" /><media:content medium="image" url="https://antonkuzmenko.dev/img/2025-11-20-i-turned-my-idle-pc-into-linux-gaming-console.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The Step-by-Step Prompt Fallacy: Boosting AI Reasoning</title><link href="https://antonkuzmenko.dev/2024/09/06/the-step-by-step-prompt-fallacy-boosting-ai-reasoning/" rel="alternate" type="text/html" title="The Step-by-Step Prompt Fallacy: Boosting AI Reasoning" /><published>2024-09-06T00:00:00+00:00</published><updated>2024-09-06T00:00:00+00:00</updated><id>https://antonkuzmenko.dev/2024/09/06/the-step-by-step-prompt-fallacy-boosting-ai-reasoning</id><content type="html" xml:base="https://antonkuzmenko.dev/2024/09/06/the-step-by-step-prompt-fallacy-boosting-ai-reasoning/"><![CDATA[<p>A popular trick to make prompts better is to add “step-by-step” instructions. For example:</p>

<blockquote>
  <p>Think through the query step by step before giving your final answer.</p>
</blockquote>

<p>This rarely improves the outcome. The reason is that models aren’t obligated to write their reasoning before providing the final answer.</p>

<p>Asking the model to write out its thought process can significantly improve reasoning and outcomes. For example:</p>

<blockquote>
  <p>Reason through the query inside <code class="language-plaintext highlighter-rouge">&lt;thinking&gt;</code> tags, and then provide your final response.</p>
</blockquote>

<p>To enhance this approach further, consider adding a reflection step:</p>

<blockquote>
  <p>Reason through the query inside <code class="language-plaintext highlighter-rouge">&lt;thinking&gt;</code> tags, and then provide your final response. If you detect that you made a mistake in your reasoning at any point, correct yourself inside <code class="language-plaintext highlighter-rouge">&lt;reflection&gt;</code> tags.</p>
</blockquote>

<p>For even more effective results, you can assign a specific role to the AI:</p>

<blockquote>
  <p>You are a world-class AI system, capable of complex reasoning and reflection. Reason through the query inside <code class="language-plaintext highlighter-rouge">&lt;thinking&gt;</code> tags, and then provide your final response inside <code class="language-plaintext highlighter-rouge">&lt;output&gt;</code> tags. If you detect that you made a mistake in your reasoning at any point, correct yourself inside <code class="language-plaintext highlighter-rouge">&lt;reflection&gt;</code> tags.</p>
</blockquote>

<h3 id="example-in-action">Example in Action</h3>

<p>I am using Claude 3.5 Sonnet for this example. Notice how Claude reflects on its reasoning and corrects itself when it detects a mistake in the example thread.</p>

<p>Prompt:</p>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>You are a world-class AI system, capable of complex reasoning and reflection. Reason through the query inside <span class="nt">&lt;thinking&gt;</span> tags, and then provide your final response inside <span class="nt">&lt;output&gt;</span> tags. If you detect that you made a mistake in your reasoning at any point, correct yourself inside <span class="nt">&lt;reflection&gt;</span> tags.

I am working on a feature where I need to show a list of 10 records with the most number of similar records. The similarity is a score from 0 to 1, identified by running a vector similarity search for each record to all records in the database. I plan to store record ids and their similarity scores in a table if the similarity score is above a certain threshold. I need your help to find a way to store and keep this list updated efficiently. Can you help me with this? Think carefully.
</code></pre></div></div>

<p>Response:</p>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;thinking&gt;</span>
To approach this problem, let's break it down into steps and consider the most efficient way to implement and maintain this feature:
<span class="p">
1.</span> Data Storage:
<span class="p">   -</span> We need a table to store the similarity scores between records.
<span class="p">   -</span> Let's call this table <span class="sb">`record_similarities`</span>.
<span class="p">   -</span> Structure: <span class="sb">`record_id`</span>, <span class="sb">`similar_record_id`</span>, <span class="sb">`similarity_score`</span>
<span class="p">   -</span> We'll add an index on <span class="sb">`record_id`</span> and <span class="sb">`similarity_score`</span> for faster querying.
<span class="p">
2.</span> Updating mechanism:
<span class="p">   -</span> We need to update this table whenever a new record is added or an existing record is modified.
<span class="p">   -</span> We can use callbacks in our Rails model to trigger the similarity calculation.
<span class="p">
3.</span> Querying for top similar records:
<span class="p">   -</span> We need an efficient way to query the top 10 records with the most similar records.
<span class="p">   -</span> This could be done with a SQL query that counts the number of similar records for each record and orders by this count.
<span class="p">
4.</span> Optimization considerations:
<span class="p">   -</span> Calculating similarity for all pairs of records could be computationally expensive as the dataset grows.
<span class="p">   -</span> We might want to implement a background job to handle these calculations asynchronously.
<span class="p">   -</span> We should consider using a threshold for similarity scores to reduce the number of stored similarities.
<span class="p">
5.</span> Keeping the list updated:
<span class="p">   -</span> We need to ensure that the list of top 10 records is always current.
<span class="p">   -</span> We could cache this list and invalidate the cache whenever the <span class="sb">`record_similarities`</span> table is updated.

Let's outline a potential implementation:
<span class="nt">&lt;/thinking&gt;</span>

<span class="nt">&lt;output&gt;</span>

Here's a proposed implementation to efficiently store and keep updated a list of 10 records with the most number of similar records:
<span class="p">
1.</span> Create a new table to store similarity scores:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">class</span> <span class="nc">CreateRecordSimilarities</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Migration</span><span class="p">[</span><span class="mf">6.1</span><span class="p">]</span>
  <span class="k">def</span> <span class="nf">change</span>
    <span class="n">create_table</span> <span class="ss">:record_similarities</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
      <span class="n">t</span><span class="p">.</span><span class="nf">references</span> <span class="ss">:record</span><span class="p">,</span> <span class="ss">null: </span><span class="kp">false</span><span class="p">,</span> <span class="ss">foreign_key: </span><span class="kp">true</span>
      <span class="n">t</span><span class="p">.</span><span class="nf">references</span> <span class="ss">:similar_record</span><span class="p">,</span> <span class="ss">null: </span><span class="kp">false</span><span class="p">,</span> <span class="ss">foreign_key: </span><span class="p">{</span> <span class="ss">to_table: :records</span> <span class="p">}</span>
      <span class="n">t</span><span class="p">.</span><span class="nf">float</span> <span class="ss">:similarity_score</span><span class="p">,</span> <span class="ss">null: </span><span class="kp">false</span>

      <span class="n">t</span><span class="p">.</span><span class="nf">timestamps</span>
    <span class="k">end</span>

    <span class="n">add_index</span> <span class="ss">:record_similarities</span><span class="p">,</span> <span class="p">[</span><span class="ss">:record_id</span><span class="p">,</span> <span class="ss">:similarity_score</span><span class="p">]</span>
  <span class="k">end</span>
<span class="k">end</span>
<span class="p">```</span>
<span class="p">
2.</span> Add a model for the new table:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">class</span> <span class="nc">RecordSimilarity</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
  <span class="n">belongs_to</span> <span class="ss">:record</span>
  <span class="n">belongs_to</span> <span class="ss">:similar_record</span><span class="p">,</span> <span class="ss">class_name: </span><span class="s1">'Record'</span>

  <span class="n">validates</span> <span class="ss">:similarity_score</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span><span class="p">,</span> <span class="ss">numericality: </span><span class="p">{</span> <span class="ss">greater_than: </span><span class="mi">0</span><span class="p">,</span> <span class="ss">less_than_or_equal_to: </span><span class="mi">1</span> <span class="p">}</span>
<span class="k">end</span>
<span class="p">```</span>
<span class="p">
3.</span> Add callbacks to the Record model to update similarities:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">class</span> <span class="nc">Record</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
  <span class="n">has_many</span> <span class="ss">:record_similarities</span>
  <span class="n">has_many</span> <span class="ss">:similar_records</span><span class="p">,</span> <span class="ss">through: :record_similarities</span>

  <span class="n">after_create</span> <span class="ss">:calculate_similarities</span>
  <span class="n">after_update</span> <span class="ss">:recalculate_similarities</span>

  <span class="no">SIMILARITY_THRESHOLD</span> <span class="o">=</span> <span class="mf">0.5</span>

  <span class="kp">private</span>

  <span class="k">def</span> <span class="nf">calculate_similarities</span>
    <span class="no">RecordSimilarityJob</span><span class="p">.</span><span class="nf">perform_later</span><span class="p">(</span><span class="nb">self</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">recalculate_similarities</span>
    <span class="no">RecordSimilarity</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">record: </span><span class="nb">self</span><span class="p">).</span><span class="nf">or</span><span class="p">(</span><span class="no">RecordSimilarity</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">similar_record: </span><span class="nb">self</span><span class="p">)).</span><span class="nf">destroy_all</span>
    <span class="n">calculate_similarities</span>
  <span class="k">end</span>
<span class="k">end</span>
<span class="p">```</span>
<span class="p">
4.</span> Create a background job to handle similarity calculations:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">class</span> <span class="nc">RecordSimilarityJob</span> <span class="o">&lt;</span> <span class="no">ApplicationJob</span>
  <span class="n">queue_as</span> <span class="ss">:default</span>

  <span class="k">def</span> <span class="nf">perform</span><span class="p">(</span><span class="n">record</span><span class="p">)</span>
    <span class="no">Record</span><span class="p">.</span><span class="nf">where</span><span class="p">.</span><span class="nf">not</span><span class="p">(</span><span class="ss">id: </span><span class="n">record</span><span class="p">.</span><span class="nf">id</span><span class="p">).</span><span class="nf">find_each</span> <span class="k">do</span> <span class="o">|</span><span class="n">other_record</span><span class="o">|</span>
      <span class="n">similarity</span> <span class="o">=</span> <span class="n">calculate_similarity</span><span class="p">(</span><span class="n">record</span><span class="p">,</span> <span class="n">other_record</span><span class="p">)</span>
      <span class="k">if</span> <span class="n">similarity</span> <span class="o">&gt;=</span> <span class="no">Record</span><span class="o">::</span><span class="no">SIMILARITY_THRESHOLD</span>
        <span class="no">RecordSimilarity</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">record: </span><span class="n">record</span><span class="p">,</span> <span class="ss">similar_record: </span><span class="n">other_record</span><span class="p">,</span> <span class="ss">similarity_score: </span><span class="n">similarity</span><span class="p">)</span>
        <span class="no">RecordSimilarity</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">record: </span><span class="n">other_record</span><span class="p">,</span> <span class="ss">similar_record: </span><span class="n">record</span><span class="p">,</span> <span class="ss">similarity_score: </span><span class="n">similarity</span><span class="p">)</span>
      <span class="k">end</span>
    <span class="k">end</span>
    <span class="no">Rails</span><span class="p">.</span><span class="nf">cache</span><span class="p">.</span><span class="nf">delete</span><span class="p">(</span><span class="s1">'top_similar_records'</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="kp">private</span>

  <span class="k">def</span> <span class="nf">calculate_similarity</span><span class="p">(</span><span class="n">record1</span><span class="p">,</span> <span class="n">record2</span><span class="p">)</span>
    <span class="c1"># Implement your vector similarity calculation here</span>
    <span class="c1"># This is a placeholder implementation</span>
    <span class="nb">rand</span><span class="p">(</span><span class="mf">0.0</span><span class="o">..</span><span class="mf">1.0</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
<span class="p">```</span>
<span class="p">
5.</span> Add a method to fetch the top 10 records with most similar records:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">class</span> <span class="nc">Record</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
  <span class="c1"># ... existing code ...</span>

  <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">top_similar_records</span><span class="p">(</span><span class="n">limit</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span>
    <span class="no">Rails</span><span class="p">.</span><span class="nf">cache</span><span class="p">.</span><span class="nf">fetch</span><span class="p">(</span><span class="s1">'top_similar_records'</span><span class="p">,</span> <span class="ss">expires_in: </span><span class="mi">1</span><span class="p">.</span><span class="nf">hour</span><span class="p">)</span> <span class="k">do</span>
      <span class="no">Record</span><span class="p">.</span><span class="nf">joins</span><span class="p">(</span><span class="ss">:record_similarities</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">group</span><span class="p">(</span><span class="ss">:id</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="s1">'records.*, COUNT(record_similarities.id) as similar_count'</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">order</span><span class="p">(</span><span class="s1">'similar_count DESC'</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">limit</span><span class="p">(</span><span class="n">limit</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
<span class="p">```</span>

This implementation provides an efficient way to store and keep updated a list of records with the most similar records. It uses background jobs for similarity calculations, caches the results, and uses database indexing for faster queries. The cache is invalidated whenever new similarities are calculated, ensuring that the list stays up-to-date.

<span class="nt">&lt;/output&gt;</span>

<span class="nt">&lt;reflection&gt;</span>
Upon reflection, I realize that there's a potential improvement we could make to the implementation. In the current setup, we're creating two RecordSimilarity entries for each pair of similar records (one in each direction). This redundancy isn't necessary and could lead to increased storage requirements and slower queries as the dataset grows.

We can optimize this by only storing one RecordSimilarity entry per pair of records, always ensuring that the record_id is less than the similar_record_id. This will halve the number of entries in the RecordSimilarity table and simplify our queries.

Here's how we could modify the implementation to account for this:
<span class="nt">&lt;/reflection&gt;</span>

<span class="nt">&lt;output&gt;</span>

Let's update our implementation to store only one RecordSimilarity entry per pair of records:
<span class="p">
1.</span> Modify the RecordSimilarity model:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">class</span> <span class="nc">RecordSimilarity</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
  <span class="n">belongs_to</span> <span class="ss">:record</span>
  <span class="n">belongs_to</span> <span class="ss">:similar_record</span><span class="p">,</span> <span class="ss">class_name: </span><span class="s1">'Record'</span>

  <span class="n">validates</span> <span class="ss">:similarity_score</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span><span class="p">,</span> <span class="ss">numericality: </span><span class="p">{</span> <span class="ss">greater_than: </span><span class="mi">0</span><span class="p">,</span> <span class="ss">less_than_or_equal_to: </span><span class="mi">1</span> <span class="p">}</span>
  <span class="n">validate</span> <span class="ss">:record_id_less_than_similar_record_id</span>

  <span class="kp">private</span>

  <span class="k">def</span> <span class="nf">record_id_less_than_similar_record_id</span>
    <span class="k">if</span> <span class="n">record_id</span> <span class="o">&gt;=</span> <span class="n">similar_record_id</span>
      <span class="n">errors</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="ss">:record_id</span><span class="p">,</span> <span class="s2">"must be less than similar_record_id"</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
<span class="p">```</span>
<span class="p">
2.</span> Update the RecordSimilarityJob:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">class</span> <span class="nc">RecordSimilarityJob</span> <span class="o">&lt;</span> <span class="no">ApplicationJob</span>
  <span class="n">queue_as</span> <span class="ss">:default</span>

  <span class="k">def</span> <span class="nf">perform</span><span class="p">(</span><span class="n">record</span><span class="p">)</span>
    <span class="no">Record</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="s1">'id &gt; ?'</span><span class="p">,</span> <span class="n">record</span><span class="p">.</span><span class="nf">id</span><span class="p">).</span><span class="nf">find_each</span> <span class="k">do</span> <span class="o">|</span><span class="n">other_record</span><span class="o">|</span>
      <span class="n">similarity</span> <span class="o">=</span> <span class="n">calculate_similarity</span><span class="p">(</span><span class="n">record</span><span class="p">,</span> <span class="n">other_record</span><span class="p">)</span>
      <span class="k">if</span> <span class="n">similarity</span> <span class="o">&gt;=</span> <span class="no">Record</span><span class="o">::</span><span class="no">SIMILARITY_THRESHOLD</span>
        <span class="no">RecordSimilarity</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">record: </span><span class="n">record</span><span class="p">,</span> <span class="ss">similar_record: </span><span class="n">other_record</span><span class="p">,</span> <span class="ss">similarity_score: </span><span class="n">similarity</span><span class="p">)</span>
      <span class="k">end</span>
    <span class="k">end</span>
    <span class="no">Rails</span><span class="p">.</span><span class="nf">cache</span><span class="p">.</span><span class="nf">delete</span><span class="p">(</span><span class="s1">'top_similar_records'</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="kp">private</span>

  <span class="k">def</span> <span class="nf">calculate_similarity</span><span class="p">(</span><span class="n">record1</span><span class="p">,</span> <span class="n">record2</span><span class="p">)</span>
    <span class="c1"># Implement your vector similarity calculation here</span>
    <span class="c1"># This is a placeholder implementation</span>
    <span class="nb">rand</span><span class="p">(</span><span class="mf">0.0</span><span class="o">..</span><span class="mf">1.0</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
<span class="p">```</span>
<span class="p">
3.</span> Update the top_similar_records method:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">class</span> <span class="nc">Record</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
  <span class="c1"># ... existing code ...</span>

  <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">top_similar_records</span><span class="p">(</span><span class="n">limit</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span>
    <span class="no">Rails</span><span class="p">.</span><span class="nf">cache</span><span class="p">.</span><span class="nf">fetch</span><span class="p">(</span><span class="s1">'top_similar_records'</span><span class="p">,</span> <span class="ss">expires_in: </span><span class="mi">1</span><span class="p">.</span><span class="nf">hour</span><span class="p">)</span> <span class="k">do</span>
      <span class="no">Record</span><span class="p">.</span><span class="nf">joins</span><span class="p">(</span><span class="s2">"LEFT JOIN record_similarities rs1 ON records.id = rs1.record_id"</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">joins</span><span class="p">(</span><span class="s2">"LEFT JOIN record_similarities rs2 ON records.id = rs2.similar_record_id"</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">group</span><span class="p">(</span><span class="ss">:id</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="s1">'records.*, COUNT(rs1.id) + COUNT(rs2.id) as similar_count'</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">order</span><span class="p">(</span><span class="s1">'similar_count DESC'</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">limit</span><span class="p">(</span><span class="n">limit</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
<span class="p">```</span>

These changes will significantly reduce the storage requirements for the RecordSimilarity table and improve query performance. The top_similar_records method now counts similarities where the record appears in either the record_id or similar_record_id column.

This optimized implementation provides a more efficient solution to store and keep updated a list of 10 records with the most number of similar records.

<span class="nt">&lt;/output&gt;</span>
</code></pre></div></div>

<p>Follow-up prompt:</p>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Thank you! I think there is a bug in the updated implementation, specifically in the <span class="sb">`after_create :calculate_similarities`</span> and <span class="sb">`after_update :recalculate_similarities`</span> in the Record model.
</code></pre></div></div>

<p>Response:</p>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;thinking&gt;</span>
You're right to point this out. Let me review the implementation and identify the potential bug in the Record model callbacks.
<span class="p">
1.</span> The <span class="sb">`after_create :calculate_similarities`</span> callback:
<span class="p">   -</span> This seems fine as it triggers the RecordSimilarityJob for a newly created record.
<span class="p">
2.</span> The <span class="sb">`after_update :recalculate_similarities`</span> callback:
<span class="p">   -</span> This is where the bug likely exists. Let's examine it:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">def</span> <span class="nf">recalculate_similarities</span>
  <span class="no">RecordSimilarity</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">record: </span><span class="nb">self</span><span class="p">).</span><span class="nf">or</span><span class="p">(</span><span class="no">RecordSimilarity</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">similar_record: </span><span class="nb">self</span><span class="p">)).</span><span class="nf">destroy_all</span>
  <span class="n">calculate_similarities</span>
<span class="k">end</span>
<span class="p">```</span>

The issue here is that this method is deleting all existing similarities for the updated record and then recalculating them all. This approach has several problems:

a) It's inefficient, as it's deleting and recreating all similarities even if the update didn't affect the similarity calculations.
b) It's not consistent with our optimized approach of storing only one RecordSimilarity entry per pair of records.
c) The <span class="sb">`calculate_similarities`</span> method only calculates similarities with records that have a higher ID, which means we might lose some similarity data after an update.

Let's correct this implementation.
<span class="nt">&lt;/thinking&gt;</span>

<span class="nt">&lt;output&gt;</span>
You're correct, and thank you for catching that. Let's fix the implementation in the Record model to address these issues:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">class</span> <span class="nc">Record</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
  <span class="n">has_many</span> <span class="ss">:record_similarities</span>
  <span class="n">has_many</span> <span class="ss">:inverse_record_similarities</span><span class="p">,</span> <span class="ss">class_name: </span><span class="s1">'RecordSimilarity'</span><span class="p">,</span> <span class="ss">foreign_key: </span><span class="s1">'similar_record_id'</span>
  <span class="n">has_many</span> <span class="ss">:similar_records</span><span class="p">,</span> <span class="ss">through: :record_similarities</span>
  <span class="n">has_many</span> <span class="ss">:inverse_similar_records</span><span class="p">,</span> <span class="ss">through: :inverse_record_similarities</span><span class="p">,</span> <span class="ss">source: :record</span>

  <span class="n">after_create</span> <span class="ss">:calculate_similarities</span>
  <span class="n">after_update</span> <span class="ss">:recalculate_similarities</span><span class="p">,</span> <span class="ss">if: :requires_similarity_recalculation?</span>

  <span class="no">SIMILARITY_THRESHOLD</span> <span class="o">=</span> <span class="mf">0.5</span>

  <span class="kp">private</span>

  <span class="k">def</span> <span class="nf">calculate_similarities</span>
    <span class="no">RecordSimilarityJob</span><span class="p">.</span><span class="nf">perform_later</span><span class="p">(</span><span class="nb">self</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">recalculate_similarities</span>
    <span class="no">RecordSimilarityJob</span><span class="p">.</span><span class="nf">perform_later</span><span class="p">(</span><span class="nb">self</span><span class="p">,</span> <span class="ss">recalculate: </span><span class="kp">true</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">requires_similarity_recalculation?</span>
    <span class="c1"># Add logic here to determine if the update requires recalculation</span>
    <span class="c1"># For example, if you have a 'content' attribute that affects similarity:</span>
    <span class="n">saved_change_to_content?</span>
  <span class="k">end</span>
<span class="k">end</span>
<span class="p">```</span>

Now, let's update the RecordSimilarityJob to handle both initial calculation and recalculation:

<span class="p">```</span><span class="nl">ruby
</span><span class="k">class</span> <span class="nc">RecordSimilarityJob</span> <span class="o">&lt;</span> <span class="no">ApplicationJob</span>
  <span class="n">queue_as</span> <span class="ss">:default</span>

  <span class="k">def</span> <span class="nf">perform</span><span class="p">(</span><span class="n">record</span><span class="p">,</span> <span class="ss">recalculate: </span><span class="kp">false</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">recalculate</span>
      <span class="c1"># Delete existing similarities</span>
      <span class="no">RecordSimilarity</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">record: </span><span class="n">record</span><span class="p">).</span><span class="nf">or</span><span class="p">(</span><span class="no">RecordSimilarity</span><span class="p">.</span><span class="nf">where</span><span class="p">(</span><span class="ss">similar_record: </span><span class="n">record</span><span class="p">)).</span><span class="nf">destroy_all</span>
    <span class="k">end</span>

    <span class="no">Record</span><span class="p">.</span><span class="nf">where</span><span class="p">.</span><span class="nf">not</span><span class="p">(</span><span class="ss">id: </span><span class="n">record</span><span class="p">.</span><span class="nf">id</span><span class="p">).</span><span class="nf">find_each</span> <span class="k">do</span> <span class="o">|</span><span class="n">other_record</span><span class="o">|</span>
      <span class="n">similarity</span> <span class="o">=</span> <span class="n">calculate_similarity</span><span class="p">(</span><span class="n">record</span><span class="p">,</span> <span class="n">other_record</span><span class="p">)</span>
      <span class="k">if</span> <span class="n">similarity</span> <span class="o">&gt;=</span> <span class="no">Record</span><span class="o">::</span><span class="no">SIMILARITY_THRESHOLD</span>
        <span class="n">create_or_update_similarity</span><span class="p">(</span><span class="n">record</span><span class="p">,</span> <span class="n">other_record</span><span class="p">,</span> <span class="n">similarity</span><span class="p">)</span>
      <span class="k">end</span>
    <span class="k">end</span>

    <span class="no">Rails</span><span class="p">.</span><span class="nf">cache</span><span class="p">.</span><span class="nf">delete</span><span class="p">(</span><span class="s1">'top_similar_records'</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="kp">private</span>

  <span class="k">def</span> <span class="nf">calculate_similarity</span><span class="p">(</span><span class="n">record1</span><span class="p">,</span> <span class="n">record2</span><span class="p">)</span>
    <span class="c1"># Implement your vector similarity calculation here</span>
    <span class="c1"># This is a placeholder implementation</span>
    <span class="nb">rand</span><span class="p">(</span><span class="mf">0.0</span><span class="o">..</span><span class="mf">1.0</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">create_or_update_similarity</span><span class="p">(</span><span class="n">record1</span><span class="p">,</span> <span class="n">record2</span><span class="p">,</span> <span class="n">similarity</span><span class="p">)</span>
    <span class="n">smaller_id</span><span class="p">,</span> <span class="n">larger_id</span> <span class="o">=</span> <span class="p">[</span><span class="n">record1</span><span class="p">.</span><span class="nf">id</span><span class="p">,</span> <span class="n">record2</span><span class="p">.</span><span class="nf">id</span><span class="p">].</span><span class="nf">sort</span>
    <span class="n">similarity_record</span> <span class="o">=</span> <span class="no">RecordSimilarity</span><span class="p">.</span><span class="nf">find_or_initialize_by</span><span class="p">(</span>
      <span class="ss">record_id: </span><span class="n">smaller_id</span><span class="p">,</span>
      <span class="ss">similar_record_id: </span><span class="n">larger_id</span>
    <span class="p">)</span>
    <span class="n">similarity_record</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="ss">similarity_score: </span><span class="n">similarity</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
<span class="p">```</span>

These changes address the issues in the previous implementation:
<span class="p">
1.</span> We only trigger recalculation when necessary, based on the <span class="sb">`requires_similarity_recalculation?`</span> method.
<span class="p">2.</span> The RecordSimilarityJob now handles both initial calculation and recalculation.
<span class="p">3.</span> We maintain the optimized approach of storing only one RecordSimilarity entry per pair of records.
<span class="p">4.</span> When recalculating, we delete existing similarities for the record before recalculating.
<span class="p">5.</span> We calculate similarities with all other records, not just those with higher IDs.
<span class="p">6.</span> We use <span class="sb">`find_or_initialize_by`</span> and <span class="sb">`update`</span> to either create new similarity records or update existing ones.

This implementation should provide a more efficient and correct way to handle similarity calculations and updates.
<span class="nt">&lt;/output&gt;</span>
</code></pre></div></div>]]></content><author><name>Anton Kuzmenko</name></author><category term="llm" /><category term="prompt" /><summary type="html"><![CDATA[A popular trick to make prompts better is to add “step-by-step” instructions. For example:]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://antonkuzmenko.dev/img/2024-09-06-the-step-by-step-prompt-fallacy-boosting-ai-reasoning.jpg" /><media:content medium="image" url="https://antonkuzmenko.dev/img/2024-09-06-the-step-by-step-prompt-fallacy-boosting-ai-reasoning.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Tailoring Claude’s Prompt for Software Development</title><link href="https://antonkuzmenko.dev/2024/09/04/modified-claude-system-prompt-for-software-development/" rel="alternate" type="text/html" title="Tailoring Claude’s Prompt for Software Development" /><published>2024-09-04T00:00:00+00:00</published><updated>2024-09-04T00:00:00+00:00</updated><id>https://antonkuzmenko.dev/2024/09/04/modified-claude-system-prompt-for-software-development</id><content type="html" xml:base="https://antonkuzmenko.dev/2024/09/04/modified-claude-system-prompt-for-software-development/"><![CDATA[<p>A few weeks ago, Anthropic released their <a href="https://docs.anthropic.com/en/release-notes/system-prompts#claude-3-5-sonnet" target="_blank" rel="nofollow noreferrer">system prompts</a> for Claude models to the mere mortals. I’ve been coding with Claude 3.5 Sonnet since its release using my custom-built Neovim plugin. Of course, I couldn’t resist the temptation to modify the system prompt for software development.</p>

<p>I don’t have evals for this one yet, or better said, my eval is <em>“looks good to me”</em>. My wife and I have been using this prompt for a few weeks now, and we’re happy with the results.</p>

<h3 id="prompt">Prompt</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;claude_info&gt;
Claude is an advanced AI coding assistant created by Anthropic. Claude's knowledge base was last updated on April 2024. The current date is September 04, 2024.

Claude's primary goal is to provide expert-level assistance to senior developers. When presented with a coding problem or any task benefiting from systematic thinking, Claude thinks through it step by step before giving a final answer.

Claude is very smart and intellectually curious. It enjoys engaging in technical dialogues that challenge and expand understanding on a wide variety of topics related to software development. Claude is familiar with advanced coding concepts, best practices, and emerging technologies.

When assisting, Claude always uses appropriate markdown for code blocks, formatting and indenting code properly for readability. It uses the latest stable versions of languages, frameworks, and technologies unless specified otherwise, employing the most up-to-date APIs and adhering to industry standards and best practices.

If the user asks for a very long task that cannot be completed in a single response, Claude offers to do the task piecemeal and get feedback from the user as it completes each part of the task. Immediately after closing coding markdown, Claude asks the user if they would like an explanation or breakdown of the code. It does not explain or break down the code unless the user explicitly requests it.

Claude provides thorough responses to more complex and open-ended questions or to anything where a long response is requested, but concise responses to simpler questions and tasks. All else being equal, it tries to give the most correct and concise answer it can to the user’s message.

Claude will be provided with editor context, including file fragments and paths, as well as core technologies of the current project. While this information is used to provide accurate and context-aware assistance, Claude maintains the flexibility to draw from its extensive knowledge across various technologies and domains to deliver optimal solutions and insights.

When faced with ambiguous or incomplete information in the provided context, Claude will:
1. Identify the ambiguity or missing information explicitly.
2. Propose reasonable assumptions based on best practices and common patterns in similar contexts.
3. Offer multiple solutions or approaches if the ambiguity allows for different valid interpretations.
4. Ask clarifying questions to the developer when critical information is missing.
5. Clearly state any assumptions made in the response.

As Claude is assisting senior developers, it uses advanced terminology and concepts without extensive explanation unless requested.
&lt;/claude_info&gt;

Core technologies of the current project:
&lt;core_technologies&gt;
Ruby 3.*, Rails 7.*, PostgreSQL 14.*, Tailwind CSS 3.*, React 19.*, TypeScript 5.*, Docker
&lt;/core_technologies&gt;

Claude follows this information in all languages, and always responds to the user in the language they use or request. Claude is now being connected with a senior developer.
</code></pre></div></div>

<p>Btw, subscribe to my social media to get more posts like this one.</p>]]></content><author><name>Anton Kuzmenko</name></author><category term="llm" /><category term="claude" /><category term="prompt" /><summary type="html"><![CDATA[A few weeks ago, Anthropic released their system prompts for Claude models to the mere mortals. I’ve been coding with Claude 3.5 Sonnet since its release using my custom-built Neovim plugin. Of course, I couldn’t resist the temptation to modify the system prompt for software development.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://antonkuzmenko.dev/img/2024-09-04-modified-claude-system-prompt-for-software-development.jpg" /><media:content medium="image" url="https://antonkuzmenko.dev/img/2024-09-04-modified-claude-system-prompt-for-software-development.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">My Constant Struggle with Neovim</title><link href="https://antonkuzmenko.dev/2024/09/01/my-constant-struggle-with-neovim/" rel="alternate" type="text/html" title="My Constant Struggle with Neovim" /><published>2024-09-01T00:00:00+00:00</published><updated>2024-09-01T00:00:00+00:00</updated><id>https://antonkuzmenko.dev/2024/09/01/my-constant-struggle-with-neovim</id><content type="html" xml:base="https://antonkuzmenko.dev/2024/09/01/my-constant-struggle-with-neovim/"><![CDATA[<p>Have you ever felt like you are trying to tame a wild animal? A fierce, ever-changing beast that constantly needs our attention and obedience? That’s exactly how I feel about Neovim. It has become both my greatest tool and my never-ending challenge.</p>

<p>Neovim offers a unique experience – a fully customizable and efficient development environment tailored specifically for you. However, this flexibility comes with a constant struggle to maintain and optimize your personal setup.</p>

<p><mark>The main goal of a code editor is to make every aspect of coding efficient.</mark></p>

<p>But Neovim offers something much bigger than that. It gives you the ability to shape it into anything you want with enough effort and dedication. And this is where my struggle with Neovim begins.</p>

<p>Being able to change everything is truly amazing and scary at the same time. I work with many programming languages, frameworks, and different tools every day. This should be as perfect a scenario for a Neovim user as it gets. But the idea that Neovim is like my personal legacy software system I have to maintain is growing more and more onto me.</p>

<p>For instance, at any moment in time, if I get asked:</p>
<blockquote>
  <p>Are there any problems with your editor?</p>
</blockquote>

<p>My answer would be:</p>
<blockquote>
  <p>YES!</p>
</blockquote>

<p>There’s always some tiny, nagging annoyance clawing at my sanity, begging to be fixed. Or a repetitive task that I desperately want to optimize. Or a plugin that broke after a recent change, disrupting my entire workflow. Like the time when I updated a few plugins, and it caused conflicts with my JavaScript setup. I wasted hours debugging and reconfiguring my environment, grinding my teeth and fighting the urge to throw my laptop.</p>

<p>It’s easy to get overwhelmed, and at some point, I did. I once stopped making any changes to my setup, hoping that I could get used to it as is and become efficient with what I have. A silly idea. The software world is always changing:</p>

<ul>
  <li>New language features get released</li>
  <li>New additions to frameworks</li>
  <li>New technologies I want to work with</li>
  <li>Work projects constantly change</li>
</ul>

<p>Nothing in software development is static.</p>

<p>Every 2 months, I dedicate a few hours to deal with TODOs. I don’t maintain a list of TODOs – major problems and improvement ideas are so engraved in me, as I patiently suffer months before finally addressing them. A strange form of self-punishment. I never update plugins just to be on the latest version. Only when it fixes an issue I have or adds an improvement I personally need.</p>

<p>I can’t put off all the little things until later, so I still make little changes here and there that don’t require much time and brain power. It’s a constant balancing act between optimizing my development environment and actually getting work done. An endless dance with the beast that is Neovim.</p>

<p>And yet, despite all the struggles and frustrations, I cannot help but love this wild beast. Because in it’s untamed nature lies the power to create something truly great - a development environment perfectly shaped for my needs. So I keep going, I keep taming, I keep customizing, forever engaged in this never-ending effort that defines the life of a Neovim user.</p>]]></content><author><name>Anton Kuzmenko</name></author><category term="neovim" /><summary type="html"><![CDATA[Have you ever felt like you are trying to tame a wild animal? A fierce, ever-changing beast that constantly needs our attention and obedience? That’s exactly how I feel about Neovim. It has become both my greatest tool and my never-ending challenge.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://antonkuzmenko.dev/img/2024-09-01-my-constant-struggle-with-neovim.jpg" /><media:content medium="image" url="https://antonkuzmenko.dev/img/2024-09-01-my-constant-struggle-with-neovim.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>