<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet href="/pretty-feed-v3.xsl" type="text/xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Notes on Harsh Shandilya</title>
    <link>https://msfjarvis.dev/notes/</link>
    <description>Recent content in Notes on Harsh Shandilya</description>
    <image>
      <title>Harsh Shandilya</title>
      <url>https://msfjarvis.dev/android-chrome-512x512.webp</url>
      <link>https://msfjarvis.dev/android-chrome-512x512.webp</link>
    </image>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <managingEditor>me@msfjarvis.dev (Harsh Shandilya)</managingEditor>
    <webMaster>me@msfjarvis.dev (Harsh Shandilya)</webMaster>
    <lastBuildDate>Wed, 29 Oct 2025 13:48:00 +0000</lastBuildDate><atom:link href="https://msfjarvis.dev/notes/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>TIL: Sending emails from my DuckDuckGo email alias</title>
      <link>https://msfjarvis.dev/notes/til-sending-emails-from-my-duckduckgo-email-alias/</link>
      <pubDate>Mon, 23 Feb 2026 17:50:00 +0530</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/til-sending-emails-from-my-duckduckgo-email-alias/</guid>
      <description>Slightly regretting using one of these for a credit card 😬</description>
      <content:encoded><![CDATA[<p>I use <a href="https://duckduckgo.com/email/">DuckDuckGo Email Protection</a> for my accounts in a lot of places, one of which happened to be a credit card company. I needed to file a support ticket for it and, rightfully so, they require the sender to be the original email that I signed up with. I was expecting this to be a bit of a nightmare but thankfully DuckDuckGo already thought of this and have a rather simple way to do this.</p>
<p>If your alias is <code>john.doe@duck.com</code> and you wish to send an email to <code>jane.doe@example.com</code>, you can do so by sending an email from your forwarding address to <code>jane.doe_at_example.com_john.doe@duck.com</code>. What we did here is replace the <code>@</code> in the receiver address with <code>_at_</code> and then append our alias, again separated with a <code>_</code>. This lets this continue being a valid email while being unambiguous for DuckDuckGo&rsquo;s routing infrastructure. I tried it out and immediately got the confirmation that my support ticket had been accepted! After the initial hurdle replying normally will continue to work.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: Easily sending eBooks to a Kobo</title>
      <link>https://msfjarvis.dev/notes/til-easily-sending-ebooks-to-a-kobo/</link>
      <pubDate>Fri, 06 Feb 2026 11:33:00 +0530</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/til-easily-sending-ebooks-to-a-kobo/</guid>
      <description>send.djazz.se is a godsend (no pun intended)</description>
      <content:encoded><![CDATA[<p>Discovered <a href="https://send.djazz.se">send.djazz.se</a> via a Reddit comment that greatly simplifies sending eBooks to a Kobo in the absence of a computer to run Calibre on.</p>
<p>Simply go to the website on the Kobo, memorize the 4 digit code it generates then go to the same website on your other device, enter the code and upload your file. Within a few seconds it should show up on the Kobo as a downloadable link, and it has the additional options to convert your eBook into a native format for the target device. Super convenient!</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Android Gradle Plugin 9.0.0 upgrade notes</title>
      <link>https://msfjarvis.dev/notes/android-gradle-plugin-9.0.0-upgrade-notes/</link>
      <pubDate>Tue, 13 Jan 2026 06:44:00 +0530</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/android-gradle-plugin-9.0.0-upgrade-notes/</guid>
      <description>Some tips to ease the Android Gradle Plugin 9.0.0 upgrade</description>
      <content:encoded><![CDATA[<p>Version 9.0.0 of the Android Gradle Plugin brings in <a href="https://developer.android.com/build/releases/agp-preview#android-gradle-plugin">a lot of breaking changes</a>, most of which are documented with clear upgrade paths except the fact that Kotlin Multiplatform libraries now ship their Android artifacts <a href="https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-api/src/main/java/com/android/build/api/dsl/KmpOptimization.kt;l=79-87;drc=04e1247ed3cc69320f919ebb46b763e31483a7a5">without consumer keep rules included</a>. This needs to be manually turned on to preserve the existing behavior:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-kotlin" data-lang="kotlin"><span class="line"><span class="cl"><span class="n">android</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">consumerKeepRules</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">publish</span> <span class="p">=</span> <span class="k">true</span>
</span></span><span class="line"><span class="cl">    <span class="k">file</span><span class="p">(</span><span class="s2">&#34;consumer-proguard-rules.pro&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>]]></content:encoded>
    </item>
    
    <item>
      <title>Collating entries in my Obsidian journal for week notes</title>
      <link>https://msfjarvis.dev/notes/collating-entries-in-my-obsidian-journal-for-week-notes/</link>
      <pubDate>Sun, 14 Dec 2025 21:21:00 +0530</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/collating-entries-in-my-obsidian-journal-for-week-notes/</guid>
      <description>Quick how-to of setting up my Obsidian journal to create a gist of noteworthy events through the week</description>
      <content:encoded><![CDATA[<p>Following up on my <a href="https://androiddev.social/@msfjarvis/115717823447859331">Mastodon</a> post about wanting to start doing week notes, inspired by <a href="https://ankursethi.com/">Ankur</a> and <a href="https://abhinavsarkar.net/notes/tags/weeknotes/">Abhinav</a>, here&rsquo;s the quick rundown of how I supplemented my existing Obsidian journal to facilitate the new endeavor.</p>
<p>I currently use <a href="https://github.com/liamcain/obsidian-periodic-notes">obsidian-periodic-notes</a> to manage my daily notes and have mostly left the weekly/monthly option untouched, until now.</p>
<p>To actually collect the necessary journal entries, I relied on <a href="https://github.com/blacksmithgu/obsidian-dataview">Dataview</a> which I&rsquo;ve <a href="https://msfjarvis.dev/posts/overengineering-an-obsidian-dashboard-to-get-better-at-marvel-snap/">used previously to get good at Marvel Snap</a>. I wanted to minimize the changes I needed to make in my day-to-day workflow so I started with the restriction that at most I would be willing to tack on <code>#weekly</code> at the end of a journal entry that was noteworthy.</p>
<p>Dataview was able to beautifully navigate this limitation and with a little bit of JavaScript I now have a template that I can plug into Periodic Notes and get a roundup of the whole week in one click. Here&rsquo;s how it looks with just today&rsquo;s entries highlighted:</p>
<p><img alt="An Obsidian page with the title 2025-W50 and listing two journal entries from today: Me writing about my Droidcon India 2025 experience and a mention of me finishing my second run of the game Dispatch." loading="lazy" src="/obsidian-weeknotes.webp" title="Week 50 roundup with entries from Sunday"></p>
<p>The relevant DataViewJS code is this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">TAG</span> <span class="o">=</span> <span class="s2">&#34;#weekly&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">m</span> <span class="o">=</span> <span class="nx">dv</span><span class="p">.</span><span class="nx">current</span><span class="p">().</span><span class="nx">file</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/^(\d{4})-W(\d{2})$/</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">dv</span><span class="p">.</span><span class="nx">paragraph</span><span class="p">(</span><span class="s2">&#34;Weekly note filename must be like `2025-W50.md`.&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">function</span> <span class="nx">isoWeekStartISO</span><span class="p">(</span><span class="nx">year</span><span class="p">,</span> <span class="nx">week</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Compute ISO week start (Monday) in UTC, then return YYYY-MM-DD
</span></span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">simple</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nb">Date</span><span class="p">.</span><span class="nx">UTC</span><span class="p">(</span><span class="nx">year</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="nx">week</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="mi">7</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">dow</span> <span class="o">=</span> <span class="nx">simple</span><span class="p">.</span><span class="nx">getUTCDay</span><span class="p">();</span> <span class="c1">// 0..6, Sun..Sat
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">start</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">simple</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">dow</span> <span class="o">&lt;=</span> <span class="mi">4</span><span class="p">)</span> <span class="nx">start</span><span class="p">.</span><span class="nx">setUTCDate</span><span class="p">(</span><span class="nx">simple</span><span class="p">.</span><span class="nx">getUTCDate</span><span class="p">()</span> <span class="o">-</span> <span class="nx">dow</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span> <span class="nx">start</span><span class="p">.</span><span class="nx">setUTCDate</span><span class="p">(</span><span class="nx">simple</span><span class="p">.</span><span class="nx">getUTCDate</span><span class="p">()</span> <span class="o">+</span> <span class="p">(</span><span class="mi">8</span> <span class="o">-</span> <span class="nx">dow</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// YYYY-MM-DD
</span></span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">start</span><span class="p">.</span><span class="nx">toISOString</span><span class="p">().</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">year</span> <span class="o">=</span> <span class="nb">Number</span><span class="p">(</span><span class="nx">m</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">week</span> <span class="o">=</span> <span class="nb">Number</span><span class="p">(</span><span class="nx">m</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">start</span> <span class="o">=</span> <span class="nx">dv</span><span class="p">.</span><span class="nx">date</span><span class="p">(</span><span class="nx">isoWeekStartISO</span><span class="p">(</span><span class="nx">year</span><span class="p">,</span> <span class="nx">week</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">end</span> <span class="o">=</span> <span class="nx">start</span><span class="p">.</span><span class="nx">plus</span><span class="p">({</span> <span class="nx">days</span><span class="o">:</span> <span class="mi">7</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">pages</span> <span class="o">=</span> <span class="nx">dv</span><span class="p">.</span><span class="nx">pages</span><span class="p">(</span><span class="s1">&#39;&#34;Daily&#34;&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">where</span><span class="p">(</span><span class="nx">p</span> <span class="p">=&gt;</span> <span class="nx">p</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">day</span> <span class="o">&amp;&amp;</span> <span class="nx">p</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">day</span> <span class="o">&gt;=</span> <span class="nx">start</span> <span class="o">&amp;&amp;</span> <span class="nx">p</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">day</span> <span class="o">&lt;</span> <span class="nx">end</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">sort</span><span class="p">(</span><span class="nx">p</span> <span class="p">=&gt;</span> <span class="nx">p</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">day</span><span class="p">,</span> <span class="s2">&#34;asc&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">let</span> <span class="nx">any</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="p">(</span><span class="kr">const</span> <span class="nx">p</span> <span class="k">of</span> <span class="nx">pages</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">bullets</span> <span class="o">=</span> <span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">lists</span> <span class="o">??</span> <span class="p">[]).</span><span class="nx">filter</span><span class="p">(</span><span class="nx">li</span> <span class="p">=&gt;</span> <span class="p">(</span><span class="nx">li</span><span class="p">.</span><span class="nx">text</span> <span class="o">??</span> <span class="s2">&#34;&#34;</span><span class="p">).</span><span class="nx">includes</span><span class="p">(</span><span class="nx">TAG</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">bullets</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">any</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// [[YYYY-MM-DD]]
</span></span></span><span class="line"><span class="cl">    <span class="nx">dv</span><span class="p">.</span><span class="nx">paragraph</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">link</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// - Line 1
</span></span></span><span class="line"><span class="cl">    <span class="c1">// - Line 2
</span></span></span><span class="line"><span class="cl">    <span class="nx">dv</span><span class="p">.</span><span class="nx">list</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="nx">bullets</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">li</span> <span class="p">=&gt;</span> <span class="nx">li</span><span class="p">.</span><span class="nx">text</span> <span class="o">??</span> <span class="s2">&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">t</span> <span class="p">=&gt;</span> <span class="nx">t</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">TAG</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">).</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\s+/g</span><span class="p">,</span> <span class="s2">&#34; &#34;</span><span class="p">).</span><span class="nx">trim</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nb">Boolean</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">dv</span><span class="p">.</span><span class="nx">paragraph</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">any</span><span class="p">)</span> <span class="nx">dv</span><span class="p">.</span><span class="nx">paragraph</span><span class="p">(</span><span class="sb">`No </span><span class="si">${</span><span class="nx">TAG</span><span class="si">}</span><span class="sb"> bullets found for </span><span class="si">${</span><span class="nx">m</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="sb">-W</span><span class="si">${</span><span class="nx">m</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="si">}</span><span class="sb">.`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">})();</span>
</span></span></code></pre></div><p>The code is relatively simple: It finds the week number from the current file name, gathers the range of dates for that week, inspects each file for lines that contain <code>#weekly</code>, and then neatly lays them out grouped by date.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: Bypassing aliases in a Bash script</title>
      <link>https://msfjarvis.dev/notes/til-bypassing-aliases-in-a-bash-script/</link>
      <pubDate>Sun, 07 Dec 2025 13:41:00 +0530</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/til-bypassing-aliases-in-a-bash-script/</guid>
      <description>Quick syntactic solution for ensuring aliases don&amp;rsquo;t mess up scripts</description>
      <content:encoded><![CDATA[<p>On all my machines I have <code>cat</code> aliased to <a href="https://github.com/sharkdp/bat">bat</a> which prints text with nice formatting and layout. This can sometimes trip up scripts if <code>bat</code> doesn&rsquo;t correctly detect it is being used in a pipe and still outputs all the nice formatting instead of the plain text. To bypass this in your scripts, you can replace uses of <code>cat file_name</code> with <code>\cat file_name</code> to always get the <code>cat</code> program in your <code>$PATH</code> instead of an alias. This also works with <code>&quot;cat&quot; file_name</code>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Migrating a Postgres database between servers</title>
      <link>https://msfjarvis.dev/notes/migrating-a-postgres-database-between-servers/</link>
      <pubDate>Sat, 08 Nov 2025 13:18:00 +0530</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/migrating-a-postgres-database-between-servers/</guid>
      <description>A quick rundown of the process so future me can have an easier time</description>
      <content:encoded><![CDATA[<p>I&rsquo;m having transitive network issues on one of my servers so I had to move out one of my services from the machine to a different one, which also involved transferring a Postgres database. The steps I followed for this are outlined below. I did this on two NixOS machines so your authentication setup and requirements may differ, please consult the documentation for the relevant commands to figure out what you need to do differently.</p>
<h2 id="on-the-server-being-migrated-out-of">On the server being migrated out of</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl"># Switch to the Postgres user
</span></span><span class="line"><span class="cl">sudo -i su - postgres
</span></span><span class="line"><span class="cl"># Export just the roles so the imported database can have the right ownership
</span></span><span class="line"><span class="cl"># I also edited this to only keep the role for the db I was moving
</span></span><span class="line"><span class="cl">pg_dumpall --roles-only &gt; roles.sql
</span></span><span class="line"><span class="cl"># Export the actual database in Postgres&#39; binary format so its smaller
</span></span><span class="line"><span class="cl">pg_dump -d atticd -Fc --create &gt; atticd.dump
</span></span></code></pre></div><p>Once I had both files I used <code>rsync</code> to ship them over to the new server</p>
<h2 id="on-the-server-being-migrated-to">On the server being migrated to</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">sudo -i su - postgres
</span></span><span class="line"><span class="cl"># Set up roles first
</span></span><span class="line"><span class="cl">psql &lt; roles.sql
</span></span><span class="line"><span class="cl"># The `-d postgres` is required because pg_restore
</span></span><span class="line"><span class="cl"># wants to connect to at least one existing database before
</span></span><span class="line"><span class="cl"># doing anything, so we give it the one that exists by default
</span></span><span class="line"><span class="cl"># at least on NixOS.
</span></span><span class="line"><span class="cl">pg_restore -d postgres ./atticd.dump
</span></span></code></pre></div><p>And that&rsquo;s it! After this I just enabled the service on the new server and it picked up the existing database right away.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>GPT-5 seems to forget things well within its context window</title>
      <link>https://msfjarvis.dev/notes/gpt-5-seems-to-forget-things-well-within-its-context-window/</link>
      <pubDate>Mon, 03 Nov 2025 16:32:00 +0530</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/gpt-5-seems-to-forget-things-well-within-its-context-window/</guid>
      <description>An instance of LLMs seemingly not being able to utilize their context window effectively</description>
      <content:encoded><![CDATA[<blockquote>
<p>I wish I had the session transcript to share for this but OpenCode doesn&rsquo;t show my old session anymore so I can&rsquo;t share it.</p>
</blockquote>
<p>Yesterday I threw GPT-5 via GitHub Copilot at a relatively simple problem: My Prometheus alerts give me a relatively useless message when an alert fires from the <a href="https://github.com/prometheus/blackbox_exporter">prometheus-blackbox-exporter</a>. I would like to see the URL that it&rsquo;s failing to reach. I used <a href="https://opencode.ai/">OpenCode</a> to drive this in an agentic manner.</p>
<p>At one point, the LLM hallucinated a <code>subject</code> field in the Prometheus <a href="https://prometheus.io/docs/alerting/latest/configuration/#email_config">Alertmanager config for email alerts</a>. I pointed out the error, after which it changed the <code>subject</code> to correctly be <code>headers { Subject = &quot;...&quot;; };</code> instead. A few iterations on other parts of the config later, it randomly went back to that line and reverted it back to the wrong <code>subject</code> field saying that the right version was actually incorrect.</p>
<p>This happened around the 45K tokens mark in its context window, which is well under the claimed values. Ultimately this was an easy mistake to fix again, but I was relatively surprised to see the LLM repeat a mistake within the same session.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Copying Nix Flake inputs to a different machine</title>
      <link>https://msfjarvis.dev/notes/copying-nix-flake-inputs-to-a-different-machine/</link>
      <pubDate>Sun, 02 Nov 2025 15:18:00 +0530</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/copying-nix-flake-inputs-to-a-different-machine/</guid>
      <description>Simple one-liner to avoid re-downloading inputs on a different machine on your LAN</description>
      <content:encoded><![CDATA[<blockquote>
<p>TL;DR: <code>nix flake archive --json | jq -r '.inputs[].path' | xargs nix --verbose copy --to ssh://user@host</code></p>
</blockquote>
<p>Due to unfortunate circumstances my homelab server is running on a relatively slow internet connection while I&rsquo;m at home. To alleviate the problems this causes with NixOS updates, I build and deploy the new generations for it from my desktop. This works in most cases, except when an update ends up restarting Tailscale or OpenSSH which cuts off my SSH session and leaves the machine in a bad state.</p>
<p>As a workaround for <em>that</em> problem I now copy the built closure to the Nix Store of the machine and do an <code>nh os switch</code> inside a tmux session there so it can run to completion without having to download everything. This usually works, but it does need to redownload inputs which seems a little wasteful so I searched around for ways to get the Nix Store paths of all my Flake inputs and came up with this small solution that lets me skip even more network I/O for the homelab.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Changing the locale set on a maching running Postgres</title>
      <link>https://msfjarvis.dev/notes/changing-locale-set-maching-running-postgres/</link>
      <pubDate>Wed, 29 Oct 2025 18:30:11 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/changing-locale-set-maching-running-postgres/</guid>
      <description>&lt;p&gt;I keep rediscovering that Postgres uses the system locale and timezone database, despite &lt;a href=&#34;https://github.com/miniflux/v2/issues/3673&#34;&gt;having read other people&amp;rsquo;s woes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I changed the locale in my NixOS configuration from en_US to en_GB to appease the spell checker on my desktop. When I deployed this updated configuration to one of my servers, all my services immediately fell over.&lt;/p&gt;
&lt;p&gt;I had the sense to look at &lt;code&gt;journalctl&lt;/code&gt; right away which made it very apparent what the problem was:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I keep rediscovering that Postgres uses the system locale and timezone database, despite <a href="https://github.com/miniflux/v2/issues/3673">having read other people&rsquo;s woes</a>.</p>
<p>I changed the locale in my NixOS configuration from en_US to en_GB to appease the spell checker on my desktop. When I deployed this updated configuration to one of my servers, all my services immediately fell over.</p>
<p>I had the sense to look at <code>journalctl</code> right away which made it very apparent what the problem was:</p>
<pre tabindex="0"><code>Oct 29 18:27:00 wailord postgres[3593]: [3593] FATAL:  database locale is incompatible with operating system
Oct 29 18:27:00 wailord postgres[3593]: [3593] DETAIL:  The database was initialized with LC_COLLATE &#34;en_US.UTF-8&#34;,  which is not recognized by setlocale().
Oct 29 18:27:00 wailord postgres[3593]: [3593] HINT:  Recreate the database with another locale or install the missing locale.
</code></pre><p>(Yes my server is called <a href="https://pokemondb.net/pokedex/wailord">wailord</a>, I was loving <a href="https://cobblemon.com/en">Cobblemon</a> when it was provisioned)</p>
<p>The solution was to simply add <code>en_US</code> back to <a href="https://github.com/NixOS/nixpkgs/blob/fc2ba10c4f0e1d4cda694e730769c563c2145745/nixos/modules/config/i18n.nix#L117"><code>i18n.supportedLocales</code></a> and a rebuild fixed everything right up.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Welcome to Notes</title>
      <link>https://msfjarvis.dev/notes/welcome-to-notes/</link>
      <pubDate>Wed, 29 Oct 2025 13:48:00 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/welcome-to-notes/</guid>
      <description>&lt;p&gt;New section woo! This is mostly going to be used for relatively smaller things that I don&amp;rsquo;t find worthy of a blogpost but are a bit awkward to fit into a &lt;a href=&#34;https://androiddev.social/@msfjarvis&#34;&gt;toot&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Over time I plan to backfill this with the contents of my Obsidian Vault&amp;rsquo;s &amp;ldquo;TIL&amp;rdquo; folder and then just use this public listing for the purpose, since it&amp;rsquo;s equally accessible to me via the excellent &lt;a href=&#34;https://github.com/sveltia/sveltia-cms/&#34;&gt;Sveltia CMS&lt;/a&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>New section woo! This is mostly going to be used for relatively smaller things that I don&rsquo;t find worthy of a blogpost but are a bit awkward to fit into a <a href="https://androiddev.social/@msfjarvis">toot</a>.</p>
<p>Over time I plan to backfill this with the contents of my Obsidian Vault&rsquo;s &ldquo;TIL&rdquo; folder and then just use this public listing for the purpose, since it&rsquo;s equally accessible to me via the excellent <a href="https://github.com/sveltia/sveltia-cms/">Sveltia CMS</a>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Adding boarding passes to Google Wallet</title>
      <link>https://msfjarvis.dev/notes/adding-boarding-passes-google-wallet/</link>
      <pubDate>Fri, 17 Oct 2025 22:34:40 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/adding-boarding-passes-google-wallet/</guid>
      <description>&lt;p&gt;Google Wallet lets you add passes via image, so rather than try to share a PDF with it you can take a screenshot and share that to the app instead. &amp;ldquo;Google AI&amp;rdquo; does the rest.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Google Wallet lets you add passes via image, so rather than try to share a PDF with it you can take a screenshot and share that to the app instead. &ldquo;Google AI&rdquo; does the rest.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Interactive reverts in Git</title>
      <link>https://msfjarvis.dev/notes/interactive-reverts-git/</link>
      <pubDate>Tue, 23 Sep 2025 21:53:23 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/interactive-reverts-git/</guid>
      <description>&lt;p&gt;Git has the capability to revert only specific hunks of a commit using the &lt;code&gt;git checkout --patch&lt;/code&gt; command. To revert the changes to file &lt;code&gt;example.md&lt;/code&gt; made in commit &lt;code&gt;0xDEADBEEF&lt;/code&gt;, you would run &lt;code&gt;git checkout --patch 0xDEADBEEF^ example.md&lt;/code&gt; and Git will open up the interactive diff editor so you can select which reverts you want to apply to your index.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Git has the capability to revert only specific hunks of a commit using the <code>git checkout --patch</code> command. To revert the changes to file <code>example.md</code> made in commit <code>0xDEADBEEF</code>, you would run <code>git checkout --patch 0xDEADBEEF^ example.md</code> and Git will open up the interactive diff editor so you can select which reverts you want to apply to your index.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Debugging issues with provisioning certificates from Let&#39;s Encrypt</title>
      <link>https://msfjarvis.dev/notes/debugging-issues-provisioning-certificates-from-let/</link>
      <pubDate>Tue, 16 Sep 2025 01:30:40 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/debugging-issues-provisioning-certificates-from-let/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://letsdebug.net&#34;&gt;Let&amp;rsquo;s Debug&lt;/a&gt; provides a way to test if your domain is set up to correctly answer Let&amp;rsquo;s Encrypt challenges.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://letsdebug.net">Let&rsquo;s Debug</a> provides a way to test if your domain is set up to correctly answer Let&rsquo;s Encrypt challenges.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Oracle Cloud&#39;s restrictive default network policy</title>
      <link>https://msfjarvis.dev/notes/oracle-cloud-network-policy/</link>
      <pubDate>Tue, 16 Sep 2025 01:30:40 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/oracle-cloud-network-policy/</guid>
      <description>&lt;p&gt;Oracle cloud doesn&amp;rsquo;t enable any ports other than SSH by default, which somehow doesn&amp;rsquo;t affect any Tailscale services but breaks the ability to negotiate a TLS certificate over ports 80 and 443.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Oracle cloud doesn&rsquo;t enable any ports other than SSH by default, which somehow doesn&rsquo;t affect any Tailscale services but breaks the ability to negotiate a TLS certificate over ports 80 and 443.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Cargo failing at gitignore-d files while publishing</title>
      <link>https://msfjarvis.dev/notes/cargo-failing-gitignore-d-files-while-publishing/</link>
      <pubDate>Sun, 14 Sep 2025 22:31:48 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/cargo-failing-gitignore-d-files-while-publishing/</guid>
      <description>&lt;p&gt;Finally managed to find a workaround for the Rust problem I was having with &lt;code&gt;cargo publish&lt;/code&gt; picking up files from my gitignore-d &lt;code&gt;.direnv&lt;/code&gt; directory and complaining about them being uncommitted.&lt;/p&gt;
&lt;p&gt;This was the result of cascading surprises: setting &lt;code&gt;package.includes&lt;/code&gt; causes gitignore to no longer be considered, and &lt;code&gt;&amp;quot;README.md&amp;quot;&lt;/code&gt; in &lt;code&gt;package.includes&lt;/code&gt; actually works like &lt;code&gt;&amp;quot;**/README.md&amp;quot;&lt;/code&gt;&amp;rsquo; and picks up the READMEs from the repositories in &lt;code&gt;.direnv/flake-inputs/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Upstream issue: &lt;a href=&#34;https://github.com/rust-lang/cargo/issues/12294#issuecomment-2171044946&#34;&gt;https://github.com/rust-lang/cargo/issues/12294#issuecomment-2171044946&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Finally managed to find a workaround for the Rust problem I was having with <code>cargo publish</code> picking up files from my gitignore-d <code>.direnv</code> directory and complaining about them being uncommitted.</p>
<p>This was the result of cascading surprises: setting <code>package.includes</code> causes gitignore to no longer be considered, and <code>&quot;README.md&quot;</code> in <code>package.includes</code> actually works like <code>&quot;**/README.md&quot;</code>&rsquo; and picks up the READMEs from the repositories in <code>.direnv/flake-inputs/</code>.</p>
<p>Upstream issue: <a href="https://github.com/rust-lang/cargo/issues/12294#issuecomment-2171044946">https://github.com/rust-lang/cargo/issues/12294#issuecomment-2171044946</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Grafana config helper to read values at runtime</title>
      <link>https://msfjarvis.dev/notes/grafana-config-helper-read-values-runtime/</link>
      <pubDate>Wed, 27 Aug 2025 22:12:03 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/grafana-config-helper-read-values-runtime/</guid>
      <description>&lt;p&gt;Grafana has a helper in its config files called &lt;code&gt;$__file{/path/to/file}&lt;/code&gt; that will read the file at runtime, making it easier to configure secrets via Nix.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Grafana has a helper in its config files called <code>$__file{/path/to/file}</code> that will read the file at runtime, making it easier to configure secrets via Nix.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>SDKMAN can use your system Java installations</title>
      <link>https://msfjarvis.dev/notes/sdkman-can-use-your-system-java-installations/</link>
      <pubDate>Thu, 03 Jul 2025 13:54:19 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/sdkman-can-use-your-system-java-installations/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://sdkman.io&#34;&gt;SDKMAN&lt;/a&gt; can symlink existing Java installations into its own managed thing so we can have the best of both worlds by installing Java from Homebrew but managing the JAVA_HOME with SDKMAN.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://sdkman.io">SDKMAN</a> can symlink existing Java installations into its own managed thing so we can have the best of both worlds by installing Java from Homebrew but managing the JAVA_HOME with SDKMAN.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Testing GitLab CI pipelines locally</title>
      <link>https://msfjarvis.dev/notes/testing-gitlab-ci-pipelines-locally/</link>
      <pubDate>Thu, 03 Jul 2025 13:54:19 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/testing-gitlab-ci-pipelines-locally/</guid>
      <description>&lt;p&gt;GitLab CI pipelines can be executed locally using &lt;a href=&#34;https://github.com/firecow/gitlab-ci-local&#34;&gt;firecow/gitlab-ci-local&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This used to be a first party feature within the official gitlab-runner binary but they deleted it citing maintenance burden. What a shame.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>GitLab CI pipelines can be executed locally using <a href="https://github.com/firecow/gitlab-ci-local">firecow/gitlab-ci-local</a></p>
<p>This used to be a first party feature within the official gitlab-runner binary but they deleted it citing maintenance burden. What a shame.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>`handle_path` in Caddy</title>
      <link>https://msfjarvis.dev/notes/handle_path-caddy/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/handle_path-caddy/</guid>
      <description>&lt;p&gt;Caddy has a &lt;code&gt;handle_path&lt;/code&gt; directive that you can use to host services that don&amp;rsquo;t like being hosted on paths, it will strip the prefix for the underlying service so it sees just the root domain&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Caddy has a <code>handle_path</code> directive that you can use to host services that don&rsquo;t like being hosted on paths, it will strip the prefix for the underlying service so it sees just the root domain</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>`lib.catAttrs` in Nixpkgs</title>
      <link>https://msfjarvis.dev/notes/libcatattrs-nixpkgs/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/libcatattrs-nixpkgs/</guid>
      <description>&lt;p&gt;In Nix it is possible to replace a call to &lt;code&gt;builtins.map&lt;/code&gt; with &lt;code&gt;lib.catAttrs&lt;/code&gt; if the transformation is just pulling out a field. For example: &lt;code&gt;builtins.map (item: item.field) list&lt;/code&gt; can instead just be &lt;code&gt;catAttrs &amp;quot;field&amp;quot; list&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In Nix it is possible to replace a call to <code>builtins.map</code> with <code>lib.catAttrs</code> if the transformation is just pulling out a field. For example: <code>builtins.map (item: item.field) list</code> can instead just be <code>catAttrs &quot;field&quot; list</code>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>`nix flake info`</title>
      <link>https://msfjarvis.dev/notes/nix-flake-info/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/nix-flake-info/</guid>
      <description>&lt;p&gt;Nix CLI&amp;rsquo;s &lt;code&gt;flake info&lt;/code&gt; subcommand is great to find duplicate inputs, &lt;a href=&#34;https://github.com/nix-community/nix-melt&#34;&gt;nix-melt&lt;/a&gt; is too much manual labor.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Nix CLI&rsquo;s <code>flake info</code> subcommand is great to find duplicate inputs, <a href="https://github.com/nix-community/nix-melt">nix-melt</a> is too much manual labor.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>`rememberUpdatedState` in Compose</title>
      <link>https://msfjarvis.dev/notes/rememberupdatedstate-compose/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/rememberupdatedstate-compose/</guid>
      <description>&lt;p&gt;In Jetpack Compose you can use &lt;a href=&#34;https://developer.android.com/develop/ui/compose/side-effects#rememberupdatedstate&#34;&gt;&lt;code&gt;rememberUpdatedState&lt;/code&gt;&lt;/a&gt; to capture values that may update over time but without a full restart of the &lt;code&gt;rememberUpdatedState&lt;/code&gt; function.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In Jetpack Compose you can use <a href="https://developer.android.com/develop/ui/compose/side-effects#rememberupdatedstate"><code>rememberUpdatedState</code></a> to capture values that may update over time but without a full restart of the <code>rememberUpdatedState</code> function.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Building derivations in the Nix REPL</title>
      <link>https://msfjarvis.dev/notes/building-derivations-nix-repl/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/building-derivations-nix-repl/</guid>
      <description>&lt;p&gt;In a Nix REPL you can run &lt;code&gt;:bl inputs.nixpkgs.legacyPackages.aarch64-linux.pkgs.attic-server&lt;/code&gt; to build the derivation and create a &lt;code&gt;result&lt;/code&gt; link. Can also run &lt;code&gt;:bl nixosConfigurations.ryzenbox.pkgs.attic-client&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In a Nix REPL you can run <code>:bl inputs.nixpkgs.legacyPackages.aarch64-linux.pkgs.attic-server</code> to build the derivation and create a <code>result</code> link. Can also run <code>:bl nixosConfigurations.ryzenbox.pkgs.attic-client</code>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Combining videos using FFmpeg</title>
      <link>https://msfjarvis.dev/notes/combining-videos-using-ffmpeg/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/combining-videos-using-ffmpeg/</guid>
      <description>&lt;p&gt;FFmpeg lets you mix videos together from different sources based on a zero-indexed map of input files. For the diagram given below, you can do &lt;code&gt;ffmpeg -i input_0.mp4 -i input_1.mp4 -c copy -map 0:v:0 -map 1:a:0 -shortest output.mp4&lt;/code&gt; to take the video from &lt;code&gt;input_0.mp4&lt;/code&gt; and audio from &lt;code&gt;input_1.mp4&lt;/code&gt;.
&lt;img loading=&#34;lazy&#34; src=&#34;https://i.sstatic.net/3ep4f.png&#34;&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>FFmpeg lets you mix videos together from different sources based on a zero-indexed map of input files. For the diagram given below, you can do <code>ffmpeg -i input_0.mp4 -i input_1.mp4 -c copy -map 0:v:0 -map 1:a:0 -shortest output.mp4</code> to take the video from <code>input_0.mp4</code> and audio from <code>input_1.mp4</code>.
<img loading="lazy" src="https://i.sstatic.net/3ep4f.png"></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Concatenating videos with FFmpeg</title>
      <link>https://msfjarvis.dev/notes/concatenating-videos-ffmpeg/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/concatenating-videos-ffmpeg/</guid>
      <description>&lt;p&gt;FFmpeg has support for concatenating files with no re-encoding&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# file_list.txt
file &amp;#39;source1.mp4&amp;#39;
file &amp;#39;source2.mp4&amp;#39;

$ ffmpeg -f concat -safe 0 -i file_list.txt -c copy output.mp4
&lt;/code&gt;&lt;/pre&gt;</description>
      <content:encoded><![CDATA[<p>FFmpeg has support for concatenating files with no re-encoding</p>
<pre tabindex="0"><code># file_list.txt
file &#39;source1.mp4&#39;
file &#39;source2.mp4&#39;

$ ffmpeg -f concat -safe 0 -i file_list.txt -c copy output.mp4
</code></pre>]]></content:encoded>
    </item>
    
    <item>
      <title>Configuring integrations in Miniflux</title>
      <link>https://msfjarvis.dev/notes/configuring-integrations-miniflux/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/configuring-integrations-miniflux/</guid>
      <description>&lt;p&gt;Miniflux requires setting up individual credentials for each integration, and the password can not be the same as your normal account password.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Miniflux requires setting up individual credentials for each integration, and the password can not be the same as your normal account password.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Configuring Windows dual-boot on NixOS automatically</title>
      <link>https://msfjarvis.dev/notes/configuring-windows-dual-boot-nixos-automatically/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/configuring-windows-dual-boot-nixos-automatically/</guid>
      <description>&lt;p&gt;NixOS has a module option in &lt;code&gt;systemd-boot&lt;/code&gt; that automatically configures boot entries for Windows without requiring me to copy over the EFI folder [&lt;a href=&#34;https://search.n%C3%83%C2%BCschtos.de/?scope=NixOS&amp;amp;option_scope=11&amp;amp;query=boot.loader.systemd-boot.windows&amp;amp;option=boot.loader.systemd-boot.windows&#34;&gt;ref&lt;/a&gt;]&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>NixOS has a module option in <code>systemd-boot</code> that automatically configures boot entries for Windows without requiring me to copy over the EFI folder [<a href="https://search.n%C3%83%C2%BCschtos.de/?scope=NixOS&amp;option_scope=11&amp;query=boot.loader.systemd-boot.windows&amp;option=boot.loader.systemd-boot.windows">ref</a>]</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Copying the timestamp of a file</title>
      <link>https://msfjarvis.dev/notes/copying-timestamp-file/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/copying-timestamp-file/</guid>
      <description>&lt;p&gt;You can use &lt;code&gt;touch -r old new&lt;/code&gt; to copy the timestamp of an older file in a newly created file. Useful for doing bulk re-encodes with FFmpeg that benefit from preserving timestamps.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>You can use <code>touch -r old new</code> to copy the timestamp of an older file in a newly created file. Useful for doing bulk re-encodes with FFmpeg that benefit from preserving timestamps.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Default padding in Compose Material3 Scaffold</title>
      <link>https://msfjarvis.dev/notes/default-padding-compose-material3-scaffold/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/default-padding-compose-material3-scaffold/</guid>
      <description>&lt;p&gt;The default Material3 &lt;code&gt;Scaffold&lt;/code&gt; component adds the height of the &lt;code&gt;bottomBar&lt;/code&gt; parameter to the inner padding which resulted in the issues I was having with the floating navigation bar. Removing all calls to &lt;code&gt;Modifier.padding&lt;/code&gt; and wiring down the padding parameter as &lt;code&gt;contentPadding&lt;/code&gt; resolved the problem.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>The default Material3 <code>Scaffold</code> component adds the height of the <code>bottomBar</code> parameter to the inner padding which resulted in the issues I was having with the floating navigation bar. Removing all calls to <code>Modifier.padding</code> and wiring down the padding parameter as <code>contentPadding</code> resolved the problem.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Disk management woes</title>
      <link>https://msfjarvis.dev/notes/disk-management-woes/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/disk-management-woes/</guid>
      <description>&lt;p&gt;GNOME does not have support to move partitions around.&lt;/p&gt;
&lt;p&gt;GParted requires the presence of &lt;code&gt;ntfs3g&lt;/code&gt; on &lt;code&gt;$PATH&lt;/code&gt; to enable NTFS support.&lt;/p&gt;
&lt;p&gt;When moving Windows installations across disks the reason why stuff doesn&amp;rsquo;t boot is that the Windows EFI for the old disk is sitting around in your &lt;code&gt;/boot&lt;/code&gt; partition so the &lt;code&gt;systemd-boot&lt;/code&gt; option I pick tries to boot into a non-existent installation. The fix for this is to go and delete the &lt;code&gt;Microsoft&lt;/code&gt; folder from &lt;code&gt;/boot/EFI&lt;/code&gt; and replace it with the one in your new disk and it&amp;rsquo;ll be fixed.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>GNOME does not have support to move partitions around.</p>
<p>GParted requires the presence of <code>ntfs3g</code> on <code>$PATH</code> to enable NTFS support.</p>
<p>When moving Windows installations across disks the reason why stuff doesn&rsquo;t boot is that the Windows EFI for the old disk is sitting around in your <code>/boot</code> partition so the <code>systemd-boot</code> option I pick tries to boot into a non-existent installation. The fix for this is to go and delete the <code>Microsoft</code> folder from <code>/boot/EFI</code> and replace it with the one in your new disk and it&rsquo;ll be fixed.</p>
<p>To extend an NTFS partition in Windows just use the good old <code>diskmgmt.msc</code> and it can just extend it while the disk is online!</p>
<p>To move the Windows recovery partition around, run <code>reagentc /disable</code> to disable the recovery agent, then go into GParted to move the partition to the end and then boot back into #Windows. Do the necessary partition changes then run <code>reagentc /enable</code> to enable it.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Documentation for error codes used in Apple&#39;s APIs</title>
      <link>https://msfjarvis.dev/notes/documentation-error-codes-used-apple/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/documentation-error-codes-used-apple/</guid>
      <description>&lt;p&gt;Apple error codes are indexed at &lt;a href=&#34;https://osstatus.com&#34;&gt;https://osstatus.com&lt;/a&gt;, searchable by hex, long, and string representation. Invaluable for debugging errors thrown by WebRTC.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Apple error codes are indexed at <a href="https://osstatus.com">https://osstatus.com</a>, searchable by hex, long, and string representation. Invaluable for debugging errors thrown by WebRTC.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Finding error logs from Plausible</title>
      <link>https://msfjarvis.dev/notes/finding-error-logs-from-plausible/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/finding-error-logs-from-plausible/</guid>
      <description>&lt;p&gt;Plausible writes error logs only into its Postgres database. Errors are in the &lt;code&gt;errors&lt;/code&gt; column of the &lt;code&gt;oban_jobs&lt;/code&gt; table.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Plausible writes error logs only into its Postgres database. Errors are in the <code>errors</code> column of the <code>oban_jobs</code> table.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Fun with the Pelican in Helldivers 2</title>
      <link>https://msfjarvis.dev/notes/fun-pelican-helldivers-2/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/fun-pelican-helldivers-2/</guid>
      <description>&lt;p&gt;In Helldivers 2 you can cause the Pelican to launch itself in the air upside down by calling in a support weapon right under the wing. On impact the Pelican will go flying in the air and land in a random spot.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In Helldivers 2 you can cause the Pelican to launch itself in the air upside down by calling in a support weapon right under the wing. On impact the Pelican will go flying in the air and land in a random spot.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Getting the full systemd unit file for a service</title>
      <link>https://msfjarvis.dev/notes/getting-full-systemd-unit-file-service/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/getting-full-systemd-unit-file-service/</guid>
      <description>&lt;p&gt;You can run &lt;code&gt;systemctl show servicename.service&lt;/code&gt; to get the &amp;ldquo;final&amp;rdquo; version of your systemd service file, including all overrides which would typically be loaded dynamically by systemd itself and not visible in the actual unit file.&lt;/p&gt;
&lt;p&gt;This is extremely helpful on NixOS where packages can sometimes re-use upstream systemd unit files and inject NixOS specific options through an override file.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>You can run <code>systemctl show servicename.service</code> to get the &ldquo;final&rdquo; version of your systemd service file, including all overrides which would typically be loaded dynamically by systemd itself and not visible in the actual unit file.</p>
<p>This is extremely helpful on NixOS where packages can sometimes re-use upstream systemd unit files and inject NixOS specific options through an override file.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Git credential helpers</title>
      <link>https://msfjarvis.dev/notes/git-credential-helpers/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/git-credential-helpers/</guid>
      <description>&lt;p&gt;Git credential helpers work via writing and reading from standard input and standard output which helped me debug an issue I was having with &lt;a href=&#34;https://github.com/languitar/pass-git-helper&#34;&gt;pass-git-helper&lt;/a&gt;. To get a credential helper to spit out the password, invoke it with the &lt;code&gt;get&lt;/code&gt; action and pass in some basic &lt;code&gt;key=value&lt;/code&gt; data. The interaction looks somewhat like given below, with &lt;code&gt;&amp;lt;&lt;/code&gt; indicating the standard input of the credential helper and &lt;code&gt;&amp;gt;&lt;/code&gt; indicating its standard output.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Git credential helpers work via writing and reading from standard input and standard output which helped me debug an issue I was having with <a href="https://github.com/languitar/pass-git-helper">pass-git-helper</a>. To get a credential helper to spit out the password, invoke it with the <code>get</code> action and pass in some basic <code>key=value</code> data. The interaction looks somewhat like given below, with <code>&lt;</code> indicating the standard input of the credential helper and <code>&gt;</code> indicating its standard output.</p>
<pre tabindex="0"><code># for URL https://git.msfjarvis.dev/msfjarvis/pass-store
$ pass-git-helper get
&lt; protocol=https
&lt; host=git.msfjarvis.dev
&lt; path=msfjarvis/pass-store
&gt; protocol=https
&gt; host=git.msfjarvis.dev
&gt; username=msfjarvis
&gt; password=hunter2
</code></pre>]]></content:encoded>
    </item>
    
    <item>
      <title>GNOME keyring daemon failing with &#39;No such secret item at path&#39;</title>
      <link>https://msfjarvis.dev/notes/gnome-keyring-daemon-failing/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/gnome-keyring-daemon-failing/</guid>
      <description>&lt;p&gt;After a GNOME related NixOS rebuild sometimes the secret store starts erroring out with this message: &lt;code&gt;No such secret item at path: /org/freedesktop/secrets/collection/login/145&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is resolved by restarting the gnome-keyring-daemon using the command &lt;code&gt;gnome-keyring-daemon -r -d&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>After a GNOME related NixOS rebuild sometimes the secret store starts erroring out with this message: <code>No such secret item at path: /org/freedesktop/secrets/collection/login/145</code></p>
<p>This is resolved by restarting the gnome-keyring-daemon using the command <code>gnome-keyring-daemon -r -d</code>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Hades and Hades 2 are written in Lua</title>
      <link>https://msfjarvis.dev/notes/hades-hades-2-are-written-lua/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/hades-hades-2-are-written-lua/</guid>
      <description>&lt;p&gt;Hades and Hades_2 are written mostly in Lua and all the code is left as-is in the game which makes modding significantly simpler. Very cool!&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Hades and Hades_2 are written mostly in Lua and all the code is left as-is in the game which makes modding significantly simpler. Very cool!</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Helldivers 2 fullscreen woes</title>
      <link>https://msfjarvis.dev/notes/helldivers-2-fullscreen-woes/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/helldivers-2-fullscreen-woes/</guid>
      <description>&lt;p&gt;Helldivers 2 on Linux hates full screen mode and will fail to start the next time after you switch display to full screen. This is why it breaks randomly for me on Linux and seemingly gets fixed after an update since Arrowhead randomly reverts back to windowed when the game is updated. Work around is to always use Borderless instead.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Helldivers 2 on Linux hates full screen mode and will fail to start the next time after you switch display to full screen. This is why it breaks randomly for me on Linux and seemingly gets fixed after an update since Arrowhead randomly reverts back to windowed when the game is updated. Work around is to always use Borderless instead.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>HTTP remotes in rclone</title>
      <link>https://msfjarvis.dev/notes/http-remotes-rclone/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/http-remotes-rclone/</guid>
      <description>&lt;p&gt;&lt;code&gt;rclone&lt;/code&gt; can use HTTP hosts as a remote, so it&amp;rsquo;s often faster and easier to move things between servers via a file-server rather than over SSH using &lt;code&gt;rsync&lt;/code&gt; assuming the contents aren&amp;rsquo;t private.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><code>rclone</code> can use HTTP hosts as a remote, so it&rsquo;s often faster and easier to move things between servers via a file-server rather than over SSH using <code>rsync</code> assuming the contents aren&rsquo;t private.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Initial setup for Nix remote builds</title>
      <link>https://msfjarvis.dev/notes/initial-setup-nix-remote-builds/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/initial-setup-nix-remote-builds/</guid>
      <description>&lt;p&gt;Nix remote builds are run through the daemon (obviously) so they are executed as root on the host delegating builds. To prevent issues, &lt;code&gt;nix store ping&lt;/code&gt; needs to be run as root first to verify the host key before Nix can start using the remote host to do builds.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Nix remote builds are run through the daemon (obviously) so they are executed as root on the host delegating builds. To prevent issues, <code>nix store ping</code> needs to be run as root first to verify the host key before Nix can start using the remote host to do builds.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Listing PipeWire inputs and outputs</title>
      <link>https://msfjarvis.dev/notes/listing-pipewire-inputs-outputs/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/listing-pipewire-inputs-outputs/</guid>
      <description>&lt;p&gt;&lt;code&gt;pw-cli list-objects | rg node.name&lt;/code&gt; will give you a full list of all connected audio inputs and outputs on a PipeWire system.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><code>pw-cli list-objects | rg node.name</code> will give you a full list of all connected audio inputs and outputs on a PipeWire system.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Managing a Nixpkgs fork without upstream tags</title>
      <link>https://msfjarvis.dev/notes/managing-nixpkgs-fork-without-upstream-tags/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/managing-nixpkgs-fork-without-upstream-tags/</guid>
      <description>&lt;p&gt;Enabling &lt;code&gt;fetch.pruneTags&lt;/code&gt; causes my Nixpkgs Git checkout to constantly delete and fetch tags, since my fork is missing most tags that upstream has so they keep getting pruned when updating from &lt;code&gt;origin&lt;/code&gt; and get re-created when fetching &lt;code&gt;upstream&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;One solution suggested for this was setting &lt;code&gt;remotes.&amp;lt;name&amp;gt;.tagOpt = &amp;quot;--no-tags&amp;quot;&lt;/code&gt; but that didn&amp;rsquo;t do the job for me.&lt;/p&gt;
&lt;p&gt;The thing that worked for me was to conditionally disable &lt;code&gt;pruneTags&lt;/code&gt; for just the &lt;code&gt;origin&lt;/code&gt; remote so it would not try to clear out the tags pulled from &lt;code&gt;upstream&lt;/code&gt;. Achieved by running &lt;code&gt;git config --local remotes.origin.pruneTags false&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Enabling <code>fetch.pruneTags</code> causes my Nixpkgs Git checkout to constantly delete and fetch tags, since my fork is missing most tags that upstream has so they keep getting pruned when updating from <code>origin</code> and get re-created when fetching <code>upstream</code>.</p>
<p>One solution suggested for this was setting <code>remotes.&lt;name&gt;.tagOpt = &quot;--no-tags&quot;</code> but that didn&rsquo;t do the job for me.</p>
<p>The thing that worked for me was to conditionally disable <code>pruneTags</code> for just the <code>origin</code> remote so it would not try to clear out the tags pulled from <code>upstream</code>. Achieved by running <code>git config --local remotes.origin.pruneTags false</code>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Minecraft villager breeders</title>
      <link>https://msfjarvis.dev/notes/minecraft-villager-breeders/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/minecraft-villager-breeders/</guid>
      <description>&lt;p&gt;In Minecraft it is imperative that there are exactly 4 villagers in a breeder, if there are more than 4 beds it makes them mad and stop producing babies.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In Minecraft it is imperative that there are exactly 4 villagers in a breeder, if there are more than 4 beds it makes them mad and stop producing babies.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Nix `builtins.toString` behaves in a surprising manner</title>
      <link>https://msfjarvis.dev/notes/nix-builtinstostring-behaves-surprising-manner/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/nix-builtinstostring-behaves-surprising-manner/</guid>
      <description>&lt;p&gt;Nix&amp;rsquo;s &lt;code&gt;builtins.toString&lt;/code&gt; doesn&amp;rsquo;t stringify a Boolean directly but instead returns an empty string for false and &lt;code&gt;&amp;quot;1&amp;quot;&lt;/code&gt; for true. The reason for this is apparently that the result is optimized for use in shell pipelines, so the result is expected to go into a &lt;code&gt;[ -z $result ]&lt;/code&gt; on the result of calling the function.&lt;/p&gt;
&lt;p&gt;Lost entirely too much time to this.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Nix&rsquo;s <code>builtins.toString</code> doesn&rsquo;t stringify a Boolean directly but instead returns an empty string for false and <code>&quot;1&quot;</code> for true. The reason for this is apparently that the result is optimized for use in shell pipelines, so the result is expected to go into a <code>[ -z $result ]</code> on the result of calling the function.</p>
<p>Lost entirely too much time to this.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Password manager resources</title>
      <link>https://msfjarvis.dev/notes/password-manager-resources/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/password-manager-resources/</guid>
      <description>&lt;p&gt;Apple maintains a repository of resources for password managers &lt;a href=&#34;https://github.com/apple/password-manager-resources&#34;&gt;GitHub&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Apple maintains a repository of resources for password managers <a href="https://github.com/apple/password-manager-resources">GitHub</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Prism Launcher login issues</title>
      <link>https://msfjarvis.dev/notes/prism-launcher-login-issues/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/prism-launcher-login-issues/</guid>
      <description>&lt;p&gt;Prism Launcher&amp;rsquo;s OAuth flow is not triggered properly when I log into Microsoft/Xbox with the usual GitHub way, I need to explicitly log in using my password to make it work.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Prism Launcher&rsquo;s OAuth flow is not triggered properly when I log into Microsoft/Xbox with the usual GitHub way, I need to explicitly log in using my password to make it work.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Quick way to spin up a Nix binary cache on your filesystem</title>
      <link>https://msfjarvis.dev/notes/quick-way-spin-up-nix-binary-cache-your-filesystem/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/quick-way-spin-up-nix-binary-cache-your-filesystem/</guid>
      <description>&lt;p&gt;Nixpkgs has a &lt;a href=&#34;https://nixos.org/manual/nixpkgs/unstable/#sec-pkgs-binary-cache&#34;&gt;&lt;code&gt;pkgs.mkBinaryCache&lt;/code&gt;&lt;/a&gt; helper that lets you create a flat-file binary cache suitable for moving around without needing a server component.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Nixpkgs has a <a href="https://nixos.org/manual/nixpkgs/unstable/#sec-pkgs-binary-cache"><code>pkgs.mkBinaryCache</code></a> helper that lets you create a flat-file binary cache suitable for moving around without needing a server component.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Reddit RSS feeds</title>
      <link>https://msfjarvis.dev/notes/reddit-rss-feeds/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/reddit-rss-feeds/</guid>
      <description>&lt;p&gt;Reddit exposes RSS feeds for subreddits and users such as &lt;a href=&#34;https://reddit.com/r/HermitCraft/.rss&#34;&gt;https://reddit.com/r/HermitCraft/.rss&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Reddit exposes RSS feeds for subreddits and users such as <a href="https://reddit.com/r/HermitCraft/.rss">https://reddit.com/r/HermitCraft/.rss</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Removing a Git submodule</title>
      <link>https://msfjarvis.dev/notes/removing-git-submodule/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/removing-git-submodule/</guid>
      <description>&lt;p&gt;To remove a Git submodule go through these annoying steps:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git submodule deinit -f path/to/module
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rm -rf .git/modules/path/to/module
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git config -f .gitmodules --remove-section submodule.path/to/module
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git add .gitmodules
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git rm --cached path/to/module
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <content:encoded><![CDATA[<p>To remove a Git submodule go through these annoying steps:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git submodule deinit -f path/to/module
</span></span><span class="line"><span class="cl">rm -rf .git/modules/path/to/module
</span></span><span class="line"><span class="cl">git config -f .gitmodules --remove-section submodule.path/to/module
</span></span><span class="line"><span class="cl">git add .gitmodules
</span></span><span class="line"><span class="cl">git rm --cached path/to/module
</span></span></code></pre></div>]]></content:encoded>
    </item>
    
    <item>
      <title>Rudimentary type-safety in Rust macro_rules macros</title>
      <link>https://msfjarvis.dev/notes/rudimentary-type-safety-rust-macro_rules-macros/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/rudimentary-type-safety-rust-macro_rules-macros/</guid>
      <description>&lt;p&gt;Although Rust&amp;rsquo;s &lt;code&gt;macro_rules&lt;/code&gt; macros operates on syntax trees and thus cannot propagate types, there are ways to make the compiler do it for you. One such trick is to insert a function call that expects only the specific type you want, which then fails for the other types that are not expected by the macro. Picked up from StackOverflow: &lt;a href=&#34;https://stackoverflow.com/a/34214916&#34;&gt;https://stackoverflow.com/a/34214916&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Although Rust&rsquo;s <code>macro_rules</code> macros operates on syntax trees and thus cannot propagate types, there are ways to make the compiler do it for you. One such trick is to insert a function call that expects only the specific type you want, which then fails for the other types that are not expected by the macro. Picked up from StackOverflow: <a href="https://stackoverflow.com/a/34214916">https://stackoverflow.com/a/34214916</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Sizing Composables to window insets</title>
      <link>https://msfjarvis.dev/notes/sizing-composables-window-insets/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/sizing-composables-window-insets/</guid>
      <description>&lt;p&gt;There are APIs in Jetpack Compose to be able to size things exactly as tall/wide as specific Insets, which is documented &lt;a href=&#34;https://developer.android.com/develop/ui/compose/layouts/insets#inset-size&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>There are APIs in Jetpack Compose to be able to size things exactly as tall/wide as specific Insets, which is documented <a href="https://developer.android.com/develop/ui/compose/layouts/insets#inset-size">here</a>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Staging a file in Git without its contents</title>
      <link>https://msfjarvis.dev/notes/staging-file-git-without-its-contents/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/staging-file-git-without-its-contents/</guid>
      <description>&lt;p&gt;&lt;code&gt;git add -N&lt;/code&gt; will stage a file without any of its changes, you can treat that as an &amp;ldquo;intention&amp;rdquo; to add as well as allow diffing additions without needing &lt;code&gt;diff --cached&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><code>git add -N</code> will stage a file without any of its changes, you can treat that as an &ldquo;intention&rdquo; to add as well as allow diffing additions without needing <code>diff --cached</code>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Staging only tracked files in Git</title>
      <link>https://msfjarvis.dev/notes/staging-only-tracked-files-git/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/staging-only-tracked-files-git/</guid>
      <description>&lt;p&gt;&lt;code&gt;git add -u&lt;/code&gt; will stage changes to all tracked files and leave untracked ones alone&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><code>git add -u</code> will stage changes to all tracked files and leave untracked ones alone</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Tailscale ACL grants</title>
      <link>https://msfjarvis.dev/notes/tailscale-acl-grants/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/tailscale-acl-grants/</guid>
      <description>&lt;p&gt;Services being routed by &lt;a href=&#34;https://github.com/tailscale/caddy-tailscale&#34;&gt;caddy-tailscale&lt;/a&gt; are treated as full-fledged Tailscale nodes and thus follow the ACL policies of deny-by-default. If I want to be able to ping a Tailscale address from the server I will have to add an ACL grant allowing the server&amp;rsquo;s tag to access the tag applied to the service. This was necessary today for the Firefly-iii data importer to be able to access the Firefly-iii instance running on the same server.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Services being routed by <a href="https://github.com/tailscale/caddy-tailscale">caddy-tailscale</a> are treated as full-fledged Tailscale nodes and thus follow the ACL policies of deny-by-default. If I want to be able to ping a Tailscale address from the server I will have to add an ACL grant allowing the server&rsquo;s tag to access the tag applied to the service. This was necessary today for the Firefly-iii data importer to be able to access the Firefly-iii instance running on the same server.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Tutorial for the NixOS module system</title>
      <link>https://msfjarvis.dev/notes/tutorial-nixos-module-system/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/tutorial-nixos-module-system/</guid>
      <description>&lt;p&gt;Found this awesome reference for the NixOS module system: &lt;a href=&#34;https://nix.dev/tutorials/module-system/index.html&#34;&gt;https://nix.dev/tutorials/module-system/index.html&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Found this awesome reference for the NixOS module system: <a href="https://nix.dev/tutorials/module-system/index.html">https://nix.dev/tutorials/module-system/index.html</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Type=&#39;oneshot&#39; services block systemctl CLI</title>
      <link>https://msfjarvis.dev/notes/systemd-oneshot-services/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/systemd-oneshot-services/</guid>
      <description>&lt;p&gt;Systemd runs all units that specify &lt;code&gt;Type=oneshot&lt;/code&gt; to completion in a blocking manner which is what causes my NixOS configuration switching to sometimes get stuck with a long-running task. The solution is to use &lt;code&gt;Type=simple&lt;/code&gt; and instead configure the restart policy to not fire unnecessarily.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Systemd runs all units that specify <code>Type=oneshot</code> to completion in a blocking manner which is what causes my NixOS configuration switching to sometimes get stuck with a long-running task. The solution is to use <code>Type=simple</code> and instead configure the restart policy to not fire unnecessarily.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Updating Fixed Output Derivations in Nix packages</title>
      <link>https://msfjarvis.dev/notes/updating-fixed-output-derivations-nix-packages/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/updating-fixed-output-derivations-nix-packages/</guid>
      <description>&lt;p&gt;Nix vendors Golang dependencies in a fixed-output derivation (FOD) which will give confusing errors if the contents change but you don&amp;rsquo;t update the hash or name. Concrete example: refreshing the &lt;code&gt;update-tailscale.patch&lt;/code&gt; file for &lt;code&gt;caddy-tailscale&lt;/code&gt; will fail with mysterious &amp;ldquo;this module is using a different version&amp;rdquo; until you change either &lt;code&gt;pname&lt;/code&gt; or &lt;code&gt;vendorHash&lt;/code&gt; to force a rebuild of the FOD and reveal any real errors.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Nix vendors Golang dependencies in a fixed-output derivation (FOD) which will give confusing errors if the contents change but you don&rsquo;t update the hash or name. Concrete example: refreshing the <code>update-tailscale.patch</code> file for <code>caddy-tailscale</code> will fail with mysterious &ldquo;this module is using a different version&rdquo; until you change either <code>pname</code> or <code>vendorHash</code> to force a rebuild of the FOD and reveal any real errors.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Updating unstable packages in Nix</title>
      <link>https://msfjarvis.dev/notes/updating-unstable-packages-nix/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/updating-unstable-packages-nix/</guid>
      <description>&lt;p&gt;The &lt;a href=&#34;https://github.com/Mic92/nix-update&#34;&gt;nix-update&lt;/a&gt; CLI allows updating unstable packages to Git commits via &lt;code&gt;--version=branch&lt;/code&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>The <a href="https://github.com/Mic92/nix-update">nix-update</a> CLI allows updating unstable packages to Git commits via <code>--version=branch</code></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Using Tailscale exit nodes on NixOS</title>
      <link>https://msfjarvis.dev/notes/using-tailscale-exit-nodes-nixos/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/using-tailscale-exit-nodes-nixos/</guid>
      <description>&lt;p&gt;Tailscale on NixOS requires setting &lt;code&gt;services.tailscale.useRoutingFeatures = &amp;quot;client&amp;quot;&lt;/code&gt; on the non-exit-node machines to allow routing to work.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Tailscale on NixOS requires setting <code>services.tailscale.useRoutingFeatures = &quot;client&quot;</code> on the non-exit-node machines to allow routing to work.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Using your IDE as the Git commit message editor</title>
      <link>https://msfjarvis.dev/notes/using-your-ide-as-git-commit-message-editor/</link>
      <pubDate>Mon, 30 Jun 2025 20:01:25 +0000</pubDate>
      <author>me@msfjarvis.dev (Harsh Shandilya)</author>
      <guid>https://msfjarvis.dev/notes/using-your-ide-as-git-commit-message-editor/</guid>
      <description>&lt;p&gt;Git has a &lt;a href=&#34;https://git-scm.com/docs/git-var#Documentation/git-var.txt-GITEDITOR&#34;&gt;&lt;code&gt;GIT_EDITOR&lt;/code&gt; variable&lt;/a&gt; that can be overridden in specific contexts to change the editor used by Git for rebase/commit etc.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve configured Zed to use itself as my commit editor from the integrated terminal, which makes for a nicer experience in the IDE than having to use the terminal text editor.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Git has a <a href="https://git-scm.com/docs/git-var#Documentation/git-var.txt-GITEDITOR"><code>GIT_EDITOR</code> variable</a> that can be overridden in specific contexts to change the editor used by Git for rebase/commit etc.</p>
<p>I&rsquo;ve configured Zed to use itself as my commit editor from the integrated terminal, which makes for a nicer experience in the IDE than having to use the terminal text editor.</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
