Commit Graph
198 Commits
Author SHA1 Message Date
David Heinemeier Hansson d3cce6e68f Make menu left arrow navigate back 2026-07-21 15:45:08 -07:00
David Heinemeier HanssonandClaude Fable 5 afcbcc0e36 Replace shell instances with quickshell's synchronous kill
With quickshell-git, qs kill blocks until the instance has fully
exited, so restarting no longer needs to resolve pids and wait for them
to die. Kill in a loop until none remain - each call takes the oldest,
and duplicates from stale sessions are the reason this script exists.
The timeout bounds a wedged shell that can't process the quit message:
its kill would otherwise report success after Qt's 30s wait gives up,
re-killing the same undead instance forever. The test mock now kills
real processes synchronously to match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:27:12 -07:00
David Heinemeier HanssonandClaude Fable 5 094619fbd5 Target the newest shell instance for IPC calls
qs parses -n before the ipc subcommand as its top-level --no-duplicate
launch flag and silently ignores it, so IPC still went to the oldest
matching instance - exactly the stale one left behind around a restart.
The --newest flag belongs to the ipc subcommand: qs ipc -n. Verified
against two live instances; the test now pins the flag position.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:27:00 -07:00
David Heinemeier HanssonandClaude Fable 5 ba91bad3a4 Move Night Light onto a first-party nightlight service
Same treatment as Stay Awake: the indicator polled the toggle CLI over
a Process with a timer to paper over the race after clicking, and the
CLI ended by asking the shell to refresh every indicator over IPC. A new
omarchy.nightlight service owns hyprsunset instead - it probes the
temperature on startup, applies changes itself for in-shell toggles, and
answers on the nightlight IPC target. The indicator becomes a plain
binding. The CLI still drives hyprctl directly so keybindings, the menu,
and ssh work without the shell, but now just nudges the service to
re-probe since hyprsunset has no state file to watch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:26:20 -07:00
David Heinemeier HanssonandClaude Fable 5 61b7cd1c12 Size the indicator tray from block implicit sizes
Deriving the tray's implicit size from childrenRect fed layout results
back into the bindings that produced them, tripping implicitWidth
binding loop warnings. Compute it from the active and inactive blocks'
own implicit sizes instead, and center the loaded blocks rather than
anchor-filling containers that are sized by their content. The contract
test now instantiates the tray to check the collapse/expand cycle and
fails on any implicitWidth binding loop in the log.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:26:10 -07:00
David Heinemeier HanssonandClaude Fable 5 bee9ab476c Bind the Stay Awake indicator to the idle service
The indicator polled omarchy-toggle-idle over a Process and re-ran it on
a timer to toggle, while the CLI called back into the shell over IPC to
apply and refresh the state it had just changed. Now the indicator binds
straight to the idle service's stayAwake property and flips it in
process. The CLI only touches the state file, which the service already
watches, so toggling from keybindings and scripts still reaches the
shell without any reentrant IPC.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:25:49 -07:00
David Heinemeier Hansson 51d6d3c291 Fix Voxtype invitation action 2026-07-21 11:22:51 -07:00
David Heinemeier HanssonandClaude Fable 5 0526ebefcc Snap monitor scaling up to the nearest clean scale Hyprland accepts
Hyprland only takes scales where the mode divides into whole logical
pixels (in 1/120 steps), so picking 3x on a 1280x800 QEMU display threw
a red error overlay and silently kept the old scale. Round the request
up to the nearest clean divisor instead, so 3x becomes 3.2x.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 21:52:32 -07:00
David Heinemeier Hansson cc9a3aadb3 Report live battery power draw 2026-07-20 16:37:33 -07:00
David Heinemeier Hansson 8719b0d031 Fix pending migration notifications 2026-07-20 11:07:44 -07:00
David Heinemeier HanssonandClaude Fable 5 9314c12718 Test that the clamshell poll is gated to docked laptops
Guards the dock-gating in omarchy-hyprland-monitor-watch: the poll runs
only when omarchy-hw-laptop and an external monitor are both present, via
sync_poll_state, with the event loop fed by process substitution so it
can start/stop the poll. Behaviourally simulated (stubbed hw checks +
synthetic monitor events): the poll runs only while docked and stops on
undock; a desktop or undocked laptop never polls.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 09:03:26 -07:00
David Heinemeier HanssonandClaude Fable 5 b87de89372 Stop the migration notifier from busy-looping the session
omarchy-update-user-notify.path used PathExistsGlob= on the packaged
migrations directory. That directive is level-triggered: systemd re-checks
it every time the triggered unit deactivates and fires again while the glob
still matches. Since applied migrations stay on disk forever (state lives in
~/.local/state/omarchy/migrations), the glob always matches, so the oneshot
notifier re-triggered itself in a tight loop (~26-66 starts/sec) — burning
about a core and flooding the journal for the whole session.

