<?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://dumidusw.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://dumidusw.dev/" rel="alternate" type="text/html" /><updated>2026-08-27T09:32:54+00:00</updated><id>https://dumidusw.dev/feed.xml</id><title type="html">Linux • Programming • Open Source • Software Engineering</title><subtitle>Exploring Linux, Python, Bash, and software engineering fundamentals through practical projects.</subtitle><author><name>Dumidu</name></author><entry><title type="html">Why I built psmon</title><link href="https://dumidusw.dev/2026/08/15/why-I-built-psmon/" rel="alternate" type="text/html" title="Why I built psmon" /><published>2026-08-15T18:30:00+00:00</published><updated>2026-08-15T18:30:00+00:00</updated><id>https://dumidusw.dev/2026/08/15/why-I-built-psmon</id><content type="html" xml:base="https://dumidusw.dev/2026/08/15/why-I-built-psmon/"><![CDATA[<p>Anyone who uses a Unix like operating system has probably come across tools like <code class="language-plaintext highlighter-rouge">top</code>, <code class="language-plaintext highlighter-rouge">htop</code>, or the graphically rich <code class="language-plaintext highlighter-rouge">btop</code>. They are indeed feature rich and powerful. They are capable of providing pretty much every system metric an experienced system administrator could ever ask for. But I wanted something simple, fast, and approachable.</p>

<!--more-->

<p>For new Linux users, or even experienced developers who just want to quickly figure out why their computer fan has gone into “helicopter mode”, these tools can feel overwhelming. They show a lot of numbers, graphs, and processes when all you really want is a straight answer. They are verbose.</p>

<p>Now if we look at the other end of the spectrum, we have the native <code class="language-plaintext highlighter-rouge">ps</code> command, which was developed in the early 1970s. It’s a fantastic tool for process analysis. It’s lightweight and very fast. But we don’t get an eye-catching dashboard with it. Another limitation of <code class="language-plaintext highlighter-rouge">ps</code> is that it gives you a static snapshot. For example, let’s say you want to find a memory hog, watch it live, and terminate it. You might start with <code class="language-plaintext highlighter-rouge">ps</code>, pipe the output through <code class="language-plaintext highlighter-rouge">grep</code> or <code class="language-plaintext highlighter-rouge">awk</code>, and repeat the command to see what’s happening. Then, when you find the process you want, you still have to copy its PID and pass it to <code class="language-plaintext highlighter-rouge">kill</code>.</p>

<p>I wanted something in the middle.</p>

<p>I didn’t want to build just another alias or another basic wrapper around the <code class="language-plaintext highlighter-rouge">ps</code> command. Instead, I wanted a tool that respected the speed and historic efficiency of <code class="language-plaintext highlighter-rouge">ps</code>, but elevated it into an interactive experience. I wanted live watching, instant sorting, and safe, tree-aware process killing, all presented in a clean, readable UI that doesn’t overwhelm the user.</p>

<p>That is why I built psmon.</p>

<hr />

<h2 id="the-architecture">The Architecture</h2>

<p>From the start, I wanted this utility to be simple and easy to deploy. So I decided early on that there would be no compilation step and no heavy dependencies.</p>

<p>Now, when it comes to building a modern CLI tool, developers usually prefer to use a language like Rust, Go, or even Python. They are great, but I wanted this to lean entirely on the shell, specifically Zsh. So if you have a terminal and a standard Linux environment, <code class="language-plaintext highlighter-rouge">psmon</code> just works. There is nothing to compile and nothing to <code class="language-plaintext highlighter-rouge">pip install</code>.</p>

<p>I also wanted this to be fast and efficient without relying on an external library like <code class="language-plaintext highlighter-rouge">ncurses</code>. A shell-based TUI doesn’t need anything beyond the terminal itself. That gave me a simple architecture. Then I split the work into two parts:</p>

<p><strong>The heavy lifters (<code class="language-plaintext highlighter-rouge">ps</code>, <code class="language-plaintext highlighter-rouge">awk</code>, <code class="language-plaintext highlighter-rouge">lsof</code>).</strong></p>

<p>If you want, you can write a shell program to read process data and sort it yourself, but that would be very time-consuming and you’d be reinventing the wheel. So <code class="language-plaintext highlighter-rouge">psmon</code> hands that work off to well-established utilities such as <code class="language-plaintext highlighter-rouge">ps</code>, <code class="language-plaintext highlighter-rouge">awk</code>, and <code class="language-plaintext highlighter-rouge">lsof</code>. This is the Unix philosophy, isn’t it?</p>

<p><strong>The presentation layer (Zsh).</strong></p>

<p>Zsh is the conductor. It takes that raw, static output and brings it to life. It runs the interactive watch loop, intercepts keypresses on the fly, and paints the terminal with ANSI color codes based on CPU and memory thresholds.</p>

<p>Here I’m showing a simplified version of that split, taken directly from <code class="language-plaintext highlighter-rouge">psmon</code>’s process list rendering:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># The heavy lifter: ps does the querying AND the sorting.</span>
<span class="c"># No custom sort logic lives in this script - we just tell it which</span>
<span class="c"># field to sort by and take what comes back.</span>
<span class="k">while </span><span class="nb">read</span> <span class="nt">-r</span> pid ppid user cpu mem etime <span class="nb">comm</span><span class="p">;</span> <span class="k">do</span>

    <span class="c"># The presentation layer: Zsh decides what the numbers mean.</span>
    <span class="k">if</span> <span class="o">((</span> cpu <span class="o">&gt;</span> 10 <span class="o">))</span><span class="p">;</span> <span class="k">then
        </span><span class="nb">echo</span> <span class="s2">"</span><span class="k">${</span><span class="nv">RED</span><span class="k">}${</span><span class="nv">pid</span><span class="k">}</span><span class="s2">  </span><span class="k">${</span><span class="nv">cpu</span><span class="k">}</span><span class="s2">%  </span><span class="k">${</span><span class="nv">comm</span><span class="k">}${</span><span class="nv">NC</span><span class="k">}</span><span class="s2">"</span>
    <span class="k">elif</span> <span class="o">((</span> cpu <span class="o">&gt;</span> 5 <span class="o">))</span><span class="p">;</span> <span class="k">then
        </span><span class="nb">echo</span> <span class="s2">"</span><span class="k">${</span><span class="nv">YELLOW</span><span class="k">}${</span><span class="nv">pid</span><span class="k">}</span><span class="s2">  </span><span class="k">${</span><span class="nv">cpu</span><span class="k">}</span><span class="s2">%  </span><span class="k">${</span><span class="nv">comm</span><span class="k">}${</span><span class="nv">NC</span><span class="k">}</span><span class="s2">"</span>
    <span class="k">else
        </span><span class="nb">echo</span> <span class="s2">"</span><span class="k">${</span><span class="nv">pid</span><span class="k">}</span><span class="s2">  </span><span class="k">${</span><span class="nv">cpu</span><span class="k">}</span><span class="s2">%  </span><span class="k">${</span><span class="nv">comm</span><span class="k">}</span><span class="s2">"</span>
    <span class="k">fi

done</span> &lt; &lt;<span class="o">(</span>ps <span class="nt">-eo</span> pid,ppid,user,%cpu,%mem,etime,comm <span class="nt">--sort</span><span class="o">=</span>-%cpu <span class="nt">--no-headers</span><span class="o">)</span>
</code></pre></div></div>

<p>Here it’s worth pointing out two important things. First, the <code class="language-plaintext highlighter-rouge">--sort=-%cpu</code> flag is essentially the entire sorting logic in <code class="language-plaintext highlighter-rouge">psmon</code>. The second is the <code class="language-plaintext highlighter-rouge">&lt; &lt;(...)</code> at the bottom. It’s a process substitution. It feeds <code class="language-plaintext highlighter-rouge">ps</code>’s output into the <code class="language-plaintext highlighter-rouge">while read</code> loop while allowing the loop itself to run in the current shell. So any state the loop needs to update stays visible to the rest of the script.</p>

<p>This is a small detail, but it’s the kind of thing that matters when you’re trying to keep a shell script fast and predictable. It avoids putting the loop behind a normal pipeline, where the loop could run in a subshell.</p>

<p>This approach keeps the script lightweight, fast, and easy to audit. You can read it from top to bottom and know exactly what’s running and why.</p>

<p>It’s the Unix philosophy in action. I let each tool do one thing, while the shell wires them together.</p>

<hr />
<h2 id="two-problems-i-had-to-deal-with">Two Problems I Had to Deal With</h2>

<p>Writing a process monitor in shell sounds easy. But once you start dealing with a modern Linux desktop, things get more complicated. Sandboxed applications, sprawling process trees, and terminal behavior all introduced their own challenges. I had to deal with two particularly interesting problems.</p>

<h3 id="1-sandbox-aware-killing">1. Sandbox-Aware Killing</h3>

<p>Modern applications are messy. Browsers and complex desktop apps often spawn a tree of processes rather than running as a single monolithic process. This multi process design uses renderers, zygotes, and helper services to isolate tasks, improve security, and manage resources. When you run them via Flatpak, the process tree gets even more layered because Flatpak enforces sandboxing with Bubblewrap (<code class="language-plaintext highlighter-rouge">bwrap</code>).</p>

<p>When an application runs inside a sandbox, its processes don’t always look like normal children of the main application process. Because the sandbox creates its own container, some of the application’s processes may appear under the Bubblewrap process instead of the original program when viewed from the host. So if you use a plain <code class="language-plaintext highlighter-rouge">kill</code> command, you can miss related processes. If you use <code class="language-plaintext highlighter-rouge">killall</code>, it can grab more processes than you intended to target.</p>

