The battery service ran `powerprofilesctl get` every two seconds to keep the
active profile visible to the wallpaper and lock services. That command is a
PyGObject script, so the shell spawned a Python interpreter for it tens of
thousands of times a day. Roughly once a day one of those exits into a CPython
3.14 finalization race (python/cpython#124619): the GLib D-Bus worker thread
calls PyGILState_Ensure after the interpreter is torn down and the process
dies with SIGSEGV, leaving a core dump and a crash notification behind.
Read the ActiveProfile property straight from power-profiles-daemon with
busctl, the same way omarchy-powerprofiles-set already reads UPower. The
output is JSON, so an empty or malformed reply when the daemon is not running
still reads as no active profile, matching the previous behaviour.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gbfh4Mi9dK6SAd1P2xMTi
The speaker's USB firmware stops answering control requests when the host
stops the audio stream after WirePlumber's 5 s idle suspend. The kernel
then logs usb_set_interface failed (-110), clock source 1 is not valid,
and cannot set freq 48000 err -110; PipeWire fails to start the sink and
only a replug recovers it. On one machine this happened on six days over
three weeks, up to hundreds of timeouts a day.
A WirePlumber rule sets session.suspend-timeout-seconds = 0 for the KEF
node only, so the stream is never stopped and the trigger never fires.
Other sinks keep the default. The migration seeds the file for existing
installs and restarts WirePlumber if it is running, since conf.d is only
read at startup.
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Electron rewrites ~/.config/Claude for as long as the app runs, so removing the package and deleting the directory while it is open leaves the app running and the directory back within the same second, holding fresh Preferences and crash-reporter state. Driven end to end on an edge worker: remove via the menu with the app open left 11 processes and a recreated ~/.config/Claude; with the app quit first the directory stayed gone. The test stubs pkill so the suite cannot take a developer's own Claude with it, and asserts the remover reached for it.
Co-Authored-By: Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>
Follows the ChatGPT flow: the Install > AI entry runs
omarchy-install-ai-claude in a floating terminal, which installs the
claude-desktop package (Anthropic's Linux desktop beta, repacked from
their Debian repo in omarchy-pkgs) and opens the app. Remove > AI
drops the package along with ~/.config/Claude and ~/.cache/Claude,
the Electron directories the desktop app owns, while keeping
~/.claude, ~/.claude.json, and ~/.cache/claude-cli-nodejs: those
belong to the Claude Code CLI, which ships in its own package and
survives this removal, just as the ChatGPT remover keeps the Codex
CLI.
The menu mark is a new U+E90E glyph in the Omarchy icon font, from
Simple Icons' Claude mark, so it reaches desktops through the next
omarchy-settings release.
Co-Authored-By: Fable 5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>
Mirrors the hey-cli stub: the wrapper in ~/.local/bin installs and
upgrades through mise on first run, so the CLI tracks releases instead
of going stale as a manually dropped binary.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Chainfire (@Chainfire) privately reported the passwordless asdcontrol watchdog reboot on August 25, 2026.
The fix landed in the 4.0.2 security work: #9200 (df819a6f) removed Omarchy's unrestricted sudo grant, while omacom/omarchy-pkgs#242 and omacom/omarchy-pkgs#243 restricted the package's grant. This records the reporter credit omitted from those changes.
Reported-by: Chainfire (https://github.com/Chainfire)
Thanks to _SiCk // afflicted.sh for independently reproducing the passwordless sudo persistence issue and reviewing the proposed fix in #7990. The follow-up fix landed in #9387 (945af75a), with the 4.0.3 backport in cf459ba7.
The original boot-cleanup patch was contributed by @Adolanium. Preserve that co-author credit alongside this acknowledgment.
Co-authored-by: Adolanium <94890352+Adolanium@users.noreply.github.com>
* Relay the Elgato Cam Link 4K as a 16:9 virtual camera
Browser meeting apps such as Zoom's web client ask the Cam Link for a
standard-definition stream, and Chromium settles on the smallest mode it
offers, 640x480. The Cam Link fills that 4:3 frame by cropping its 16:9
input, and the app then paints the frame into a 16:9 tile, so everyone
comes out stretched wide. The web client has no HD switch to avoid it.
Hide the raw capture node from users and re-expose it through v4l2-relayd
as a 1280x720 virtual camera with the same name, so there is still just
one "Cam Link 4K" to pick and no way to negotiate 4:3 from it. udev
starts the relay whenever the Cam Link enumerates and stops it on unplug,
and the relay only pulls frames while something is watching. The sink
runs unsynced because v4l2src stamps each frame with its capture time,
which a synced sink treats as already late and drops.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Take the review fixes for the Cam Link 4K relay
Tie only the device's stop into the relay instance. A start dependency on
it left a job waiting on a device that never comes whenever the base
v4l2-relayd.service is started without a Cam Link attached, since the
package generator wants every configured instance.
Let the loopback unit rerun on each relay start, so a deleted or unloaded
device is recreated on replug instead of the oneshot staying satisfied.
Start the relay outright at the end of the migration. The udev trigger
only starts it when the rule is new to the device, and a failed module
build would otherwise pass silently with the raw camera already hidden.
Run the hardware fix after the Panther Lake kernel swap, as it pulls in a
DKMS module that would otherwise build twice.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Arch removed the prebuilt broadcom-wl package on 2026-09-02 and rebuilt
broadcom-wl-dkms with replaces=(broadcom-wl). A replaces entry only helps
upgrades of an already-installed package, so the name is now unresolvable
as an explicit pacman target and the ISO offline mirror download fails
with "target not found: broadcom-wl".
broadcom-wl-dkms depends on dkms, so the explicit dkms in the hardware fix
is redundant; linux-headers stays because the module has to build against
the running kernel.
1Password reads the display scale itself, the way Electron apps do, so
on a scaled monitor it comes up oversized next to every other window.
Pin it with --force-device-scale-factor=1 and let the compositor scale
it.
The app menu is covered by the packaged .desktop, which we build
ourselves in omarchy-pkgs. This is the other route in: the hotkey runs
the binary directly and never reads that file.
Claude-Session: https://claude.ai/code/session_01JB9phxP56gnP7qSidkkUJE
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Clicking the keyboard layout widget switches one device, chosen by
filtering the seat through UNTYPED_KEYBOARDS and then taking whichever
survivor sits furthest through the layout list. That filter has to
recognise every non-keyboard by name, and a laptop registers far more as
a keyboard than it lists.
On a Dell XPS 14, Hyprland reports ten keyboards and one of them is a
keyboard. The filter catches three of the other nine, leaving vendor
hotkey blocks (intel-hid-events, intel-hid-5-button-array,
dell-privacy-driver, dell-wmi-hotkeys) and two HID endpoints ahead of
at-translated-set-2-keyboard, which sorts last. Every click switches
hid-sdw:...-consumer-control instead, so the label cycles convincingly
while typing never changes. Device order is stable across polls, so it
is deterministic rather than a race, and needs no pre-existing bad state.
Switch every keyboard holding the same layout list instead, naming an
absolute index. "next" advances each device from wherever it sits, so a
seat that has already drifted apart stays drifted and merely inverts;
one index converges it in a single click, and a seat in lockstep leaves
the reading nothing to disagree about. Keyboards given their own
kb_layout hold a different list and are left alone, since an index into
this list would not mean the same layout to them.
The evdev KEY bitmap would separate these cleanly - the real keyboard
emits 167 keys, the pseudo-devices at most 19 - but hyprctl devices
reports no capability information, so the switch is taken out from
behind the name filter rather than the filter being lengthened.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Hiding the top bar and removing the window gaps are the two things you
do to give the screen entirely to your windows, and doing both took two
hands and two hotkeys. `omarchy toggle fullscreen desktop` does them
together.
It only leaves full screen when both halves are in it, so hitting the
hotkey with just the bar hidden (or just the gaps gone) pulls the other
half into line instead of flipping the one you already set.
Claude-Session: https://claude.ai/code/session_01JB9phxP56gnP7qSidkkUJE
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
T3 Code reads themes an environment publishes into its state directory, so
a generated t3code.json carries the palette the same way claude.json and
vscode-theme.json already do, and omarchy-theme-set-t3code republishes it
on every theme change for the app to pick up live.
The template overrides only the roles a theme actually designs -- terminal
and code surfaces, text on canvas, borders, selection -- and leaves muted
text, placeholders, and status foregrounds to T3 Code, which contrast-solves
them against whatever canvas it is given. Overriding those directly cost
readability on light themes: White fell to 1.0:1 on placeholder text.
Installing from the menu now routes through omarchy-install-ai-t3-code so a
fresh install publishes the current palette and opens wearing it.
Keep the package launcher visible when Hermes builds register a second desktop entry. Use the existing launcher hide list so in-app updates cannot restore the duplicate menu row.
An open terminal can retain deleted SQLite WAL files across removal and reinstall, causing the updated desktop to refuse session writes. Check user processes before package/runtime removal and again after data confirmation, without killing sessions. Cover the failure with real SQLite writers in isolated fixtures.
Co-Authored-By: GPT-6 Codex (xhigh) <noreply@openai.com>
Align main with the packaged release and fetch connected history so the updater detects and rebuilds the first update. Guard local branch work before upstream installation, force only the admitted incomplete release pin, preserve existing command files, and explain incompatible packages. Exercise empty-directory publication races and delayed launches.
Co-Authored-By: GPT-6 Codex (xhigh) <noreply@openai.com>
Use the packaged upstream installer and matching prebuilt app to prepare the writable user installation before launch. Preserve existing builds and modified sources; record the upstream build stamp only for a matching prebuilt app.
Co-Authored-By: GPT-6 Codex (xhigh) <noreply@openai.com>