The loop existed since the unit was introduced, but the default start-rate
limit killed it after 5 iterations, taking the .path unit down with
'unit-start-limit-hit'. That symptom was reported as #6174 and fixed
yesterday by setting StartLimitIntervalSec=0 — which removed the only brake
and turned the capped hiccup into an unbounded busy-loop.

Fix the actual cause instead:

* Drop PathExistsGlob= from the .path unit, keeping the edge-triggered
  PathModified= watch for updates that land mid-session.
* Revert the StartLimitIntervalSec=0 override; with the level trigger gone
  there is no self-re-fire to trip the limit, and the default limit is a
  useful backstop again.
* Preserve the once-per-login pending check the glob used to provide by
  giving the service its own WantedBy=graphical-session.target, enabled at
  first-run alongside the other user units.
* Add a migration that daemon-reloads, revives a rate-limit-killed .path,
  restarts the watcher, and enables the login-time notifier on existing
  installs.

Verified with transient path/service units: the old config runs the service
200 times in 3 seconds; the new config runs it zero times while idle and
exactly once when a new migration file lands.

Thanks to @HANCORE-Linux for finding and diagnosing the problem.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 21:49:41 -07:00
David Heinemeier HanssonandClaude Fable 5 e96163c075 Give glyph notifications with bodies the large icon slot
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 21:17:04 -07:00
David Heinemeier HanssonandClaude Fable 5 54d79d9d16 Fix screen flash when waking from sleep into the unlock screen
The lock service arms a 5s blank timer whenever the screen locks, and
input at the lock screen re-arms it. Closing the lid sprays pointer
noise over the lock surface, so the timer was routinely armed right
before suspend, froze mid-countdown, and fired moments after resume --
blanking the freshly woken unlock screen under the user.

Guard the timer with a wall-clock check: if far more time elapsed than
the interval, the countdown slept through a suspend, so take a fresh
run-up instead of blanking. This also blanks the lock screen 5s after
an untouched resume.

Two accomplices made the flash worse and hid the real bug:

- The clamshell watcher's 2s poll fired an unconditional global DPMS
  enable whenever no external monitor was active, relighting any blank
  within 2 seconds (lock-screen blanking never stuck on undocked
  laptops) and racing the resume modeset. Recovery now only wakes
  displays when it actually re-enables one.

- Every keystroke at the lock screen dispatched a redundant DPMS
  enable via omarchy-system-wake, forcing extra modesets in the
  fragile just-resumed DRM state. Brightness "on" now skips the
  dispatch when every active display is already lit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 19:42:18 -07:00
