#6746 added the unit, the binary, the enable-user-units.sh entry, and a
migration, but not the install line here -- so omarchy-settings shipped
omarchy-crash-watch.service only into the default/ template tree and never
into the search path systemd actually reads.
install/user/first-run/enable-user-units.sh enables its six units in a single
`systemctl --user enable --now` call, so the missing unit failed the whole
call. omarchy-provision-first-run only marks first-run-user when every step
succeeds, which meant first-run never completed and replayed on every login,
re-firing the "Learn Keybindings" and "Update System" notifications. Because
enable is atomic, it also left the other five units disabled -- no bluetooth
agent, sleep lock, monitor recovery, migrate notifier, or fcitx5.
Migration 1786539345 falls back to writing the wants symlink by hand when
there is no live user manager, pointing at the /usr/lib path this omission
left empty, so existing installs got a dangling symlink too.
No new migration is needed: affected installs retry first-run on the next
login and succeed, and the dangling symlinks resolve as soon as the file
exists at that path.
test/shell.d/config-test.sh already asserts this install and fails without it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm1hEGtGRUrfqxMbTi1fWe
The first version checked for pacman and refused anything else, so it would
have declined to run on the actual repository host. Nothing about that host
needs to be Arch: makepkg, repo-add and signing all happen inside containers.
Setup now detects apt or pacman and installs the right names for each --
bsdtar is libarchive-tools on Debian and libarchive on Arch. The requirement
list drops gnupg and the Arch build tools, which the host never runs directly,
leaving Docker, rclone, bsdtar, jq, git and rsync.
Docker is checked before being installed. A host may be running a version from
Docker's own repository, and replacing that underneath a working builder would
be a poor trade for consistency; setup starts it if stopped and otherwise
leaves it alone.
Verified both paths: apt installs the five dependencies and docker.io on a
bare Ubuntu 24.04 container, and an Arch host with Docker already running is
left untouched. A missing systemctl now reports that a container cannot be a
repository host instead of failing on an unknown command.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The sync guard could not read the repository database because bsdtar was not
installed on the host, and the first fix was to parse around its absence. The
better answer is for the host to have what the tooling needs: libarchive ships
the library pacman links against without necessarily installing the binary, so
bsdtar being present was an assumption, not a fact.
bin/setup installs the dependencies, enables Docker, creates the state
directory, and installs and enables the release timers -- the steps the README
previously listed by hand. It is idempotent and takes --check to report without
changing anything. Signing credentials and the rclone remote hold secrets, so
it reports on those rather than creating them.
sync-repo goes back to reading the database with bsdtar alone, and says to run
bin/setup when it is missing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The partial-tree guard parsed omarchy.db with bsdtar, which is not installed on
the repository host. Every sync there aborted with "the remote database exists
but could not be read" -- a guard meant to catch a partial tree instead blocked
a complete one, stopping a publish after sign, promote and update had already
succeeded.
GNU tar reads the database fine when it is a seekable file; the pipe was what
defeated it originally, and that is already downloaded to a temp file. tar now
leads, with bsdtar as a fallback for a tar too old to detect zstd.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
--package meant a pkgbase to bin/build and a literal package name to
bin/push-build, so deploy --package nvidia-580xx-utils built three packages and
published one, leaving nvidia-580xx-dkms and opencl-nvidia-580xx behind with no
indication anything was missing. Hit while deploying exactly that package.
Selection now matches on the pkgbase recorded in .PKGINFO as well as on the
package name, so a pkgbase ships all of its outputs and an individual name
still selects just that one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
bin/build asks the local repository database which packages are already built.
A build machine has no such database, so every package looks out of date: an
unscoped 'bin/repo deploy' on this laptop would have built all 108 packages and
published them. Verified with a dry run.
deploy now refuses to run unscoped when that database is absent, and push
refuses the same combination under --yes, where nobody would see the list it
prints before publishing. Both are allowed on the repository host, which has
the database that makes the comparison meaningful.
Also states the split in the README: build, push and deploy are the three
commands that may run off the repository host; everything else works on the
published tree directly.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The warning dated from when .build-host was the release trigger's own setting
and push was a second consumer of it. One setting now names one machine for all
three commands, so there is nothing to keep separate -- and the advice was
wrong regardless: OMARCHY_REPO_HOST is read by the same resolver, so it arms
the trigger exactly as the file does. Only --host is per-invocation.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
OMARCHY_BUILD_HOST and .build-host were carried as fallbacks through the
rename. Nothing in this checkout ever set either one, so they were a second
name for a setting that has only one real name.
Resolution is now --host, OMARCHY_REPO_HOST, .repo-host.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Builds now happen wherever the operator likes, so naming the destination after
building described the old arrangement rather than the current one. What the
push and deploy commands reach is the machine that serves pkgs.omarchy.org and
holds the signing key: the repository host. It also runs the scheduled builds,
which is why the trigger in omarchy-pkgs release points at the same place.
Resolution moves into helpers/host-helpers.sh, which all three commands now
share instead of repeating: --host, then OMARCHY_REPO_HOST, then .repo-host.
OMARCHY_BUILD_HOST and .build-host keep working as fallbacks, so existing
environments and checkouts are unaffected.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The worst was fatal: push passed --skip-prod-check to upload-prebuilt, which
forwards every argument to sign, promote and update as well, and sign rejects
unknown options. Every non-dry-run push and deploy would have uploaded and
verified its artifacts and then failed before signing. upload-prebuilt now
routes publishing flags to sync alone.
The partial-tree guard was weaker than it looked:
- it counted archive files locally against package names in the remote
database, and this tree keeps two versions per package, so a checkout with
a spare version of half the repository could pass while still hiding
hundreds of packages. It now compares package-name sets and lists what
would be hidden.
- it treated any unreadable remote as an empty one, so an auth failure or a
corrupt database disabled it. Only rclone's "directory not found" now
counts as a fresh mirror; every other failure aborts.
Also:
- sync had no set -e, so a failed package upload fell through to publishing
the database, advertising packages that were never uploaded. Each transfer
is now checked before the next step.
- --package with no names silently meant "every package", which under --yes
could publish everything from one unset variable in a script.
- push now refuses to run when the host has packages staged from an earlier
failure, since publishing would sign and promote those too.
- epoch versions contain a colon, which rsync reads as host:path, so no
package with an epoch could be transferred. Sources are ./-prefixed.
- remote paths are quoted for the remote shell.
- sync spun forever on a missing option value.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
deploy runs build then push, which is the whole workflow on a local build
machine. It resolves the build host before building so a missing --host fails
in a second rather than after a long compile.
--host now overrides $OMARCHY_BUILD_HOST and .build-host on deploy, push, and
the build trigger in omarchy-pkgs release, so a server can be named per
invocation without arming the release auto-trigger.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Heavy packages build faster on a local machine, but there was no way to get
the artifacts to the server: bin/upload-prebuilt publishes to the rclone
remote from whatever tree it runs in, so the local -> host hop was manual.
bin/repo push rsyncs build-output artifacts to the host, verifies checksums,
and runs upload-prebuilt over ssh. Signing stays on the host, which is the
only machine with the key and the only one holding a complete repository.
Publishing from a local checkout was worse than merely unsupported. sync ran
rclone sync --delete-after against a tree that pkgs.omarchy.org/ gitignores,
so on any machine that had not run a full release it would have deleted the
production repository -- guarded only by a y/N prompt that --skip-prod-check
turns off. Package uploads are now additive, deletion moves behind --prune,
and sync refuses to publish a database built from a tree holding fewer
packages than the remote already lists.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The build image compresses at zstd's default level, which leaves these
unstripped driver blobs 22% larger than they need to be. Measured against the
packages on the quattro-beta3 ISO:
nvidia-580xx-utils 359.4 -> 276.2 MiB
lib32-nvidia-580xx-utils 74.2 -> 48.8 MiB
nvidia-580xx-dkms 85.5 -> 79.8 MiB
That is 114 MiB off the ISO's offline mirror, which stores packages
essentially uncompressed inside squashfs, so it comes straight off the image.
The dkms package rides along on its pkgbase.
Carried as .omarchy patches so they survive AUR syncs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The build image sets COMPRESSZST to zstd's default level, which leaves this
1.3 GB Electron tree at 448 MB -- larger than the 334 MB deb it repackages.
Maximum zstd brings it to 323 MB, beating xz on both size and decompression
speed, for ~4 extra minutes of build time.
Carried as an .omarchy patch so it survives AUR syncs. pkgrel picks up the
Omarchy suffix accordingly.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Official ChatGPT/Codex desktop app, now shipping native Linux debs from
OpenAI. Fast ring, so it lands in stable alongside edge.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both fixes we carried are upstream now, in the only two commits made
since our pin: 43d4fa9 strips the crash relaunch environment and closes
the info fd, and 28771c7 makes IpcHandler deregister through the
registry it registered with rather than re-resolving its engine
generation.
Upstream reaches the IPC fix differently - IpcHandlerRegistry became a
QObject held in a QPointer, where we kept a raw back-pointer cleared
from ~IpcHandlerRegistry - but it covers the same two cases: a handler
outliving its QML context, and a registry destroyed before its handlers.
Built clean without the patches at 0.3.0.r20.g28771c7-1.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
v0.1.1 was withdrawn upstream — it was tagged without the Cargo.toml
bump, so its binary reported 0.1.0. v0.1.2 corrects the version string.
Rebuilt with makepkg on x86_64; packaged binary reports ttfx 0.1.2.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The repo is now omacom-io/ttfx, matching the binary and package name, so
the source URL and archive checksum change with it (the tarball's
top-level directory is the repo name). v0.1.1 adds NOTICE and a
standard-form MIT LICENSE, both now installed.
Rebuilt and verified with makepkg on x86_64.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rust port of terminaltexteffects that renders byte-identical frames to
the Python original, as one dependency-free binary.
- ~1 ms startup vs ~107 ms for the Python import alone
- median 9.6x faster rendering; heavy effects hold 120fps fullscreen
where Python drops to ~71fps
- CLI-compatible with tte: same option names, defaults, and exit codes
Built and verified locally with makepkg (x86_64): cargo test passes in
check(), package installs the binary plus shell completions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The desktop file and icon now ship as local sources, since the upstream
repo dropped its in-tree pkgbuild directory in favor of this one.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Includes the .omarchy/package.json metadata the release pipeline
requires to enumerate a package -- without it, bin/repo release
silently skips the directory.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Half the package was git history: lazy.nvim clones with
--filter=blob:none, which marks packs as promisor packs that gc refuses
to touch, so every plugin shipped its full commit graph. Cut each repo
to its checked-out tips (drop remote/tag refs, mark the tips as shallow
boundaries, strip the promisor markers, gc for real) and exclude
test/tests/spec via sparse-checkout so the restore pass in package()
does not resurrect them.
:Lazy update keeps working -- fetch into a shallow repo stays shallow
and re-fetches tags. 116 -> 52.5 MiB installed, 67 -> 32 MB download.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A transient network failure cloning retroarch-joypad-autoconfig-git took
the whole sync workflow red. Clones now retry up to 3 times, and the
failure message includes git's actual error instead of guessing "may not
exist in AUR" — which was never the cause anyway: AUR serves an empty
repo for unknown package names, so that case is now detected explicitly
by the missing PKGBUILD.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Installs the upstream app.slice oomd drop-in so memory pressure kills an
app scope instead of the compositor session, and protects user edits to
etc/systemd/oomd.conf.d/10-omarchy.conf on upgrade.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The dev packages are versioned off the quattro tip, so rebuilding the
same upstream commit yields the same filename. Promotion treated any
pre-existing filename as fatal, which wedged the release loop whenever a
run promoted but died before update-repo rebuilt the database: the stale
database kept advertising the older hash, so every later run rebuilt the
identical package and failed here again, retaining the state file each
time.
Compare the bytes instead. Identical packages are skipped and the run
continues, so the following update-repo step fixes the database and the
loop unsticks itself. Differing content under a published filename still
aborts. Signatures are judged by the package they sign, since gpg stamps
a timestamp into every signature and a re-signed package never matches.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
package() staged the LazyVim data tree twice: once at
/usr/share/omarchy-nvim/data and again at /etc/skel/.local/share/nvim. Only
the /etc/skel copy is ever read — new users are seeded from it, and
omarchy-nvim-setup prefers it — so the /usr/share copy was dead weight worth
close to half the package, which today is 243 MB installed and 178 MB read off
the ISO on every install. That made omarchy-nvim the largest package in an
Omarchy install after noto-fonts-cjk.
Drop it once /etc/skel has its copy, after the chmod and worktree restore that
copy inherits. config/ stays: both the Omarchy 4 remote-clipboard migration and
the 3.x disable-news-alert migration read it from there.
omarchy-nvim-setup's package-dir fallback narrows to config/ to match. It could
never have fired for data anyway — the setup script and /etc/skel ship in the
same package, so a new script can't pair with an old layout — and the remaining
way to lose the seed, hand-clearing /etc/skel, now says which directory is
missing and that pacman owns it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The settings package now ships /etc/systemd/zram-generator.conf, so it needs
a backup entry to protect user edits across upgrades like every other file it
places in /etc, and an optdepends line pointing at the package that reads it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The builder image is layer-cached, so its glibc drifts behind the
mirror while makepkg -s installs makedepends from the freshly synced
database. omarchy-settings-dev died on that partial upgrade: the new
imagemagick needs GLIBC_2.44 and magick refused to run in package().
pacman -Syu runs before the Omarchy repos are appended, so only
core/extra take part -- in-flight build-output packages can't be
pulled into the container.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The sync regenerated the PKGBUILD from AUR and clobbered the splashsrc
patch (restored in 564d0b4). Pin it so the local changes survive.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The pin to d79f157 rebuilt 1.94.10.r12.gd79f157-1.1, but those exact
filenames were already published, so promotion failed. And an untested
1.94.10.r220.g695663f build from master had already been released,
which sorts above the pinned version, so the pin could never reach
users anyway. epoch=1 makes the pinned build win the version
comparison and gives it promotable filenames; once published, the
commit-hash check skips further rebuilds.
Also disable AUR sync: the bot would otherwise regenerate the PKGBUILD
from AUR and wipe out both the pin and the epoch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Commit 7922065 added 0002-escape-optional-splashsrc-expansion.patch
directly to the package dir, but the AUR sync bot regenerates the dir
from AUR plus .omarchy/patches, so the next sync (f886efe) dropped the
patch and reverted pkgrel to 2.1. That stale pkgrel then made the build
server rebuild 0.2.0-2.1, whose filenames already exist in production,
failing promotion.
Restore the patch and pkgrel=2.2, carry the customization as an
.omarchy/patches sync patch, and bump the metadata pkgrel suffix to 2
so future syncs keep producing 2.2.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
omarchy moves fcitx5 off Hyprland's fire-and-forget autostart onto a
supervised systemd user service, so ~/.XCompose compose sequences stop
dying silently when it goes away. Ship the unit.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
omarchy-tailscale-receive.service was in default/systemd/user/ but never
installed, so `systemctl --user enable` found no unit for it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
omarchy renamed omarchy-update-user-notify to omarchy-migrate-notify and
dropped the .path watcher that fired during every package update.
Keep the old service name as a symlink onto the new unit. Existing users hold
an absolute graphical-session.target.wants symlink to the old path, and the
migration that repoints it only runs for users who run an update, which is the
opposite of who the notifier is for. Without the alias their symlink dangles
and they are never told about pending migrations.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
libfprint 1.94.100 ships the focaltech_moc driver and the FocalTech
FT9349 (2808:a97a) ID, so Omarchy is back on stock libfprint. Keep
this package as an escape hatch, pinned to the commit behind the
currently published build so it can't drift onto untested master.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V6ADCjSXt3kd9XGCAJKJkT
/etc/systemd/zram-generator.conf collided with the copy archinstall writes on
every ISO install. zram-generator.conf(5) reserves /etc for the local admin and
has vendors ship snippets under /usr/lib/systemd/zram-generator.conf.d/, where
drop-ins outrank the main config file.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjeyQZsNBxqyYy9z8KaKm7
omarchy ships etc/systemd/logind.conf.d/20-inhibit-delay.conf, which raises
InhibitDelayMaxSec so the pre-suspend lock can finish securing the session
before logind stops honouring its inhibitor and suspends anyway.
package() already installs it along with the rest of the etc tree, so this
changes nothing about whether the file lands. Listing it here is what keeps
pacman from clobbering a user's edit to it on upgrade, matching every other
/etc path this package owns.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Tools for authoring the per-model speaker tunings Omarchy ships. Split out of the
Omarchy tree because measuring a laptop and fitting a filter-chain is contributor
work almost nobody does, and it needs python, ffmpeg and mpv, none of which
Omarchy installs.
Depends on lsp-plugins-lv2 as well, since that supplies the lookahead limiter a
generated chain ends in and is needed to audition the result, not only author it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An IpcHandler deregisters itself from its destructor, but re-resolved its
registry by walking to its engine generation first — a walk that needs a
QML context that is already gone when the handler is destroyed along with
a reloading bar, a swapped plugin, or the shell root. The deregistration
was skipped and the registry kept a pointer to freed memory, so the next
`qs ipc call` into that target segfaulted the shell. Omarchy hits this
through omarchy.indicators refresh, which fires on every reminder, tmux
alert, and silencing toggle.
Carried on the fix-ipc-handler-lifetime branch of
https://github.com/omacom-io/quickshell
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
After a crash relaunch, quickshell kept __QUICKSHELL_CRASH_* and the
instance-info fd in its environment, so every child it spawned inherited
them and any `qs` invocation from those children booted a duplicate
shell instead of running its command (phantom instances on every
menu-launched picker after a crash).
Patch carried on the fix-crash-env-leak branch of
https://github.com/omacom-io/quickshell
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Quickshell 0.3.0's qs kill returns before the instance exits, which is
what forces omarchy-restart-shell to track pids and wait for death
itself. Master fixed kill to block until the instance is gone (025c709),
so ship our own build pinned at e649d24 until a release catches up.
The #commit= pin plus sync:false keeps upgrades entirely manual: nothing
rebuilds or resyncs until the sha is bumped by hand. Note quickshell
links Qt private APIs, so every Arch qt6 bump needs a pkgrel bump and
rebuild here (the packaged quickshell-check hook warns users if we lag).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>