<p>To solve this, I had to carefully design <code class="language-plaintext highlighter-rouge">psmon</code>’s interactive kill mode (<code class="language-plaintext highlighter-rouge">-k</code>) to actually understand modern application architectures.</p>

<p>When you target a process by name, <code class="language-plaintext highlighter-rouge">psmon</code> doesn’t just take the first match. It checks each process’s command-line arguments to identify auxiliary browser processes, such as Chromium’s <code class="language-plaintext highlighter-rouge">--type=renderer</code>. These processes are filtered out of the target list because they will terminate when the main application dies. This keeps the list clean and lets you select the actual application instance.</p>

<p>Then, once you’ve picked a target, <code class="language-plaintext highlighter-rouge">psmon</code> walks up the process tree. If it hits a <code class="language-plaintext highlighter-rouge">bwrap</code> or <code class="language-plaintext highlighter-rouge">flatpak-bwrap</code> process, it doesn’t stop there. It treats the wrapper as a pass-through and keeps climbing, looking for the real top-level ancestor above the sandbox layer. That topmost process is what gets treated as the actual root. Once the true root is identified, <code class="language-plaintext highlighter-rouge">psmon</code> asks for confirmation. If you confirm, then it terminates the entire tree at once.</p>

<h3 id="2-flicker-free-live-updates">2. Flicker-Free Live Updates</h3>

<p>The obvious way to build a live dashboard in shell is to call <code class="language-plaintext highlighter-rouge">clear</code> at the top of the <code class="language-plaintext highlighter-rouge">while</code> loop. But if you do that on every refresh, the whole screen gets cleared and redrawn again and again. The result is noticeable flicker.</p>

<p>To make <code class="language-plaintext highlighter-rouge">psmon</code>’s live watch mode (<code class="language-plaintext highlighter-rouge">-w</code>) update cleanly, I removed <code class="language-plaintext highlighter-rouge">clear</code> from the periodic refresh. While <code class="language-plaintext highlighter-rouge">clear</code> is still called once when you first enter watch mode to give you a clean slate, and again if you switch the sort order, it is completely absent from the continuous refresh loop. Instead, each refresh tick uses two small ANSI escape sequences to control the terminal.</p>