David Heinemeier Hansson d4d1b518e0 Remove redundant Hyprland launch wrapper
With initial workspace tracking disabled, windows naturally open on the active workspace. Remove the explicit Hyprland workspace dispatch and let shell actions, shell restarts, and presentation terminals launch directly.
2026-07-19 17:36:34 -07:00
David Heinemeier HanssonandClaude Fable 5 12dc7ae558 Shrink lock screen password dots to fit the field
Long passwords used to overflow the input field and clip with no
feedback that typing was still registering. Scale the dot size and
letter spacing down as the password grows, like macOS, so every
keystroke stays visible.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 11:03:00 -07:00
David Heinemeier HanssonandJon Kinney ec9f8241c1 Fix power action terminal scope race
Co-authored-by: Jon Kinney <jonkinney@gmail.com>
2026-07-19 10:31:27 -07:00
David Heinemeier HanssonandClaude Fable 5 17c8af3f14 Simplify shell restart around quickshell instance management
omarchy-restart-shell now kills by config dir via quickshell kill and
relaunches with --no-duplicate, polling kill until every instance is
gone since kill returns without waiting and -n silently exits if one
remains. The locked-session refusal reads Hyprland monitor state alone,
which covers a hung shell holding the lock; the redundant shell IPC
probe, availability guards, and omarchy-shell path indirection are gone.

Shell IPC calls now time out (2s default, OMARCHY_SHELL_IPC_TIMEOUT to
override) so probing an unresponsive shell fails fast instead of
hanging the caller.

omarchy-hyprland-launch checks dispatch output for "ok" rather than the
exit code, which is 0 even on Lua errors, so a failed dispatch falls
through to the bash -lc fallback instead of silently launching nothing.

The Quattro upgrade cutover delegates to omarchy-restart-shell instead
of carrying its own copy of the lock check, pkill, and readiness loop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 10:09:54 -07:00
David Heinemeier HanssonandClaude Fable 5 0f2f3f11cb Remember power profile choices per power source across reboots
Explicit profile selections from the power panel or menu are now saved
under an ac/battery key in ~/.local/state/omarchy/powerprofiles and
reapplied on boot and on plug/unplug. Only successful, user-made
selections are persisted, so the performance/balanced defaults still
apply when nothing has been chosen.

All entry points key off the same power signal, UPower's OnBattery:
the shell reads it natively and omarchy-powerprofiles-set autodetect
queries it via busctl. This replaces the sysfs online checks, which
disagreed with the shell on desktops without power_supply entries and
lagged behind plug events on some USB-C laptops.

Plug/unplug switching moves from the udev rule into the shell's battery
service, which already receives UPower's debounced state changes, so
the udev rule and its settle-sleep workaround are gone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 09:33:23 -07:00
David Heinemeier Hansson 6ba0e9c234 Fix monitor scaling down getting stuck at 3x due to floating point drift
Hyprland can report a scale set to 3 as something like 3.0000000000000004.
The previous directional comparison treated that as above the 3 preset, so
Super+Alt+Slash (scale down) would stay at 3 instead of reaching 2.

Snap the reported scale to the nearest preset first, then step up/down.
Add a regression test for the floating-point case.
2026-07-19 09:10:14 -07:00
Stephen TaylorandDavid Heinemeier Hansson 9030ba870c Force software cursors on nouveau
Adapt the fix from PR #6161 to Quattro's per-user hardware setup and add coverage for detection, idempotency, and proprietary-driver handling.
2026-07-18 21:49:47 -07:00
David Heinemeier Hansson 73efa7d926 Remove stale nofile config during Quattro upgrade 2026-07-18 21:42:00 -07:00
David Heinemeier Hansson 7b5c915c8c Clear bar move outline on release 2026-07-18 21:23:09 -07:00
David Heinemeier Hansson 6742adce3d Focus weather city input on return 2026-07-18 21:19:14 -07:00
David Heinemeier Hansson be1aab859d Prevent weather icon flicker 2026-07-18 21:19:10 -07:00
David Heinemeier Hansson c7952c980f Synchronize weather hero icon 2026-07-18 21:11:52 -07:00
cb989615f0 Align MAX_SNAPSHOT_ENTRIES with Snapper retention (off-by-one) (#6175)
* Align MAX_SNAPSHOT_ENTRIES with Snapper retention

Snapper is configured with NUMBER_LIMIT="5", but limine-snapper-sync
also counts the freshly-created / currently-booted snapshot, so five
retained snapshots are reported as six entries and it warns on every
snapshot and update:

  Snapshot limit mismatch: 6 Snapper snapshots exceed configured
  MAX_SNAPSHOT_ENTRIES=5

Raise MAX_SNAPSHOT_ENTRIES to 6 (NUMBER_LIMIT + 1) so the boot-menu cap
and Snapper's retention agree and the off-by-one warning stops. (An
alternative is MAX_SNAPSHOT_ENTRIES=auto, which derives the cap from
Snapper directly; kept an explicit value here to preserve the existing
boot-menu limit.)

