key

My Pacman Workflow Was Too Slow, So I Wrote a C Wrapper

I love Arch Linux. I love the AUR. I run Niri on an AMD box, and my setup is a constant work-in-progress of makepkg and -git packages. But there’s one thing that’s always annoyed me: startup lag.

VERT_2025-11-04 10-10-27

When you’re checking for updates, searching for a package, or installing a small tool 20 times a day, those milliseconds add up. Even fast AUR helpers like yay or paru -- great tools, written in Go and Rust respectively -- have a tiny, perceptible delay as they spin up.

It’s just enough to be annoying. And as a sysadmin wannabe and a crappy developer who loves C, I decided to stop complaining and fork archie into something I could use daily.

The Problem

My package management workflow is dead simple. I use maybe four commands 99% of the time:

  • Update everything (official repos + AUR)
  • Install a package (from official or AUR)
  • Remove a package
  • Search for a package

I don't need a complex TUI. I don't need a million flags. I just want a wrapper that’s instant. I wanted a tool with the startup speed of a core utility like ls or grep, not a complex application.

Step 1 - The Core Logic

I didn't want to reinvent the wheel. pacman is the source of truth, and AUR helpers are complex for a reason. My tool just needed to be a smart, fast wrapper that called the right tool for the job.

So, I built archium. It's a single, tiny C binary and loosely based on archie, though not much of the original code still exists.

The logic is simple: it checks its arguments (argv[]) and runs the correct command. The "smart" part is that it automatically detects if you have yay or paru installed.

If you type archium i firefox:

  1. archium does cool shit.
  2. It checks: Do yay or paru exist?
  3. Yes? It executes yay -S firefox.
  4. No? It falls back and executes sudo pacman -S firefox.

I mapped my simple commands: u for upgrade, i for install, r for remove, and s for search. I even started using more commands that I didn't before because it just felt so damn good to use.

/* A simplified look at the core execution logic */
int main(int argc, char **argv) {
    // ... find preferred package manager (pm) ...

    if (argc < 2) {
        // No args? Run the interactive shell.
        run_interactive_mode();
        return 0;
    }

    /* u - upgrade */
    if (strcmp(argv[1], "u") == 0) {
        run_command(pm, "-Syu", NULL);
    }
    /* i - install */
    else if (strcmp(argv[1], "i") == 0 && argc > 2) {
        run_command(pm, "-S", argv[2]);
    }
    /* ... and so on ... */

    return 0;
}

Step 2 - Making it Usable

A simple wrapper is fine, but I wanted a good user experience.

First, we added an interactive mode using the readline library. If you just run archium, you get a prompt with command history, just like a proper shell.

Second, and most importantly, I needed tab completion. This was non-negotiable. I wrote completion scripts for Bash, Fish, and Zsh. Now, when I type archium i nir... and hit [TAB], it completes to niri by feeding the output of pacman -Ssq to the shell.

Step 3 - A Plugin System (Losing my sanity)

This is where things got out of hand. I had other helper scripts I’d run after an update, like checking for orphaned packages or .pacnew files. I decided to build that capability directly into Archium.

I designed a C plugin API. You can write a tiny shared library (.so file), drop it in ~/.config/archium/plugins/, and Archium will load it as a new command.

The API is minimal:

/* The entire 'hello world' plugin */
#include <stdio.h>
#include <string.h>

// ArchiumError enum would go here

char *archium_plugin_get_name(void) {
  return "Hello World";
}

char *archium_plugin_get_command(void) {
  return "hello";
}

char *archium_plugin_get_description(void) {
  return "Prints a hello message";
}

ArchiumError archium_plugin_execute(const char *args, const char *package_manager) {
  printf("\033[1;32mHello from my very own plugin!\033[0m\n");
  if (args && strlen(args) > 0) {
    printf("Arguments: %s\n", args); // you can even get the args
  }
  printf("Package manager: %s\n", package_manager); // we expose this too
  return ARCHIUM_SUCCESS;
}

You just compile it: gcc -fPIC -shared -o hello.so hello.c or simply make from ~/.config/archium/plugins

Now, archium hello is a valid command. This turned a simple wrapper into a fully extensible maintenance framework.

The Reality Check

Is Archium for everyone? Absolutely not.

This is a massive time sink to solve a "problem" that's measured in milliseconds. Most users are, and should be, perfectly happy with yay or just a shell alias (alias u="yay -Syu").

It’s another layer of abstraction. It's written in C, which is a high barrier to entry for contributions. If it breaks, I'm the one who has to debug it.

But just like tweaking my hyprland.conf for hours to get the perfect animation curve, Archium solves my specific annoyance. The binary is \~60KB. It's instant. It works exactly how my brain wants it to work. And best of all, I built it (technically gurov built it first since its a fork but who's counting).

If you're a sigma who loves Arch and is irrationally annoyed by startup lag, you can check it out on GitHub.

Thoughts? Leave a comment

Comments
  1. qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq — Nov 10, 2025:

    very cool