<p>On every refresh, <code class="language-plaintext highlighter-rouge">psmon</code> moves the cursor back to the top-left corner (<code class="language-plaintext highlighter-rouge">\033[H</code>) and redraws the process list. Each line ends with <code class="language-plaintext highlighter-rouge">\033[K</code>, which tells the terminal to erase everything from the cursor to the end of that line:</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Instead of clearing the whole screen, jump the cursor home and let</span>
<span class="c"># each line erase its own trailing remainder as it's printed.</span>
<span class="nb">printf</span> <span class="s2">"</span><span class="se">\0</span><span class="s2">33[H"</span>
<span class="k">while </span><span class="nb">read</span> <span class="nt">-r</span> line<span class="p">;</span> <span class="k">do
    </span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$line</span><span class="se">\0</span><span class="s2">33[K"</span>
<span class="k">done</span> &lt; &lt;<span class="o">(</span>ps <span class="nt">-eo</span> pid,ppid,user,%cpu,%mem,etime,comm <span class="nt">--sort</span><span class="o">=</span>-%cpu <span class="nt">--no-headers</span><span class="o">)</span>
</code></pre></div></div>

<p>This means each row overwrites the previous one in place. If the new row is shorter than the old one, <code class="language-plaintext highlighter-rouge">\033[K</code> removes the remaining characters. No leftover text is left on the screen.</p>

<p>When you press <code class="language-plaintext highlighter-rouge">c</code>, <code class="language-plaintext highlighter-rouge">m</code>, or <code class="language-plaintext highlighter-rouge">t</code> to switch the sort order, <code class="language-plaintext highlighter-rouge">psmon</code> does a quick clear to safely reset the canvas, remembers your new choice, and immediately resumes this ANSI-powered loop.</p>

<p>The result is a clean update on every tick, without the constant visual flicker or unnecessary screen tearing you usually get from shell dashboards.</p>

<hr />
<h2 id="zsh-glues-programs-together">Zsh glues programs together</h2>

<p>Building <code class="language-plaintext highlighter-rouge">psmon</code> reminded me why the Unix philosophy has survived for so long. You don’t always need a heavy compiled binary or a massive dependency tree to build a fast, modern CLI tool. Sometimes, taking reliable tools like <code class="language-plaintext highlighter-rouge">ps</code> and <code class="language-plaintext highlighter-rouge">awk</code> and connecting them with just enough Zsh is all you need to solve a real problem.</p>

<p>It took extra effort to polish the rough edges, such as regex validation, clear error messages, and cryptographically signed Git tags. But the payoff is a tool that feels native and finished.</p>

<p>If you are tired of piping raw <code class="language-plaintext highlighter-rouge">ps</code> output through <code class="language-plaintext highlighter-rouge">grep</code>, but don’t want a complex dashboard every time your fan spins up, give <code class="language-plaintext highlighter-rouge">psmon</code> a try.</p>

<p>You can find the source code, full documentation, and installation instructions on my GitHub account:</p>

<p><a href="https://github.com/dumidusw/psmon"><strong>https://github.com/dumidusw/psmon</strong></a></p>

<p>It includes a simple <code class="language-plaintext highlighter-rouge">./install.sh</code> script, or you can load it through your favorite Zsh plugin manager.</p>

<p>I’d love to hear what you think. If you find a bug or get an idea for a feature that keeps that balance between utility and simplicity, please feel free to open an issue or send a pull request. I’d genuinely appreciate it.</p>

<hr />

<p>Got questions, corrections, or suggestions?</p>

<p>Open an issue on <a href="https://github.com/dumidusw">GitHub</a> or <a href="mailto:dumidu.github@gmail.com">drop me an email</a>.</p>

<div class="author-bio">
  <img class="author-bio-avatar" src="https://avatars.githubusercontent.com/u/197898757?v=4" alt="dumidusw" width="44" height="44" loading="lazy" />
  <div class="author-bio-text">
    <span class="author-bio-name">Dumidu</span>
    <span class="author-bio-links">
      <a href="https://github.com/dumidusw" target="_blank" rel="me noopener">GitHub Profile</a>
      <span class="dot-separator">&bull;</span>
      <a href="mailto:dumidu.github@gmail.com">Email</a>
    </span>
  </div>
</div>]]></content><author><name>Dumidu</name></author><category term="projects" /><summary type="html"><![CDATA[Why I built psmon, a lightweight interactive process monitor that brings the simplicity of ps together with the interactivity of modern process monitors, using nothing but Zsh and standard Linux utilities.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://dumidusw.dev/assets/images/posts/psmon.webp" /><media:content medium="image" url="https://dumidusw.dev/assets/images/posts/psmon.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">This is why I don’t like NixOS</title><link href="https://dumidusw.dev/2026/08/04/this-is-why-i-donot-like-nixos/" rel="alternate" type="text/html" title="This is why I don’t like NixOS" /><published>2026-08-04T04:30:00+00:00</published><updated>2026-08-04T04:30:00+00:00</updated><id>https://dumidusw.dev/2026/08/04/this-is-why-i-donot-like-nixos</id><content type="html" xml:base="https://dumidusw.dev/2026/08/04/this-is-why-i-donot-like-nixos/"><![CDATA[<p>As I remember, it was around 2004 when I first installed Linux using a Red Hat CD bought from a local store. I spent days learning where configurations lived in <code class="language-plaintext highlighter-rouge">/etc</code>, where binaries sat in <code class="language-plaintext highlighter-rouge">/bin</code>, how shared libraries linked together via <code class="language-plaintext highlighter-rouge">/usr/lib</code>, and how text files drove the entire operating system, that beautiful concept of everything is a file. It took some time and effort, but learning those fundamentals paid off. 
<!--more-->
Now, over two decades later, my daily driver is Arch Linux. The init system changed from SysVinit to systemd, Wayland replaced X11, and package managers evolved. But the foundational mental model I built still remains virtually untouched. That knowledge is still directly applicable. That’s the beauty of the UNIX legacy, what you learn today stays useful for decades. But NixOS throws that away, and most people who recommend NixOS to beginners don’t realize that.</p>

<h2 id="learning-an-abstraction-layer-not-the-os">Learning an abstraction layer, not the OS</h2>

<p>The biggest selling point of NixOS is, as they say, that it’s declarative and reproducible. Let’s see what those two terms actually mean</p>

<ul>
  <li>Declarative: On standard Linux, you configure a system imperatively. That means you run step-by-step commands over time (<code class="language-plaintext highlighter-rouge">apt install</code>, edit a file in <code class="language-plaintext highlighter-rouge">/etc</code>, enable a service). But in NixOS, you don’t run steps, you just write down a blueprint of the end result (like <code class="language-plaintext highlighter-rouge">services.nginx.enable = true;</code>), and the system figures out how to make it happen.</li>
  <li>Reproducible: If you take that blueprint and run it on a new computer five years from now, NixOS uses cryptographic hashes to pull the exact same dependencies, libraries, and configs. You get a bit-for-bit identical setup every single time.</li>
</ul>

<p>So it’s easy to understand why some developers love this pitch. But my opinion is that in chasing that declarative magic, they end up mastering that abstraction layer, rather than the operating system itself. That means NixOS doesn’t teach you Linux. Instead, it teaches you something called Nix.</p>

<h2 id="no-fhs-and-the-knowledge-is-not-transferable">No FHS and the knowledge is not transferable</h2>

<p>The Filesystem Hierarchy Standard (FHS) is a fundamental design of UNIX-like operating systems. We see it throughout the history of UNIX evolution, from early BSD and Red Hat to modern Arch Linux. It’s why you always know where to look, header files live in <code class="language-plaintext highlighter-rouge">/usr/include</code>, binaries in <code class="language-plaintext highlighter-rouge">/bin</code> or <code class="language-plaintext highlighter-rouge">/usr/bin</code>, and dynamic linkers in <code class="language-plaintext highlighter-rouge">/lib64</code>.</p>

<p>NixOS completely ignores this convention. It doesn’t use standard folders. Instead, it uses long cryptographic hashes to bury every application inside a location called <code class="language-plaintext highlighter-rouge">/nix/store</code>.</p>

<p>Most Linux software expects a standard environment. It assumes header files live in <code class="language-plaintext highlighter-rouge">/usr/include</code> and dynamic linkers sit in predictable paths like <code class="language-plaintext highlighter-rouge">/lib64/ld-linux-x86-64.so.2</code>. The moment you try to run an unpackaged binary, compile a native C extension, or execute a basic shell script on NixOS, that abstraction collapses.</p>

<p>Of course, you can fix it. But instead of standard Linux tools, you’re forced to learn bespoke Nix workarounds like <code class="language-plaintext highlighter-rouge">patchelf</code>, <code class="language-plaintext highlighter-rouge">buildFHSUserEnv</code>, or <code class="language-plaintext highlighter-rouge">nix-ld</code>. And here’s my question, do any of those troubleshooting skills transfer anywhere else?</p>

<p>If a beginner starts their Linux journey on NixOS today, they are not learning the universal laws of UNIX. They are learning a highly specific, bespoke abstraction layer. They are learning Nix, not Linux. The moment they log into an Ubuntu server at a new job or try to troubleshoot a standard Debian container, they will be paralyzed. They won’t know where files actually live, because Nix hid the real Linux architecture behind a wall of hashes.</p>

<hr />

<p>Got questions, corrections, or suggestions?</p>

<p>Open an issue on <a href="https://github.com/dumidusw">GitHub</a> or <a href="mailto:dumidu.github@gmail.com">drop me an email</a>.</p>

<div class="author-bio">
  <img class="author-bio-avatar" src="https://avatars.githubusercontent.com/u/197898757?v=4" alt="dumidusw" width="44" height="44" loading="lazy" />
  <div class="author-bio-text">
    <span class="author-bio-name">Dumidu</span>
    <span class="author-bio-links">
      <a href="https://github.com/dumidusw" target="_blank" rel="me noopener">GitHub Profile</a>
      <span class="dot-separator">&bull;</span>
      <a href="mailto:dumidu.github@gmail.com">Email</a>
    </span>
  </div>
</div>]]></content><author><name>Dumidu</name></author><category term="nixos" /><category term="arch-linux" /><summary type="html"><![CDATA[NixOS promises declarative, reproducible systems, but its abstraction over the filesystem hierarchy means you're learning Nix, not Linux.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://dumidusw.dev/assets/images/posts/this-is-why-i-donot-like-nix-os.webp" /><media:content medium="image" url="https://dumidusw.dev/assets/images/posts/this-is-why-i-donot-like-nix-os.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Why I Use mise to Manage Python, Node, and Rust</title><link href="https://dumidusw.dev/2026/07/22/why-i-use-mise-to-manage-python-node-and-rust/" rel="alternate" type="text/html" title="Why I Use mise to Manage Python, Node, and Rust" /><published>2026-07-22T23:50:00+00:00</published><updated>2026-07-22T23:50:00+00:00</updated><id>https://dumidusw.dev/2026/07/22/why-i-use-mise-to-manage-python-node-and-rust</id><content type="html" xml:base="https://dumidusw.dev/2026/07/22/why-i-use-mise-to-manage-python-node-and-rust/"><![CDATA[<p>When you install Python, Node, or Rust with pacman, you get whatever version Arch currently ships. That’s exactly what your operating system expects, but it isn’t always what your projects expect. One project might require Python 3.11 while another uses Python 3.14, and the official repositories generally don’t let you choose between multiple language versions. They’re designed to provide a single current version of each package.</p>

<!--more-->

<p>Managing those different language versions without interfering with the operating system is exactly the problem <code class="language-plaintext highlighter-rouge">mise</code> solves.</p>

<p>There are plenty of version managers available, including <code class="language-plaintext highlighter-rouge">pyenv</code>, <code class="language-plaintext highlighter-rouge">nvm</code>, <code class="language-plaintext highlighter-rouge">rustup</code>, <code class="language-plaintext highlighter-rouge">asdf</code>, and others. I chose <code class="language-plaintext highlighter-rouge">mise</code> because it gives me a single tool with a consistent interface for all of my development toolchains. Instead of learning and maintaining a different workflow for each language, I can manage them all in one place while still keeping them separate from the operating system.</p>

<p>Let’s look at how it works and the gotchas I hit while setting it up.</p>

<h2 id="1-the-problem">1. The problem</h2>

<p>Arch Linux is built around one core idea: everything moves together. Your kernel, drivers, desktop environment, and supporting libraries are all expected to stay in sync. That’s why a system update upgrades everything together.</p>

<p>You can update an individual package if you want, but doing that without updating the rest of the system can leave your software out of sync. This is known as a partial upgrade. It can lead to unexpected problems because different parts of your system are no longer compatible.</p>

<p>Programming language toolchains include interpreters, compilers, and related development tools. Unlike most system packages, they often need multiple versions installed at the same time.</p>

<p>Imagine you’re maintaining a project that requires Python 3.11 because one of its dependencies hasn’t been updated to support Python 3.14 yet. Arch’s official repositories don’t maintain multiple versions of Python. You get whichever version they’re currently shipping. So there’s no official way to install an older version just for that project.</p>

<p>And even if there were, updating a project’s Python shouldn’t mean performing a full system update that also upgrades unrelated system packages.</p>

<p>That’s the gap <code class="language-plaintext highlighter-rouge">mise</code> fills. It lets your projects use the language versions they need while leaving the operating system’s versions exactly where they belong.</p>

<h2 id="2-the-ownership-idea">2. The ownership idea</h2>

<p>The solution is to keep two separate layers, each managed by a different tool.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>                Operating System
           -------------------------
              Managed by pacman
           /usr/bin/python
           /usr/bin/node
           /usr/bin/rustc


                  Projects
           -------------------------
               Managed by mise
           Python 3.11
           Python 3.14
           Node 20
           Node 22
           Rust stable
           Rust nightly
</code></pre></div></div>

<p>The system copy of Python, Node, and Rust stays managed by pacman. It’s used by the operating system and anything that expects those tools to exist in their standard locations.</p>

<p>The project copy is managed by you. It’s switchable per project, versioned independently of the operating system, and managed by <code class="language-plaintext highlighter-rouge">mise</code>.</p>

<p>This is the same idea I try to apply throughout my Arch setup. I let each tool manage what it was designed to manage.</p>

<h2 id="3-what-mise-does">3. What mise does</h2>

<p>A common misconception is that <code class="language-plaintext highlighter-rouge">mise</code> replaces your system Python, Node, or Rust. It doesn’t.</p>

<p>Instead, it installs each toolchain into its own directory and adds itself to the front of the list your shell searches when you type a command. That list is called <code class="language-plaintext highlighter-rouge">PATH</code>.</p>

<p>So when you type:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python
</code></pre></div></div>

<p>your shell finds <code class="language-plaintext highlighter-rouge">mise</code>’s Python before it finds <code class="language-plaintext highlighter-rouge">/usr/bin/python</code>.</p>

<p>That’s really all there is to it.</p>

<p>When you type <code class="language-plaintext highlighter-rouge">python</code>, your shell searches each directory listed in <code class="language-plaintext highlighter-rouge">PATH</code> from left to right and runs the first match it finds. After <code class="language-plaintext highlighter-rouge">mise activate</code> runs, the <code class="language-plaintext highlighter-rouge">mise</code> version comes first. The system copy hasn’t moved and hasn’t changed. It’s simply no longer first in your interactive shell.</p>

<p>This distinction matters because many parts of Linux don’t use your interactive shell at all. Pacman hooks, AUR build scripts, systemd services, and scripts that begin with:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/python</span>
</code></pre></div></div>

<p>use an absolute path instead of searching <code class="language-plaintext highlighter-rouge">PATH</code>.</p>

<p>Those continue using the pacman-managed Python exactly as before.</p>

<h2 id="4-installing-mise">4. Installing mise</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 1. Install mise from the official repositories.</span>
<span class="nb">sudo </span>pacman <span class="nt">-S</span> mise

<span class="c"># 2. Install build dependencies some toolchains may require.</span>
<span class="nb">sudo </span>pacman <span class="nt">-S</span> base-devel openssl zlib readline sqlite

<span class="c"># 3. Activate mise in your shell.</span>
<span class="nb">echo</span> <span class="s1">'eval "$(mise activate zsh)"'</span> <span class="o">&gt;&gt;</span> ~/.zshrc
<span class="nb">source</span> ~/.zshrc

<span class="c"># If your shell uses a different location for .zshrc</span>
<span class="c"># (for example, because you use ZDOTDIR),</span>
<span class="c"># add the activation line there instead.</span>

<span class="c"># 4. Install the toolchains you use.</span>
mise use <span class="nt">-g</span> python@latest
mise use <span class="nt">-g</span> node@latest
mise use <span class="nt">-g</span> rust@latest
</code></pre></div></div>

<p>One small gotcha: if you have zsh’s <code class="language-plaintext highlighter-rouge">setopt correct</code> enabled, typing <code class="language-plaintext highlighter-rouge">mise</code> can trigger this prompt:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>zsh: correct 'mise' to 'nice' [nyae]?
</code></pre></div></div>

<p>If you answer that prompt without paying attention, the next prompt, often the real <code class="language-plaintext highlighter-rouge">sudo</code> password request, can become confusing. A command that looked like it ran may not have actually executed.</p>

<p>If you use <code class="language-plaintext highlighter-rouge">setopt correct</code>, pay close attention to which prompt you’re answering.</p>

<h2 id="5-migration-notes">5. Migration notes</h2>

<p>These notes are only relevant if you’re migrating from an existing setup. Feel free to skip this section if you’re starting from scratch.</p>

<h3 id="coming-from-nvm-pyenv-or-something-similar">Coming from nvm, pyenv, or something similar?</h3>

<p>Remove the old version manager before activating <code class="language-plaintext highlighter-rouge">mise</code> for that language.</p>

<p>Running two version managers at the same time rarely produces a clear error. Instead, whichever one modifies <code class="language-plaintext highlighter-rouge">PATH</code> last usually wins.</p>

<p>I had <code class="language-plaintext highlighter-rouge">zsh-nvm</code> installed through <code class="language-plaintext highlighter-rouge">zinit</code>. Before using <code class="language-plaintext highlighter-rouge">mise</code> for Node, I removed the plugin, its environment variables, and the deferred initialization block.</p>

<h3 id="rust-works-a-little-differently">Rust works a little differently</h3>

<p>After installing everything, I checked where each executable actually lived.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>which python node cargo rustc

/home/dumidu/.local/share/mise/installs/python/latest/bin/python
/home/dumidu/.local/share/mise/installs/node/latest/bin/node
/home/dumidu/.cargo/bin/cargo
/home/dumidu/.cargo/bin/rustc
</code></pre></div></div>

<p>Python and Node are installed directly by <code class="language-plaintext highlighter-rouge">mise</code>.</p>

<p>Rust is different.</p>

<p>Instead of downloading Rust itself, <code class="language-plaintext highlighter-rouge">mise</code> delegates that work to <code class="language-plaintext highlighter-rouge">rustup</code>. If <code class="language-plaintext highlighter-rouge">rustup</code> is already installed, <code class="language-plaintext highlighter-rouge">mise</code> simply reuses it.</p>

<p>You still get per-project Rust versions through <code class="language-plaintext highlighter-rouge">mise.toml</code>, but the actual toolchain lives under <code class="language-plaintext highlighter-rouge">~/.cargo/bin</code>.</p>

<h3 id="make-sure-youre-editing-the-right-zshrc">Make sure you’re editing the right .zshrc</h3>

<p>At one point, <code class="language-plaintext highlighter-rouge">mise activate</code> simply refused to work.</p>

<p>The problem wasn’t <code class="language-plaintext highlighter-rouge">mise</code> at all.</p>

<p>My shell was using:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">ZDOTDIR</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/.config/zsh"</span>
</code></pre></div></div>

<p>which meant zsh was reading:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/.config/zsh/.zshrc
</code></pre></div></div>

<p>instead of:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/.zshrc
</code></pre></div></div>

<p>I had been editing the wrong file.</p>

<p>If your changes don’t seem to take effect, verify which configuration file your shell is actually using.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="nv">$ZDOTDIR</span>
<span class="nb">readlink</span> <span class="nt">-f</span> ~/.zshrc
</code></pre></div></div>

<p>These two commands can save a lot of confusion.</p>

<h2 id="6-verify-it-worked">6. Verify it worked</h2>

<p><code class="language-plaintext highlighter-rouge">mise ls</code> shows what <code class="language-plaintext highlighter-rouge">mise</code> thinks it’s managing.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>mise <span class="nb">ls

</span>Tool    Version           Source                      Requested
node    26.5.0            ~/.config/mise/config.toml  latest
python  3.14.6            ~/.config/mise/config.toml  latest
rust    1.97.1 <span class="o">(</span>symlink<span class="o">)</span>  ~/.config/mise/config.toml  latest
</code></pre></div></div>

<p>A more convincing check is <code class="language-plaintext highlighter-rouge">which -a</code>.</p>

<p>Unlike <code class="language-plaintext highlighter-rouge">which</code>, it lists every matching executable in <code class="language-plaintext highlighter-rouge">PATH</code>.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>which <span class="nt">-a</span> python

/home/dumidu/.local/share/mise/installs/python/latest/bin/python
/usr/bin/python

<span class="nv">$ </span>which <span class="nt">-a</span> node

/home/dumidu/.local/share/mise/installs/node/latest/bin/node
/usr/bin/node
</code></pre></div></div>

<p>This confirms that both layers still exist.</p>

<p>The <code class="language-plaintext highlighter-rouge">mise</code> version appears first because it comes first in <code class="language-plaintext highlighter-rouge">PATH</code>.</p>

<p>The pacman-managed version is still there, exactly where the operating system expects it. That’s the copy used by pacman hooks, AUR builds, system services, and anything that references an absolute path.</p>

<p>The two layers aren’t competing. They have different responsibilities.</p>

<p>The system copy serves the operating system.</p>

<p>The <code class="language-plaintext highlighter-rouge">mise</code> copy serves your projects.</p>

<p>Once you’ve made that separation, operating system updates and development toolchain updates become completely independent. That’s the boundary I wanted, and it’s the reason I use <code class="language-plaintext highlighter-rouge">mise</code>.</p>

<hr />

<p>Got questions, corrections, or suggestions?</p>

<p>Open an issue on <a href="https://github.com/dumidusw">GitHub</a> or <a href="mailto:dumidu.github@gmail.com">drop me an email</a>.</p>

<div class="author-bio">
  <img class="author-bio-avatar" src="https://avatars.githubusercontent.com/u/197898757?v=4" alt="dumidusw" width="44" height="44" loading="lazy" />
  <div class="author-bio-text">
    <span class="author-bio-name">Dumidu</span>
    <span class="author-bio-links">
      <a href="https://github.com/dumidusw" target="_blank" rel="me noopener">GitHub Profile</a>
      <span class="dot-separator">&bull;</span>
      <a href="mailto:dumidu.github@gmail.com">Email</a>
    </span>
  </div>
</div>]]></content><author><name>Dumidu</name></author><category term="linux" /><category term="arch-linux" /><category term="arch-linux" /><category term="mise" /><category term="python" /><category term="node" /><category term="rust" /><category term="version-management" /><category term="developer-tools" /><summary type="html"><![CDATA[Learn why I use mise to manage Python, Node, and Rust on Arch Linux. Understand how it keeps project toolchains separate from the operating system while supporting multiple language versions.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://dumidusw.dev/assets/images/posts/mise-python-node-rust.png" /><media:content medium="image" url="https://dumidusw.dev/assets/images/posts/mise-python-node-rust.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">My Two Layer Safety Net for Arch Linux</title><link href="https://dumidusw.dev/2026/07/19/my-two-layer-safety-net-for-arch-linux/" rel="alternate" type="text/html" title="My Two Layer Safety Net for Arch Linux" /><published>2026-07-19T00:00:00+00:00</published><updated>2026-07-19T00:00:00+00:00</updated><id>https://dumidusw.dev/2026/07/19/my-two-layer-safety-net-for-arch-linux</id><content type="html" xml:base="https://dumidusw.dev/2026/07/19/my-two-layer-safety-net-for-arch-linux/"><![CDATA[<p>Arch Linux is a rolling release distribution, so it doesn’t have version numbers like Ubuntu 26.04, Linux Mint 22.3, or Fedora 44. Instead, new versions of packages are released continuously. Whenever you update your system, you receive the latest available software.</p>

<p>That’s one of Arch’s biggest strengths. New features, hardware support, and bug fixes arrive quickly. You don’t want to wait for the next major release, but there is a trade-off. 
<!--more-->
Since Arch stays much closer to upstream software, changes reach you sooner. Most updates work perfectly, but every now and then an update can introduce a regression or create an unexpected compatibility issue in your system. It may be a little screen glitch to a complete boot failure. New Arch users hear such stories and naturally become nervous about running updates.</p>

<p>Rather than worrying about whether an update might break something, I prefer to think about what I’ll do if it does. Having a clear recovery plan removes most of the uncertainty. Instead of guessing, I simply work through the same two recovery steps every time.</p>

<p>My safety net has two layers. I first try an LTS kernel to determine whether the problem is limited to the latest kernel. If that doesn’t help, I restore a Timeshift snapshot to return my system to a known-good state. Each layer serves a different purpose, and together they cover most of the problems I’m likely to encounter after an update.</p>

<h2 id="safety-net-one-a-second-older-kernel">Safety net one: a second, older kernel</h2>

<p>The “kernel” is the core part of Linux that talks to your hardware, your graphics, your keyboard, your wifi, everything. Arch updates the kernel often, and once in a while a brand new kernel version has a bug that breaks something on your specific computer.</p>

<p>The fix is simple: install a second kernel. Arch offers a package called <code class="language-plaintext highlighter-rouge">linux-lts</code> (LTS stands for “Long Term Support”). Unlike your regular kernel, this one barely changes, it gets small safety fixes but skips all the fast-moving updates. Because it changes so little, it’s very unlikely to have the same bug that just broke your regular kernel.</p>

<p>Once installed, it shows up as an extra option in your boot menu (GRUB), usually under something like “Advanced options for Arch Linux.”</p>

<p>So here’s what I do if something looks wrong after an update — screen won’t turn on, system freezes, whatever:</p>

<ol>
  <li>Restart the computer.</li>
  <li>In the boot menu, pick the LTS kernel instead of the normal one.</li>
  <li>See what happens.</li>
</ol>

<p>If the LTS kernel boots up fine, I’ve learned something important: the problem is most likely related to the latest kernel. I can keep using LTS for a few days while waiting for a fix, or investigate the issue further.</p>

<p>If the LTS kernel has the same problem, then I know it’s not the kernel’s fault at all, something else broke. Time for safety net number two.</p>

<p>This step is quick and safe. You’re not deleting anything or changing any settings. You’re just trying a different, more stable kernel for one boot. That’s why it’s always my first move.</p>

<p><strong>One small tip:</strong> when you install a second kernel, double check which one your computer boots into automatically.</p>

<blockquote class="callout-warning">
  <p><strong>Tip</strong></p>

  <p>After installing <code class="language-plaintext highlighter-rouge">linux-lts</code>, make sure your regular <code class="language-plaintext highlighter-rouge">linux</code> kernel is still your default boot entry. I prefer to keep the LTS kernel as an emergency fallback rather than my everyday kernel.</p>
</blockquote>

<h2 id="safety-net-two-recovering-with-timeshift-snapshots">Safety net two: Recovering with Timeshift snapshots</h2>

<p>The LTS kernel only helps if the <em>kernel</em> is the problem. But sometimes an update breaks something else — a setting, a program, a config file. In those cases, switching kernels won’t fix anything.</p>

<p>That’s where <a href="https://github.com/linuxmint/timeshift">Timeshift</a> comes in. It’s a free, open source system snapshot tool originally created by Tony George and now maintained by the Linux Mint team. It lets you create and restore snapshots of your system, making it easy to return to a known-good state if an update causes problems. I configure it to create regular snapshots, so I always have a recent restore point available. If something goes wrong, I can roll my system back to how it was before the problem started—packages, configuration files, and system settings included.</p>

<p>I keep Timeshift snapshots saved on a separate hard drive, just in case something happens to my main drive too.</p>

<p>So if I try the LTS kernel and the problem is <em>still</em> there, that tells me it’s not kernel-related — and that’s my cue to restore the last Timeshift snapshot instead of trying to fix things by hand.</p>

<h2 id="putting-the-two-together">Putting the two together</h2>

<p>Neither of these tools is new or special on its own — plenty of people use one or the other. What makes this combination useful is doing them <strong>in order</strong>:</p>

<ol>
  <li>Something breaks after an update.</li>
  <li><strong>Try the LTS kernel first.</strong> It’s fast and doesn’t change anything permanently.
    <ul>
      <li>Works fine? The regular kernel was the problem. Stick with LTS for now.</li>
      <li>Still broken? It’s not the kernel.</li>
    </ul>
  </li>
  <li><strong>Restore the latest Timeshift snapshot.</strong> This returns the system to the state it was in before the problematic update.</li>
</ol>

<p>Each step tells you something the last one didn’t, so you’re never just guessing. You try the easy, safe option first, and only reach for the bigger fix if you actually need it.</p>

<h2 id="what-this-wont-fix">What this won’t fix</h2>

<p>To be fair, this combo isn’t magic. If your <strong>boot menu itself</strong> breaks, let’s say GRUB gets misconfigured, neither of these will help, because you can’t even get to the point of picking a kernel or restoring a backup. In that rare case, you’d need to boot from a USB drive and fix things manually. It’s worth knowing that step exists too, even if you hopefully never need it.</p>

<p>I don’t expect to use these recovery tools very often. In fact, most Arch updates complete without any issues at all. The point isn’t that Arch is unreliable, it’s that having a recovery plan removes the uncertainty when something unexpected does happen.</p>

<p>Keeping an LTS kernel installed gives me a quick, non-destructive way to check whether the latest kernel is responsible. If it isn’t, Timeshift lets me return my system to a known-good state in just a few minutes.</p>

<p>For me, that simple two-step process has made updating Arch much less stressful.</p>

<hr />

<p>Got questions, corrections, or suggestions?</p>

<p>Open an issue on <a href="https://github.com/dumidusw">GitHub</a> or <a href="mailto:dumidu.github@gmail.com">drop me an email</a>.</p>

<div class="author-bio">
  <img class="author-bio-avatar" src="https://avatars.githubusercontent.com/u/197898757?v=4" alt="dumidusw" width="44" height="44" loading="lazy" />
  <div class="author-bio-text">
    <span class="author-bio-name">Dumidu</span>
    <span class="author-bio-links">
      <a href="https://github.com/dumidusw" target="_blank" rel="me noopener">GitHub Profile</a>
      <span class="dot-separator">&bull;</span>
      <a href="mailto:dumidu.github@gmail.com">Email</a>
    </span>
  </div>
</div>]]></content><author><name>Dumidu</name></author><category term="linux" /><category term="arch-linux" /><category term="arch-linux" /><category term="grub" /><category term="kernel" /><category term="timeshift" /><category term="backups" /><summary type="html"><![CDATA[A simple two-layer recovery strategy using the Linux LTS kernel and Timeshift to recover from most Arch Linux update problems with confidence.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://dumidusw.dev/assets/images/posts/two-layer-safety-net-arch-linux.png" /><media:content medium="image" url="https://dumidusw.dev/assets/images/posts/two-layer-safety-net-arch-linux.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Why pacman -Sy Is Dangerous on Arch Linux</title><link href="https://dumidusw.dev/2026/07/17/why-pacman-sy-is-dangerous-on-arch-linux/" rel="alternate" type="text/html" title="Why pacman -Sy Is Dangerous on Arch Linux" /><published>2026-07-17T03:30:00+00:00</published><updated>2026-07-17T03:30:00+00:00</updated><id>https://dumidusw.dev/2026/07/17/why-pacman-sy-is-dangerous-on-arch-linux</id><content type="html" xml:base="https://dumidusw.dev/2026/07/17/why-pacman-sy-is-dangerous-on-arch-linux/"><![CDATA[<!--
Introduction
Write one or two paragraphs introducing the problem this article
solves.
This text becomes the homepage excerpt, so it should stand on its own
and encourage readers to continue.
Imagine someone only reads these two paragraphs.
Would they understand what this article is about?
-->

<p>If you’ve spent any time on the Arch Wiki or community forums, you’ve probably come across this warning: 
Never run <code class="language-plaintext highlighter-rouge">pacman -Sy package_name</code>. Never run <code class="language-plaintext highlighter-rouge">-Sy</code> on its own and walk away. 
This is known as a partial upgrade. Some people follow this rule almost like a superstition. They avoid it because they’ve been told not to, not because they understand what’s happening underneath.
<!--more--></p>

<p>That’s the part worth fixing. The rule is easy to remember. Understanding the mechanism behind it is what makes it stick. Once you see it, you’ll understand exactly why <code class="language-plaintext highlighter-rouge">pacman -Syu</code> is the safe method to do your update.</p>

<h2 id="why-arch-updates-work-differently">Why Arch updates work differently</h2>

<p>There are two main types of Linux distributions. They are point-release (or fixed-release) distributions and rolling-release distributions. Arch Linux follows the rolling-release model.</p>

<p>Now, let me show you the practical difference with an example.</p>

<p>Suppose I’m using Linux Mint or Debian and my web browser needs an urgent update. I can update the browser without upgrading every other package on my system. The rest of the system can remain at its current versions, and that’s a normal part of how a fixed-release distribution is maintained.</p>

<p>Now suppose the same thing happens on Arch Linux. I need the latest version of my browser, but I haven’t updated the rest of my system for a while. It might seem reasonable to upgrade only the browser and leave everything else alone.</p>

<p>Technically, I can try to do that. But on Arch, packages in the repositories are continuously moving forward together. The latest browser package may have been built against newer versions of libraries and other packages than the ones currently installed on my system.</p>

<p>If I refresh the package databases and install only the new browser, I mix packages from the current repository state with packages from an older system state. This is what Arch calls a partial upgrade, and partial upgrades are unsupported.</p>

<p>So on Arch, if I need to upgrade a package from the official repositories, the safe approach is to update the system as a whole rather than selectively upgrading only that package.</p>

<p>This difference is important because Arch’s repositories are constantly changing. 
Think of this as a remote package environment that is continuously moving forward.</p>

<p><code class="language-plaintext highlighter-rouge">pacman</code> command you type on your computer, is a program installed in your computer. 
So how does <code class="language-plaintext highlighter-rouge">pacman</code> know which packages and which versions of those packages are currently available in the remote repositories?</p>

<h2 id="how-pacman-knows-whats-available">How pacman knows what’s available</h2>

<p>Pacman maintains two distinct types of package databases on your computer. Together, they allow pacman to know both <strong>what is installed on your system</strong> and <strong>what is available from the repositories</strong>.</p>

<h3 id="1-the-sync-databases--what-is-available">1. The sync databases — “What is available?”</h3>

<p>The sync databases contain information about packages available from the configured Arch repositories, such as <code class="language-plaintext highlighter-rouge">core</code> and <code class="language-plaintext highlighter-rouge">extra</code>.</p>

<p>They are stored under:</p>

<pre><code class="language-note">/var/lib/pacman/sync/
</code></pre>

<p>These are local copies of repository metadata. They contain information pacman needs about available packages, including their versions and dependencies.</p>

<p>When you run:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Sy</span>
</code></pre></div></div>

<p>pacman refreshes these local sync databases using the current repository databases from your configured mirrors.</p>

<p>An important point is that refreshing the sync databases does <strong>not</strong> upgrade any installed packages. Pacman now has current information about what is available remotely, while your installed system remains unchanged.</p>

<h3 id="2-the-local-database--what-is-installed">2. The local database — “What is installed?”</h3>

<p>The local database records information about packages currently installed on your computer.</p>

<p>It is stored under:</p>

<pre><code class="language-note">/var/lib/pacman/local/
</code></pre>

<p>When pacman installs, upgrades, or removes a package, it updates this database accordingly. It records information such as the installed package version, dependencies, and the files belonging to that package.</p>

<p>Because this information is stored locally, pacman can answer questions about your installed packages without contacting the Arch repositories.</p>

<p>For example:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacman <span class="nt">-Q</span>
</code></pre></div></div>

<p>can list your installed packages entirely from local information.</p>

<p>A simple way to remember the distinction is:</p>

<pre><code class="language-note">Sync databases  → What packages are available?
Local database  → What packages are installed?
</code></pre>

<p>Pacman uses these two views together when managing your system. Understanding the difference between them is the key to understanding what happens when you run <code class="language-plaintext highlighter-rouge">pacman -Sy</code> and why <code class="language-plaintext highlighter-rouge">pacman -Syu</code> behaves differently.</p>

<h2 id="how-a-partial-upgrade-happens">How a partial upgrade happens</h2>

<p>Let’s see what happens when we run:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Sy</span> package_name
</code></pre></div></div>

<h3 id="step-1-pacman-refreshes-the-sync-databases">Step 1: Pacman refreshes the sync databases</h3>

<p>The <code class="language-plaintext highlighter-rouge">-y</code> option refreshes the sync databases under:</p>

<pre><code class="language-note">/var/lib/pacman/sync/
</code></pre>

<p>Pacman now has current information about the packages available in the configured repositories.</p>

<p>But nothing installed on your system has been upgraded yet.</p>

<p>At this point, pacman’s view of the repositories is current, while your installed system may still contain package versions from the last time you performed a full system upgrade.</p>

<h3 id="step-2-pacman-looks-up-the-requested-package">Step 2: Pacman looks up the requested package</h3>

<p>Pacman uses the newly refreshed sync databases to find <code class="language-plaintext highlighter-rouge">package_name</code> and determine its dependencies.</p>

<p>The requested package therefore comes from the <strong>current repository state</strong>, not necessarily from the repository state that existed when you last upgraded your system.</p>

<h3 id="step-3-pacman-resolves-the-transaction">Step 3: Pacman resolves the transaction</h3>

<p>Pacman checks the requested package’s declared dependencies against the packages installed on your system and the packages currently available in the repositories.</p>

<p>If dependencies need to be installed or upgraded to satisfy the transaction, pacman can include them.</p>

<p>But this is the important part:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Sy</span> package_name
</code></pre></div></div>

<p>does <strong>not</strong> tell pacman to perform a full system upgrade.</p>

<p>Pacman resolves the transaction needed for the package you requested, but unrelated installed packages are not automatically brought forward simply because newer versions exist.</p>

<p>You can therefore end up mixing packages from the current repository state with packages from an older system state.</p>

<p>That is a <strong>partial upgrade</strong>.</p>

<h2 id="why-this-can-cause-problems">Why this can cause problems</h2>

<p>A useful mental model is to think of the Arch repositories as a package environment that is continuously moving forward.</p>

<p>Packages in that environment are not isolated. They may depend on other packages or be built against shared libraries that are also evolving.</p>

<p>Imagine your system was last fully upgraded some time ago:</p>

<pre><code class="language-note">Your installed system          Current Arch repositories

Application A   older         Application A   newer
Library X       older         Library X       newer
Library Y       older         Library Y       newer
Other packages  older         Other packages  newer
</code></pre>

<p>You then refresh the sync databases and install one package from the current repositories:</p>

<pre><code class="language-note">Your installed system

Application A   older
Library X       older
Library Y       older
New package     current   ← brought in from current repositories
Other packages  older
</code></pre>

<p>Software often relies on other packages and shared libraries in the same environment. If you update only part of the system, you can end up mixing newer packages with older ones that were not meant to work together.</p>

<p>This is how a partial upgrade can leave your system in an inconsistent state.</p>

<h2 id="the-correct-arch-approach">The correct Arch approach</h2>

<p>Instead of refreshing the package databases and selectively installing a package:
we can perform a full system upgrade while installing the package:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Syu</span> package_name
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">u</code> makes the crucial difference.</p>

<ul>
  <li>Pacman refreshes the sync databases</li>
  <li>Upgrades installed packages for which newer versions are available</li>
  <li>Resolves the requested package and its dependencies</li>
  <li>and performs the transaction together.</li>
</ul>

<p>Instead of pulling one piece from the current repository environment into an older system, you bring your installed system forward as a whole.</p>

<h2 id="what-about-pacman--s-package_name">What about <code class="language-plaintext highlighter-rouge">pacman -S package_name</code>?</h2>

<p>There is one more command worth understanding:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-S</span> package_name
</code></pre></div></div>

<p>Unlike <code class="language-plaintext highlighter-rouge">pacman -Syu package_name</code>, this command does <strong>not</strong> refresh the sync databases. Pacman uses the repository information it already has locally to find and install the package.</p>

<p>This can be useful when installing several packages within a short period of time.</p>

<p>For example, suppose I have just performed a full system upgrade:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Syu</span>
</code></pre></div></div>

<p>Later that day, I decide to install another package:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-S</span> package_name
</code></pre></div></div>

<p>There is no need to download the repository databases again just for that installation. Pacman can use the sync databases it already has.</p>

<p>But what if I haven’t refreshed those databases for two weeks?</p>

<p>In that case, <code class="language-plaintext highlighter-rouge">pacman -S package_name</code> still uses the old repository information stored on my computer. The package version recorded there may no longer be available on the current mirror, because Arch’s repositories have continued moving forward.</p>

<p>The installation may therefore fail when pacman tries to download a package version that has already been replaced.</p>

<p>So my rule is simple: if my sync databases are old, I don’t solve the problem by running:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Sy</span> package_name
</code></pre></div></div>

<p>Although this quickly refreshes my view of the repositories, it then selectively installs the requested package without upgrading the rest of the system. This can create that problematic partial upgrade.</p>

<p>Instead, I bring my system and sync databases forward together:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Syu</span> package_name
</code></pre></div></div>

<p>So <code class="language-plaintext highlighter-rouge">pacman -S package_name</code> is useful when I already have reasonably current sync databases and don’t need to refresh them again. If those databases have become old, I perform a full system upgrade rather than refreshing them only for a selective package installation.</p>

<h2 id="then-why-doesnt-arch-block-pacman--sy">Then why doesn’t Arch block <code class="language-plaintext highlighter-rouge">pacman -Sy</code>?</h2>

<p>Okay, it’s clear <code class="language-plaintext highlighter-rouge">pacman -Sy package_name</code> can lead to a partial upgrade, then you might wonder, why doesn’t Arch simply prevent you from running it?</p>

<p>Because <code class="language-plaintext highlighter-rouge">pacman -Sy</code> itself is not an invalid operation. It refreshes the sync databases, and there are legitimate situations where an administrator may need to do that without immediately upgrading the system.</p>

<p>Arch generally gives you control over your system rather than trying to prevent every potentially unsafe operation. It assumes that you, as a system administrator, understand the consequences of the commands you run.</p>

<p>Pacman gives you the tools. It does not make every system management decision for you.</p>

<p>So, understand <strong>why</strong> <code class="language-plaintext highlighter-rouge">pacman -Sy package_name</code> is dangerous. Don’t memorize it as a command that you shouldn’t run.</p>

<hr />

<p>Got questions, corrections, or suggestions?</p>

<p>Open an issue on <a href="https://github.com/dumidusw">GitHub</a> or <a href="mailto:dumidu.github@gmail.com">drop me an email</a>.</p>

<div class="author-bio">
  <img class="author-bio-avatar" src="https://avatars.githubusercontent.com/u/197898757?v=4" alt="dumidusw" width="44" height="44" loading="lazy" />
  <div class="author-bio-text">
    <span class="author-bio-name">Dumidu</span>
    <span class="author-bio-links">
      <a href="https://github.com/dumidusw" target="_blank" rel="me noopener">GitHub Profile</a>
      <span class="dot-separator">&bull;</span>
      <a href="mailto:dumidu.github@gmail.com">Email</a>
    </span>
  </div>
</div>]]></content><author><name>Dumidu</name></author><category term="linux" /><category term="arch-linux" /><summary type="html"><![CDATA[pacman -Sy looks harmless because it only refreshes a package list, but running it alone can leave your system in a broken, version-inconsistent state. Here's the mechanism behind partial upgrades on Arch, and why -Syu is the only safe way to update.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://dumidusw.dev/assets/images/posts/why-pacman-sy-is-dangerous-on-arch-linux.png" /><media:content medium="image" url="https://dumidusw.dev/assets/images/posts/why-pacman-sy-is-dangerous-on-arch-linux.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Timeshift: Snapshots Are Not Backups</title><link href="https://dumidusw.dev/2026/07/16/timeshift-snapshots-are-not-backups/" rel="alternate" type="text/html" title="Timeshift: Snapshots Are Not Backups" /><published>2026-07-16T04:30:00+00:00</published><updated>2026-07-16T04:30:00+00:00</updated><id>https://dumidusw.dev/2026/07/16/timeshift-snapshots-are-not-backups</id><content type="html" xml:base="https://dumidusw.dev/2026/07/16/timeshift-snapshots-are-not-backups/"><![CDATA[<p>One of the first tools many Arch Linux users install is Timeshift.
After creating their first snapshot, it’s easy to feel like the
system is fully protected. I thought the same thing when I first
started using it.</p>

<p>The reality is a little different. Timeshift is an excellent
recovery tool, but it isn’t a backup solution. Understanding that
difference can save you from unpleasant surprises.</p>

<!--more-->

<h2 id="what-timeshift-actually-does">What Timeshift actually does</h2>

<p>Before looking at commands, it helps to understand what a snapshot
actually is. A snapshot is a saved copy of your system’s state at a
specific point in time — not a copy of your files sitting somewhere
safe, but a checkpoint you can roll the whole system back to.</p>

<p><img src="/assets/images/snapshots.png" alt="Diagram showing how a Timeshift snapshot restores a previous system state" width="400" /></p>

<p><em>A snapshot lets you return your system to an earlier state.</em></p>

<p>That’s the entire mental model. Timeshift doesn’t watch your files
or protect anything going forward — it just gives you a point you
can rewind to.</p>

<h2 id="what-timeshift-protects">What Timeshift protects</h2>

<p>A snapshot captures the state of your system, which typically
includes:</p>

<ul>
  <li>System files</li>
  <li>Installed packages</li>
  <li>Configuration files</li>
  <li>Bootloader (depending on setup)</li>
</ul>

<p>This makes Timeshift excellent for recovering from a bad update, a
broken package, or a configuration change that left your system in a
worse state than before. That’s exactly the scenario it was designed
for.</p>

<h2 id="what-it-doesnt-protect">What it doesn’t protect</h2>

<p>This is the part that matters most.</p>

<p>Suppose your SSD dies tomorrow. Where are your photos? Where are
your documents? Where is your Git repository?</p>

<p>They’re gone.</p>

<p>A snapshot stored on the same disk disappears with the disk. Timeshift
protects you from <em>software</em> problems — bad updates, broken configs,
a misbehaving package. It does nothing for <em>hardware</em> failure, theft,
or a drive that simply gives out one day, because the snapshot never
left the drive that failed.</p>

<h2 id="snapshots-vs-backups">Snapshots vs backups</h2>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>Snapshots</th>
      <th>Backups</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Recovers from</strong></td>
      <td>Bad updates</td>
      <td>Disk failure</td>
    </tr>
    <tr>
      <td><strong>Storage location</strong></td>
      <td>Usually same disk</td>
      <td>Usually another disk</td>
    </tr>
    <tr>
      <td><strong>Restore speed</strong></td>
      <td>Fast</td>
      <td>Slower</td>
    </tr>
    <tr>
      <td><strong>What it protects</strong></td>
      <td>System state</td>
      <td>Your data</td>
    </tr>
    <tr>
      <td><strong>Survives disk failure?</strong></td>
      <td>❌ No</td>
      <td>✅ Yes</td>
    </tr>
  </tbody>
</table>

<p>They solve different problems, which is why the right setup uses
both — not one instead of the other.</p>

<hr />

<p>If you’re running Timeshift today, it’s worth checking one thing:
where are your snapshots actually stored? If the answer is “the same
drive as everything else,” that’s the gap I was trying to close in this article.</p>

<hr />

<p>Got questions, corrections, or suggestions?</p>

<p>Open an issue on <a href="https://github.com/dumidusw">GitHub</a> or <a href="mailto:dumidu.github@gmail.com">drop me an email</a>.</p>

<div class="author-bio">
  <img class="author-bio-avatar" src="https://avatars.githubusercontent.com/u/197898757?v=4" alt="dumidusw" width="44" height="44" loading="lazy" />
  <div class="author-bio-text">
    <span class="author-bio-name">Dumidu</span>
    <span class="author-bio-links">
      <a href="https://github.com/dumidusw" target="_blank" rel="me noopener">GitHub Profile</a>
      <span class="dot-separator">&bull;</span>
      <a href="mailto:dumidu.github@gmail.com">Email</a>
    </span>
  </div>
</div>]]></content><author><name>Dumidu</name></author><category term="linux" /><category term="arch-linux" /><summary type="html"><![CDATA[Timeshift protects your system state, not your personal files. Here's the real difference between snapshots and backups.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://dumidusw.dev/assets/images/posts/timeshift-snapshots-are-not-backups.png" /><media:content medium="image" url="https://dumidusw.dev/assets/images/posts/timeshift-snapshots-are-not-backups.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Understanding Arch News (and Automating It with Informant)</title><link href="https://dumidusw.dev/2026/07/16/understanding-arch-news-and-automating-it-with-informant/" rel="alternate" type="text/html" title="Understanding Arch News (and Automating It with Informant)" /><published>2026-07-16T03:30:00+00:00</published><updated>2026-07-16T03:30:00+00:00</updated><id>https://dumidusw.dev/2026/07/16/understanding-arch-news-and-automating-it-with-informant</id><content type="html" xml:base="https://dumidusw.dev/2026/07/16/understanding-arch-news-and-automating-it-with-informant/"><![CDATA[<p>Arch’s rolling-release model means breaking changes are announced on
the news page, not hidden behind a version number. There’s no
“upgrading from 22.04 to 24.04” moment that forces you to read release
notes. Packages just update, continuously, and pacman has no idea
whether any given update needs your attention first. 
I’ve seen people say, “An update broke my system, so I’m leaving Arch.”
Sometimes the update itself isn’t the real problem. 
It was a manual intervention announced in the Arch News that went unnoticed.</p>

<!--more-->

<h2 id="why-this-is-easy-to-skip">Why this is easy to skip</h2>

<p><code class="language-plaintext highlighter-rouge">pacman -Syu</code> doesn’t check the news for you. 
It has no concept of “this update requires manual intervention”. 
That information only exists on the Arch News page. pacman doesn’t know about it, 
so nothing stops you from updating without reading it first.
Most of the time that’s fine. Occasionally it isn’t. A filesystem
migration, a bootloader change, a package split that needs a manual
step before or after upgrading. The news page is the only place these
get announced, and reading it before every update is a discipline,
not a safeguard pacman enforces for you.</p>

<p>It’s easy to forget. You’re in a hurry, or you’ve updated your system 
dozens of times without any issues. Eventually you skip checking the 
news and that might be the one time it mattered.</p>

<h2 id="what-informant-does">What Informant does</h2>

<p>Informant closes that gap by turning “read the news” from something 
you have to remember into something pacman enforces automatically.</p>

<p>It’s a pacman hook, specifically a <code class="language-plaintext highlighter-rouge">PreTransaction</code> hook. 
That means it runs before an upgrade or installation begins, not after.</p>

<p>Install it from the AUR:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yay <span class="nt">-S</span> informant
</code></pre></div></div>

<p>Once installed, its hook checks for unread Arch Linux news items
every time you run an upgrade or install. The transaction is aborted 
before a single package changes that you can’t
accidentally proceed without reading the news first. 
Informant only checks installs and upgrades. Package removals aren’t blocked 
because Arch News announcements are generally about changes you’ll encounter 
when installing or upgrading packages.</p>

<p>Informant gives you three subcommands:</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">informant check</code></strong> — checks for unread items. This is what the
hook actually calls; its exit code equals the number of unread
items, which is how the hook knows whether to abort the transaction.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">informant list</code></strong> — lists news item titles (add <code class="language-plaintext highlighter-rouge">--unread</code> to
filter to only what you haven’t read yet).</li>
  <li><strong><code class="language-plaintext highlighter-rouge">informant read</code></strong> — prints an item and marks it read. Run it with
no argument and it loops through everything unread, one at a time.</li>
</ul>

<h2 id="the-actual-workflow">The actual workflow</h2>

<p>Once Informant is installed, your normal update process doesn’t change.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Syu</span>
</code></pre></div></div>

<p>If there are unread Arch News items, Informant stops the transaction
before any packages are upgraded.</p>

<p>Read the news with:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>informant <span class="nb">read</span>
</code></pre></div></div>

<p>When you’ve finished reading, simply run the update again:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Syu</span>
</code></pre></div></div>

<p>If there’s no unread news, the update proceeds as usual.</p>

<blockquote class="callout-note">
  <p><strong>NOTE</strong></p>

  <p>When you install Informant for the first time, it treats every
existing Arch News item as unread because it doesn’t know what you’ve
already read.</p>

  <p>Run:</p>

  <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>informant <span class="nb">read</span>
</code></pre></div>  </div>

  <p>once after installing it. After that, Informant will only stop you
when new Arch News is published.</p>
</blockquote>

<!--more-->

<h2 id="where-arch-sysreport-fits-in">Where arch-sysreport fits in</h2>

<p>Reading a news item doesn’t always tell you whether it actually
applies to <em>your</em> system. Some announcements are conditional. For example, 
“if you’re using this bootloader,” “if this package is installed,” 
“if you’re on this filesystem.” Answering that usually means running two
or three separate commands to check.</p>

<p>That’s exactly why I created <a href="https://github.com/dumidusw/arch-sysreport"><code class="language-plaintext highlighter-rouge">arch-sysreport</code></a>. 
It collects the system details you typically need when deciding whether a news item applies to your system.
Instead of running several separate commands, you get everything in one place.</p>

<p>Informant makes sure you never miss the news. <a href="https://github.com/dumidusw/arch-sysreport"><code class="language-plaintext highlighter-rouge">arch-sysreport</code></a> makes it
faster to figure out what to do about it.</p>

<hr />

<p>Got questions, corrections, or suggestions?</p>

<p>Open an issue on <a href="https://github.com/dumidusw">GitHub</a> or <a href="mailto:dumidu.github@gmail.com">drop me an email</a>.</p>

<div class="author-bio">
  <img class="author-bio-avatar" src="https://avatars.githubusercontent.com/u/197898757?v=4" alt="dumidusw" width="44" height="44" loading="lazy" />
  <div class="author-bio-text">
    <span class="author-bio-name">Dumidu</span>
    <span class="author-bio-links">
      <a href="https://github.com/dumidusw" target="_blank" rel="me noopener">GitHub Profile</a>
      <span class="dot-separator">&bull;</span>
      <a href="mailto:dumidu.github@gmail.com">Email</a>
    </span>
  </div>
</div>]]></content><author><name>Dumidu</name></author><category term="linux" /><category term="arch-linux" /><summary type="html"><![CDATA[Arch Linux announces breaking changes through its news page, not version numbers. Here's why that matters, and how Informant automates checking it.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://dumidusw.dev/assets/images/posts/understanding-arch-news-informant.png" /><media:content medium="image" url="https://dumidusw.dev/assets/images/posts/understanding-arch-news-informant.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">A Safer Arch Linux Update Workflow</title><link href="https://dumidusw.dev/2026/07/08/a-safer-arch-linux-update-workflow/" rel="alternate" type="text/html" title="A Safer Arch Linux Update Workflow" /><published>2026-07-08T04:30:00+00:00</published><updated>2026-07-08T04:30:00+00:00</updated><id>https://dumidusw.dev/2026/07/08/a-safer-arch-linux-update-workflow</id><content type="html" xml:base="https://dumidusw.dev/2026/07/08/a-safer-arch-linux-update-workflow/"><![CDATA[<p>Over the past few years, I’ve noticed that Arch Linux has become one of the most talked-about Linux distributions.</p>

<p>Many Linux enthusiasts recommend it for its simplicity, rolling-release model, and excellent documentation.</p>

<p>Along with that recommendation usually comes a warning:</p>

<blockquote class="callout-warning">
  <p><strong>WARNING</strong></p>

  <p>Before updating your system, make sure you have a recent Timeshift snapshot or another reliable backup.</p>
</blockquote>

<p>When I first started using Arch, that warning made updates feel much riskier than they actually are.</p>

<p>After using Arch for a while, I realized something interesting.</p>

<!--more-->

<p>Most system updates complete without any problems.</p>

<p>Every so often, however, an upgrade requires a manual step before or after installation. These situations are usually announced through the Arch News.</p>

<p>The difficult part isn’t reading the announcement.</p>

<p>The difficult part is determining whether it actually applies to <em>your</em> system.</p>

<p>That realization led me to rethink how I update my system.</p>

<p>The workflow below is the one I now follow whenever I update Arch Linux. It gives me a recovery plan if something goes wrong and a structured way to handle updates that require manual intervention.</p>

<h2 id="the-goal">The Goal</h2>

<p>I wanted a workflow that provides:</p>

<ul>
  <li>a recovery plan if something goes wrong</li>
  <li>a structured way to review Arch News</li>
  <li>a repeatable process instead of relying on memory</li>
</ul>

<h2 id="my-workflow">My workflow</h2>
<p><img src="/assets/images/safearchupdateworkflow.png" alt="arch linux update" width="800" /></p>

<h3 id="1-create-a-timeshift-snapshot">1. Create a Timeshift snapshot</h3>

<p>Before touching the system, I ensure I have a recent Timeshift snapshot.</p>

<p>That snapshot becomes my recovery point.</p>

<p>If something unexpected happens during the update, I can always restore my filesystem.</p>

<h3 id="2-attempt-the-update">2. Attempt the update</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Syu</span>
</code></pre></div></div>

<p>If everything updates successfully, great.</p>

<p>Most of the time, that’s exactly what happens.</p>

<h3 id="3-if-the-update-is-blocked">3. If the update is blocked</h3>

<p>Rather than blindly following instructions from random forum posts, I collect two pieces of information:</p>

<p>unread Arch News
a structured report describing my system</p>

<p>Those two documents contain almost everything needed to determine whether the announcement applies to my machine.</p>

<h3 id="4-review-the-information">4. Review the information</h3>

<p>Sometimes I review the information myself.</p>

<p>Sometimes I ask another experienced Arch user.</p>

<p>Sometimes I ask an AI assistant to explain:</p>

<p>whether the announcement applies
which commands should be run
whether they happen before or after the update
why those steps are necessary</p>

<p>The important part is that the original Arch News remains the source of truth.</p>

<h3 id="5-perform-the-required-manual-steps">5. Perform the required manual steps</h3>

<p>If manual intervention is required, I perform those steps.</p>

<p>Examples include:</p>

<ul>
  <li>package replacements</li>
  <li>ownership fixes</li>
  <li>configuration migrations</li>
  <li>service changes</li>
</ul>

<h3 id="6-mark-the-news-as-read">6. Mark the news as read</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>informant <span class="nb">read</span> <span class="nt">--all</span>
</code></pre></div></div>

<h3 id="7-update-again">7. Update again</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pacman <span class="nt">-Syu</span>
</code></pre></div></div>
<p>At this point the update usually completes normally.</p>

<h3 id="why-timeshift-isnt-enough">Why Timeshift isn’t enough</h3>

<p>One realization I had while developing this workflow is that Timeshift and system reports solve different problems.</p>

<p>Timeshift answers:</p>

<p>Can I recover?</p>

<p>A system report answers:</p>

<p>What changed?</p>

<p>Those are complementary.</p>

<p>One protects the filesystem.</p>

<p>The other helps explain the system.</p>

<p>I now use both.</p>

<h3 id="why-i-built-arch_sysreport">Why I built arch_sysreport</h3>

<p>While following this workflow I noticed I was collecting the same information every time:</p>

<ul>
  <li>kernel</li>
  <li>bootloader</li>
  <li>filesystem</li>
  <li>graphics driver</li>
  <li>installed packages</li>
  <li>enabled services</li>
</ul>

<p>Eventually I automated that process.</p>

<p>The result was <a href="https://github.com/dumidusw/arch-sysreport"><code class="language-plaintext highlighter-rouge">arch-sysreport</code></a>, a small utility that collects the system information I often need when reviewing Arch News or asking for help.</p>

<p>It doesn’t analyze anything or make decisions for you.</p>

<p>It simply gathers the information that’s usually needed to understand whether an announcement applies to your system.</p>

<hr />

<p>Got questions, corrections, or suggestions?</p>

<p>Open an issue on <a href="https://github.com/dumidusw">GitHub</a> or <a href="mailto:dumidu.github@gmail.com">drop me an email</a>.</p>

<div class="author-bio">
  <img class="author-bio-avatar" src="https://avatars.githubusercontent.com/u/197898757?v=4" alt="dumidusw" width="44" height="44" loading="lazy" />
  <div class="author-bio-text">
    <span class="author-bio-name">Dumidu</span>
    <span class="author-bio-links">
      <a href="https://github.com/dumidusw" target="_blank" rel="me noopener">GitHub Profile</a>
      <span class="dot-separator">&bull;</span>
      <a href="mailto:dumidu.github@gmail.com">Email</a>
    </span>
  </div>
</div>]]></content><author><name>Dumidu</name></author><category term="linux" /><category term="arch-linux" /><summary type="html"><![CDATA[A step-by-step guide to updating Arch Linux safely, with tips on snapshots and handling potential issues.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://dumidusw.dev/assets/images/default-card.jpg" /><media:content medium="image" url="https://dumidusw.dev/assets/images/default-card.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Welcome!</title><link href="https://dumidusw.dev/2026/07/06/welcome/" rel="alternate" type="text/html" title="Welcome!" /><published>2026-07-06T17:00:00+00:00</published><updated>2026-07-06T17:00:00+00:00</updated><id>https://dumidusw.dev/2026/07/06/welcome</id><content type="html" xml:base="https://dumidusw.dev/2026/07/06/welcome/"><![CDATA[<p>If you’re reading this, thanks for stopping by.</p>

<p>I’m a software developer who enjoys understanding how things work beneath the surface. This website is where I’ll document that journey.</p>

<p>Rather than focusing only on <em>how</em> to do something, I like exploring <em>why</em> it works that way, what happens behind the scenes, and how different pieces fit together.</p>

<!--more-->

<h2 id="what-to-expect">What to Expect</h2>

<p>Here you’ll find articles about:</p>

<ul>
  <li><strong>Linux and the Unix philosophy</strong></li>
  <li><strong>Neovim</strong></li>
  <li><strong>Arch Linux and system administration</strong></li>
  <li><strong>Bash scripting and shell utilities</strong></li>
  <li><strong>Open-source projects I build</strong></li>
  <li><strong>Lessons learned while solving real-world problems</strong></li>
</ul>

<h2 id="how-i-write">How I Write</h2>

<p>My posts will take a few different forms:</p>

<ul>
  <li><strong>Tutorials</strong> — Step-by-step guides with practical examples</li>
  <li><strong>Design discussions</strong> — The reasoning behind design decisions</li>
  <li><strong>Documentation</strong> — Notes and ideas I’ve found useful enough to share</li>
</ul>

<p>I believe the best way to learn is to build things, ask questions, and explain what you’ve learned to others.</p>

<p>If any of these topics interest you, I hope you’ll find something useful here.</p>

<h2 id="whats-coming-first">What’s Coming First</h2>

<p>My first few articles will cover topics I’ve been working on recently:</p>

<ul>
  <li><strong>A safer Arch Linux update workflow</strong></li>
  <li><strong>Understanding Arch News and Informant</strong></li>
  <li><strong>Why I built <code class="language-plaintext highlighter-rouge">arch_sysreport</code></strong></li>
  <li><strong>Designing small Unix utilities</strong></li>
  <li><strong>Building <code class="language-plaintext highlighter-rouge">passfzf</code></strong> — A fuzzy finder for the <code class="language-plaintext highlighter-rouge">pass</code> password manager</li>
</ul>

<p>Thanks for reading, and I hope you’ll enjoy following along as this collection of articles grows.</p>

<p>See you in the next post! 🚀</p>]]></content><author><name>Dumidu</name></author><category term="introduction" /><summary type="html"><![CDATA[If you’re reading this, thanks for stopping by. I’m a software developer who enjoys understanding how things work beneath the surface. This website is where I’ll document that journey. Rather than focusing only on how to do something, I like exploring why it works that way, what happens behind the scenes, and how different pieces fit together.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://dumidusw.dev/assets/images/default-card.jpg" /><media:content medium="image" url="https://dumidusw.dev/assets/images/default-card.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>