Co-Authored-By: Claude <noreply@anthropic.com>

* Clarify Limine snapshot limit

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
2026-07-18 18:40:11 -07:00
58e13cd079 Prevent empty drive encryption passwords (#6306)
* Prevent empty drive encryption passwords

* Use sudo, quote the confirmation compare, and cover mismatches in test

The unquoted [[ $new_password == $confirmation ]] made the confirmation
a glob pattern, so a confirmation like * matched any password. And pkexec
brought nothing over the repo-standard sudo here while failing outright
in sessions without a polkit agent.

Verified against a loopback LUKS device: new key lands from stdin without
a trailing newline while the current passphrase is prompted on the tty.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: mplaczek99 <mplaczek99@gmail.com>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 18:21:39 -07:00
David Heinemeier Hansson 1620b3467b Refresh applications during Quattro upgrade 2026-07-18 12:56:46 -07:00
1024bf5e7a Backfill pre-quattro hardware support and tmux fixes for existing installs
Existing quattro installs get sof-firmware, the Mesa Vulkan drivers,
the tmux terminal-features and pane-binding fixes, and the XPS 13 text
scaling via migration, while Omarchy 4 upgraders get the same hardware
support and scaling through omarchy-upgrade-to-quattro.

The Vulkan driver backfill adapts da46ad85 from master.

Co-authored-by: Sai Sridhar <tarrasridhar1154@gmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:31:34 -07:00
David Heinemeier HanssonandClaude Fable 5 a4c13bdefb Make package removal match exact installed names only
pacman -Q resolves provider names, so dropping a virtual package could
remove whichever package provides it. Read pacman -Qq once and match
requested names exactly, ignoring providers and duplicate arguments.
Ports the provider-ignoring semantics of 9791b227 from master with a
single pacman query instead of one per package.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:31:03 -07:00
David Heinemeier HanssonandClaude Fable 5 9aa1dcd664 Drag the bar to move it, drop the config panel
Position the bar by dragging (or click-and-holding) empty bar space
toward a screen edge, with a ghost slab previewing the target edge.
With drag for position and double-click for transparency, the bar
config panel, its inline gear button, and the omarchy-launch-bar-settings
CLI are no longer needed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 11:44:35 -07:00
David Heinemeier Hansson 4d3165d8c1 Keep new browser windows on current workspace 2026-07-18 10:29:38 -07:00
David Heinemeier Hansson 8862fb22bd Use Omarchy command helpers consistently 2026-07-18 10:08:43 -07:00
David Heinemeier Hansson 784996c378 Scale webcam overlay to monitor resolution 2026-07-17 18:28:44 -07:00
David Heinemeier Hansson ca0cf8bff9 Fix webcam resize controls and placement 2026-07-17 18:28:44 -07:00
David Heinemeier Hansson 1174f2a70b Add live webcam overlay sizing 2026-07-17 18:28:44 -07:00
David Heinemeier Hansson 73e5968c64 Show context in polkit prompt 2026-07-17 17:45:29 -07:00
David Heinemeier Hansson 28d853402e Make the Copy URL extension reliable across install and upgrade
The Copy URL extension was intermittently failing to copy anything, and
its notification looked oversized with no icon. Several distinct problems:

- The MV3 service worker was pinned to stale cached code. Chromium caches
  the worker script for a --load-extension command-line extension and does
  NOT re-register it when the file changes in place — not on restart, not on
  a manifest version bump, not even after a clean shutdown. So updated code
  never took effect: the old worker kept calling chrome.scripting.executeScript,
  which throws once the scripting permission is gone, and the copy silently
  failed. Renaming the worker to a versioned filename (background-2.js) is a
  new script URL, which forces a fresh registration for everyone — new
  installs and existing installs alike. Rename it again on any future worker
  change (see the note at the top of background-2.js).

- Clipboard writes now go through an offscreen document (MV3's sanctioned
  path) using a textarea + execCommand('copy'), replacing executeScript +
  navigator.clipboard. This works on chrome:// pages and needs no scripting
  permission. execCommand is used deliberately: navigator.clipboard.writeText
  rejects in an unfocused offscreen document.

- Add a toolbar action (chrome.action.onClicked) so the extension is
  clickable, not keyboard-only — it was greyed out in the extensions menu
  with nothing to invoke.

- Slim the "URL copied" notification: lead the summary with a glyph so the
  omarchy notification shell collapses it to a single-line toast with an
  icon, instead of an oversized card with a blank icon slot.

- Guard the Quattro shortcut-repair migration: it edits Chromium Preferences
  to move the Alt+Shift+L binding to the new extension id, but a running
  browser rewrites Preferences on exit and reverts the edit. Prompt (via gum)
  to close the browser first, only when a browser is running and there is
  actually a stale binding to repair.
2026-07-17 16:28:18 -07:00
David Heinemeier Hansson 182330465a Simplify omarchy-bar into a bar-settings and bar-plugin split
The omarchy-bar command had grown three overlapping ways to inspect the
bar (show/layout/list/options, plus selected/active/available/widgets
aliases) and mixed layout mutation in with bar-level settings. Untangle
it into two focused commands:

- omarchy-bar keeps only the bar-level settings that write shell.json:
  use, reset, position, transparent, and settings. reset now delegates
  to `use omarchy.bar` rather than duplicating the del(.bar.id) write.
- omarchy-bar-plugin owns all layout mutation: add, move, remove, set,
  and replace, with the placement flags and jq resolve/anchor helpers.
  `omarchy bar plugin ...` routes here via the dispatcher.

Drop the inspection commands entirely: the layout is visible on the bar,
the config is shell.json, and widget/option ids come from
`omarchy plugin list`. Nothing consumed the show output programmatically
except tests. This also removes omarchy-bar-position, whose jq write was
a duplicate of `omarchy bar position`.

Strip environment-invariant guards (require_command, require_omarchy_path)
that defended against jq or OMARCHY_PATH being absent — neither happens on
a real system. Keep the user-input validation (--section/--index) and the
atomic shell.json write.

Update callers (service install/remove, refresh-shell, plugin-clone,
plugin enable), keybindings, the menu, tests, and docs to the new split.
2026-07-17 16:28:17 -07:00
David Heinemeier Hansson f8fec7cccf Tighten compact status icon spacing 2026-07-17 16:17:49 -07:00
David Heinemeier Hansson 8211b86ac6 Restore compact status icon spacing 2026-07-17 16:15:01 -07:00
David Heinemeier Hansson 6867f16b78 Restore compact bar indicator sizing 2026-07-17 16:08:33 -07:00
David Heinemeier Hansson 22791803ed Align vertical bar widgets to the icon grid 2026-07-17 16:03:49 -07:00
David Heinemeier Hansson 0c8c4ea26a Align bar icons on a shared baseline 2026-07-17 15:37:01 -07:00
David Heinemeier Hansson 6e3b69b8da Standardize bar icon geometry 2026-07-17 15:20:55 -07:00
David Heinemeier Hansson fe48e83222 Repair Tailscale authorization flow 2026-07-17 10:20:08 -07:00
David Heinemeier Hansson 16b5f2157f Preserve user state during theme setup 2026-07-17 07:59:20 -07:00
David Heinemeier Hansson 09aac40eae Gate first-run setup as one lifecycle 2026-07-17 07:59:16 -07:00
David Heinemeier Hansson 39756d485d Synchronize weather location updates 2026-07-16 21:54:57 -07:00