Skip to content

omarchy-base

Recipe card from the charly-distros plugin (Images — the deployable catalog).

The foundation every other layer-omarchy-* composes. One repo, one external pin, three members installed in order.

omarchy-base:
candy:
candy: [omarchy-repo, omarchy-runtime, omarchy-skel]

Consumers pin only the meta, at its sub-path:

candy:
- '@github.com/opencharly/layer-omarchy-base/candy/omarchy-base:v<CalVer>'

Members are named by bare sibling name inside the repo and are never pinned from outside — they are always installed together.

Why the pacman configuration is a separate, package-less candy

Section titled “Why the pacman configuration is a separate, package-less candy”

A candy’s plan: steps are emitted after its distro: packages. A single candy that both configured pacman and installed from it would therefore configure too late. omarchy-repo installs nothing; omarchy-runtime require:s it.

Omarchy publishes its own snapshot of the Arch repositories and installs against that, not upstream Arch. Measured 2026-08-29, stable-mirror.omarchy.org served linux 7.1.9.arch1-2 while geo.mirror.pkgbuild.com was on 7.1.11.arch1-1. 125 of the 148 base packages come from core/extra/multilib, so leaving the base image’s Arch mirrorlist in place produces a mixed snapshot — worse than either pure one, and silently so.

Channel → mirror (upstream’s own mapping; note edge uses the unprefixed host, and there is no dev channel):

OMARCHY_CHANNEL Arch repos [omarchy]
stable (default) stable-mirror.omarchy.org pkgs.omarchy.org/stable
edge mirror.omarchy.org pkgs.omarchy.org/edge
rc rc-mirror.omarchy.org pkgs.omarchy.org/rc

Why an image installs a bootloader it never uses

Section titled “Why an image installs a bootloader it never uses”

The omarchy package hard-depends on limine, limine-mkinitcpio-hook, limine-snapper-sync, snapper and sddm. A container installs the whole boot stack whether it wants it or not. It is inert — the alpm hooks that would drive limine-entry-tool are never extracted, and no unit is enabled.

limine-entry-tool requires a genuinely mounted FAT32 ESP, which a container cannot have, so its hooks always fail there. omarchy-repo adds five NoExtract rules to /etc/pacman.conf so the hook files never land:

  • usr/share/libalpm/hooks/80-limine-efi-deploy.hook
  • usr/share/libalpm/hooks/10-limine-snapper-lock.hook
  • usr/share/libalpm/hooks/60-limine-mkinitcpio-remove-pre.hook
  • usr/share/libalpm/hooks/90-limine-mkinitcpio-remove-post.hook
  • etc/pacman.d/hooks/90-mkinitcpio-install.hook

Do not use /etc/pacman.d/hooks/<name> masking here. It was tried first and is worse on three counts:

  1. It cannot cover 90-mkinitcpio-install.hook at all — limine-mkinitcpio-hook owns that path, so pre-creating it aborts the transaction with failed to commit transaction (conflicting files).
  2. It leaves one unmaskable failure behind. No ESP_PATH value silences it; the tool insists on a real mounted FAT32 partition.
  3. That leftover is not cosmetic. charly check run fails a build whose log carries failure lines even when podman exits 0 — reported as “image-build exited 0 but its log carries N error line(s)”. The R10 gate is stricter than pacman, and correctly so.

ENABLE_HOOKS inside limine-entry-tool is set by invocation mode, not by /etc/limine-entry-tool.conf, so there is no supported config switch to turn the hooks off. NoExtract is pacman’s own mechanism for exactly this, and it yields a transaction that exits 0 with a completely clean log.

omarchy and omarchy-settings ship everything — /usr/share/omarchy/{bin,shell,themes,default,install,migrations} and all of /etc/skel. There is no copy of config/hypr/*.lua, no themes/ tree and no default/themed/*.tpl in this repo.

omarchy-skel exists only because a charly image creates its user before candies run, so useradd’s /etc/skel copy has already happened and the home would otherwise be empty.