e1b0e5e9bb72b15dc494458925655bf32656382b
643
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
+12 |
e1b0e5e9bb |
Converge omarchy-mac and omarchy-mx-mac into upstream Omarchy (#14431)
* Add omarchy-hw-platform to tell Apple Silicon and Qualcomm machines apart
aarch64 covers Apple Silicon Macs, Snapdragon laptops, Raspberry Pis and
VMs, so the CPU architecture can't pick platform setup. omarchy-hw-platform
prints apple-silicon, qualcomm, generic-aarch64 or generic from the vendor
prefixes in the device tree's root compatible (/proc/device-tree, then
/sys/firmware/devicetree/base) and the CPU, and fails when they contradict
each other. Its qualcomm answer uses the same evidence as the dragon
branch's omarchy-hw-qualcomm-soc, and the fixtures check the two agree.
omarchy-hw-apple-silicon is the Apple predicate on top of it.
An image built away from its hardware names its target in a root-owned
manifest, /var/lib/omarchy/image/target (format=1, platform=). While the
root is being built rather than booted, the detector answers from it and
never reads the build host's device tree; a booted system always answers
from its hardware. As root it restarts in an empty environment, so no
variable picks the platform for privileged setup.
Co-authored-by: Birk Skyum <74932975+birkskyum@users.noreply.github.com>
Co-authored-by: Jimmy Van Veen <8206925+JimmayVV@users.noreply.github.com>
* Reject platform gates keyed only on the CPU architecture
An architecture check is right for an ABI, a binary or a repository's
$arch, not for picking a platform. The lint lists each shipped check after
review and fails on a new one, so platform setup goes through
omarchy-hw-platform.
* Compose default packages from base, architecture and platform lists
omarchy-reinstall-pkgs installed the base list on every machine. A
platform's default set is now the base list, then install/omarchy-aarch64.packages
on aarch64, then the platform's own list when it has one
(install/omarchy-qualcomm.packages adds linux-firmware-qcom).
omarchy-pkg-defaults prints the set for the detected platform, or for the
one named, and reinstall installs it. x86_64 still gets exactly the base
list, and an image build gets its target's set.
* Early-load thunderbolt only where the kernel builds the module
linux-aarch64 has no thunderbolt module, and mkinitcpio fails the whole
image over a MODULES entry it cannot find. The optional form, thunderbolt?,
is not enough: a systemd initramfs copies MODULES as written into
modules-load.d, where "thunderbolt?" names no module, and a kernel without
the module would still list it there. thunderbolt_module.conf now adds plain
thunderbolt only when modinfo finds it as a module for the kernel being
built.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
* Compose mkinitcpio HOOKS from an early baseline drop-in
omarchy_hooks.conf assigned HOOKS outright, and mkinitcpio sources drop-ins in
name order, so it ran after any numbered drop-in (90-*.conf) and threw its
hooks away. HOOKS now comes from 00-omarchy-hooks.conf, which sorts first, and
later drop-ins add to it. The NVIDIA kms filter and the vconsole handling stay
in omarchy_hooks.conf. With the drop-ins Omarchy writes, machines keep the
same HOOKS, MODULES and FILES; a user drop-in that sets HOOKS and sorts before
omarchy_hooks.conf now takes effect instead of being overwritten.
Migration 1786605598 now sources the baseline first, since without it the
migration would read empty HOOKS and also rebuild hybrid systems. It skips a
machine that lacks the baseline.
* Resolve the LUKS parent from raw lsblk output
lsblk -s prints the ancestor tree with box-drawing prefixes ("└─/dev/nvme0n1p6"), so the crypto_LUKS parent came back as a path that does not exist and first-boot setup stopped with "Could not locate the LUKS device to re-key". -r prints raw names. Factory reset uses the same lookup.
* Check the factory-reset passphrase against keyslots only
cryptsetup open tries enrolled tokens before the key file, so a TPM2 or
FIDO2 token could authorize the re-key with a wrong passphrase.
* Test LUKS parent lookup during owner setup and factory reset
Exercise raw ancestry output without invoking provisioning or reset. Cover btrfs subvolume roots, absent encryption, failed probes, and explicit cryptdevice specifications.
* Cover LUKS parent lookup through an LVM volume group
* Journal the first-boot LUKS re-key so an interrupted attempt resumes
A first boot killed after the staged install key's slot was retired left the
key file behind, and every retry then stopped at "the staged LUKS key no
longer unlocks". A lost key file with the boot-time auto-unlock still
configured let setup finish with the disk unlocking unattended.
The re-key now runs from install/provisioning/luks-rekey.sh and records its
phase and slot numbers (never key material) in
/var/lib/omarchy/provisioning/luks-rekey.state. It reuses the owner's slot
instead of adding a duplicate, retires LUKS1 slots too, and destroys the
staged key only after the volume proves it opens nothing. Setup refuses to
finish while any part of the provisioning unlock remains. The journal ends at
phase=done and leaves together with pending, so a retry after the staged key
is retired must use the password the disk already holds.
Key checks exclude LUKS2 tokens: cryptsetup open tries an enrolled token
(say a TPM2 slot a previous owner left behind) before the key and reports its
slot whatever key it was given. Slot listings read only the keyslot section,
since a luks2-keyring token looks like a keyslot in luksDump.
* Change the root volume's LUKS key before the login and root passwords
Installation gives the login user, root and the disk holding / one password,
but omarchy-drive-password changed only the LUKS key, so the three drifted
apart. For the disk holding / it now checks the current password opens the
disk, changes the LUKS key, confirms the new key opens the disk and the old
one no longer does, and only then sets the login and root passwords. Any other
encrypted drive changes its LUKS key alone. Every drive now asks for the
current password with gum instead of cryptsetup's prompt.
A journal in ~/.local/state/omarchy/drive-password.state (disk UUID, key slots
and phase, never a password, written with the re-key journal helpers) lets the
next run finish an interrupted change. The rerun accepts only the old key
(removing the slot the interrupted change added) or the new one (retiring the
old slot), so another key such as a recovery passphrase never becomes the login
password. luksChangeKey is judged by whether the new key opens the disk, not
by its exit status, and key checks exclude LUKS2 tokens, which cryptsetup
open would otherwise accept in place of any password.
Runs are serialised, cryptsetup calls hold a disk lock, a / whose LUKS
partition cannot be resolved fails closed, and passwords are never traced. A
new password equal to the current one is refused, and --pbkdf argon2id is
passed only to LUKS2, so LUKS1 drives can change their password again.
* Add omarchy-lifecycle-dispatch for platform boot operations
Provisioning, factory reset and update call a fixed set of operations
through it. A platform whose boot chain the generic Limine path can't drive
registers a directory of root-owned entrypoints in the dispatcher; every
other platform gets a no-op and keeps its generic path. Apple Silicon is
registered to omarchy-mac-boot's /usr/lib/omarchy/mac-boot, with its
required operations failing clearly when the package or an entrypoint is
missing. docs/lifecycle-dispatch.md is the contract, including how a
Qualcomm boot package would plug in.
* Let the platform's boot package own first-boot setup's boot chain and key slots
Owner provisioning asks provision-prepare before the owner form, hands the
staged unlock to provision-commit and provision-verify where the platform
implements both, and records the kept LUKS slot through luks-slots before
the staged key is destroyed; the disk password change records the owner's
new slot the same way. On x86, Snapdragon and generic aarch64 every call is
a no-op and first boot is unchanged.
* Reset through the platform's boot package where it owns the boot chain
Where a platform implements the reset operations, reset-prepare and
reset-verify stage and prove the factory root's boot files, the throwaway
slot is added only after that, and reset-commit gets the key on standard
input once the factory root is active. A failure before the switch rolls the
boot state back and revokes the slot. Elsewhere the Limine UKI path is
unchanged.
* Check the platform's boot chain after an update
omarchy-update-boot runs update-verify after AUR packages, the last
sudo-capable step, so it also covers the initramfs rebuilds they trigger.
It follows third-party build code, so like AUR it authenticates through the
no-update wrapper. A failed verification finishes the update's remaining
steps, then exits non-zero without offering the reboot. Where the platform
does not implement it nothing runs and nothing asks for root.
* Hand a machine to its platform's migration through lifecycle dispatch
migrations/1790347292.sh resolves the new optional migrate operation and,
where the platform's boot package implements it, runs it as root. The
entrypoint moves the machine onto the platform's official package set,
idempotently and resumably; its failure leaves the migration pending. Once
it succeeds, a root-owned marker spares other accounts the migration and its
root prompt. Everywhere else, Macs without the boot package included, the
migration is a no-op, and an undetermined platform keeps it pending.
* Refuse packages tagged for another platform in a pacman hook
A platform package names its platform with groups=('omarchy-platform-<name>'),
<name> being what omarchy-hw-platform prints. omarchy-settings ships a
pre-transaction hook, the guard it runs and a copy of the detector, so the
guard is resident before the runtime and any platform package. The guard
reads tags from the synced databases and refuses a transaction that installs
a package tagged for another platform; a transaction without a tagged
package passes without asking which machine this is. Image builds answer
from the image's root-owned target manifest, as the detector does.
The guard ships on aarch64 only: no platform package is built for x86_64,
so x86 transactions run no hook. Hardware setup starts by proving the guard
is resident and checking the packages an installer placed without it. On
generic aarch64, where no platform packages exist, a missing guard is
logged, not fatal, and on x86 it is expected.
docs/platform-guard.md is the contract.
Co-authored-by: Birk Skyum <74932975+birkskyum@users.noreply.github.com>
Co-authored-by: Jimmy Van Veen <8206925+JimmayVV@users.noreply.github.com>
* Enable Voxtype's Vulkan backend only when it is installed
omarchy-hw-vulkan reports a Vulkan runtime, not whether this voxtype build
has a Vulkan backend. The aarch64 voxtype-bin package ships only the CPU and
ONNX binaries, so on any aarch64 machine with a Vulkan driver setup ran
`voxtype setup gpu --enable` and printed "Vulkan backend not installed" in
the middle of an otherwise working install. Require the backend binary too.
x86_64 voxtype-bin always ships /usr/lib/voxtype/voxtype-vulkan, so x86
installs still switch to the GPU backend as before.
Ported from omacom/omarchy-mac#483.
Co-authored-by: Oliver Lukschander <33756270+oliverlukschander@users.noreply.github.com>
* Link the system Widevine CDM into Brave
The widevine package registers its CDM for Chromium and Firefox only.
Brave looks for the CDM in its own install directory, finds nothing, and
DRM sites (Netflix, Apple TV+, Spotify) fail with a blank player and no
useful error. This hits machines where Widevine comes from that package,
such as aarch64 ones, since no Widevine component is published for them.
Link /opt/WidevineCdm/chromium into /opt/brave-bin and /opt/brave-origin-bin
through as_root when Brave or Brave Origin is installed, and add a migration
that repairs existing installs. Both do nothing when the widevine package is
absent or the browser already has a CDM. A standard x86 install has no
widevine package, so nothing changes there.
Ported from omacom/omarchy-mac#474, extended to Brave Origin.
Co-authored-by: Caleb Marshall <68087341+cajomar@users.noreply.github.com>
* Report failed setup steps on the console
With file logging, run_logged sends a failing leaf's output and its
"Failed:" marker to the install log only, so the caller sees setup stop
with an exit status and nothing else. A missing command (exit 127) was the
case that made this hard to diagnose.
Print the failed script, its exit status and the log path on stderr. Stdout
logging mode already shows the failure marker and is unchanged, and
successful steps stay quiet.
Ported from omacom/omarchy-mac#389 (the logging part).
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
* Let a migration defer itself without stopping the update
A migration that exits 75 changed nothing and cannot finish yet: omarchy-migrate
leaves it pending with its login notification, runs the migrations after it and
exits 0, so omarchy update carries on. Any other failure still stops the queue.
The platform migration passes a deferred refusal of its entrypoint through, and
defers itself where the dispatcher can't resolve its entrypoint (the platform
can't be told, or the entrypoint isn't trusted): nothing has run then, so the
update goes on to its boot verification, which fails there, as documented.
* Keep Apple Silicon's systemd initramfs on the HOOKS baseline
00-omarchy-hooks.conf set the busybox line on every machine. On a Mac,
omarchy-mac-boot's drop-ins then add the Asahi firmware hooks, but its
encryption drop-in reads busybox encrypt as a Mac unlocked through
cryptdevice= and leaves the line alone. The image came out as
"... block encrypt asahi omarchy-vendorfw filesystems ...", with no
systemd, sd-encrypt or omarchy-mac-encrypt, so an encrypted Mac could not
unlock its disk. Reproduced against an M1 Pro's installed drop-ins.
The baseline now asks omarchy-hw-platform. Apple Silicon starts from the
systemd line its boot package builds on. A Mac whose own mkinitcpio.conf
carries the asahi hook, or busybox encrypt, keeps that line, as a legacy
install needs. x86, Snapdragon and generic aarch64 keep today's busybox
line, as does a machine with no detector. The detector is the runtime's,
or else the copy omarchy-settings ships for its platform guard, so a
settings package newer than the runtime still places a Mac. A detector
that cannot place the machine stops the build.
The HOOKS test now composes the baseline on each platform and on legacy
Mac lines. A new test composes it with omarchy-mac-boot 20260926-1.45's
drop-ins, kept as fixtures, and checks the exact HOOKS the M1 Pro builds.
The NVIDIA test pins its platform.
* Hide optional installs that have no package on this machine
Not every optional install exists on every architecture: some vendors ship no
aarch64 build, and some repositories don't carry a package at all. Each
Install row now carries a `when:` guard naming every package its install
command adds, checked with omarchy-pkg-available, so a row with nothing to
install disappears instead of failing halfway through a pacman transaction.
The rows that build from the AUR (Chrome, Edge, Brave, Brave Origin, Zen,
NordVPN) are guarded on the CPU architectures their vendors publish for.
omarchy-pkg-available asks the sync databases: one `pacman -Slq` per batch,
and `pacman -Sp` for a name that list doesn't hold, so a provided name
(libappindicator-gtk3) and a version constraint resolve the way `pacman -S`
will. The menu's guard prelude sources the same function, so the whole batch
still costs one fork. omarchy-reinstall-pkgs reports and skips a default
that no configured repository offers instead of failing the transaction.
On x86_64 every guarded row resolves against the stable and edge
repositories, so the menu is unchanged there.
Tests derive each row's packages from its install command on x86_64 and
aarch64 and fail when the guard names different ones.
Co-authored-by: Ryan Hughes <1630358+ryanrhughes@users.noreply.github.com>
* Run 1Password with software GL where there is no render GPU
Electron draws a blank window when the machine has no DRM render node: a VM,
a headless or passthrough GPU, or a GPU whose driver isn't up yet (Apple M3
and later on Linux today). omarchy-hw-render-gpu tells whether a renderD node
exists, and omarchy-cmd-electron-gl-args prints --ozone-platform=wayland
--disable-gpu only when it doesn't.
omarchy-cmd-electron-gl-wrap installs a marked PATH wrapper in /usr/local/bin
that execs the real binary with those flags, so it follows the machine rather
than the moment it was installed. It refuses to replace a launcher it didn't
write, or to wrap a binary over itself, and stages the write so a failure
leaves the old launcher in place. omarchy-cmd-desktop-exec-repair points the
user's desktop entry at the wrapper by replacing only the executable token,
keeping arguments, other actions and customizations, with a backup.
The 1Password installer uses them when the machine has no render node. With
one, which is every x86 machine with a working GPU, nothing changes.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
* Record with wf-recorder when gpu-screen-recorder can't start
gpu-screen-recorder knows NVIDIA, AMD, Intel and Broadcom GPUs and aborts
during GL init on anything else, such as Apple Silicon's, before a recording
starts. Screen recording now falls back to wf-recorder, when it is installed,
if gpu-screen-recorder is missing or exits before the file appears. The
picker, file naming, notifications and post-processing are shared. wf-recorder
records one audio device, so desktop plus microphone go through a temporary
null sink that stop unloads, and its track is pinned to 48 kHz. Portal
capture and --resolution stay gpu-screen-recorder only.
The finalize pass keeps 48 kHz too: loudnorm declares 192 kHz output, so
without -ar the AAC encoder wrote 96 kHz from a 48 kHz recording, which many
editors decode as silence, and which on Apple Silicon makes the speaker
safety daemon lock the amps. #11092 makes the same one-line change; whichever
lands second drops it.
Stop and status matched `pgrep -f ^gpu-screen-recorder`, which misses
wf-recorder and matches any command line that starts with that path. The
script now records the recorder's pid, and the new
omarchy-capture-screenrecording-process checks or signals it by its
executable, through a pidfd opened before the check so a reused pid can't be
signalled. When that pid is no longer a recorder (a recording started before
this change, or one that died), every recorder the user runs counts, as it
does for the bar indicator and the Stop row, which use the same helper.
Where gpu-screen-recorder works, which is every x86 GPU it supports today, it
records as before.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
Co-authored-by: Issac Trotts <15530+ijt@users.noreply.github.com>
* Hold logind's lid switch while a display it doesn't count is in use
systemd-logind treats a closed lid as docked only when an external display
is on a connector type it lists (HDMI, DisplayPort, DVI, VGA...). Displays on
"USB" connectors, which Apple Silicon uses for USB-C displays, aren't on that
list, and a missing comma fuses DVI-A and Composite into one entry. With such
a display in use, closing the lid suspended a laptop that was still being
used on it.
omarchy-system-lid-inhibit holds a handle-lid-switch inhibitor while one of
those connectors is connected and enabled in Hyprland, on a laptop where
HandleLidSwitchDocked is ignore, which is exactly the case logind would have
ignored had it counted the display. It releases the inhibitor when the display
goes. A compositor or logind that doesn't answer changes nothing, since
releasing then would suspend a closed lid. The inhibitor runs as a transient
user unit bound to the monitor watcher's unit, so a watcher that dies can't
leave the lid inhibited until logout.
The monitor watcher runs it alongside the clamshell sync. On a machine whose
external displays are all on connectors logind counts, it does nothing.
* Keep the focused workspace in front when a monitor goes away
When a monitor is unplugged, or the lid turns off the laptop panel, Hyprland
first warps focus to whichever monitor it lists first and only then moves the
removed monitor's workspaces over. The workspace you were on lands hidden
behind that monitor's own (Hyprland 0.56.2, CMonitor::onDisconnect).
monitor.focused fires before Hyprland records the new focus, so the monitor
still reported as active is the one being left: its workspace is remembered
until the event loop next turns, and a monitor.removed in that window focuses
it again once the removal has finished. An open special workspace already
comes along, and any focus or workspace change made before the restore runs
wins.
* Drive the keyboard backlight from the ambient light sensor
Laptops with an ambient light sensor and a keyboard backlight LED now light
the keys in the dark and dim them as the room brightens, inverse to display
auto-brightness. omarchy-brightness-keyboard-auto polls the sensor every five
seconds (preferring an IIO device that names itself ALS, and converting a raw
channel with its offset and scale) and maps lux onto the LED, with a deadband
so it doesn't chase noise. It pauses while the screen is locked or the lid is
closed.
A level set with the keyboard-brightness keys wins until the light changes
enough that it no longer fits. omarchy-brightness-keyboard records each level
it sets in the session's runtime directory (a private state directory without
one), so the loop can tell keys turned off on purpose from keys left off by
the lock screen or a restored zero, which it lights again.
The user unit runs it in the graphical session. Its ExecCondition asks
--available, so it is a no-op on machines without both a sensor and a
keyboard LED. First run enables it, and a migration enables it for existing
installs, writing the enable symlink itself when there is no live user
manager.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
Co-authored-by: Gabe Ohlson <3355909+6abe@users.noreply.github.com>
* Defer an image build's hardware setup to the machine's first boot
An image is built away from the machine it will run on, so its hardware
leaves would probe the builder. While the image manifest the detector
already reads (/var/lib/omarchy/image/target) exists, omarchy-apply-hardware
queues every leaf of install/hardware/all.sh instead of running it and arms
omarchy-provision-hardware.service. On the first boot, before owner setup
and the login screen, omarchy-provision-hardware retires the manifest and
runs the queue on the real hardware: a failed step stays queued for the
next boot (exit 75), and the initramfs is rebuilt once after the last step
when a step changed its inputs or asked for it. Bluetooth starts its
service on that boot, whose target is already up. Root ignores any
environment override of these paths. Without a manifest, as on every
ISO install, hardware setup runs exactly as before. Nothing here fetches
package databases: an image carries its sync databases and every package
its steps install.
* Give an image-built root a UTF-8 locale when LANG is still C
A root built from a distribution tarball instead of the ISO (Arch Linux
ARM's ships LANG=C) never went through the ISO's locale step, so it ran
non-UTF-8. The config phase now selects en_US.UTF-8, generating it if
needed, but only when LANG is unset, C or POSIX: any named locale is
somebody's choice and stays. The ISO writes the locale before this runs,
so an ISO install is unchanged.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
* Let a platform's packages run their own boot, system and user setup
Three dispatch operations give a platform one place for the setup it
needs beyond Omarchy's, instead of inline platform branches in the setup
leaves. The last hardware leaf runs setup-boot, then setup-system, as
root, so an image build queues them with the others and its first boot
runs them, with image-first-boot (offline-safe, asking for the one boot
rebuild instead of building). setup-boot belongs to the boot package and
is required on Apple Silicon, where hardware setup has no other way to
run the Mac's boot setup; a failed setup-boot stops the leaf before
setup-system. setup-user runs as the user being set up, refuses root,
and gets only the user's home and session variables: from the last user
leaf at finalization (skipped inside an image build, where the detector
would read the build host) and again from first run once the session is
up. On Apple Silicon setup-boot resolves in omarchy-mac-boot's directory
and the other two, both optional, in omarchy-mac's, /usr/lib/omarchy/mac;
x86, generic aarch64 and Qualcomm register none, so all three are no-ops
there.
A failed finalization now keeps first run pending, like any failed
first-run step, instead of letting the other steps mark it complete.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
* Find batteries, lids and panels that aren't named like a PC's
Laptop detection assumed PC names: a battery called BAT*, a lid in /proc/acpi, a
touchpad or trackpad in the device name, a GPU backlight. Apple Silicon has
none of them (macsmc-battery, the SMC lid switch, apple-mtp-multi-touch,
apple-panel-bl), and some Framework and Chromebook firmware calls its battery
CMB0, so those machines lost the battery panel, laptop-only services, lid
handling, the touchpad toggle and display brightness.
- Battery presence goes by type instead of name, and skips a battery scoped
Device (a wireless mouse or keyboard), so a desktop with one isn't a laptop.
- Battery status takes the first UPower battery that powers the machine, reads
thresholds and cycles from it (BAT* stays the fallback), shows the magnitude
of a signed power_now, and rounds the percentage half-up for display like the
bar, while the charge-hold check keeps the unrounded value.
- A laptop is also one with any input device that reports a lid switch
(SW_LID), whatever its name: Apple's SMC input device has the same name on a
Mac mini, where it reports none. Whether the lid is closed comes from ACPI
where there is an ACPI lid, as before; otherwise logind is asked, with a
short timeout, only when a device reports a lid switch.
- A device named touchpad or trackpad still wins; only when there is none does
the touchpad match take a mouse udev marks as a touchpad (Apple's
multi-touch trackpad), never a touchscreen.
- The platform package can describe its displays in
/usr/share/omarchy-platform/displays.conf: backlights that never drive the
panel (a Touch Bar's), the panel's own where there is no GPU backlight, and
a display driver without DDC channels, where a probe walks unrelated I2C
buses for about 3 s: there only a connector with a ddc node is probed, and
a monitor without one reports no brightness instead of dimming the built-in
panel. Omarchy ships no such file and names no device in it; without it the
backlight choice and DDC probing are unchanged.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
Co-authored-by: Ryan Hughes <1630358+ryanrhughes@users.noreply.github.com>
Co-authored-by: Sparsh Kumar <22640187+skkumarsparsh@users.noreply.github.com>
Co-authored-by: dl-alexandre <166029845+dl-alexandre@users.noreply.github.com>
* Keep the user's XDG config and state directories in platform user setup
setup-user runs with an allowlisted environment, which dropped
XDG_CONFIG_HOME and XDG_STATE_HOME. A platform's user setup reads the user's
configuration and keeps its setup markers there, so for a user who sets
either it looked in, and wrote to, the default directories instead. Both now
pass through with the rest of the session; XDG_DATA_HOME and everything else
still don't.
* Let a platform package add Hyprland defaults of its own
A platform's runtime package may need Hyprland defaults of its own (a Mac's
capture keys and three-finger workspace swipe, say), and Omarchy's config
should carry no branch for them. Three directories under the platform root,
/usr/share/omarchy-platform, now take them. The one installed platform package
owns that root, Omarchy reads it by literal path and ships nothing there, so
without a platform package nothing changes. Each file is loaded by its path,
so it can't shadow a module, and one that fails is logged and shown as a
notification while the rest of the config loads.
- hypr/defaults/*.lua loads before Omarchy's defaults. A
chord bound there replaces Omarchy's default for it, and a decorator it adds
runs before every later bind, so it can bind what has to run first. It sees
the command a bind runs, including the command a shell shortcut such as
{ menu = "root" } stands for when it binds the shell's global shortcut.
- hypr/settings/*.lua loads after Omarchy's defaults and
before the theme, for settings that replace Omarchy's.
- hypr/gestures/*.lua loads after the user's files, only for what must
see them: the gesture registry, which now records on every platform, lets a
default gesture step aside for the user's own.
The user's files load after the first two and can unbind or rebind any of it.
* Let a platform package name keys in the keybindings menu
The keybindings menu shows a key by its keysym, which on some keyboards is not
what the key says: on a MacBook, XF86MonBrightnessUp and Down are the F2 and
F1 keys, so the menu listed rows like "SHIFT + XF86MonBrightnessUp". A
platform package can now list names for such keys in /usr/share/omarchy-
platform/key-names, one "<keysym> <name>" per line, and the menu shows those
instead. The file is part of the menu cache's key, so installing or changing
it refreshes the menu. Without it the menu is as before.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
Co-authored-by: kx0101 <90087463+kx0101@users.noreply.github.com>
* Keep the top bar out of a panel's camera cutout
A laptop panel with a camera notch at its top (Apple Silicon MacBooks, for
one) covered the middle of the top bar, and a bar shorter than the notch left
a sliver of every window beside the camera. Omarchy knows no panel's cutout
itself: the platform's own package describes them in
/usr/share/omarchy-platform/display-cutouts.json, by
connector, physical mode and the rows the cutout covers. On a described panel
a top bar is never shorter than the cutout, its center section sits beside
the right one, and hiding it parks all of it; [bar] notch-height sets that
floor by hand, on that panel only. Without a description, which is every
machine without such a package, the bar is as before.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
* Keep PC and Intel Mac quirks off Apple Silicon
A few hardware steps and commands written for PCs and Intel Macs do the wrong
thing on Apple Silicon:
- The Intel Mac Wi-Fi quirk turns off the Broadcom firmware supplicant for
every Mac whose DMI vendor is Apple and whose chip is on its list. Apple
Silicon reports Apple Inc. through U-Boot's DMI tables, and the M1 Pro and
Max's BCM4387 is on the list, but there the firmware supplicant is the one
that works: turning it off makes firmware commands time out and breaks
scanning. The install step and its migration now skip Apple Silicon.
- fnmode=2 for Apple-like keyboards is left to the Mac's own platform package
on Apple Silicon, where the built-in keyboard's top row depends on it.
- The SPI keyboard check reads the DMI product name without failing the
hardware pass where there is none.
- The Windows VM, an x86_64 guest under KVM, runs on x86_64 only, and direct
boot (U-Boot finds the bootloader and makes its boot entries itself)
refuses Apple Silicon; the menu hides both there. Hibernation setup skips
it; its kernel has no hibernation today, and resume there is not wired.
Everywhere else each step runs as before.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
* Let a platform's runtime package adjust the apps it needs to
Some apps need a platform's own touch once they are installed. On Apple
Silicon, Chromium-family browsers must decode video in software (the hardware
decoder renders green frames in them), and Steam only runs through a
FEX launcher, which then depends on Steam and must go before Steam can be
removed. Until now the Mac runtime did this with inline branches in the
installers.
Two optional dispatch operations take their place. post-install <app> runs
as the user once an installer has installed the app and finished its own
setup of it: every browser install (after its flags file, before it says the
browser is installed) and Steam's (after the package, before the 32-bit
drivers and the first launch). pre-remove <app> runs before Steam's removal
drops its packages. Where a platform registers them they refuse root (a
platform with nothing registered is a no-op, so sudo installs still work
there) and get the same home and session variables as setup-user, and a
failure fails the install or stops the removal. On Apple Silicon they
resolve in omarchy-mac's directory; every other platform registers none, so
installs and removal run as before there.
Steam's 32-bit driver step also stops failing the install on a machine with no
Intel, AMD or NVIDIA GPU (Apple Silicon, but also Snapdragon or a VM): it has
nothing to add there and now says so.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
* Ask the platform's boot package before an update takes over its files
When an Omarchy package's upgrade stops only on files no package owns, the
update moves them aside and retries. On a Mac some of those files belong to its
boot chain or were written by its image (initramfs and pacman configuration,
say), and moving them aside can leave it unable to boot or update. The Mac
runtime refused those paths with an inline list.
update-takeover <path>... asks the platform's boot package instead, before
anything moves: read-only, exit 0 lets the takeover go ahead, anything else
keeps every file and the update fails as it did before the retry existed. The
update resolves it as the user and runs it with sudo only where it resolves,
inside the authorization the move needs anyway. On Apple Silicon it is
required: a Mac without its boot package, or with one too old to answer, keeps
its files. Every other platform registers none, so the takeover goes ahead as
before, asking no one.
* Install the Mac's package set on Apple Silicon
omarchy-pkg-defaults already composes install/omarchy-<platform>.packages
after the base and aarch64 lists, but Apple Silicon had no list, so a Mac got
the generic aarch64 set: no omarchy-mac or omarchy-mac-boot, whose entrypoints
the dispatcher requires there.
install/omarchy-apple-silicon.packages names the Mac's runtime and boot
packages, plus the defaults an owner may remove: the startup-volume tool,
hardware video decode, Widevine, and wf-recorder, since gpu-screen-recorder
can't capture on Apple Silicon and screen recording falls back to it. What a
Mac can't work without (its speaker stack, PipeWire's PulseAudio server and
realtime scheduling, the GPU's Vulkan driver) comes as omarchy-mac's
dependencies, so a new Mac driver needs no Omarchy change. Other platforms
compose exactly what they did.
Co-authored-by: Scott Jones <444693+scottjones@users.noreply.github.com>
* Give existing aarch64 machines the zram swap Omarchy configures
omarchy-settings configures swap on zram and tunes memory reclaim for it.
x86_64 gets zram-generator from its installer and new aarch64 installs from
their default packages, but an aarch64 machine installed before
omarchy-aarch64.packages named it has no generator, so the configuration asks
for a device nothing creates.
Migration 1790328426 installs zram-generator where the platform's default
packages name it and it is missing, and starts the zram swap wherever it is
down, unless no device is configured (then the generator makes no swap unit)
or the administrator masked it. A swap that won't start, or whose unit can't
be read, only warns: the generator's unit starts with every boot, so a reboot
retries it, and failing the migration would stop every update. A failed
install waits (75) for the next migrate, as it does where the platform can't
be told, changing nothing. It keeps the name it has in omarchy-mac, so Macs
that already ran it skip it. It also retires an /etc copy of the drop-in
identical to the packaged one, which earlier Mac setups made and which would
hide the packaged file's updates; an edited copy stays. On x86_64 the default
packages don't name the generator and there is no copy, so it does nothing.
* Keep an ARM machine's repositories when it changes channel
omarchy-refresh-pacman and install finalization copied x86_64 templates
everywhere, so on an aarch64 machine a channel change or a finished install
wrote Arch Linux's x86 [core]/[extra]/[multilib] and dropped Arch Linux ARM
and the platform's own repositories.
Channel changes now tell the platform apart. x86_64 is unchanged. On aarch64
the machine's configuration is kept, with its repositories, mirrors and
signature policies, and only the [omarchy] server moves to the new channel;
a configuration whose Omarchy server can't be identified is refused
unchanged, and one with no Omarchy repository gets it at the end (not on
Apple Silicon, whose own repository must not come first). Only pacman.conf is
backed up and rewritten, straight from this process through sudo, never
through a file another process could change first.
Before that, a channel must be qualified for the platform: a signed upgrade
and reboot tested there, not only a published repository. x86_64 keeps
stable, rc and edge; Snapdragon and other aarch64 machines take edge, as
dragon does; Apple Silicon takes none until the Mac packages qualify on edge.
The refresh then checks, as the user, that the channel's omarchy.db
publishes the runtime pair, and on Apple Silicon omarchy-mac and
omarchy-mac-boot. omarchy-channel-set refuses an unqualified channel before
anything else, the dev confirmation included.
Install finalization writes a whole template, as before on x86_64. Other
aarch64 platforms get Arch Linux ARM (dragon's pacman-aarch64.conf and
mirrorlist-aarch64, byte for byte) with its keyring, plus Omarchy on a
qualified channel. Apple Silicon gets omarchy-mac's template on a qualified
channel and keeps its image's configuration otherwise. In an image build,
finalization leaves the keyring to the machine's first boot, so machines
flashed from one image don't share a pacman master key. On an unqualified
channel, a machine that gets no Omarchy repository is told why.
Co-authored-by: Birk Skyum <74932975+birkskyum@users.noreply.github.com>
Co-authored-by: Jim Martin <1334144+jdvmi00@users.noreply.github.com>
* Keep Arch Linux ARM's signing keys current on ARM machines
omarchy-update-keyring reinstalls archlinux-keyring before every system
upgrade, since keys change without a version bump. An aarch64 machine's Arch
Linux ARM repositories are signed with keys from archlinuxarm-keyring, which
nothing refreshed, so a rotated ALARM key failed the upgrade that followed.
On an aarch64 platform where archlinuxarm-keyring is installed, it is
reinstalled in the same transaction. On x86_64 the keyring step runs exactly
as before, even where that package happens to be installed.
* Mark the runtime's platform files as deciding at runtime
The omarchy-settings recipe leaves the mkinitcpio, Limine, memory and USB
drop-ins out of its aarch64 package, because they used to assume x86_64. That
leaves an aarch64 install without the HOOKS baseline its initramfs needs, and
without the zram and reclaim settings every other Omarchy machine gets.
Each of those files now decides at runtime whether it applies: the HOOKS
baseline asks the platform, thunderbolt is added only where the kernel has the
module, the Limine files are read only where Limine is installed, the oomd
drop-ins are inert without systemd-oomd, aarch64 installs the zram generator
the zram drop-in needs, and the USB autosuspend option is ignored by a kernel
that builds usbcore in. default/settings-runtime-profile says so, file by
file; a recipe that finds it ships the same files on every architecture
(omacom/omarchy-pkgs#638), and older sources keep today's aarch64 package. A
test checks that every file it names exists and that each runtime decision is
in place.
* Set the wireless regulatory domain from the owner's timezone at first-boot setup
A deferred install (an Apple Silicon image, an OEM ISO install) runs its
hardware steps before the owner picks a timezone, on the UTC placeholder,
which names no country, so install/hardware/set-wireless-regdom.sh leaves the
regulatory domain unset and the radios stay on the world domain. Owner setup
now runs that step again once the owner's timezone is set, and applies it to
the radios through wireless-regdb's helper, since no reboot follows setup. An
up-front install, which picks the timezone before its hardware steps, is
unchanged.
* Ask again for a keyboard layout first-boot setup could not apply
First-boot setup kept going when the chosen layout did not take: loadkeys
errors were ignored, a keymap localectl did not list kept the default, and a
failed or partial write of /etc/vconsole.conf was only logged. The owner then
typed the disk password in one layout while the boot files asked for it in
another, and could only unlock the disk by typing US-style.
The keyboard step now fails closed. On a console loadkeys must succeed, the
keymap must be in localectl's list exactly (a list localectl cannot produce
counts as a failure too, logged apart), and after systemd-firstboot or the
localectl fallback, /etc/vconsole.conf is read back in a clean shell and must
name the chosen keymap with an XKB layout. Any failure is logged, the owner is
told the layout could not be set, and the layout is asked for again, so the
password form is never reached with a layout that did not take.
* Refresh a platform's own signing keyrings before an update
omarchy-update-keyring reinstalls archlinux-keyring (and Arch Linux ARM's on
aarch64) before the system upgrade, so a rotated key never fails that
upgrade's signature checks. A platform's own repository has a keyring of its
own that nothing refreshed: on Apple Silicon, asahi-alarm-keyring for
[asahi-alarm].
A platform package now lists those keyrings in
/usr/share/omarchy-platform/keyrings, one package name per line, and
omarchy-update-keyring reinstalls each one that is installed in the same
transaction. It adds no repository the machine didn't already trust. A line
that isn't one keyring package name is skipped with a warning, so a mistake in
the list can't stop every update. Without the file, as on x86 today, the step
runs as before.
* Drive an untyped default input from the audio panel
Quickshell types only exact media classes, so a virtual source (an
Audio/Source/Virtual: EasyEffects' source, or the microphone mapping a
platform package adds) has no PwNode.audio. With one as the default input the
audio panel showed the input at 0% and its slider changed nothing, the peak
meter stayed flat, the microphone widget read it as muted, and the panel could
not list it unless it was already the default.
Such an input now goes through wpctl for its volume and mute (UntypedInput in
shell/Commons, one reader and one pactl subscribe for the whole shell), the
panel meters it with the new omarchy-audio-source-level, and the input list
takes an untyped node PulseAudio lists as a source.
A platform whose audio runs through its own processing can also name nodes
that are neither devices nor apps in /usr/share/omarchy-platform/audio.json,
which Omarchy ships none of: the panel and the microphone widget leave them
out, and a "replaced" node only while its replacement exists. Without the
file nothing is hidden.
On every machine: the input list leaves out a source whose ports are all
unavailable (an empty headset jack) unless it is the default, as the output
list does for sinks; choosing an input no longer moves a filter's own capture
(a source output with node.link-group), which would feed the filter from the
new input or from itself; the shell's own level meters no longer light the
microphone widget; and omarchy-audio-sink-availability reads pactl in the C
locale for sinks too, since "not available" is translated.
* Give first-boot setup an XKB layout for keymaps systemd cannot map
systemd-firstboot writes an XKB layout only for keymaps listed in
kbd-model-map. Nine the setup form offers are not (Colemak, Azerbaijani,
Bulgarian, Czech, Swiss German, Kyrgyz, Norwegian, Polish, Ukrainian), so it
wrote KEYMAP= alone, the readback refused it, and owner setup could never get
past the keyboard step for them.
Setup now adds the XKB settings itself when firstboot left none, matching the
console map so the shared password types the same on the desktop: kbd's cz is
QWERTY, bg-cp1251 phonetic and azerty French AZERTY, and non-Latin layouts keep
a US layout to switch to, as kbd-model-map's own rows do. A test checks every
layout the form offers ends with an XKB layout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>
* Leave keys a firmware key turned off dark
The ambient keyboard backlight treated any 0 the keyboard-brightness keys had
not recorded as an accident and relit it within five seconds. Firmware Fn keys
(Fn+Space on ThinkPads and Framework laptops, Fn+F10 on Dells) write the LED
directly, so on those laptops turning the keys off never stuck.
The lock screen's off now records a blank, and only that blank or a 1%
leftover is taken back; any other off is a choice that pauses auto like the
keys do. A wake clears the blank only once the restore succeeded, the command
runs one at a time so a blank racing a wake can't leave the LED and record
disagreeing, and the loop drops a blank once it has taken the keys back.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>
* Drop the optional-install availability guards
Each menu open checked every Install row against the sync databases, which
costs most of a second of pacman work on every machine to hide rows only an
ARM machine is missing. The fix for those is publishing the ARM packages, not
hiding the rows, so this removes omarchy-pkg-available, the Install rows'
availability and architecture guards, and reinstall's skipping of defaults no
repository offers.
The Windows VM row keeps its x86_64 guard, since no package fixes a guest that
needs an x86_64 host, and reinstall keeps its aarch64 channel handling.
This reverts commit aea001cbde4d0852b311ef42b5e8c380c719f833.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>
* Put the current root back when the factory root cannot take its place
Factory reset moved the running root aside, marked the reset committed, then
renamed the staged factory root to @. If that second rename failed, cleanup
saw a committed reset: it skipped the boot package's rollback and kept the
throwaway LUKS slot, and since the swap had not happened it deleted the staged
root as well, leaving nothing at @.
The reset now commits only once the factory root is at @. A failed activation
renames the old root back first, then cleanup rolls the platform's boot state
back and revokes the throwaway slot. If that rename fails too, both roots are
kept, cleanup still rolls back and revokes, and the error names the rename
that recovers the machine. The generic Limine path has already rebuilt its
boot files from the factory root by then, as it had before this change.
* Leave other recorders alone when the saved recorder pid is stale
A saved pid that no longer named a recorder made status and stop select every
gpu-screen-recorder and wf-recorder the user ran, so stopping could interrupt,
and after five seconds kill, a recording started somewhere else.
A stale pid now means no recording of ours is running: the toggle starts a new
one, and --stop-recording finds nothing to stop. Stop acts on the recorder the
status check selected rather than selecting again. Without a saved pid, as for
a recording started before the pid was saved, every recorder the user runs
still counts.
* Name the audio a wf-recorder recording could not capture
With desktop and microphone audio both requested, wf-recorder records a null
sink fed by two loopbacks, and a loopback that failed to load was ignored: the
recording went ahead without that source, or silent when both failed. A
missing null sink or default device dropped audio just as quietly.
A source that cannot be captured is now left out with a notification naming
it, the loopbacks that did load are unloaded, and the recording carries the
source that remains, or no audio track at all.
* Show the Edge, Spotify and Dropbox installers on x86_64 only
These vendors currently publish Linux builds for x86_64 alone (the AUR's
microsoft-edge-stable-bin and spotify are arch=('x86_64'), and Dropbox lists
no Linux ARM client), so no native aarch64 build is available and choosing
one on an ARM machine only fails. Like the Windows VM row they keep a uname
check, which the menu answers once per open without asking pacman. The other
Install rows are unchanged.
* Revoke the generic reset's throwaway slot when the reset fails
The generic Limine path added its throwaway LUKS slot without recording it,
so a reset that failed before activation never revoked it. Once the factory
root's UKI was on the ESP, a failed activation that put the old root back left
a machine that booted the factory kernel and unlocked unattended with a key
readable on the ESP, while the screen said the current root was back.
The generic slot is now recorded like the platform's and revoked by cleanup
whenever the reset fails before the factory root is active. A failed
activation on that path says the boot files were already rebuilt from the
factory system and to run limine-update before rebooting.
* Clear a stale recorder pid when a recording starts
The recorder's pid is saved only once its file exists. Until then a pid left
by a recording that ended without a stop still counted as stale, so pressing
the toggle again while the new recorder started found nothing of ours and
could start a second recording. Starting a recording now clears that pid,
and during startup the toggle falls back to the user's recorders as before.
* Word the dropped-audio notice for every reason a source is left out
The notice said the dropped source "could not be captured", which was wrong
when the null sink itself failed to load: the microphone was never tried, and
desktop audio recorded alone as it always has. It now says the source could
not be added to the recording, true for a missing device, a failed loopback
and a failed null sink alike.
* Show the Heroic and Minecraft installers on x86_64 only
Heroic publishes Linux builds for x86_64 alone (its arm64 builds are for
macOS and Windows), and Mojang's Linux launcher is a single x86_64 tarball.
They join Edge, Spotify and Dropbox under the same uname check, so every row
whose vendor ships no native Linux aarch64 build is treated alike.
* Ask the recorder script whether its stop has a recording to end
The bar indicator and the menu's Stop Screenrecording row asked the process
helper whether any recorder the user runs was alive, while the toggle's stop
acts only on the recording it saved. With a stale saved pid alongside an
unrelated recorder, both offered a stop that did nothing.
omarchy-capture-screenrecording --status answers with the selection the stop
uses, and both now ask it. Status needs no recordings directory and never
notifies, so the recordings-directory check moved below argument parsing and
skips it.
* Copy every platform's pacman templates into place, as x86_64 does
On aarch64 a channel change edited the machine's pacman.conf in place: an awk
pass found the [omarchy] server and rewrote its channel, appended a section
where there was none, checked the channel's omarchy.db first, and gated it all
on a per-platform table of qualified channels. Install finalization appended
Omarchy to a template, or on a Mac copied one bundled inside omarchy-mac. What
a machine ended up with was never in the repository.
Each platform now has a pacman.conf and mirrorlist per channel, copied whole:
x86_64's stay in default/pacman, Snapdragon and other aarch64 machines use
default/pacman/aarch64, and Apple Silicon default/pacman/apple-silicon, with
Omarchy and Asahi ALARM ahead of Arch Linux ARM. Omarchy publishes aarch64
packages on edge alone so far, so every ARM channel points at edge for now and
channel changes work there; moving a channel is a template edit. A channel
without both files is refused before anything changes, including a dev
checkout's own templates. Reinstall goes back to resetting to stable, and the
update confirmation loses the missing-repository notice it no longer needs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>
* Revert "Copy every platform's pacman templates into place, as x86_64 does"
This reverts commit 9a07e138cc6c3a19b58d2f3d7eb536dd3042ccc5.
* Copy every platform's pacman templates into place, as x86_64 does
On aarch64 a channel change edited the machine's pacman.conf in place: an awk
pass found the [omarchy] server and rewrote its channel, appended a section
where there was none, checked the channel's omarchy.db first, and gated it all
on a per-platform table of qualified channels. Install finalization appended
Omarchy to a template, or on a Mac copied one bundled inside omarchy-mac. What
a machine ended up with was never in the repository.
Each platform now has a pacman.conf and mirrorlist per channel, copied whole:
x86_64's stay in default/pacman, Snapdragon and other aarch64 machines use
default/pacman/aarch64, and Apple Silicon default/pacman/apple-silicon, with
Omarchy and Asahi ALARM ahead of Arch Linux ARM. Omarchy publishes aarch64
packages on edge alone so far, so every ARM channel points at edge for now and
channel changes work there; moving a channel is a template edit. A channel
without both files is refused before anything changes, including a dev
checkout's own templates. Reinstall goes back to resetting to stable, and the
update confirmation loses the missing-repository notice it no longer needs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>
* Drop the migrations no installed machine needs
Fresh installs mark every migration done, and every Apple Silicon machine is a
fresh install, so the Mac handoff to omarchy-mac-boot (and the migrate
operation it called), zram for aarch64 installs that predate the package list,
the Brave Widevine link and the Broadcom migration's Apple Silicon guard never
run anywhere. The exit-75 deferral in omarchy-migrate existed only for two of
them. Keyboard backlight auto stays on new installs through first run rather
than switching on for existing ones, and migration 1786605598 goes back to
quattro: the mkinitcpio drop-ins arrive by package.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Drop the generic changes Mac support doesn't need
The pacman platform guard (and the detector copy omarchy-settings shipped for
it, which the HOOKS baseline fell back to), the lint against uname gates, first
run staying pending after a failed finalization, run_logged echoing failures to
stderr, half-up battery rounding, hiding empty-jack inputs and leaving a
filter's capture alone when choosing an input all rode along with the Mac work
without serving it. Each goes back to quattro's behaviour and can come back on
its own merits.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Drop the platform Hyprland slots
A platform package could load its own Hyprland binds, settings and gestures:
binds that replaced Omarchy's chords and decorated every later bind, settings
ahead of the theme, and gestures after the user's files, which needed every
hl.gesture call wrapped so a default could step aside. On a Mac those carried
macOS habits (a three-finger workspace swipe, tap-to-click off, menus opening
on the built-in screen, other screenshot and keyboard-backlight chords), not
anything the hardware needs, and Omarchy should behave the same on every
machine. The one bind a Mac does need, its lid switch under the SMC's name,
joins Omarchy's own lid binds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Keep aarch64 machines off the release channels until a release supports them
Every aarch64 channel's template pointed at the edge repository, but a switch
to stable or rc installs the release-named omarchy and omarchy-settings. On
edge/aarch64 those are the 4.0.4 release line, which has no omarchy-hw-platform,
lifecycle dispatch or omarchy-pkg-defaults, so `omarchy-channel-set stable` on
a Mac replaced the quattro runtime it runs with one that cannot run it, and
succeeded.
aarch64 platforms now have edge templates alone, so a switch to stable or rc is
refused before anything changes; adding those templates once a release
supports aarch64 opens them. Refresh with no channel named, as reinstall runs
it, and install finalization for a channel the platform has no templates for
take the platform's default channel: stable on x86_64, edge on aarch64.
* Leave a filter's own capture alone when choosing an input again
d0b94d98c returned omarchy-audio-input-set-default to moving every source
output, as not serving Mac support. It does: asahi-audio's microphone DSP on
Apple Silicon records the raw array through a filter-chain capture stream
(audio_effect.jNNN-mic, node.link-group "filter-chain-..."). On an M1 Pro,
choosing the Mac's microphone in the audio panel moved that stream onto the
DSP's own output, and the microphone recorded digital silence (-91 dB, from
-55 dB of room noise) until PipeWire restarted. With the skip it keeps
recording (-54 dB).
This restores the skip of source outputs carrying node.link-group, and its
test, as they were before that commit.
* Say aarch64 offers edge alone where the templates are described
The aarch64 edge templates, the template helper and the update-process docs
still said every platform has a template per channel and every ARM channel
installs from edge, which the previous commit made untrue.
* Point the Mac packages at omacom/omarchy-mac-pkgs
omarchy-mac and omarchy-mac-boot now live in omacom/omarchy-mac-pkgs, with
each package at the top level. The dispatcher, its documentation and the
Apple Silicon package list name that repository, and the drop-in test's
fixtures, byte for byte the same as omarchy-mac-boot/files/etc/mkinitcpio.conf.d
at 4399105, cite it there.
* Stop naming a platform migration among the dispatcher's callers
The migrate operation went with the Mac migrations, and no caller hands a
machine to a platform migration any more, so the header lists only the
flows that still dispatch. The optional-operations comment is rewrapped.
* Keep the Intel Mac Broadcom migration off Apple Silicon again
A fresh install marks every migration done only for the user it creates, so
an account added later runs them all on its first update. On an Apple
Silicon Mac this one matches: an M1 Pro reports sys_vendor "Apple Inc." and
a BCM4387 (14e4:4433), so it would append feature_disable=0x82000, which
stops that chip scanning once brcmfmac reloads. Restore the guard and its
test case.
* Say when Steam's post-install hook runs now that the drivers go first
Steam's installer now adds the 32-bit drivers before Steam itself, so the hook runs after both and before the first launch.
* Release fallback audio after the recorder exits
When wf-recorder ends outside the normal Stop path, status rejects the saved PID before unloading the combined-audio loopbacks. Release those owned modules when the saved recorder is gone, so the next status or stop call ends microphone capture without signaling another recorder. Leave a mix without a saved PID alone: its recorder can still be starting.
Co-Authored-By: GPT-6 in Codex <noreply@openai.com>
Co-Authored-By: Codex Medium <noreply@openai.com>
* Serialize recording state changes and stale audio cleanup
Status can finish checking an exited recorder after another command has replaced its audio modules, and stop finalization can outlive the recorder while a new recording starts. Share a lock across start, stop and cleanup so each command finishes updating its resources before another changes them. Status uses a read-only check when the lock is busy, keeping the bar responsive during the picker. Close the lock descriptor in persistent children so recording and preview cleanup cannot retain it.
Co-Authored-By: GPT-6 in Codex <noreply@openai.com>
Co-Authored-By: Greptile <165735046+greptile-apps[bot]@users.noreply.github.com>
* Keep automatic and manual keyboard brightness updates together
A brightness key can update the LED and its chosen-level record after the automatic loop checks for a manual change but before it applies a new target. The automatic write then overwrites the user's choice and deletes the record. Take the manual command's lock for the whole tick, skipping a busy tick and releasing the descriptor on every return. Create the private fallback directory before opening the lock outside a session runtime directory.
The normal lock screen waits five seconds before blanking, so an ordinary tick should already see the session locked. The regression exercises a brightness key arriving within a tick instead of relying on an implausibly delayed lock-state check.
Co-Authored-By: GPT-6 in Codex <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 High via Pi <noreply@anthropic.com>
* Read the split hook baseline in the NVIDIA migration
The NVIDIA firmware migration decides whether to rebuild by sourcing the hardware and filter drop-ins. With HOOKS now defined in the earlier baseline, that partial read treats every hybrid machine as if kms had been removed. Source the new baseline first when it exists, keeping the legacy two-file layout working and skipping rebuilds when the effective hooks still include kms.
Co-Authored-By: GPT-6 in Codex <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 High via Pi <noreply@anthropic.com>
* Use a hardware helper for x86-only menu entries
Keep the x86_64 availability checks for Windows and vendor-specific installers in a hardware predicate, so menu conditions use the same command style as other hardware checks.
Co-Authored-By: GPT-6 in Codex <noreply@openai.com>
* Keep restored keyboard levels from pausing automatic brightness
Idle wake, quick unlock and hibernate can restore a saved level older than the ambient loop current level without the lock blanking first. Treat that restoration as a one-tick event, preserving existing manual pauses and the normal blank-and-restore path. Consume unmatched and unchanged restore records too, so a later firmware key cannot look like the earlier restore.
Co-Authored-By: GPT-6 in Codex <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 High via Pi <noreply@anthropic.com>
* Preserve restored keyboard levels across a later lock blank
The ambient loop skips a locked session, so a restored level may still be unconsumed when the next blank saves it. Carry that origin through blanking and restore failures so fingerprint unlock cannot make the old saved level look like a manual choice. A brightness key replaces the marker with its chosen level and retains the ordinary blank behavior.
Co-Authored-By: GPT-6 in Codex <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 High via Pi <noreply@anthropic.com>
* Preserve firmware brightness choices before a lock blank
Firmware keys change the LED without updating the record. Carry a pending restoration through the next blank only if the observed LED still matches that restoration, or is still zero from its previous blank. A firmware change otherwise follows the ordinary blank-and-restore path so automatic lighting pauses on the chosen level.
Co-Authored-By: GPT-6 in Codex <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 High via Pi <noreply@anthropic.com>
* Change only the disk password in omarchy-drive-password
Changing the system disk's password also set the login and root passwords
to match. That changes account-password policy on every platform, x86
included, and overwrites passwords someone chose to keep different, so it
moves to its own change with an explicit confirm.
The disk change itself stays as it was: the new key must open the disk and
the old one must not before the change counts, the journal finishes an
interrupted change, and where the platform's boot checks prove the key
slots, the owner's new slot is recorded before the run finishes. The
journal's confirmed phase is now "record" and no longer needs a login user.
* Cancel a pending recording start instead of queueing behind it
Starting a recording holds the recorder lock through the picker and until the
recorder creates its file. A second toggle or a stop then waited on that lock,
with no end while a portal pick or a stuck recorder never finished, and once
the start gave up the queued toggle began another recording.
While a start is pending, a toggle or stop that cannot take the lock within a
second now leaves a cancel marker and returns. The start checks it after the
picker, after the webcam overlay and while waiting on its recorder, then stops
that recorder and releases its audio. A recorder other than the portal's that
has not created its file after 15 seconds is stopped and the next backend
tried.
* Move automatic keyboard lighting to its own change
Ambient-light keyboard backlight is a new feature on every laptop with the
sensor, not something Apple hardware needs to run Omarchy, so it leaves this
change for a separate review. The keyboard-brightness command returns to
upstream's version, and first run no longer enables the user service.
* Move workspace refocus on monitor removal to its own change
Keeping the viewed workspace in front after a monitor is unplugged changes
desktop behaviour on every machine, not just Apple hardware, so it leaves
this change for a separate review.
* Move prebuilt-image hardware deferral to its own change
Building an image away from its machine needs a manifest the detector reads,
a queue of hardware steps for the first boot, a first-boot service and a
per-machine pacman keyring. An install on the machine itself needs none of
it, so it leaves this change for a separate review with an installer and
package boundary of its own. Hardware and user setup now run where they are
installed, and the platform setup operations take no image argument.
* Move the Qualcomm platform to its own change
Snapdragon support is separable from Apple compatibility, so the detector no
longer names a qualcomm platform: a "qcom," device tree is generic aarch64,
which Snapdragon already behaves as everywhere else here, and a tree naming
both Apple and Qualcomm is still refused. linux-firmware-qcom's platform list
leaves with it.
* Keep a cancel that arrives while a recording start finishes
A stop could land after the start's last cancel check, while it saved its
recording as started, and be dropped with the marker. The start now removes
its starting marker before a final check, a request reads that marker only
after leaving its own, and one that finds the start gone waits for the lock
and acts unless the start already used its request. A recorder ended by a
cancel or a readiness timeout gets two seconds after TERM before KILL, so a
recorder ignoring TERM cannot hold the start and its lock.
* Defer an image build's hardware setup to the machine's first boot
Brings back prebuilt-image support split out of #14431 so it gets its own review. An image built away from its machine names its target in a root-owned manifest the detector reads; hardware setup is queued for the machine's first boot, run there by omarchy-provision-hardware, which also makes the machine's own pacman keyring; and the platform setup operations learn they run on an image's first boot. Apple Silicon images built by the omarchy-mac installer need this; an install on the machine itself does not.
* Rebuild the initramfs when deferred setup changes module options
mkinitcpio's modconf hook copies /etc/modprobe.d into the initramfs, but the
deferred first-boot setup only compared mkinitcpio's configuration and the
kernel command line when deciding whether to rebuild. A step that only wrote
module options, as nvidia.sh does, left the old ones in the boot image.
* Put the Omarchy repository first on aarch64, as on x86_64
quattro now searches [omarchy] before the Arch repositories (
|
||
|
|
9d48fc402e |
Install gliff by default and show when a remote session is active (#14712)
* Install gliff by default Gliff is the Hyprland remote desktop over SSH. Ship it in the base package set for new installs, with a migration for existing ones. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Show a bar indicator while a gliff remote session is active The machine being controlled should make it obvious that someone is on it. A first-party remote-session service watches Hyprland's screencast events, which gliff-server triggers through ext-image-copy-capture, and probes for the server process, picking up the ssh client address from its environment. The RemoteSession indicator in the default tray lights up in the urgent colour while a session runs, and a notification announces each session start and end. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Address review of the remote session indicator Probe only the current user's gliff-server processes, forward refresh through the third-party service proxy so cloned indicator widgets can re-probe, exercise the Hyprland screencast event path in the service test with a grim capture instead of calling refresh by hand, and describe the indicator as status only in the manual. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Drop the remote session notifications The bar indicator is the signal; a toast on every connect and disconnect is noise on top of it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Tighten remote session detection after review Hyprland reports a screencast stopped as soon as frames pause for half a second and says nothing more when the server later exits, so poll every two seconds while a session is active instead of trusting a stop event. Match only the screencast event, not its screencastv2 twin, and debounce the burst around one transition so it costs one probe. Move the probe into its own script that the service and the test both run, poll for state in the service test instead of fixed delays, and drop the unused session count. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
988f44ea1a |
Delete extra themes from the theme picker (#14713)
* Delete extra themes from the theme picker Delete on an extra (user-installed) theme opens the shared faded confirmation dialog; confirming runs omarchy-theme-remove and selection lands on the theme before the deleted one. Stock themes and user overrides of them are not offered for deletion, apply/re-ask are blocked while a removal runs, and row refreshes queue so a deletion never leaves the list stale. * Fail closed on theme deletion until stock themes are known Keep Delete disabled until the stock listing finishes successfully, so a stock override cannot look deletable in the startup window. Also hold theme apply (and further delete asks) from removal exit until the refreshed rows load, so Enter cannot apply the just-deleted theme in the gap. |
||
|
|
fcf9eeb5c4 |
Show the image picker instantly, with no backdrop (#14709)
Remove the carousel's fade and geometry transitions, hold the reveal until every visible preview has decoded and two frames have pre-rendered (falling back to revealing anyway after 400ms), and drop the fullscreen scrim and its theme tokens so the picker sits directly on the desktop. Only Escape is accepted before the picker is visible. |
||
|
|
7f95505dec | Slow down the reveal effect a little on background changes | ||
|
|
be052339d8 |
Fix lopsided cursor highlight on network panel header actions (#8787)
* Fix lopsided cursor highlight on network panel header actions The QR and speed-test header buttons used raw Button components with asymmetric horizontal/vertical padding, producing a highlight box wider than tall around their near-square icons. Swap them for PanelActionButton, the canonical square inline-action component already used elsewhere in the kit (e.g. connectPwBtn), which sizes itself symmetrically around the icon. Fixes #8782 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Center icons in PanelActionButton on whole pixels A fractional size and anchors.centerIn put the glyph on half-pixel coordinates, so it rounded a pixel off the center of the fill: the speed-test icon sat low in the network header. Round the size, make it odd so odd-width glyphs get even margins, and place the icon on whole pixels. Co-authored-by: Fabian Behrendt <7931874+fabianbehrendt@users.noreply.github.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Fabian Behrendt <7931874+fabianbehrendt@users.noreply.github.com> |
||
|
|
c24889096e |
Add selectable Voxtype and Superwhisper dictation (#14552)
* Add selectable dictation backends * Move dictation migration after repository priority update * Extract backend-specific dictation installers * Keep dictation installer dispatcher executable * Call dictation backend installers directly * Drop legacy Superwhisper migration and runtime cleanup * Separate dictation defaults from generic recording protocol * Add backend-specific dictation removers * Preserve existing Voxtype selection during upgrade * Make dictation backend selection safe and retryable * Show the dictation indicator only for selected Voxtype * Allow switching away from stopped Superwhisper * Remove the built-in bar dictation indicator * Store default dictation selection under defaults * Rename dictation backend selector to use * Move dictation removers into their own menu category |
||
|
|
b83d3df084 | Qualify shell palette references for Qt 6.12 (#14553) | ||
|
|
902fd8aebd |
Play matching background intros at boot and on theme switches (#9639)
* Play matching theme background intros at boot * Add Tokyo Night sunset lake boot intro * Stage Tokyo Night boot intros on update * Add user controls for background boot intros * Optimize Tokyo Night boot intro videos * Add Tokyo Night cityscape boot intro * Add Ristretto boot intro videos * Add Solitude boot intro videos * Add White boot intro videos * Add Vantablack boot intro videos * Add Miasma nature boot intro * Add Matte Black boot intro videos * Add Lupine wave boot intro videos * Add Last Horizon blink boot intro * Add Everforest tree tops boot intro * Add Ethereal cosmic boot intro * Add four Retro 82 boot intros * Add Tokyo Night Quattro boot intro * Add Catppuccin Latte color fade boot intro * Add five Gruvbox boot intros * Expand Retro 82 boot intro coverage * Complete Ethereal boot intros * Complete Retro 82 boot intros * Stage boot intros for the active theme * Add Catppuccin boot intros * Complete Tokyo Night boot intros * Expand Lupine boot intros * Add Osaka Jade mountain boot intro * Prime boot intros before revealing wallpaper * Complete Osaka Jade boot intros * Keep kernel migration test valid after timestamp reuse * Shorten packaged boot intros to six seconds * Revert "Shorten packaged boot intros to six seconds" This reverts commit 5530403aa9e789b977a1a1a77ea7acf37a9e3598. * Document five to seven second intro target * Ease Matte Black intros into six seconds * Play boot intros through OWE instead of a shell player The merged desktop video path removes BackgroundVideo.qml and makes BackgroundMedia image-only. This keeps the intro feature by resolving the matching intro as before and playing it with 'owe intro', which owns the decode and the reveal. OWE 0.2.3 adds that command. The shell holds the theme color while resolving and cancels with 'owe intro-stop'. * Make boot intro startup atomic * Retry boot intro through login window * Document required OWE intro protocol * Add Last Horizon video boot intros * Play boot intros with released OWE Use `owe intro` instead of the unreleased intro-prepare/intro-commit protocol from omacom/owe#5. The boot is recorded before playback, and OWE's intro_result status decides whether a failed intro never started (release the boot for retry) or was interrupted (keep it consumed). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Replace Matte Black boot intros with shorter cuts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hide the still behind black until the boot intro starts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shorten the Everforest boot intro Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Document that boot intros should open dark Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Refine the Osaka Jade boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Skip compositor fades on the background layers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shorten the Catppuccin Latte boot intro Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shorten the Catppuccin boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shorten the White boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shorten the Vantablack boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shorten the Gruvbox boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shorten the Retro 82 boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shorten the Solitude boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Rework the Ristretto boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shorten the Tokyo Night boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Complete the Lupine boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Complete the Last Horizon boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Complete the Miasma boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the Nord boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the Rose Pine boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the Flexoki Light boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the Hackerman boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the Kanagawa boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the Lumon boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fade in the Last Horizon intros from black Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Animate the Catppuccin boot intros from their wallpapers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KAPp37DLjmKQy8GZr3vFvF * Animate the third White boot intro from its wallpaper Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KAPp37DLjmKQy8GZr3vFvF * Animate the Flexoki Light, Lumon and Rose Pine plants intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KAPp37DLjmKQy8GZr3vFvF * Shorten the Ethereal boot intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KAPp37DLjmKQy8GZr3vFvF * Animate the remaining placeholder intros from their wallpapers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KAPp37DLjmKQy8GZr3vFvF * Replace Catppuccin intros with themotion scenes Totoro moonrise, waves swelling from a line, and the blue eye tracing itself open, rendered by https://github.com/yamz8/themotion (scenes/catppuccin/*). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KAPp37DLjmKQy8GZr3vFvF * Re-encode Catppuccin intros with exact final frames Same motion; the settled frames are encoded at a fixed high quality so the handoff lands on the wallpaper (themotion 0c5e86c). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Replace Lumon intros with themotion scenes United in severance draws its lines and globe with a small pen-tip light; Opinions equally wakes inside the picture's own screen and types out the mark and tagline. Both keep the wallpaper's proportions, so the handoff holds its shape. Made with https://github.com/yamz8/themotion (scenes/lumon/*). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Land the Last Horizon intros exactly on their wallpapers Same footage and timing; the last 0.4 s now blends into the wallpaper as the shell draws it (libwebp decode, BT.709 limited range), with the settled frames at high quality. Re-finished with themotion fit (09f156e). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add Nord video boot intro for Night Hawks Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Replace Rose Pine intros with themotion scenes Funky shapes pop in on a jelly spring and the doodles draw on (replacing the reversed stock clip), the dot map spins in from a swelling dot, and the plants spring up before the OMARCHY letters drop in. Made with https://github.com/yamz8/themotion (scenes/rose-pine/*). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Replace Hackerman intros with themotion scenes The synthwave terrain unfolds as the sun rises and the valley glow flares into the floor; the geometric network bursts out from a triangle at its core and locks into place. Made with https://github.com/yamz8/themotion (scenes/hackerman/*). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Replace White 3-white with a themotion scene and land 1-2 exactly 3-white folds and slides its paper sheets into place along their diagonal (themotion scenes/white/3-white). 1-white and 2-white keep their footage and timing; their last 0.4 s now blend into the wallpaper as the shell draws it (themotion fit). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Replace Ristretto 0-1 with themotion scenes and land 2-3 exactly 0-launch lifts its stripes off and bends them into their curves, and 1-color-curves fans its colour bands in along their curves (themotion scenes/ristretto/*). 2-coffee-beans and 3-industrial-moon keep their footage and timing; their last 0.4 s now blend into the wallpaper as the shell draws it (themotion fit). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Replace Vantablack intros: new layer scenes, shared dot-hands cut 0-dot-hands uses the Matte Black cut, since both themes ship the same wallpaper. 1-twisted-stairs keeps its footage and lands exactly on the wallpaper (themotion fit). 2-layers-deep opens its depth front to back and 3-layers-stacked lays its papercut stack down sheet by sheet (themotion scenes/vantablack/*), replacing footage that opened on unrelated shapes and a plain fade-in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop the shockwave ring from the Totoro intro The moon now opens from its seed of light with only its halo; the thin ring racing outward read as clutter (themotion 6970484). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop the shockwave ring from the blue-eye intro The eye closes with its pulse and halo only (themotion, same change as Totoro's). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Land the earlier footage intros exactly on their wallpapers Everforest, Osaka Jade, Catppuccin Latte and two Matte Black intros were finished before the exact-ending tooling and ended 0.9-4 levels off their wallpapers (up to 134 on small spots). Their footage and timing are unchanged; the last 0.4 s now blend into the wallpaper as the shell draws it (themotion fit). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fade two Matte Black intros up from black ship-at-sea and dark-waters opened at brightness 17-20, so they popped in after the black cover. They now fade up over 0.3 s; the cuts and their exact endings are otherwise unchanged (themotion fit --fade-in). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop the Flexoki Light intro for now Its orb scene isn't good enough yet, so Flexoki Light starts on its still until a better intro is ready. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit bfe60d6c0a7a0983509a2dc2b295693bec2ceeb8) * Skip boot intros while animations are off A VM starts with animations off, and there Hyprland renders on the CPU, so a video intro costs the most. The launcher now consumes the boot without playing when Hyprland reports animations:enabled false, and the shell's cover check treats that, like the intros toggle, as nothing to wait for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add Miasma video boot intro for Crowned Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep boot intro startup outside the background service OWE destroys and recreates the background plugin during playback. Keep the launcher and black cover in the persistent shell host, consume the boot before waiting briefly for OWE, and start on the video's first frame. The startup check runs with a video background too, so enabling the still background service later cannot play an intro over an established desktop. Co-Authored-By: Codex Medium <codex@openai.com> * Release the boot marker lock before waiting for OWE The marker settles startup once it is written. Keeping the lock through readiness and playback makes a fresh shell wait for an older launcher before it can discover that the boot was consumed, leaving the still covered during that wait. * Keep the boot intro cover above native and cloned backgrounds Cloned backgrounds receive a scoped shell interface without the startup coordinator. Keep the input-transparent cover in the persistent host so every background stays hidden until OWE has a frame, without widening the plugin interface. Co-Authored-By: Codex Medium <codex@openai.com> * Map the startup cover only for an unsettled boot The cover must know the boot was already consumed before its first frame, so restarting the shell during playback leaves OWE visible. Snapshot the marker without watching subsequent writes: the launcher consumes this boot before the intro starts, while the cover remains needed until the first decoded frame. * Exercise automatic boot cover release in the clone test The fixture hid the cover itself before the fake launcher exited, so a broken exit handler still passed. Let the launcher finish before checking the actual background pixels and leave cover release to the service. Co-Authored-By: Greptile <165735046+greptile-apps[bot]@users.noreply.github.com> * Finish the Miasma, Kanagawa, Ethereal and Nord intros Start each intro on its scene instead of fading in from black, since OWE now starts intros on their first frame. - Miasma Crowned: ejuro's intro, shortened to 6.7 s and opening on the lit hand - Nord Night Hawks: ejuro's intro - Kanagawa: rendered in the wallpaper's own shape, so the handoff matches on 16:10 and 3:2 screens too - Ethereal, Nord and Miasma Crowned: 1080p endings that blend into the exact wallpaper, so the handoff no longer sharpens visibly Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Finish the Tokyo Night intros Start each intro on its scene instead of fading in from black, since OWE now starts intros on their first frame. - Winding Road: a new starry night to sunset with no added clouds or sun, ending on the wallpaper - Quattro: a new take where the car lands in the wallpaper's exact pose, colour-matched to the wallpaper - Oma Cityscape: drop the second, larger moon that faded out at the end - Quattro, Swirl Buck, Omakub and Oma Cityscape: 1080p endings that blend into the exact wallpaper, so the handoff no longer sharpens visibly Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pair background intros by filename and play them on theme switches Keep matching clips in backgrounds/intros so the selected image determines playback without registration, overrides, or checksum sidecars. Retain one global toggle and play automatically at boot and on a different theme selection. Launch theme playback after releasing the selection lock. Check the staged theme directory identity so an older launcher cannot play a newer selection when filenames are reused. Skipped or failed playback immediately hands the selected still to the shell, including new pixels behind an unchanged path. Synchronize the clone screenshot fixture with capture instead of a fixed launcher lifetime, while still requiring the real exit handler to release the cover. Co-Authored-By: Codex Medium <codex@openai.com> * Settle pending background colors when applying the current theme An intro applies its theme immediately while a previous still-image reveal may still hold an older palette. Replace and consume that pending palette through the background's existing handoff methods so its reveal or fallback timer cannot restore old colors. Reusing those methods also works with existing background clones. Publish the fake renderer's PID before announcing playback readiness, so the lock test cannot read an unwritten PID file. Regressions reproduce both failures on 7b238cf1 and pass with the fixes, including a deliberate scheduling delay at PID publication. Co-Authored-By: Greptile <165735046+greptile-apps[bot]@users.noreply.github.com> * Use the existing animations menu toggle for background intros Keep the separate intro command available without another Style menu control. Disabled animations already suppress playback at boot and on theme changes. Use remembered backgrounds with matching clips when testing suppressed theme intros, and require the normal still transition so the checks cannot pass merely because no clip was selected. Co-Authored-By: Codex Medium <codex@openai.com> * Finish the Lupine intros Start each intro on its scene instead of fading in from black, since OWE now starts intros on their first frame. - Cherry Blossom White: a new take that pulls back from fresh leaves to the whole tree, easing to a stop on the wallpaper - Pastel Clouds: drop the unrelated starry opening and its dip to black - Elegant Blue Wave: drop the empty white opening - Cherry Blossom Bokeh, Pastel Clouds, Elegant Blue Wave and Cherry Blossom White: 1080p endings that blend into the exact wallpaper Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JBE1V6gjrqn2aXCNNGhrUY * Synchronize theme intro and bar crossfades * Start theme intro fades from a cached first frame * Open theme intros on moving scenes * Start theme crossfades promptly * Prepare theme intros before switching * Finish the Catppuccin intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JBE1V6gjrqn2aXCNNGhrUY * Keep theme intro handoffs covered * Reload Hyprland after theme intro playback * Finish the Rose Pine intros Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JBE1V6gjrqn2aXCNNGhrUY * Restore the wallpaper early on each login * Keep the startup wallpaper cover transparent * Wait for readiness in the intro lifecycle test * Consume login intros for updates outside Hyprland * Fade login directly into the ready desktop intro * Sharpen Quattro, Swirl Buck and Oma Cityscape Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep compositor backgrounds black during login * Keep the shell visible through compositor shutdown * Bound the login cover when startup media fails * Encode the 1440p intros at H.264 level 5.1 At 2560x1440 the previous encodes used 16 reference frames, which puts them at level 6.0. Intel hardware decoding plays those with stray grey blocks. Four reference frames keep them at level 5.1, like the other intros. Swirl Buck's stag now changes colour as one silhouette instead of leaving a shrinking black disc on its head. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hide the startup cursor until the desktop fades in * Restore Swirl Buck's original stag The stag now changes colour exactly as in the original clip again; the previous edit made it jump from black to purple in one frame. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Initialize the startup cursor before the first compositor frame * Render the Hackerman intros at 1440p Both open on their first motion instead of fading in from black. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Render the Lumon intros at 1440p Both open on their first motion instead of fading in from black. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Sharpen the Lupine intros Upscaled from the original 720p clips and exported at 1440p with a gentler encode, keeping the same frames, timing and endings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Resolve login intros before the wallpaper daemon starts * Synchronize cold-start captures with the fixture phases * Sharpen the rest of the Tokyo Night intros Winding Road and Sunset Lake are regenerated natively at 1440p from their wallpapers, since their original clips were 360p and 720p. Omakub and Oma are redrawn from their wallpapers with the same motion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Bjarne Oeverli <1419214+bjarneo@users.noreply.github.com> Co-authored-by: Erik Johansson <172146456+ejuro@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Omarchy Bot <omarchybot@users.noreply.github.com> Co-authored-by: Codex Medium <codex@openai.com> Co-authored-by: Greptile <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: David Heinemeier Hansson <david@hey.com> |
||
|
|
0a55a3c554 |
Keep overlays sharp without parked surfaces (#14458)
* Keep overlays sharp without parked surfaces * Refresh overlay monitor scale after live changes * Reset menu layout when its monitor changes |
||
|
|
d9b970dd62 |
Let users choose passwordless sudo duration (#14435)
* Let users choose passwordless sudo duration * Warn in the menu bar when passwordless sudo is active * Fix sudo indicator hover behavior and repeated authentication * Disable passwordless sudo from the bar without a terminal * Shorten passwordless sudo indicator tooltip * Recover interrupted passwordless sudo duration switches * Allow sudo grant changes when listings require authentication * Start passwordless sudo setup with the duration question |
||
|
|
b6f2c1cef7 |
Describe the agents panel's limit rows and sign-in link as they are (#14430)
The manual still said the panel shows the percentage used and that an idle account keeps its last known limits, and the README that sign-in trouble is only text. Rows show the time to reset with the percentage on hover, and a lapsed sign-in is a Sign-in required link that signs the account in again. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b9e0ac4f1d |
Prevent clipboard capture hangs (#9488)
* Bound clipboard capture reads * Bound the watched clipboard read and drop copies cut off at the deadline In watch mode capture.sh reads the copy from the owner's pipe on stdin, to EOF, with no bound. An owner that stalls without closing its end keeps the callback alive, and wl-paste --watch handles no further clipboard events until it exits. That matches #9443, whose stuck capture.sh had no wl-paste child: --list-types never reads from the owner. Every read now goes through one bounded reader into a temporary file, and the copy is recorded only when the read finished, so a snapshot that stalls halfway no longer records its first half. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Omarchybot <317366263+omarchybot@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
5a0e7348af | Show Elsewhen remove button only on mouse hover | ||
|
|
ec76c070d2 | Give Elsewhen remove buttons a circular corner bubble (#14258) | ||
|
|
e86c8f1ab7 | Reveal indicators only before the clock (#14267) | ||
|
|
879d6583da |
Fix fingerprint enrollment and lock-screen recovery (#7158)
* Restart fprintd after resume to clear a claim wedged by suspend A fingerprint verify still open when the machine suspends leaves fprintd unable to hand the reader back: the verify dies with "Cannot run while suspended" and the follow-up ReleaseDevice fails on the still-busy device. The wedged claim then rejects every lock-screen attempt after resume until fprintd exits on its own 30-second idle timer -- and the retry loop keeps it from ever reaching that timer, so the reader stays dead until the user gives up and types a password. Install a system-sleep hook that restarts fprintd on resume, dropping the claim so the reader answers on the first touch. It is installed by omarchy-setup-security-fingerprint and removed by its teardown, so it is present exactly when a fingerprint reader is configured. try-restart is a no-op when fprintd is not running, so a healthy resume pays nothing. Approach suggested in #7229 and measured by @paracycle: 45 stray PAM sessions after resume down to 2. * Pace fingerprint retries and show when the reader is unavailable The lock screen retried fingerprint auth on a flat 250ms timer with no sign to the user, so a reader it could not reach -- a claim wedged across suspend, one held by another client, or a sensor gone from the bus -- spun PAM sessions at four per second behind an icon still inviting touches that could never unlock. Pace and report on one signal: whether an attempt reached the reader at all. pam_fprintd relays a finger prompt only once the claim lands, so an attempt that ends without prompting never reached the device. Those advance a streak that backs the retry off exponentially (to a ceiling above fprintd's 30s idle exit) and, past a few in a row, crosses out the icon and shows a "Fingerprint reader unavailable" notice. An attempt that did prompt proves the reader works -- a finger that merely did not match still reaches it -- so it clears the streak and the loop stays responsive. User presence (a keypress or touch) collapses a backed-off wait to a prompt retry, rate-limited so a moving cursor cannot respin the storm. An attempt that never reaches the reader within a few seconds is aborted and settled as unreached, so a claim orphaned by the resume restart surfaces the notice and retries a fresh daemon rather than hanging silently. The pacing, streak, nudge, and reach-timeout logic live in FingerprintModel.js with Node coverage; the new Text elements declare textFormat; lock status reports fingerprintUnavailable. The attempt state machine tracks the open attempt with fingerprintAuthenticating alone; the first settle closes it, and one PAM attempt raising both onError and onCompleted still folds into the streak exactly once. Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Install the fprintd resume hook root-owned and keep it with the PAM file cp -p carried the checkout's owner and mode into /usr/lib/systemd/system-sleep/, so under dev-link the root-executed hook was user-owned, and a tree whose exec bit had been stripped installed a hook that systemd-sleep silently never ran. Use install -Dm755 -o root -g root, as the migration that installs the same file already does. The hook also belongs exactly where the fingerprint PAM file does: omarchy-apply-lock creates and removes /etc/pam.d/omarchy-lock-fingerprint on its own, and any apply-lock run after enrollment left PAM without the hook while its removal branch left a hook behind without PAM. Have apply-lock install and remove the hook together with the PAM file, and teach apply-lock-test.sh to redirect the hook into its scratch tree and assert the hardened run lands it beside the PAM fixtures. Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Only treat fingerprint as configured when a print is enrolled The lock screen and omarchy-apply-lock decided fingerprint was set up with fprintd-list | grep -qi finger, which also matches "has no fingers enrolled" and "ListEnrolledFingers failed". A second account on a machine where one user enrolled, or anyone who ran fprintd-delete, was therefore handed the fingerprint loop: every attempt bailed before the claim, and with the new pacing that showed up as a crossed icon and "Fingerprint reader unavailable" for a reader the account simply has no print on. Match the per-print " - #N:" lines instead. apply-lock-test.sh follows: its fprintd-list stubs answer with a real enrolled-print row and its helper patcher matches the new probe line. Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Exercise the migration's default hook source in its test Every case overrode OMARCHY_FPRINTD_RESUME_SRC, so the path the migration really reads from was never checked, while its -f guard turns a missing source into a clean exit and a permanent per-user marker. Add a case that runs against the shipped hook under the repo, and adopt set -euo pipefail like the sibling tests. Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Take the fprintd restart off the thaw and bound its stop timeout The resume hook ran systemctl try-restart synchronously while user sessions were still frozen, so its cost landed on the wake path: half a second when fprintd answers SIGTERM, but a wedged fprintd on a stale device handle (the reader re-enumerated across the sleep) does not, and then the desktop stayed frozen for the whole stop timeout -- precisely in the case the hook exists for. Enqueue the restart with --no-block instead, as the unmount-fuse hook already does for the same reason, and ship a drop-in capping fprintd's TimeoutStopSec at 3s so the restart lands within seconds either way. The drop-in is numbered 10-stop-timeout.conf, as the other Omarchy system drop-ins are, so an administrator's override.conf sorts after it and wins. It is installed and removed wherever the hook is (setup, teardown, apply-lock, migration), and apply-lock-test.sh redirects it into its scratch tree alongside the hook. The hook's comments now say what actually happens on a locked resume -- Omarchy locks before every suspend and the lock screen opens a verify at once, so the restart is real, not a no-op -- and name the upstream defects this works around, fprintd#173 and fprintd#216, so the hook and the drop-in can be retired when upstream fixes them. Measured by MaxMad75 on an X390 Yoga (S3): 2 of 10 fprintd stops rode out the timeout to SIGKILL; the 3s cap verified with systemctl show. Co-authored-by: Omabot <omabot@omarchy.org> Co-authored-by: MaxMad75 <44462964+MaxMad75@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Codex XHigh <noreply@openai.com> Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Close the status-check and start-failure exits through settle Two paths left the fingerprint loop stuck or misreporting. A mid-lock status check that found fingerprint unconfigured aborted the PAM context directly; abort() delivers no signal, so fingerprintAuthenticating stayed true and every later attempt and nudge returned on it until the password unlock. And a fingerprintPam.start() that fails synchronously means the PAM file is gone -- a configuration problem, not a reader miss -- yet it fed the reader streak and reported "Fingerprint reader unavailable". Route the abort through settleFingerprintAttempt like the reach timeout does, drop the pending retry with it, and on a start failure re-check the configuration so the icon disappears instead; a pending retry owns the next attempt when a status check comes back configured. Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Pace fingerprint nudges by the pending tier and the cap's idle stretch The nudge cooldown was a flat 2s, shorter than every backoff step, so a user moving the mouse at a wedged reader collapsed each wait to 2s -- thirty claims a minute against the cap's 1.5 -- and each claim re-armed fprintd's 30s idle timer, so the hook-less recovery the cap exists for never happened while anyone was present. Grow the cooldown with the pending wait, so presence collapses each backed-off wait once and repeat nudges are paced by the tier. At the cap the wait itself is the cure -- it is what lets fprintd idle out and drop a wedged claim -- so there the idle stretch is measured from the last settle, not the last nudge: a nudged attempt that hung until the reach timeout would otherwise eat most of the window, and under continuous input fprintd would never be left alone long enough to exit. Wall-clock steps are handled in both directions: a clock stepped back past the last nudge does not hold a fresh nudge back, and one stepped back past the last settle counts as no idle time at the cap rather than as enough. The retry test drives continuous input against attempts that hang to the reach bound and checks the gap fprintd is left. Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Give a slow fingerprint claim time to land before aborting it The reach bound aborted any attempt that had not prompted within 5s by SIGKILLing the PAM child mid-Claim. A reader whose device open takes longer than that (out-of-tree drivers, and any reader right after the resume hook forces a re-open) could then never prompt: each kill left fprintd tearing the claim down until the open finished, the 1s retry hit "already claimed", and three misses later the reader was reported unavailable for good. Raise the bound to 20s, under GDBus's 25s Claim timeout and pam_fprintd's 30s verify timeout (whose "Verification timed out" is a non-error message that would read as reached), and name the hazard the bound actually covers: a daemon restarted under the verify fails the attempt promptly, a stuck device open does not. Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Detect resume and hold the streak through the restart window Monotonic timers pause across suspend, so a backed-off wait armed before the sleep picked up mid-count afterwards: with the streak at the cap the "Fingerprint reader unavailable" notice stayed up for the remaining wait after the resume hook had already freed the reader, and misses collected around the suspend edge carried across it, so a healthy reader could cross the notice threshold in the first seconds after waking. With the restart enqueued off the thaw, the loop's first attempts after a wake can also land on the old daemon while it is being stopped -- up to ~3s when it ignores SIGTERM -- and three of those would show the notice for a reader that was merely being restarted underneath. Notice a resume from any of three signals -- a sleep watch ticking the wall clock for the whole lock, a retry that fired late, or an unreached attempt whose settle finds the watch's last tick far in the past (so a suspend shorter than the reach bound is caught before the tick itself gets a chance to) -- and open a grace window: the stale streak is dropped, a pending wait retries the fresh daemon at once, and misses inside the window hold the streak at the first tier without ever counting toward the notice. Detection is idempotent within the window, since more than one timer can notice the same resume. Pinned by MaxMad75's reading: the window is armed by the resume, not by the first miss. Verified on his X390 (S3, frozen sessions): six lid-close cycles, fingerprint-resume at +15ms, streak held, notice never fired. Co-authored-by: MaxMad75 <44462964+MaxMad75@users.noreply.github.com> Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Only let a definitive probe change whether fingerprint is configured The status probe collapsed every fprintd-list result into yes or no, so an unreachable fprintd -- restarting under the resume hook, or failing a D-Bus activation mid-resume -- read as "not configured": the icon vanished, the retry loop and the sleep watch stopped, and nothing asked again for the rest of the lock. One transient miss killed fingerprint until the next lock, with the password as the only clue. MaxMad75 hit it on hardware in run 6 of the X390 series; osborng filed the stock repro as #9453 (mask fprintd, lock, unmask -- fingerprint never returns). Classify the probe's output instead: an enrolled-print row is yes, fprintd's explicit no-prints answer (or a missing PAM file or binary) is no, and anything else is unknown -- the probe could not tell, so nothing changes and it is retried on the attempt-retry pacing. The unavailable notice, backoff, and resume detection all sit downstream of this flag; now only an answer that actually means something can clear it. Fixes #9453. Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Log the fingerprint loop's misses, notice, and recovery as lock events The reach timeout, an unreached settle, the streak crossing into the notice, a resume restart, and the recovery all changed lock state without touching logEvent, so a report of "Fingerprint reader unavailable" left no omarchy lock line to line up with suspend and resume timestamps in omarchy-debug-idle output. Log those transitions; reached attempts are the steady state and stay quiet. A match that unlocks after a run of misses is the recovery too -- the unlock resets the streak without settling, so it logs fingerprint-recovered there as well. Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Abort an attempt stranded in flight when a resume is detected A verify that survived into the suspend still prompted comes back to a daemon the resume hook has already replaced, and the loop's resume handling deliberately left it alone: the reach timer stopped at the prompt, so nothing bounded it but pam_fprintd's own ~25s timeout, and until that ran out the icon invited touches that could not work. Most visible where user sessions are not frozen across sleep and the lock races the hook. Abort the stranded session when the resume is detected and route it through settle: it lands inside the grace window, so the kill never counts toward the notice, and the settle arms the fast retry against the fresh daemon itself. Suggested by sliekens in review. Claude-Session: https://claude.ai/code/session_0168egYTXrVBVg16ugszGzQt * Simplify fingerprint recovery and consolidate enrollment checks Use the enrolled-entry matcher from #9551 while retaining the lock's tri-state probe recovery and the privileged /usr/bin/fprintd-list call. Unknown enrollment probes must preserve existing PAM and resume recovery rather than deleting the machinery needed to recover. Preserve administrator-owned unnumbered timeout files during migration. Remove presence-driven retry overrides and their cooldown, clock, and idle-window state: resume has its own fast recovery path, while other errors can follow the bounded automatic backoff. Let the existing sleep watcher detect resume instead of also tracking the age of each retry. Setup now uses apply-lock so PAM and recovery installation have one implementation. Keep the restart, stop bound, unreachable-attempt pacing, unavailable feedback, reach watchdog, and probe rechecks because each handles a distinct failure. Co-Authored-By: Karl Ahlin <kalle.ahlin@gmail.com> Co-Authored-By: Codex Medium <noreply@openai.com> * Preserve failed-enrollment coverage in the setup fixture The successful-enrollment fixture accepts PAM commands, so failure checks must explicitly reject those commands instead of relying on an unexpected-command error. Log both sed and tee and stub apply-lock for every case so premature authentication setup is detected without reaching live PAM files. Co-Authored-By: Codex Medium <noreply@openai.com> * Complete fingerprint recovery and setup reporting Back off immediate device errors after the verification prompt as well as failed claims, while retaining fast retries for mismatches and normal scan timeouts. Measure from the prompt so a slow claim cannot hide a fast failure. Paced user activity retries preserve the daemon idle window required to clear a wedged claim. Initial probe outages remain visible without inventing enrollment, and setup cannot claim lock-screen success when the PAM configuration was not installed. Exercise the real QML service rather than a copy of its state machine. Co-Authored-By: GPT-6 <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 Medium <noreply@anthropic.com> * Avoid competing fingerprint probes and partial setup Known enrollment is recovered by the PAM retry loop, so failed status probes must not raise a false unavailable notice or interrupt its daemon idle window. Initial unknown enrollment still gets paced probes. Install recovery files before enabling fingerprint PAM so a missing source cannot leave a new partial configuration. Co-Authored-By: GPT-6 <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 Medium <noreply@anthropic.com> * Keep the fingerprint error clock at the first prompt pam_fprintd also sends Verification timed out as an informational message. Updating the prompt timestamp on that message made a normal full scan window look like an immediate device error and caused unnecessary backoff. Record the first prompt of each PAM attempt so later status messages cannot move the error window. Co-Authored-By: GPT-6 <noreply@openai.com> --------- Co-authored-by: Omabot <omabot@omarchy.org> Co-authored-by: MaxMad75 <44462964+MaxMad75@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Codex XHigh <noreply@openai.com> Co-authored-by: David Heinemeier Hansson <david@hey.com> Co-authored-by: Karl Ahlin <kalle.ahlin@gmail.com> Co-authored-by: Omarchy Bot <omarchybot@users.noreply.github.com> |
||
|
|
27a3feffc6 | Fix icon spacing | ||
|
|
454b67d95f |
Fix the bar startup stall and the shell restart race (#11015)
* Instantiate only the current orientation's indicator tree Indicators.qml built both the horizontal Row and the vertical Column and toggled them with `visible`, so every indicator existed twice per bar, and so did every process an indicator spawns: Dictation.qml ran two `voxtype status --follow` per monitor. On a six-monitor bar that is 72 indicator instances and twelve followers for six visible icons, and each instance registers a click target and re-syncs the active-indicator model as its state resolves at startup. A Loader now instantiates the tree that matches `root.vertical`. Each tree is wrapped in an Item that keeps the stock explicit implicit-size expressions, so the root's size still follows the blocks synchronously; a bare positioner only updates its implicit size on polish, which the indicator contract test's center-hover check catches. Measured on a six-monitor, 23-widget bar (three runs each, `omarchy restart shell`): time from "Configuration Loaded" to "polkit agent registered" 19.8-20.3s -> 15.5-15.7s, quickshell CPU 29-30s -> 24-25s, voxtype followers 12 -> 6. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Coalesce plugin API resyncs and key bar object ownership by target Every WidgetButton registers itself as a bar click target when it is created. registerClickTarget replaced the clickTargets array, the change handler ran syncAllPluginBarApiObjects() inline, and that walked every plugin API times every click target times a linear scan of pluginObjectOwners in pluginObjectRecord. Startup is a few hundred registrations, so the cost is quadratic in bar size and multiplied by the number of monitors: a six-monitor, 23-widget bar spent 16-20 seconds of pegged QML thread before it was populated, and an 8-second qmlprofiler capture showed 1.36 million pluginOwnsBarObject calls and 46-71ms per registration. - pluginObjectOwners is a Map keyed by target, so pluginObjectRecord, markPluginObject, unmarkPluginObject and releasePluginObjects are O(1) per object. Nothing outside Bar.qml read the array. - The activePopout, clickTargets and layoutConfig change handlers schedule one resync per event-loop turn through Qt.callLater, the way onModuleSlotsChanged already defers prunePluginBarApis. bindPluginBarApi still syncs a brand-new API inline, and requestPluginPopout and releasePluginPopout sync the owning API inline, so a plugin never reads a stale API on its own actions. - A flush serialises the layout once and hands each API its own parsed copy instead of deep-copying it once per API per sync. - ModuleSlot's cursorShape read clickTargets for every slot on every monitor (26,700 evaluations per start). It is now gated on the slot's HoverHandler, which is the only time the cursor is over it. Measured on the same bar, launching the shell from a checkout with this and the indicators change (two runs): "Configuration Loaded" to "polkit agent registered" 19.8-20.3s -> 0.70s, bar populated 1.7s after launch (from ~30s), quickshell CPU 29-30s -> 2.0s. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Wait for the old shell to exit before restarting it omarchy-restart-shell stopped the running shell with `quickshell kill` under a five-second timeout and launched the replacement as soon as the loop ended. A six-monitor bar takes 5.4-6.0 seconds to tear down (every widget button unregisters its click target on destruction, and each unregistration re-synced every plugin API), so the client timed out while the shell was still exiting, the fresh instance's no-duplicate check saw the dying one and quit, and the user was left with no bar and "Omarchy shell did not become ready after restart". Give the kill client thirty seconds, then wait, bounded, until `quickshell list` shows no instance of the session config before launching. The readiness check also waits on a sixty-second deadline instead of twenty attempts: a large bar answers ping only after its plugins have loaded, which on the stock bar was well past the old twelve-second window. Verified three consecutive restarts against the stock shell on the six-monitor machine: each returned 0 in about six seconds with exactly one instance and no "already running" in the journal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Say what the bar's ownership Map actually saves Qt's V4 Map (ESTable::get) finds a key by scanning its keys, so ownership lookups are not O(1). The win is that a registration no longer copies the owner array and rescans it in QML. Co-Authored-By: Codex Medium <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: Omarchybot <317366263+omarchybot@users.noreply.github.com> Co-authored-by: Codex Medium <noreply@openai.com> |
||
|
|
2b2d462652 |
Merge pull request #13725 from houz42/fix/monitor-panel-display-toggle
Fix Display panel display toggle using rejected hyprctl keyword |
||
|
|
00cee6d319 |
Merge pull request #7806 from berndb/lock-ignore-autorepeat
Drop key auto-repeat in the lock screen password field |
||
|
|
7901d7d0b6 |
Merge pull request #12538 from paulogeyer/fix/10860-idle-timeout-zero
Treat idle timeout 0 as disabled, not immediate |
||
|
|
4a568a1388 |
Merge pull request #14225 from omacom/fix/agents-usage-display
Fix agent usage resets, stale display, and icon underline alignment |
||
|
|
7f91a8d49e | Show recovery guidance when paused usage has no cache | ||
|
|
6809987892 | Align panel underlines with native bar icons | ||
|
|
d21e5810b1 | Reset elapsed agent usage and show stale ages on hover | ||
|
|
5c4da02146 |
Merge pull request #7783 from omacom/fix/issue-6952
Keep PwNode objects out of the audio panel's Repeater models |
||
|
|
18328559b9 |
Keep the Wi-Fi icon steady on OWE transition-mode networks (#14133)
* Keep the Wi-Fi icon steady on OWE transition-mode networks An OWE transition-mode network pairs an open SSID with a hidden "_owetm_" twin on the same BSSID. Between scans NetworkManager reports the in-use access point under the hidden SSID and drops the active profile from the device's AvailableConnections, which is the only place Quickshell builds known networks from. No listed network is then connected, so the bar fell back to the disconnected icon until the next scan brought the open SSID back, flickering on and off while the link stayed up. Fall back to the Wi-Fi device's own connected state when no listed network is connected, and read the in-use access point's strength from nmcli (without a rescan) while the connected network has none of its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Discard stale in-use AP reads and key Wi-Fi checks on the device Bump a generation whenever the cached in-use access point strength stops describing the link (leaving Wi-Fi or a device change), and drop any nmcli read started before it, re-reading immediately instead of a full interval later. Key Wi-Fi connectivity checks on the device rather than the SSID, so the listed network coming and going with each scan on an OWE transition-mode network no longer schedules a check. A real network switch still passes through "disconnected". Add a QML fixture that runs the panel against a mocked device through the scan churn, a mid-read disconnect, and a final disconnect. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
e5663c7e3a | Keep image picker previews sharp on HiDPI displays | ||
|
|
e0b0f349f8 |
Escape the output name in the Display panel's hl.monitor eval
Hyprland lets a headless output take any name (`hyprctl output create headless <name>`), so a name with a quote broke out of the Lua string and the toggle failed for that output. Escape backslashes and quotes instead of asserting a character set the names do not actually follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Codex Medium <noreply@openai.com> |
||
|
|
a8e09b9ce2 | Keep refreshed image picker selection inside the active filter | ||
|
|
2ba1015ef2 | Keep image picker work bounded for large theme collections | ||
|
|
0537ae121b |
Merge pull request #11925 from joewinke/fix/plugin-thirdparty-sourcedir
fix(shell): keep __sourceDir on third-party plugin manifests |
||
|
+14 |
75250d37ac |
Fix Codex limits, Claude counting, and agent usage reliability from community PRs (#14049)
* Read Codex app-server replies from the raw fd (#13703) * Resolve Codex through mise which instead of running the lazy launcher (#13109) * Skip the Codex app-server probe when there are no credentials (#13106) Adapted: credentials are checked in the home being probed rather than in the CODEX_HOME environment variable, since each registered account is probed in its own home, so a signed-out secondary account isn't hidden behind the primary's login. A home without credentials reports "Waiting for auth" like any other signed-out home. The credentials store setting is read with tomllib, so a single-quoted value counts too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show the Codex CLI's own error when its app-server dies (#8977) Detect an app-server that exits or stops answering, and report the end of its stderr instead of a bare RPC method name. Rebased onto the raw-fd reply reader; the switch from "-a on-request" to "-a never" is left out, keeping the current approval flags. * Count pi sessions when HOME is a git checkout (#13209) * Count only OpenAI-backed native sessions as Codex usage (#12032) * Deduplicate Pi usage across forked sessions (#8602) * Skip unchanged native Codex token snapshots (#10531) * Count omp and pi profile sessions in the agent usage collectors (#9546) `omp --profile=<name>` (and pi's equivalent) relocates the whole agent tree under <base>/profiles/<name>/. The Claude and Codex collectors only ever scanned <base>/agent/sessions, so a subscription driven entirely through a profile was invisible to the agents panel: no tokens by day, no tokens by model, no prompt or session counts. Discover the profile roots alongside the default one. Sessions are keyed by file path, so a profile adds sessions instead of double-counting the default root, and a missing or unreadable profiles directory leaves the existing behavior untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014zFbJcDEEpV5BAmsH6kAB3 * Skip unrelated Codex session lines before JSON parsing (#12803) Adapted: session_meta lines also pass the pre-filter, since the provider filter from #12032 reads them to skip rollouts served by a non-OpenAI provider. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Read only the Codex session files that changed since the last scan (#12595) Native Codex rollouts keep per-file totals between runs, replayed while a file's mtime and size are unchanged. Rebased onto the session_meta provider filter, snapshot dedup, and line pre-filter, which now live in the per-file reader. pi and omp sessions are left out of the per-file cache: a forked pi session repeats its parent's messages, so they are deduplicated across the whole tree on every scan. * Count streamed Claude messages by their highest-output usage line (#10606) Claude Code writes a streamed assistant response as several transcript lines that share one message id, one per content block. Each line carries a usage object. The first line's output_tokens is a placeholder, often 1, and the last line has the real count. Input and cache fields usually match across the lines. The scanner dedupes by message id and keeps the first line it sees, so it under-counts output tokens. On a machine with 2,577 transcripts it reported 39.0M output tokens against 60.1M used, a 35% shortfall. Input and both cache fields differed by under 0.01%. Keep the line with the highest output count, with the last one scanned winning a tie. The whole line is kept because a response can fall back to another model mid-stream. Those lines are separate snapshots with different cache figures and a different model, and taking a maximum per field across them over-counts cache tokens and credits the wrong model. The zero-usage check now runs before dedup, so a zero-usage first line no longer claims a message id and hides a later line with real usage. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: GPT-6 Astra <noreply@openai.com> * Index Claude transcripts so the agents refresh reads only what was appended (#8313) omarchy-agent-usage-claude re-parsed every line of every transcript under ~/.claude/projects on each refresh: no mtime cutoff, no memory of the last pass. The agents widget is on by default and ticks every 15 minutes, so the cost grew for the life of the machine. After one month here that was 803 files, 640 MB, 127k lines and 57k JSON parses per tick, about 1 core-second, pushed through the page cache every quarter hour forever. Keep a per-file index next to the scan cache: the unique usage records already parsed out of each transcript and the byte offset they end at. A file whose size and mtime match is not opened; a file that grew is read from the stored offset; a file that shrank or was rewritten is read from the start. --force drops the index and rescans from scratch. The summary is built from the indexed records in the same directory order the walk always used. That matters: when a resumed session carries earlier messages, the same message id appears in two files with different usage, and the first file visited wins. 91 ids differed on this machine; sorting the walk moved one model's output total by 25k tokens. Output is now byte-identical to the previous scan on a frozen copy of the corpus, cold, warm, and after an append. Warm refresh: 1.0 s -> 0.10 s of CPU, of which the scan itself is 70 ms; the index for this corpus is 2.9 MB. Adapted: - Rebased onto #10606: the highest-output rule for streamed messages now lives where the index parses records, and decides between files too. - The index records the timezone it was written in, and a change rereads every transcript, since its records hold local days. - A file only counts as appended to when its inode and the hash of what was already read still match, so a transcript replaced by a larger one, or rewritten in place, is read from the start. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Label a Claude Team seat by its subscription, not its rate-limit tier (#11109) The collector built the plan label from the OAuth rateLimitTier first, so a Team premium seat, which runs on default_claude_max_5x, showed in the agents panel as "Max 5x". Lead with subscriptionType and keep the multiplier as its qualifier: Max still reads "Max 5x", a Team seat reads "Team 5x". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Label the Claude plan from the profile the CLI refreshes (#7225) Adapted: the profile is found the same way current_account_id() finds it, now shared as profile_path(): ~/.claude.json for the default home, the home's own .claude.json otherwise. The original fell back to ~/.claude.json for any home without CLAUDE_CONFIG_DIR set, so a secondary account read the primary's tier. The profile's tier also keeps the subscription in the label, so a Team seat stays "Team" (#11109). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Call a lapsed Claude access token paused, not signed out (#8093) * Refresh Claude usage after the clock moves backwards (#9956) * Bound unreadable Claude transcript warnings (#12414) * Count Claude usage from opencode v2 sessions (#13894) * Reload agent usage records when an inotify watch fails to rearm (#10067) * Reload agent usage records after each update run instead of on a timer Rather than #10067's two-minute timer per record, reload every record when the omarchy-agent-usage-update process exits, the moment its files can have been replaced. A reload that finds a file unchanged keeps its record, so the panel isn't stirred up by identical data. The grep test now runs the QML functions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show the agent status when the trouble line has no help text (#8497) * Clear stale agent login guidance after a successful probe (#8892) * Clear the Grok login hint after a successful probe #8892 cleared the default login hint after a successful probe in the Claude and Codex collectors; Grok's collector had the same stale hint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Read Fireworks credentials from pi's auth.json (#7455) The Fireworks collector skipped pi, Omarchy's default agent, when walking its credential ladder, so a machine signed in to Fireworks only through pi (/login fireworks) never showed the tab. Insert the key pi stores in $PI_CODING_AGENT_DIR/auth.json (default ~/.pi/agent) between the firectl auth.ini and the opencode fallback. pi keys can be literals, $ENV_VAR/${ENV_VAR} references, or !command shell lookups. The collector resolves the first two; command lookups stay pi-only and are skipped rather than sent to the API verbatim. * Call a lapsed Grok access token paused, not signed out Grok's access token lives six hours and Grok mints a new one from its refresh token whenever it starts, so a lapsed one is routine. Reporting it as an expired sign-in made the panel offer Sign-in required several times a day, sending people through grok login for nothing. With a refresh token present it now reads as paused, like Claude's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep showing Grok's last limits while it sits idle While Grok hasn't run, nothing on the machine has spent its allowance, so with a refresh token on hand the last numbers still stand: they show as current rather than dimmed under a status line. A weekly window that reset in the meantime starts over at 0%, a whole number of weeks on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Ask for a Grok sign-in once its refresh token is past 30 days A refresh token older than Grok's 30-day sign-in can't renew anything, so the panel offers Sign-in required again instead of showing the last limits as current. With nothing cached yet it says to start Grok, rather than showing an empty section without a word. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Check both ends of what the Claude index read before resuming a transcript A transcript rewritten in place could grow and change only after its first kilobytes, and the index took it for an append. It now compares the last kilobytes before the resume point too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Simplify the agent usage collectors - Codex: pass the forced-scan choice down instead of a module global, make the per-file reader's cache arguments required, shrink the cache record check, and drop guards for shapes that can't occur: an empty launcher path, realpath raising, mise itself being a lazy launcher, multi-line `mise which` output, and probing without a temp file for stderr. - Claude: decide an append by the digest of both ends of what was read alone; the inode and mtime checks it made redundant are gone. - Snapshot: the device id falls back to the hostname, which always exists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Share fixture setup in the agent usage scanner tests Every fixture home lives under one scratch directory with a single cleanup trap, instead of a trap rewritten with a longer list for each new home, and the Codex test builds its signed-in homes with one helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Treat a replaced Claude transcript as new even when its ends match Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Probe Codex without its error text when there's no temporary space Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: tossbaws <17258053+tossbaws@users.noreply.github.com> Co-authored-by: surim0n <suritech@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: anonwurcod <anonwurcod@proton.me> Co-authored-by: Kevin Rajan <7121943+kvnloo@users.noreply.github.com> Co-authored-by: Nate Ashby <nate.ashby11@gmail.com> Co-authored-by: Aris Gysel <aris.gysel@me.com> Co-authored-by: Brams <76213579+Brams-s@users.noreply.github.com> Co-authored-by: This_Is_NPC <gabrielfollone27@gmail.com> Co-authored-by: sanjyay <102979855+sanjyay@users.noreply.github.com> Co-authored-by: PapistProtocol <12738904+PapistProtocol@users.noreply.github.com> Co-authored-by: steez <stevedimakos97@gmail.com> Co-authored-by: GPT-6 Astra <noreply@openai.com> Co-authored-by: Ryan Yogan <ryanyogan@gmail.com> Co-authored-by: Oli Denton <41393837+omdenton@users.noreply.github.com> Co-authored-by: Igor Kramar <i@ikramar.ru> Co-authored-by: Martin Eidensten <martin@meibe.se> Co-authored-by: Romain Perron <rdj.perron@gmail.com> Co-authored-by: Omarchy Contributor <contributor@users.noreply.github.com> Co-authored-by: manuaudio <manu@arimaka.com> Co-authored-by: Tyler South <tsouth2@gmail.com> Co-authored-by: whathek <Hek846@users.noreply.github.com> Co-authored-by: Ty Richards <me@tyrichards.com> |
||
|
|
821ae58905 |
Reorder the agents in the panel, count Grok's tokens, and install Grok through mise (#14004)
* Let the agents in the panel be put in any order Drag an agent by its mark to move its section; the header it will land on lights up, and the move happens on release. Each agent's header is now a keyboard stop with its own highlight, and Ctrl+Up/Down moves the agent the cursor is in. The order is kept in agents/order.json beside the usage records. The key catcher turns Ctrl+Up/Down into a reorder only for panels that opt in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Light only an agent's mark when the cursor or a drag is on it The mark is the handle the agent moves by, so the keyboard cursor and the drop spot while dragging box it alone rather than the header line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep a lit agent mark's box from being clipped at the panel's edge The box overhangs the content's left edge, which the scrolling area clipped. The scrolling area now reaches a little into the panel's padding with the content shifted back, so nothing moves and the box draws whole. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Reuse a Grok session scan only on the day it was made A limits-only refresh just after midnight reused a scan from the evening before, which counted yesterday's sessions as today's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep Ctrl+Up/Down from moving an agent when the cursor is outside one The hero's buttons and the starter tiles carry indices too, and the lookup read them as accounts, so with several accounts Ctrl+Up/Down on one of them moved an unrelated agent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Report a failed mise update even after the Grok upkeep runs The Grok block ran after `mise up` and its last command set the script's status, so a failed tool update could read as a success to callers that warn about it. The update's own status is now the script's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Unpack a Grok update into ~/.grok whatever GROK_HOME says The upkeep replaces ~/.grok's link, but the npm launcher unpacks into GROK_HOME when it's set, so with a custom home the link never came back at the new release and the old one was restored. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hold off reordering agents while an account name is being edited Ctrl+Up/Down reached the key catcher during an inline rename, and moving the agent rebuilt its section, dropping the unfinished name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Install Grok through mise's first-party package The npm launcher keeps an old ~/.grok/bin binary because mise skips its postinstall. Use mise's grok tool, and drop the npm tool so its shim does not stay ahead of the stub. * Drop the npm Grok workarounds now that mise installs Grok itself With Grok installed through mise's first-party package, the CLI is the binary mise manages, so the update upkeep that repointed ~/.grok/bin and the shared bin directory for added Grok accounts have nothing left to do. omarchy-update-mise is back to running mise up and nothing else, and adding a first Grok account installs the same package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count Grok's tokens and prompts from its usage ledger Each Grok session keeps a usage.json, the ledger `grok usage` prints, with every finished turn's end time and tokens by model. The collector now reads it for tokens today, by day for the last week, and by model, with cached input kept apart, and counts today's prompts by the turns that ended today. Found in #12352's research. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count cache writes in Grok's daily token totals Grok's totalTokens leaves cache writes out while the per-model buckets count them, so a turn with cache writes added less to its day than to its model. The day's total is now the sum of those same buckets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Remove the npm launcher's old Grok binaries when moving to mise's Grok Omarchy's npm wrapper ran the binary the launcher unpacked into ~/.grok/bin, where x.ai's installer also puts a copy with a PATH entry ahead of mise. Once the wrapper is replaced, a binary left there would keep shadowing the mise tool, so the migration removes it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Jesse Miller <jmiller@jmiller.com> |
||
|
|
f45461a38f |
Bring Grok up to par with Claude and Codex in the agents panel (#13992)
* Let Grok updates through mise take effect Grok's npm launcher runs ~/.grok/bin/grok whenever it exists, and the install script that repoints it at a new release doesn't run under mise, so every machine kept running the release it first unpacked. Updating mise tools now drops a link to an older release and the old binary, and lets the launcher unpack the installed one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep several Grok accounts, the way Claude and Codex do Grok honors GROK_HOME, so an added Grok account gets its own home holding only its login and settings cache, with the CLI binary, sessions, skills, plugins, memory, and config linked back to ~/.grok. The account commands, the add flow (a second account signs in through a private window), the launcher, and a grok shell function all take it like the others, and its identity and plan come from the files Grok writes at login. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show Grok's plan and credits in the agents panel A grok collector reads each account's plan from the settings Grok caches and its credits from the endpoint behind Grok's own /usage view, so Grok gets a section, per-account limits, and autoswitch like Claude and Codex. A signed-in agent with a plan now shows before its first numbers, so a lapsed sign-in has somewhere to say so. Grok's mark joins the assets, and with every agent able to take another account the add screen no longer needs to dim one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Document Grok accounts and limits alongside Claude and Codex Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Read Grok's credits the way xAI actually answers The answer nests under config, names a weekly period with its end, and as protobuf JSON leaves the usage percentage out while it's zero. The collector now reads that shape, so a fresh week shows as 0% until it resets rather than as nothing known. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count Grok's prompts and sessions from its session summaries Grok keeps a summary beside each session with when it was last active and how many prompts it had, so its section and the hero's summary get today's prompts and sessions and its active days. It records no token counts there, so none are claimed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Give each Grok limits cache write its own temporary file Two overlapping collector runs wrote the same cache through one .tmp path, so one rename could leave the other's failing and its record not updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Read a single Grok account from GROK_HOME when it's set The launcher and the CLI honor GROK_HOME, but the collector always read ~/.grok, so a Grok signed in only in a custom home showed nothing. With one account, the collector now reads the home the CLI would; with several registered, the primary stays ~/.grok. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop guesses the real Grok credits answer made unnecessary The collector carried fallbacks for fields and shapes guessed from the binary before xAI's actual answer was seen, a numeric timestamp branch nothing writes, the panel's default for prompt stats, and guards that an empty sign-in already covers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the working Grok release until its update is in place The update dropped the link and older binaries before the new release was unpacked and ignored a failed unpack, which could leave every Grok account without a CLI. The old release now stays until the new one is linked, and its link comes back if it never is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count only Grok sessions for today, not prompts A session's summary holds all its prompts and only when it was last active, so a resumed session put its whole history on today. Today now counts the sessions active in it; prompts stay an all-time total. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Reuse the Grok session scan on a limits-only refresh Opening the panel and near-limit checks only need fresh limits, so they reuse a scan up to 15 minutes old, as the Codex collector does; --force still rescans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c05d90196f |
Switch between several Claude and Codex subscriptions, and build apps the Omarchy way (#13770)
* Plan multiple Claude and Codex accounts with manual or automatic switching Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep several Claude and Codex accounts and start new sessions as the active one Each added account gets its own home holding only its login, with history, settings and skills linked back to ~/.claude or ~/.codex so --continue works across a switch. Accounts are added through the CLI's own login, and cx, cy, plain claude/codex and omarchy-agent all start as the active account unless CLAUDE_CONFIG_DIR or CODEX_HOME is already set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Report limits for every Claude and Codex account in the usage records Each registered account is probed with its own sign-in and cached on its own, and a parked account whose sign-in lapsed keeps its last-known numbers marked stale. The record's top-level limits keep describing the active account. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Switch accounts automatically near a limit, or notify with a one-click switch After each usage update, an active account at or over its provider's threshold (95% by default) moves new sessions to the account with the most headroom in auto mode, or offers that switch as a notification in manual mode. It never flaps back to an account that just reset, and says once when every account is over. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show every subscription account's limits in the agents panel With several Claude or Codex accounts, the limits become one card per account with the active one badged. Pick a card with its number and press Enter (or click Use) to move new sessions to it, press a to add an account, and m to toggle automatic switching. Limits refresh every minute while an active account is above 80%. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add Setup > Agent Accounts to list, switch and add Claude and Codex accounts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Document switching between several Claude and Codex subscriptions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count a rested parked account as available, and pin Main to its own home A parked Claude account whose windows all reset now reads as 0% instead of unknown, so switching can pick it. Main's Codex limits come from ~/.codex even when CODEX_HOME is set, and duplicate logins are checked against who each home is signed in as now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Key limits caches by subscription and report when an account truly frees up An added account's limits cache follows its account id, so a new account reusing a removed one's label never inherits its allowance. The all-accounts notice now names when an account's blocking windows have all reset, not the earliest reset of any window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep account ids clear of routing keywords and refresh the panel after removal Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Share Codex plugins and hooks across accounts, and key Claude caches by current sign-in Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop the key hint from the Add account button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Sign new agent accounts in through a private browser window The main browser is almost certainly signed in to the account you already have, and the login would silently reuse it. Both CLIs open their login page through $BROWSER, so it now points at omarchy-launch-browser --private. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Let agent account commands default to your default agent's provider With Claude or Codex as the default agent, the provider can be left out: omarchy agent account use work, and primary names the primary account. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop the primary alias, which shadowed an account named Primary Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Replace the auto switch button with a small Notify / Autoswitch toggle Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add accounts from a small + beside the switch toggle Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix the punctuation of the switch toggle's README line Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop the border around the add account + Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Rename Claude and Codex accounts without moving their homes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Lay out agent accounts on accent rails instead of boxed cards The active account gets an accent rail and the others a quiet one, each window is a single compact line, and the switch toggle, add, and Use are text. Clicking an account's name renames it in place. A window without a reset time no longer leaves an empty line, and last-known numbers are only red when the sign-in needs attention. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Read Codex limits without waiting on account/read Codex 0.158's app-server can leave account/read unanswered, and asking it first lost the limits whenever it did, leaving the agents panel showing "Codex limits unavailable". The limits name the plan themselves, so they're asked first and account/read is only a short fallback when they don't. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Switch agent providers from their marks in the panel header The row of provider buttons gives way to a small mark per provider in the hero's corner, the selected one at full strength, with the add account + beside them in place of the + by the switch toggle and the full-width Add account button. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the agents panel's scrollbar off its contents The panel's content narrows to leave the scrollbar its own strip whenever it scrolls, and the add account + leads the provider marks instead of sitting at the very edge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add Claude, Codex, or Grok subscriptions from one Add Account menu The first account for a provider installs its CLI if needed and signs in to the CLI's own home through the normal browser; only additional accounts get a home of their own and a private window. Grok signs in its first account. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Reveal Autoswitch beside Use instead of a Notify / Autoswitch row The panel's + now opens the Add Account menu for any provider. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Split agent accounts with plain separators instead of rails ACTIVE already marks the account new sessions use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Only call Claude limits stale once they're old, and poll near a limit less Anthropic rate-limits its usage endpoint, and polling two accounts every minute near a limit got every re-check refused, so both accounts read "Last known" with numbers a minute old. A refused check of numbers under 15 minutes old now counts as current, older ones say how old they are, and near-limit polling is every three minutes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show every agent's limits on one page under an Agents hero The panel stops switching between one provider at a time and lists every agent and account with its limits, dropping the tokens-by-day and by-model charts. The hero carries the agents robot and rotates through what the token counts add up to: tokens this week and today, the most used model, the busiest day, and today's prompts and sessions. Middle-clicking the bar icon refreshes, since there's no provider left to advance to. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Report Codex's free rate-limit resets in its usage record Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Give the agents panel more room, and show Codex's free resets Limit lines are a notch larger with more space between them, each account's limits sit a clear step below its name, and sections breathe. Codex has one limit on Pro, so its section now also says how many free full resets are waiting and when the next one lapses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Mark Claude's Fable limit on the Weekly meter instead of its own row A model-scoped allowance on the same clock as a base window is drawn as a tick on that window's meter and named in the row's tooltip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Let omarchy-default-agent set the default without launching it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Let the agents panel drive adding an account without a terminal --check says whether adding one now would be each provider's first sign-in or an additional account, and --events reports progress as tagged lines alongside the CLI's own output, notifies with the result, and cleans up the login and its scratch home when cancelled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add subscriptions and pick the default agent right in the agents panel The + is a proper accent button, and it swaps the list for a picker of Claude, Codex, and Grok that signs in without a terminal: name a further account, then follow the sign-in with its status, Grok's confirmation code, a field for Claude's pasted code, and a link to reopen the page. A dropdown at the bottom sets the default agent without launching it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Draw the Fable tick in its meter's own color Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Revert "Let omarchy-default-agent set the default without launching it" This reverts commit da96261f7d26bb76774cbdc1cb9e0abde92bb841. * Make the first agent signed in the default when none is picked Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the agents panel in the bar, with setup, starters, and adding in it A machine with no agent opens the panel on setting one up. Once set up, the list ends with starter prompts for a new theme, plugin, or app, and a quiet Add a subscription. The panel no longer sets the default agent, and the hero drops its add button. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Offer the starter prompts as tiles, and adding as a row beneath them Theme, Plugin, and App each get a tile with its glyph, and Add a subscription a matching row with the + in a tinted square. The panel is allowed to grow tall enough to show it all without scrolling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Put the tinted add button in the agents panel's hero corner Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show when a limit resets in small type under its meter The percentage keeps the right edge to itself, so the meter runs longer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Revert "Show when a limit resets in small type under its meter" This reverts commit 108d9de59da1af12cddbf232b0b5333ad8994c64. * Put each account's plan beside its name, and its email in a tooltip Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Stack each limit's percentage over its time left, so the meter runs longer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show only each limit's time left, with the exact percentage on hover The meter already says how full a window is. Dropping the percentage beside it leaves one calm figure per row, and the row's tooltip carries the number. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Sign an existing account in again with omarchy-agent-account-add --reauth It signs in where the account already lives: the CLI's own home (:primary) through the normal browser, an added one through a private window. The usage records now say which account is the primary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Offer Sign-in required in the agents panel instead of how old the numbers are A lapsed sign-in shows as a link that signs that account in again right in the panel. The "as of" and "last known" notes are gone; trouble that isn't about signing in still shows as text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the separator dot out of the Sign-in required link Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop the Setup > Agent Accounts menu and the stale plan The agents panel now lists, switches, and adds accounts, so the menu's duplicate of it goes, and the plan written before the design settled no longer describes it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Install the compiler and Qt pieces for building Omarchy-style apps base-devel plus qt6-base, qt6-declarative, qt6-multimedia, and qt6-wayland, which is what Hype, Monologue, and Omacut build with through qmake6 and make. Qt was only there as a dependency of those apps, and the compiler not at all. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add an omarchy-app agent skill for building apps the Omarchy way It teaches how Hype, Monologue, and Omacut are built: C++ and Qt Quick in one flat project, qmake6 and make into a single binary, a theme that follows Omarchy's accent live, portal dialogs, keyboard-first conventions, Qt Test offscreen, and a PKGBUILD that puts the app in the launcher, with starter files that build and pass their tests as written. The agents panel's App starter uses it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Link the omarchy-app skill on existing installs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Let Cancel stop a waiting login, and list a lone account's limits Bash holds a trap until the foreground command finishes, so a login waiting on the browser outlived Cancel. It now runs behind an interruptible wait. With one account the usage record keeps its limits at the top level, which omarchy agent account list now reads for the primary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Re-read identity even when signed out, and count Grok as set up A home whose login is gone no longer keeps the identity the registry saved, so it reads as signed out and can be added again. The agents panel leaves its setup screen once any agent is signed in, not only once one has usage to show, since Grok has no usage collector. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Save each account's current identity before collecting usage A home signed in to someone else since it was added kept the old email in the registry, which the usage records name accounts by. The usage update now refreshes the registry from each home first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Offer Claude's paste field from the start, and keep providers with accounts Claude's login prompts for a pasted code without a newline, so the panel's line reader never saw it; the field is simply there for Claude sign-ins. A provider with accounts stays listed even when the active one's limits are unavailable, so its other accounts can still be switched to. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Never autoswitch to a signed-out account, and report Codex's missing sign-in An account nobody is signed in to is left out of switching, however much room its cached numbers show. Codex answers a home without a login with an error, which now reads as Waiting for auth, so the panel offers Sign-in required for Codex accounts too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Link shared files before they exist, and only call every account over when it is A shared file the primary home didn't have yet was left unlinked, so an added account made its own copy and the two diverged for good; it's linked up front now, and written in the primary home by whichever account writes it first. The all-accounts-over notice waits until every account's limits are actually known. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Make the agent starter tiles compact and call the section Make something cool Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hold the agents hero line until its next fade Every usage record that landed rebuilt the summary phrases, and the hero indexed that live list, so opening the panel could swap the line several times between fades. It now keeps what it shows until the timed swap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Start the default agent from the agents panel hero A console button beside the add button runs the same launcher as the right click: the default agent, or the picker when none is set. It hides while adding a subscription, where the add button becomes the way back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Put the add button before the agent launcher in the hero corner Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Bring keyboard navigation back to the agents panel The one-page redesign dropped left and right with the per-agent pages, leaving the arrows only to scroll. They now walk everything that does something, row by row: the hero's add and launch buttons, each switchable account, and the starter tiles. Enter acts on the cursor, the cursor scrolls into view, and hovering moves the same cursor so only one thing is lit. Number keys still jump to an account. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Let adding an account take over the agents hero While adding, the hero's line reads "Add an account" in place of the rotating summary, and the X in its corner is the only way back, so the add view drops its own title and Back link. Each agent to add is just its mark and name; one that can't be added is dimmed and says why on hover. The arrows walk that list too, and Enter picks one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show the agents to add as large marks, three across Each agent is a large mark over its name with no box around it, in one row the arrows move along. The chosen one turns accent and grows a touch. The reason an agent can't be added is shortened to fit inside the panel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move between Autoswitch and Use on an account with the arrows An account that isn't active is now two stops, Autoswitch then Use, so left and right move between them and Enter acts on the one that's lit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Land on Use when moving up or down onto an account Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hide Use on an autoswitching account until you're on its line With Autoswitch on, the line shows only Autoswitch. Use appears when the line is hovered anywhere or the keyboard is on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Start adding an account with the first agent focused Opening the add screen puts the keyboard cursor on the first agent, so Enter picks it straight away. A focused agent lights up even before the check says whether it can be added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop the Sign in link under the account name field Enter in the field already starts the sign-in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Key the primary Claude account's limits cache by its subscription The primary home always used claude-limits.json, so signing it in to another subscription could carry the old one's numbers over when the first probe failed, and autoswitch would act on them. Once the home says who it's signed in as, its cache is keyed by that like every other account's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Leave Qt Multimedia out of the base packages again Quattro dropped it once the shell no longer needed it, and the app skill already has an app that plays audio or video add it and list it in its own depends. The compiler and the rest of Qt stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Render the agents panel's dynamic text as plain text Sign-in status, help text, and provider names come from outside the shell, so none of them should be read as markup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep an account's plan and trouble clear of its Use and Autoswitch links The details beside an account's name grew to their full width, so a long plan or warning could run under the links on the right. They now shorten with an ellipsis instead, and Sign-in required keeps its whole width. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Let primary name the first account, as the manual says `omarchy agent account rename primary Hey` was documented but failed, since the primary account's id is main and lookups took exact ids only. primary now reaches the account marked primary, whatever it's been renamed to, and no new account can take primary as its id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Install everything an Omarchy app needs by default The app skill builds with Qt Multimedia, SVG icons, and ffmpeg as well as the compiler and the rest of Qt, so qt6-multimedia, qt6-svg, and ffmpeg join the base packages and the migration. The shell still plays no video through Qt Multimedia, which is what its test now checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Dim agent limits kept from an earlier check, with their age on hover When a Claude probe fails, the last numbers carry on and looked just like fresh ones. Those meters now dim, and their tooltip says how old they are. The record carries limitsStale and limitsFetchedAt for this. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Give the app skill templates for every file its build needs The templates named src/backend.{h,cpp} and a test file without showing them, so each app had to invent its own. They're now templated, with a starter icon, a note that LICENSE and the icon must exist for package(), and qt6-wayland in the PKGBUILD's depends. Scaffolded from the templates alone, the app builds and its tests pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Start the agents panel cursor over when the agent list comes or goes Right after the shell starts, the panel can briefly look like a first setup and focus the first agent to add. When the records land the rows change under the cursor, which then lit an account nobody had picked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop dead hover and limit checks from the agents panel The tiles and hero buttons fell back on their own hover when there were no keyboard rows, but the hero always has one, so hover only ever moves the cursor. Stale meters only exist when there are limits, so neither the panel nor the record needs to check for some. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop the a hotkey for adding an agent subscription The + in the hero is the way in, by mouse or by arrowing to it. The plugin README also catches up with the panel: the launcher, dimmed stale limits, the new add screen, and the arrows walking a cursor rather than scrolling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * List a command family that sits under a flags-only command `omarchy agent account` reached omarchy-agent, which takes only flags, and failed on the word instead of listing the account commands. When the command matched so far takes only flags and the next word names visible commands, the router now lists them. `omarchy update aur` likewise lists the update aur commands rather than running a full update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Refuse to remove an agent account a running session uses Removing an account deleted its home at once, pulling the login out from under any session started in it, though running sessions are never meant to be touched. It now says to quit that session first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Prefer an account checked just now when switching near a limit Autoswitch weighed numbers kept from an earlier check like fresh ones. A parked account's sign-in lapses within hours, so a stale one stays a candidate, but an account checked just now wins over it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Leave a user's own omarchy-app skill in place when linking ours Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Reach Sign-in required with the keyboard in the agents panel Both the link on a lapsed account and the one on a single-account agent are now stops in the cursor's walk, and Enter signs in again. A picked link scrolls into view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Bring the manual's agent accounts paragraph up to date Near-limit checks run every three minutes, not every minute, and Autoswitch now appears on hovering an account's line and takes Use's place while it's on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the agents panel cursor on things you can act on The active account was a stop with nothing to do, so the cursor seemed to vanish there. It now only stops on it to sign in again. The hero's buttons also show the cursor plainly, with an accent border and a deeper tint instead of a shade's difference. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Never leave an added agent account's login outside the registry Registering moved the login into its home before carrying settings over and saving the registry, so a failure in either stranded a home holding a sign-in that the account commands couldn't see. Settings are now carried while the login is still pending, and a failed save moves the home back there for the add command to clean up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Put room before freshness when picking an account to switch to Preferring accounts checked just now outright could pick a fresh one at 94% over a stale one at 10%. An account within 15 points of the threshold now counts as near its limit however fresh, so accounts with room come first and freshness only decides among them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Check agent limits more often relative to the switch threshold Faster checks started at a fixed 80%, so a threshold set lower could be crossed and wait out the 15-minute interval. They now start 15 points below the threshold, which is still 80% at the default 95%. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
3cebdc3412 |
End a running idle cycle when both timeouts are set to 0
With both at 0 the monitor is disabled and handleIdleChanged returns early, so a cycle already running when shell.json changed never cancels: omarchy-system-wake never runs, and if the screensaver never opened a window nothing else ends it. Cancel it the way turning on stay-awake does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Codex Medium <noreply@openai.com> |
||
|
|
3839d0b4e0 |
Keep a pending idle action on its deadline when the timings change
With 0 meaning off, setting the screensaver to 0 while the screensaver is up moves the first idle deadline to the lock's, which turns the pending lock's bound interval to 0 and locks at once, minutes early. Set each timer's interval when the cycle starts, so a change to shell.json takes effect from the next cycle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Codex Medium <noreply@openai.com> |
||
|
|
377b15be4b |
Don't fire a pending idle action whose timeout was set to 0
The timers' intervals are bound to the configured delays, so setting the lock or screensaver to 0 while the screensaver is up turns a pending timer's interval to 0 and it fires at once. Check the action is still enabled when its timer fires. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
146fe5d368 |
Say only what is true in the __sourceDir comment
Bar widget instances are not handed sourceDir (ModuleSlot.injectProps sets only bar, moduleName and settings), and a plugin could reach its directory through Qt.resolvedUrl, so the comment's rationale was wrong on both counts. Two lines carry what the code cannot say. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1095f73aa6 |
Fix Display panel display toggle using rejected hyprctl keyword
Under the Lua config system, 'hyprctl keyword monitor ...' is rejected
("keyword can't work with non-legacy parsers") yet still exits 0, so the
panel's enable/disable row silently did nothing. Use the hl.monitor eval
API instead, as omarchy-hyprland-monitor-scaling already does.
The re-enable must pass disabled = false explicitly: hl.monitor rules
merge, so a disabled = true already in config (e.g. the
internal-monitor-disable toggle file) otherwise survives and the
re-enable no-ops.
|
||
|
|
a383e3efcb |
Say what nodeFor resolves a row to after PipeWire recreates its node
Co-Authored-By: Codex Medium <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b18ab4952b |
Add a no-animations mode, on by default in VMs (#13550)
A machine without a GPU, like most VMs, renders through llvmpipe on the CPU, where every animated frame and every translucent window costs. In a VM, opening and closing a terminal took ~5s of CPU; a panel ~3.4s. omarchy toggle animations (also under Toggle > Animations) places a Hyprland flag that turns off animations, blur and shadows and makes windows opaque. The shell follows Hyprland's animations:enabled, rereading it on every config reload: its one-shot animations run for Style.duration(ms), which is then 0, and its spinners, pulses and title marquee hold still. A new install in a VM starts with the flag in place. Measured in the ISO test VM (llvmpipe), CPU per interaction: terminal open+close 5000ms -> 481ms, workspace switch 1670ms -> 409ms, audio panel 3446ms -> 796ms, volume OSD 2324ms -> 584ms, menu 2028ms -> 1241ms. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
de63134b88 |
Collapse identical notifications from the same sender into one toast (#13522)
* Collapse identical notifications from the same sender into one toast A web app open in several tabs fires one notification per tab for a single reminder, stacking identical toasts. A new notification matching an on-screen toast's app, summary, and body now replaces it like a replaces_id update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Only collapse live duplicates that share image and click target Screen recording toasts share text but preview and open different files, and replayed history rows share images with entries still in history. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Compare a notification's current content when collapsing duplicates A replaces_id update can land while the insert is deferred, so the initial snapshot may no longer describe what the notification says. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
349ecc09a2 |
Flip Elsewhen between Fahrenheit and Celsius with Alt+T (#13450)
* Flip Elsewhen between Fahrenheit and Celsius with Shift+T Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Flip Elsewhen's temperature units with Alt+T instead of Shift+T PanelKeyCatcher's textKey now carries the held modifiers, which is how the panel tells Alt+T from T. Existing handlers take only the text and are unaffected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
ed5837a05b |
Give the picked Elsewhen city one bright highlight (#13452)
A row lit itself by lifting its own time-of-day fill, so a picked night row could read darker than the daytime rows around it. The picked city now takes midday's lifted fill, the brightest, whatever its time of day; hover still lifts each row from its own. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
25f9795221 |
Flip Elsewhen's time format with t and line up its weather (#13448)
* Flip Elsewhen between 24-hour and AM/PM time with t Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Line up Elsewhen's weather in one column The temperature and weather icon sat against each row's time, which is narrower for "4:06" than "10:06", and shared the name's slack. The time column now takes the widest time's width in every row, and a spacer holds the weather against it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
773e19e145 |
Drive Elsewhen from the keyboard and summon it with Super+Ctrl+Alt+E (#13445)
* Navigate Elsewhen from the keyboard and summon it with Super+Ctrl+Alt+E Up and down walk home and the cities, lighting the picked row and turning the globe to it. Left and right move the clocks an hour, held until Escape or close. Escape now clears a shifted time before leaving the globe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Reach Add a city from the keyboard and shift time past a day Down past the last city selects Add a city, where Return or Space opens the search. The arrow keys no longer stop at twelve hours, and shifts past a day read in days. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Delete the picked Elsewhen city from the keyboard Delete (or x) removes the picked city and moves the cursor to the one that takes its place. The picked row shows its × so the target is plain. Delete now reaches every panel's deleteRequested, as it already does in the clipboard and the menu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Center bar glyphs on the open-panel underline The 16px icon canvas in the 27px slot was snapped from 5.5 to 6, and the glyph's fractional centering correction was snapped too, so glyphs sat up to 0.9px right of the underline, which centers on the slot. Both are now placed exactly, and the geometry test measures against the slot to within 0.05px. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
82979b9a18 |
Remove the IPC socket of each shell a test starts (#13443)
* Answer the Elsewhen panel over the shell's IPC socket The Elsewhen panel arrived with a plain IpcHandler, so omarchy-shell reached it only through the slower qs ipc fallback, and the test that every first-party handler registers as ShellIpc failed on quattro. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Remove the IPC socket of each shell a test starts The runtime smoke and screenshot sanity tests start the real shell from a temporary copy and kill it, which leaves its IPC socket behind in XDG_RUNTIME_DIR. A session that runs the suite a few times collected dozens of them. base-test.sh gains shell_ipc_socket, which derives a shell's socket as omarchy-shell does, and both tests remove theirs in cleanup. The socket test derives its fixture's socket through it too, so the helper cannot drift from omarchy-shell. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |