Vendor upstream docs, manual, agent guides; add fork brief and parity audit

swadhinbiswas committed 2 months ago
3c98dd1
1 parent bbfe3c7
commit 3c98dd1
114 files changed
+5755 -0
Showing 114 changed files+5755-0
AGENTS.mdagents/skills/acceptance-tests.mdagents/skills/command-metadata.mdagents/skills/icon-font.mdagents/skills/install-scripts.mdagents/skills/migrations.mdagents/skills/shell-dev.mdagents/skills/visual-verification.mdaudit/PARITY-AUDIT.mddocs/FORK-NOTES.mddocs/audio-tuning.mddocs/cli-router.mddocs/file-layout.mddocs/menu.mddocs/notifications.mddocs/omarchy-shell.mddocs/testing.mddocs/theming.mddocs/update-process.mdmanual/01-welcome-to-omarchy.mdmanual/02-getting-started.mdmanual/03-coming-from-mac-or-windows.mdmanual/04-navigation.mdmanual/05-the-top-bar.mdmanual/06-themes.mdmanual/07-hotkeys.mdmanual/08-unified-clipboard-history.mdmanual/09-reminders.mdmanual/10-notices.mdmanual/11-text-extraction-dictation.mdmanual/12-screenshots-recording.mdmanual/13-toggles-idle-screensaver.mdmanual/14-omarchy-cli.mdmanual/15-terminal.mdmanual/16-neovim.mdmanual/17-ai.mdmanual/18-development-tools.mdmanual/19-shell-tools.mdmanual/20-shell-functions.mdmanual/21-tuis.mdmanual/22-guis.mdmanual/23-browsers.mdmanual/24-commercial-apps-services.mdmanual/25-web-apps.mdmanual/26-gaming.mdmanual/27-filling-out-pdfs.mdmanual/28-windows-vm.mdmanual/29-other-packages.mdmanual/30-updates.mdmanual/31-dotfiles.mdmanual/32-shell-plugins.mdmanual/33-monitors.mdmanual/34-keyboard-mouse-trackpad.mdmanual/35-networking.mdmanual/36-system-sleep.mdmanual/37-hardware-authentication.mdmanual/38-fonts.mdmanual/39-backgrounds.mdmanual/40-prompt.mdmanual/41-branding.mdmanual/42-common-tweaks.mdmanual/43-making-your-own-theme.mdmanual/44-mac-support.mdmanual/45-troubleshooting.mdmanual/46-faq.mdmanual/47-system-snapshots.mdmanual/48-security.mdmanual/49-omarchy-on.mdmanual/50-dual-boot-install.mdmanual/51-unattended-installs.mdmanual/images/bootloader.webpmanual/images/branding-about.webpmanual/images/branding-plymouth-shopify.webpmanual/images/branding-screensaver.webpmanual/images/clipboard-history-search.webpmanual/images/clipboard-history.webpmanual/images/dual-boot-1.webpmanual/images/dual-boot-2.webpmanual/images/dual-boot-3.webpmanual/images/dual-boot-4.webpmanual/images/dual-boot-5.webpmanual/images/dual-boot-6.webpmanual/images/dual-boot-7.webpmanual/images/fonts-jetbrainsmono.webpmanual/images/gaming-geforce-now.webpmanual/images/gaming-minecraft.webpmanual/images/gaming-retroarch.webpmanual/images/gaming-starcraft.webpmanual/images/gaming-steam.webpmanual/images/gaming-xbox-cloud.webpmanual/images/install-config.webpmanual/images/install-done.webpmanual/images/macbook-omarchy.webpmanual/images/navigation-browser-terminal.webpmanual/images/navigation-dwindle-layout.webpmanual/images/navigation-fourway-tiling.webpmanual/images/navigation-popped-window.webpmanual/images/navigation-scrolling-layout.webpmanual/images/navigation-stacked.webpmanual/images/notice-battery.webpmanual/images/notice-datetime.webpmanual/images/notice-weather.webpmanual/images/prompt.webpmanual/images/reminders.webpmanual/images/snapshots-bootloader.webpmanual/images/snapshots-restore.webpmanual/images/text-extraction.webpmanual/images/tmux-tdl.webpmanual/images/tmux-tdl2.webpmanual/images/tmux-tdlm.webpmanual/images/tmux-tsl.webpmanual/images/troubleshooting-1password.webpmanual/images/update-available.webpmanual/images/windows-vm.webp
▼AGENTS.md
+125-0
1
+# de-omarchy — Project Brief for AI Assistants
2
+
3
+Read this file first. It tells you what this project is, how it is shaped, and exactly where to write different kinds of code.
4
+
5
+## What this project is
6
+
7
+`de-omarchy` is a **pure Arch / CachyOS port of [Omarchy](https://github.com/omarchy/omarchy)** — DHH's opinionated Hyprland desktop config — with every macOS assumption removed and Arch tooling (pacman/AUR, systemd, uwsm) used instead. It is a desktop environment layer, not an application: it configures Hyprland, a Quickshell QML status bar, keybindings, themes, and ~435 small CLI helper commands.
8
+
9
+The repo at `/home/swadhin/de-omarchy` is the **source**. It is deployed (rsync'd) to the runtime at `/usr/share/de-omarchy`. The running desktop reads from the runtime, never from the repo. `OMARCHY_PATH` (set in `/etc/environment.d/10-de-omarchy.conf`) always points at the runtime dir.
10
+
11
+## Architecture in one breath
12
+
13
+- **Hyprland** (Wayland compositor) configured in Lua: `default/hypr/` is the source tree, merged into `~/.config/hypr/` on deploy/refresh.
14
+- **Quickshell** (a QML Wayland shell) renders the bar, panels, OSD, notifications, lock screen, etc. Source: `shell/`.
15
+- **~435 bash commands** in `bin/`, all prefixed `omarchy-`, routed by `bin/omarchy`. They are the stable CLI surface for scripts, keybinds, and the menu.
16
+- **Themes**: `themes/*/colors.toml` + `default/themed/*.tpl` templates rendered into user config.
17
+- **Plugin system**: first-party shell plugins live in `shell/plugins/`; installable plugins are listed in `registry.json` and surfaced in a Plugin Library window (`plugin-library/`).
18
+- **Keybindings**: `default/hypr/keymap.lua` (Lua table of binds) — the live copy is `~/.config/hypr/keymap.lua`.
19
+
20
+## Directory map (where things live)
21
+
22
+```
23
+de-omarchy/
24
+ bin/ # ALL CLI commands (omarchy-*). Router = bin/omarchy
25
+ shell/ # Quickshell QML desktop
26
+ shell.qml # entry point; loads plugins via pluginRegistry
27
+ Commons/ Ui/ # shared QML imports (use `import qs.Commons`, `import qs.Ui`)
28
+ plugins/ # first-party plugins, one dir each
29
+ bar/ # the main bar + indicators/ widgets (+ BarStyles.js presets)
30
+ panels/ # popup panels (audio, bluetooth, network, power, ...)
31
+ services/ # background services (idle, media, nightlight, battery)
32
+ notification-center/ # bell widget + history panel (SUPER+ALT+N)
33
+ plugin-library/ plugin-manager/ docker-status/ sysmon/ ... # feature plugins
34
+ plugin-library/ # STANDALONE Plugin Library window (ShellRoot + Window)
35
+ shell.qml # launched by `omarchy-plugin-library` (SUPER+SHIFT+I)
36
+ default/ # system configs copied to runtime (the "defaults")
37
+ hypr/ # Hyprland Lua config (keymap.lua, bootstrap.lua, apps/, bindings/)
38
+ themed/ # theme templates (*.tpl) with {{ variable }} placeholders
39
+ agents/skills/ # AI agent skills symlinked into ~/.claude, ~/.codex, ...
40
+ chromium/ xcompose voxtype/ tensaku/ audio/ alacritty/ foot/ ghostty/
41
+ bash/ uwsm/ applications/ systemd/ fonts/
42
+ config/ # user-dotfile defaults copied to ~/.config (hypr, kitty, git, ...)
43
+ themes/ # 22 themes, each themes/<name>/colors.toml
44
+ docs/ # vendored upstream dev docs + FORK-NOTES.md (read deltas first)
45
+ manual/ # vendored 51-chapter upstream user manual (paths rewritten)
46
+ agents/ # vendored agent guides (command-metadata.md etc.)
47
+ audit/PARITY-AUDIT.md # fork-vs-upstream feature audit
48
+ registry.json # plugin catalog shown in the Plugin Library
49
+ keybindings/KEYMAP.md # human-readable keybind reference
50
+ install.sh uninstall.sh # deploy / remove runtime
51
+ packages/ applications/ scripts/ display/ monitor-manager/
52
+```
53
+
54
+## Where to write each kind of change
55
+
56
+### 1. A new CLI command → `bin/omarchy-<group>-<name>`
57
+- Create `bin/omarchy-<group>-<name>`, `#!/bin/bash` shebang, executable bit.
58
+- Add the metadata header block the router parses (`bin/omarchy` scans for these):
59
+ ```bash
60
+ # omarchy:summary=One-line description.
61
+ # omarchy:group=<group> # optional; inferred from filename prefix otherwise
62
+ # omarchy:args=[--flag] <arg>
63
+ # omarchy:examples=omarchy <group> <name> | omarchy <group> <name> foo
64
+ # omarchy:hidden=true # optional, hide from listings
65
+ ```
66
+- If `<group>` is new, register it in `GROUP_DESCRIPTIONS` inside `bin/omarchy` so it shows in the top-level help.
67
+- Use bash 5 style: `[[ ]]` for strings/paths, `(( ))` for numbers. Quote string literals in comparisons. Avoid `exec`/`exit` to skip unreachable code; prefer full `if/else`.
68
+- After writing, deploy the single file to the runtime: `sudo cp bin/omarchy-x /usr/share/de-omarchy/bin/` (or re-run `install.sh`).
69
+
70
+### 2. A new shell plugin (bar widget / panel / service) → `shell/plugins/<name>/`
71
+- Make `shell/plugins/<name>/` with:
72
+ - `manifest.json` — `schemaVersion`, `id` (`deomarchy.<name>`), `name`, `version`, `author`, `kinds` (one of `bar-widget` | `panel` | `service`), `entryPoints`, and a kind-specific block (see `shell/plugins/docker-status/manifest.json` for a `bar-widget`).
73
+ - The QML entry file(s). Use `import qs.Commons` and `import qs.Ui` for shared helpers/colors. Read runtime paths from `Quickshell.env("OMARCHY_PATH")` — never derive from `HOME`.
74
+- `shell/shell.qml` auto-discovers plugins under `plugins/` via `pluginRegistry`; you normally do **not** edit `shell.qml` to add a plugin (only to change core loading).
75
+- Deploy: copy the plugin dir to `/usr/share/de-omarchy/shell/plugins/` and reload the shell (`omarchy-restart-shell` or `hyprctl reload` after the Lua/plugin change).
76
+- A `bar-widget` is placed by the user via the menu; `panel`/`service` kinds start with the shell.
77
+
78
+### 3. The standalone Plugin Library window → `plugin-library/shell.qml`
79
+- This is a **self-contained** Quickshell app (`ShellRoot` with a `Window` child), launched by the `omarchy-plugin-library` command, bound to **SUPER+SHIFT+I** in `default/hypr/keymap.lua`.
80
+- It is NOT a shell panel and must not `import qs.Commons`/`qs.Ui` (those only resolve inside the main shell). Use literals for colors and `import QtQuick.Controls` for `Button`.
81
+- It reads the catalog with `cat $HOME/.config/omarchy/plugins/registry.json || cat $OMARCHY_PATH/registry.json`. The catalog is `registry.json` at repo root (and deployed to `/usr/share/de-omarchy/registry.json`).
82
+- **Gotcha already hit:** `loadRegistry()` must be invoked from `Component.onCompleted`; a `Process` with `running: true` but no `command` produces empty output and shows "0 plugins".
83
+
84
+### 4. A catalog entry for an installable plugin → `registry.json`
85
+- Add an object to `plugins[]`: `id`, `name`, `description`, `author`, `category`, `tags`, `kind`, `status`, and `installCommand` (a bash snippet that copies/fetches the plugin into `~/.config/omarchy/plugins/`).
86
+- The Plugin Library's Install button runs `installCommand` via `mkdir -p ~/.config/omarchy/plugins && <installCommand>`.
87
+
88
+### 5. A keybinding → `default/hypr/keymap.lua`
89
+- Append to the `k` table:
90
+ ```lua
91
+ k[#k + 1] = { cat = "System", keys = "SUPER + SHIFT + I", dsp = exec("omarchy-plugin-library"), desc = "Plugin library" }
92
+ ```
93
+- `dsp` is a Hyprland dispatcher string; use `exec("...")` for shell commands. Do not append raw `hl.bind(...)` calls to `hyprland.lua` (they persist across reloads and stack). Deploy `~/.config/hypr/keymap.lua` via `omarchy-refresh-config hypr/keymap.lua`, then `hyprctl reload`.
94
+- `keymap.lua` is in the Hyprland Lua `reload_prefixes` list (`default/hypr/bootstrap.lua`), so `hyprctl reload` re-reads it. `hyprland.lua` is NOT in that list — editing it requires a full Hyprland restart.
95
+
96
+### 6. Theming → `themes/<name>/colors.toml` + `default/themed/*.tpl`
97
+- Add a theme dir with `colors.toml` (accent, background, foreground, red…cyan, bright_*). Templates under `default/themed/` consume `{{ variable }}` placeholders.
98
+
99
+### 7. User-facing dotfiles → `config/<app>/...`
100
+- Copied to `~/.config/<app>` on deploy. Refresh a single one with `omarchy-refresh-config <relpath>` (backs up the existing file first).
101
+
102
+## Conventions (follow these exactly)
103
+
104
+- Shebangs: `#!/bin/bash` only (never `env bash`).
105
+- Commands & scripts: all start with `omarchy-`. Prefixes hint purpose (`cmd-`, `pkg-`, `hw-`, `refresh-`, `restart-`, `launch-`, `install-`, `setup-`, `toggle-`, `theme-`, `update-`, `capture-`, `plugin-`…).
106
+- In markdown/plans/docs: full lines, two-space indent, no 80-col wrapping.
107
+- `OMARCHY_PATH` is the single source of truth for runtime location. In QML use `Quickshell.env("OMARCHY_PATH")`; in bash `${OMARCHY_PATH:-/usr/share/de-omarchy}`.
108
+- Keep changes atomic and grouped. Don't mix unrelated work in one commit.
109
+
110
+## Build / deploy / test loop
111
+
112
+1. Edit in the repo (`/home/swadhin/de-omarchy`).
113
+2. Deploy what you changed to the runtime:
114
+ - Full reinstall: `sudo bash install.sh` (rsyncs repo → `/usr/share/de-omarchy`, sets `OMARCHY_PATH`).
115
+ - Single file: `sudo cp <repo/path> /usr/share/de-omarchy/<relpath>`.
116
+3. Apply: `hyprctl reload` for Hyprland/Lua config; `omarchy-restart-shell` (or `hyprctl reload` if the shell is a reload-prefix plugin) for QML; `omarchy-refresh-config <relpath>` for user dotfiles.
117
+4. Verify in the running UI (visual check) plus any CLI sanity check. For QML, watch the Quickshell log at `/run/user/1000/quickshell/by-id/<id>/log.qslog`.
118
+
119
+## Gotchas (learned the hard way)
120
+
121
+- **Background processes in this shell:** never leave a `quickshell … &` holding the tool's stdout pipe — redirect with `>/dev/null 2>&1 &` and don't put a trailing `&` on the harness command line, or the command appears to hang until timeout. Launch detached via the `omarchy-*` wrapper instead.
122
+- **`keymap.lua` vs `hyprland.lua` reload:** only the prefixes in `default/hypr/bootstrap.lua` `reload_prefixes` are re-evaluated on `hyprctl reload`. Add a new prefix there if you need live reload for it.
123
+- **Standalone QML windows** can't use the main shell's `qs.Commons`/`qs.Ui` imports; inline what they need.
124
+- **Plugin Library "0 plugins":** ensure `loadRegistry()` runs on `Component.onCompleted` and the registry path resolves (`OMARCHY_PATH` set in the session).
125
+- The runtime dir is owned by root; edits there need `sudo`. The repo is owned by `swadhin`. Sudo password for this machine is the user's login password.
0
126
▼agents/skills/acceptance-tests.md
+46-0
1
+# Acceptance Tests
2
+
3
+Read this before writing or running the graphical acceptance suite under
4
+`test/acceptance.d/`.
5
+
6
+The graphical acceptance suite lives in `test/acceptance` with test files under
7
+`test/acceptance.d/*-test.sh`. It exercises a real installed Omarchy desktop,
8
+including session health, shell surfaces, panels, keyboard navigation,
9
+representative applications, and system setup. Source
10
+`test/acceptance.d/base-test.sh` for the shared helpers.
11
+
12
+Run acceptance tests in a disposable VM through the sibling `omarchy-iso`
13
+repository, not in the active development session. The suite opens and closes
14
+applications and temporarily changes desktop configuration.
15
+
16
+For acceptance-test-only changes, reuse an installed base and sync the suite:
17
+
18
+```bash
19
+cd ../omarchy-iso
20
+./bin/omarchy-iso-test release/<iso>.iso --reuse-base --sync-omarchy ../omarchy --no-preview
21
+```
22
+
23
+Use `--sync-all ../omarchy` instead of `--sync-omarchy ../omarchy` when the
24
+acceptance run must exercise local `bin/`, `config/`, or `shell/` source too.
25
+Changes to package manifests, installation, finalization, or shipped defaults
26
+require a fresh ISO built from the local checkouts and a run without
27
+`--reuse-base`:
28
+
29
+```bash
30
+cd ../omarchy-iso
31
+./bin/omarchy-iso-make --no-boot-offer --local-source ../omarchy ../omarchy-pkgs
32
+./bin/omarchy-iso-test release/<generated-iso>.iso --no-preview
33
+```
34
+
35
+Keep unrelated acceptance workflows in separate test files. The runner records
36
+a failed file and continues with the remaining files, which preserves as much
37
+diagnostic coverage as possible. Restore modified user state with traps, close
38
+anything the test opens, and capture every visually distinct state (including
39
+entered input where relevant) as `success-<step>.png`; failure helpers capture
40
+`failure-<step>.png`. The ISO harness collects the screenshots and logs under
41
+its timestamped `test-runs/` directory and opens the screenshots after the run
42
+unless `--no-preview` is passed.
43
+
44
+The ISO harness exercises compositor-level shortcuts with QMP virtual keyboard
45
+input. In-guest `wtype` is suitable for typing into focused controls, but it
46
+does not reliably prove that a global Hyprland keybinding works.
0
47
▼agents/skills/command-metadata.md
+31-0
1
+# Command Metadata
2
+
3
+Read this before adding or changing commands in `bin/`.
4
+
5
+Commands in `bin/` can declare CLI metadata in comments near the top of the
6
+file. `bin/omarchy` scans the first 80 lines, and tests expect command metadata
7
+to remain valid.
8
+
9
+Supported metadata keys:
10
+
11
+- `# omarchy:group=...` - override the command group inferred from the filename
12
+- `# omarchy:name=...` - override the command name inferred from the filename
13
+- `# omarchy:summary=...` - short help text
14
+- `# omarchy:args=...` - usage arguments
15
+- `# omarchy:examples=...` - examples separated with ` | `
16
+- `# omarchy:alias=...` / `# omarchy:aliases=...` - alternate routes
17
+- `# omarchy:hidden=true` - hide from default command listings
18
+- `# omarchy:requires-sudo=true` - mark commands that require sudo
19
+
20
+Only use `omarchy:examples` where there are args that need explaining.
21
+
22
+Prefer explicit metadata for user-facing commands. Keep routes consistent with
23
+the filename unless there is a deliberate alias or compatibility route.
24
+
25
+Example:
26
+
27
+```bash
28
+# omarchy:summary=Take a screenshot
29
+# omarchy:args=[smart|region|windows|fullscreen] [slurp|copy]
30
+# omarchy:examples=omarchy screenshot | omarchy capture screenshot region
31
+```
0
32
▼agents/skills/icon-font.md
+79-0
1
+# Omarchy Icon Font
2
+
3
+Read this before adding a branded glyph to `default/fonts/omarchy/omarchy.ttf`.
4
+
5
+The Omarchy icon font is a small private-use font carrying the marks Nerd
6
+Fonts does not have: the Omarchy logo and the agent and app brand marks. The
7
+menu draws one by naming the font on an entry:
8
+
9
+```jsonc
10
+"setup.default.agent.grok": {"icon":"","iconFont":"omarchy","label":"Grok", ...}
11
+```
12
+
13
+Without `iconFont`, an entry's `icon` is drawn in the menu font, so reach for
14
+this font only when a Nerd Font glyph would misrepresent the thing. A generic
15
+robot for four different AI apps is the case that justifies a real mark; a
16
+folder or a microphone is not.
17
+
18
+`default/fonts/omarchy/README.md` lists every glyph with the URL its artwork
19
+came from. Keep that list accurate — it is the only record of provenance.
20
+
21
+## Adding a glyph
22
+
23
+`omarchy dev font` does the work:
24
+
25
+```bash
26
+omarchy dev font list
27
+omarchy dev font add ollama https://simpleicons.org/icons/ollama.svg
28
+```
29
+
30
+`add` fetches the SVG, scales it into the same 64..960 box the existing marks
31
+use so it lands at their optical size, appends it at the next free private-use
32
+codepoint, and adds a line to the font README. It prints the codepoint and the
33
+glyph itself.
34
+
35
+The source must be a **monochrome SVG with a single `<path>`**, because the
36
+menu recolors the glyph with the active theme's foreground and selection
37
+colors. Brand icon sets such as <https://simpleicons.org> publish exactly that
38
+shape. App favicons usually do not: they are multi-color, carry a container
39
+tile, or split across several paths. Prefer the official mark when it is
40
+published as flat monochrome art, and fall back to an icon set's redraw when it
41
+is not.
42
+
43
+Two-tone marks are a trap. Every path becomes solid foreground, so a logo whose
44
+meaning depends on lighter and darker halves turns into an unreadable blob.
45
+Pick a source whose silhouette alone reads.
46
+
47
+## After adding
48
+
49
+The command prints these, and all of them matter:
50
+
51
+- Point the menu entry at the new codepoint with `"iconFont":"omarchy"`.
52
+- Bump the charset range asserted in `test/shell.d/menu-test.sh`; that test
53
+ pins the font's coverage and fails until it matches.
54
+- Check the README line the command added, and give it a proper display name
55
+ with `--label` if the glyph name is not the brand's name.
56
+
57
+The font is package-owned: `omarchy-settings` installs it to
58
+`/usr/share/fonts/omarchy/omarchy.ttf`, so a new glyph reaches the desktop
59
+through a settings release, not through `omarchy update`. Between the merge and
60
+that release, a pulled checkout renders the new entry with no icon.
61
+
62
+## Verifying
63
+
64
+Render the whole font and look at it, which catches inverted contours and
65
+filled counters that a glyph list cannot show:
66
+
67
+```bash
68
+python3 -c "open('/tmp/row.txt','w').write(' '.join(chr(c) for c in range(0xE900, 0xE910)))"
69
+magick -background white -fill black -font default/fonts/omarchy/omarchy.ttf \
70
+ -pointsize 110 label:@/tmp/row.txt /tmp/font-row.png
71
+```
72
+
73
+Then confirm it in the running menu per
74
+[`visual-verification.md`](visual-verification.md). Fontconfig prefers the
75
+packaged font over a copy in `~/.local/share/fonts` for the same family, so a
76
+preview needs either the real file replaced or a `<rejectfont>` rule in
77
+`~/.config/fontconfig/conf.d/` pointing fontconfig away from the packaged one.
78
+Restart the shell afterwards — Qt reads the font database at startup, so
79
+`omarchy menu refresh` alone will not pick up a changed font.
0
80
▼agents/skills/install-scripts.md
+19-0
1
+# Install Scripts
2
+
3
+Read this before working under `install/` or on the system/user setup commands.
4
+
5
+The ISO owns installation orchestration. This repo ships target-side setup
6
+commands and reusable setup leaves:
7
+
8
+- `bin/omarchy-apply-system` runs root-owned system setup during ISO finalization.
9
+- `bin/omarchy-apply-hardware` runs idempotent hardware-specific setup and is called by `omarchy-apply-system`.
10
+- `bin/omarchy-finalize-user` runs the per-user runtime finalization (skill symlinks, xdg-user-dirs, mime defaults, `install/user/all.sh`). Shipped user defaults are seeded by `/etc/skel` from `omarchy-settings`, not by this command. `bin/omarchy-reinstall-configs` is the explicit destructive resync of those defaults into an existing user's `$HOME`.
11
+- leaf scripts under `install/` are sourced by `run_logged $OMARCHY_INSTALL/path/to/script.sh` and intentionally do not have shebangs.
12
+- avoid `exit` in sourced setup scripts unless intentionally aborting setup.
13
+- use `$OMARCHY_INSTALL` and `$OMARCHY_PATH` instead of hard-coded Omarchy paths.
14
+- keep root-scoped hardware setup under `install/hardware/` and orchestrate it through `install/hardware/all.sh`.
15
+- keep every per-user setup leaf under `install/user/` (including `install/user/hardware/` and `install/user/first-run/`) so it is clear what must run for each user.
16
+- prefer helper commands for package and command checks where available.
17
+
18
+Raw `command -v`, `pacman`, and `pacman-key` are acceptable in package-helper
19
+contexts where direct package-manager behavior is the point of the script.
0
20
▼agents/skills/migrations.md
+167-0
1
+# Omarchy migrations
2
+
3
+Read this before creating or changing migrations under `migrations/`.
4
+
5
+Omarchy migrations are one-time repair scripts for existing installs. They are
6
+used when a package update needs to change state that pacman cannot safely own by
7
+itself.
8
+
9
+## Migration model
10
+
11
+Migrations live in:
12
+
13
+```text
14
+migrations/*.sh
15
+```
16
+
17
+They run as the current Omarchy user through `omarchy-migrate`, normally during
18
+`omarchy update`. A migration may touch user/session state (`~/.config`,
19
+`~/.local`, user systemd, browser/editor prefs, DBus/session state), and may also
20
+perform machine-wide repairs when needed.
21
+
22
+Completion state is per-user:
23
+
24
+```text
25
+~/.local/state/omarchy/migrations/<migration filename>
26
+```
27
+
28
+That means every user gets a chance to run every migration. Migrations run as the
29
+user; privileged operations should invoke the appropriate helper or privilege
30
+prompt themselves. Migrations must be idempotent: if one user already applied a
31
+machine-wide repair, the same migration running for another user should detect
32
+that and no-op.
33
+
34
+## When migrations run
35
+
36
+### During `omarchy update`
37
+
38
+`omarchy update` is the normal update path. It runs package updates, then:
39
+
40
+```bash
41
+omarchy-migrate
42
+omarchy-hook post-update
43
+```
44
+
45
+`omarchy-migrate` waits for any active pacman transaction to finish, then runs
46
+all pending migrations for the current user in the visible update terminal.
47
+
48
+### At login
49
+
50
+Every graphical login starts `omarchy-migrate-notify.service` after
51
+`graphical-session.target`. The notifier checks:
52
+
53
+```bash
54
+omarchy-migrate --pending
55
+```
56
+
57
+It stays silent while `omarchy update` holds its lock, since that update applies
58
+the pending migrations itself.
59
+
60
+If that user has pending migrations, it shows a notification that opens a
61
+terminal for:
62
+
63
+```bash
64
+omarchy-migrate
65
+```
66
+
67
+The notifier never runs migrations silently in the background.
68
+
69
+This is what covers users who did not run the update themselves: someone who
70
+bypassed the pacman guard with `sudo env OMARCHY_ALLOW_DIRECT_PACMAN=1 pacman
71
+-Syu`, and any second user on the machine, whose migration markers are per-user
72
+and therefore still missing after another user updated.
73
+
74
+Login is the only trigger on purpose. Watching the packaged migration directory
75
+also fires during a normal `omarchy update`, which prompts for migrations that
76
+`omarchy-migrate` is about to run in the visible update terminal.
77
+
78
+### Manually
79
+
80
+Users can safely run:
81
+
82
+```bash
83
+omarchy-migrate
84
+```
85
+
86
+at any time. Already-completed migrations are skipped.
87
+
88
+## Inspecting pending migrations
89
+
90
+Use:
91
+
92
+```bash
93
+omarchy-migrate --pending
94
+```
95
+
96
+Exit behavior:
97
+
98
+- `0` — one or more migrations are pending
99
+- non-zero — no migrations are pending
100
+
101
+Output is one pending migration per line:
102
+
103
+```text
104
+1781158082.sh
105
+```
106
+
107
+## Creating a migration
108
+
109
+Use the helper:
110
+
111
+```bash
112
+omarchy-dev-add-migration --no-edit
113
+```
114
+
115
+This creates:
116
+
117
+```text
118
+migrations/<unix timestamp>.sh
119
+```
120
+
121
+New migration format:
122
+
123
+- File permissions must be `0644` (`-rw-r--r--`). Migration runners execute them
124
+ with `bash -euo pipefail`, not through executable bits.
125
+- No shebang line.
126
+- Start with an `echo` describing what the migration does.
127
+- Use `$OMARCHY_PATH` to reference the Omarchy directory.
128
+- Be idempotent. Check existing state before changing it.
129
+- Use helper commands such as `omarchy-cmd-present`, `omarchy-cmd-missing`,
130
+ `omarchy-pkg-add`, `omarchy-pkg-drop`, `omarchy-pkg-present`, and
131
+ `omarchy-pkg-missing` when appropriate.
132
+- Never restart the Omarchy shell. `omarchy update` restarts it unconditionally
133
+ after migrations run, and the login-time shell already runs current code and
134
+ hot-reloads `shell.json` edits.
135
+- Raw `pacman`, `command -v`, and direct config edits are acceptable when
136
+ needed for one-off repair work.
137
+
138
+Example:
139
+
140
+```bash
141
+echo "Relink Neovim theme to Omarchy current state"
142
+
143
+theme_link="$HOME/.config/nvim/lua/plugins/theme.lua"
144
+current_relative_target="../../../../.local/state/omarchy/current/theme/neovim.lua"
145
+
146
+[[ -L $theme_link ]] || exit 0
147
+ln -sfn "$current_relative_target" "$theme_link"
148
+```
149
+
150
+## Testing migrations
151
+
152
+Run a migration against a temporary home when possible:
153
+
154
+```bash
155
+HOME=$(mktemp -d) bash -euo pipefail migrations/<timestamp>.sh
156
+```
157
+
158
+To rerun a migration locally, remove its marker and run the migrator:
159
+
160
+```bash
161
+rm ~/.local/state/omarchy/migrations/<migration>.sh
162
+omarchy-migrate
163
+```
164
+
165
+Omarchy 4.0 is upgraded through `bin/omarchy-upgrade-to-quattro`, not through the
166
+normal migration runner. Do not add compatibility migrations for old installer
167
+layouts; put pre-4 package-layout transition work in the upgrade command instead.
0
168
▼agents/skills/shell-dev.md
+49-0
1
+# Omarchy Shell Development
2
+
3
+Read this before editing the Quickshell desktop under `shell/`.
4
+
5
+The Quickshell desktop runs as a single long-running process out of
6
+`shell/`. Hyprland autostart launches it directly with `quickshell -n -p`;
7
+do not start additional standalone Quickshell instances for individual
8
+components.
9
+
10
+Run `omarchy-restart-shell` after making changes to QML files.
11
+
12
+## Plugin contract
13
+
14
+- First-party plugins live directly under `shell/plugins/` or one category
15
+ level deeper, such as `shell/plugins/panels/weather/`. First-party bar-only
16
+ widgets may use adjacent `*.manifest.json` files. Third-party plugins live
17
+ at `~/.config/omarchy/plugins/<id>/` with a `manifest.json` at the root.
18
+- Every plugin manifest declares `schemaVersion`, `id`, `name`, `version`,
19
+ `kinds`, and `entryPoints`. See
20
+ [`docs/omarchy-shell.md`](../../docs/omarchy-shell.md) and
21
+ `shell/services/PluginRegistry.qml` for the current contract; fields such as
22
+ `activation` are optional.
23
+- Entry-point QML files are `Item`s (not `ShellRoot`), and accept the
24
+ shell-injected properties `omarchyPath`, `shell`, `manifest`, and
25
+ `pluginRegistry` / `barWidgetRegistry` as appropriate.
26
+- Panel / overlay / menu plugins must expose `open(payloadJson)` and
27
+ `close()` lifecycle methods for `shell summon` and `shell hide`.
28
+
29
+## IPC
30
+
31
+- `bin/omarchy-shell` is the canonical IPC entry point. It forwards to
32
+ the running shell and does not start it. Prefer it over re-implementing
33
+ direct Quickshell socket calls in every CLI.
34
+- The `shell` IPC target exposes lifecycle and configuration methods including
35
+ `ping`, `summon`, `hide`, `toggle`, `call`, `rescanPlugins`, `reloadConfig`,
36
+ `setPluginEnabled`, and `listPlugins`. `shell.qml` also registers
37
+ `image-selector`, which drives the `omarchy.image-picker` panel.
38
+- Individual plugins register their own IPC targets, named for the plugin rather
39
+ than for where they appear: the background switcher registers `background`, and
40
+ bar widgets register one target each — `omarchy.indicators`,
41
+ `omarchy.system-update`, `omarchy.clock`. There is no `bar` target.
42
+
43
+## Editing widget files with glyphs
44
+
45
+Widget files in `shell/plugins/bar/widgets/` contain Nerd Font glyphs as raw
46
+unicode characters. Agent file-editing tools can strip multi-byte codepoints
47
+in some positions — do **not** rewrite widget files wholesale through those
48
+tools. For glyph fixes, make a targeted edit with the surrounding context, or
49
+use a Python script that inserts codepoints via `chr(0xXXXXX)`.
0
50
▼agents/skills/visual-verification.md
+44-0
1
+# Visual Verification
2
+
3
+Read this before finishing any change with a visual effect: Omarchy shell
4
+styling and layout, panels, menus, notifications, desktop appearance,
5
+animations, transitions, screenshots, and screen recording flows.
6
+
7
+Visual changes must be verified in the running UI in addition to automated
8
+tests. Creating an artifact is not sufficient: inspect it for clipping,
9
+overlap, incorrect spacing, stale state, focus problems, and visual
10
+regressions before finishing.
11
+
12
+Take a full-screen screenshot without opening the editor:
13
+
14
+```bash
15
+omarchy capture screenshot fullscreen save
16
+```
17
+
18
+The command prints the saved path and writes to the configured Pictures
19
+directory. Use `omarchy screenshot` for the interactive smart-region flow.
20
+Capture reference and candidate states as separate images when changing a
21
+layer-shell surface or layout, then compare both.
22
+
23
+Record a short full-screen video for animation, transition, timing, capture, or
24
+screen-recording changes:
25
+
26
+```bash
27
+omarchy screenrecord --fullscreen
28
+# Exercise the changed behavior.
29
+omarchy screenrecord --stop-recording
30
+```
31
+
32
+The stop command prints the saved video path in the configured Videos
33
+directory. Review the recording before finishing, and keep it short and focused
34
+on the changed behavior.
35
+
36
+For interactive UI work, use `wtype` to simulate keyboard input when available.
37
+Example: start the UI in the background, wait briefly for focus, then run
38
+`wtype -k Right -k Return` to exercise keyboard selection and confirm the
39
+resulting command output or state change. Prefer this over manual-only
40
+verification when a UI returns a selected value or changes a symlink/config.
41
+
42
+If a launched UI would otherwise remain open, keep track of its PID and stop it
43
+after the screenshot or recording; avoid broad process kills unless checking
44
+with `ps` first.
0
45
▼audit/PARITY-AUDIT.md
+157-0
1
+# PARITY AUDIT — de-omarchy vs upstream Omarchy
2
+
3
+Audited 2026-08-23 against `/home/swadhin/omarchy` (upstream checkout).
4
+Method: full recursive diffs of every tree (`bin/`, `shell/`, `config/`,
5
+`default/`, `themes/`, `applications/`), plus top-level structure comparison
6
+and spot verification of behavioral claims. Every "missing" below was
7
+verified against actual file presence and cross-references from surviving
8
+code, not assumed from docs.
9
+
10
+## RESOLUTION LOG (2026-08-23, later same day)
11
+
12
+Scope confirmed: UI/shell/theme/application layer only — no ISO/distro
13
+machinery. Resolved per §8 action order:
14
+
15
+- ✅ §3.1 Ported `default/chromium/` (extensions + native-messaging-hosts) — unbreaks both installers
16
+- ✅ §4.1 Ported `default/agents/skills/` (paths rewritten to de-omarchy); fork's provision-user loop + new install.sh wiring activate them
17
+- ✅ §4.2 Ported `default/xcompose`; install.sh writes `~/.XCompose` including it (never overwrites)
18
+- ✅ §4.3 Ported `default/voxtype/config.toml`; install.sh deploys it when absent
19
+- ✅ §4.4 Ported `default/tensaku/state.toml`
20
+- ✅ §4.5 Ported screensaver configs for foot/alacritty (+ Alacritty.desktop) and ghostty
21
+- ✅ §4.6 Ported `default/audio/filter-chain-host.conf` + `tunings/`
22
+- ✅ §4.9 Ported `default/xdg-terminal-exec/hyprland-xdg-terminals.list`
23
+- ✅ §6 Vendored `docs/` (with `docs/FORK-NOTES.md` deltas), `manual/`, `agents/`; runtime paths rewritten inside
24
+- ⏸️ §4.10 gpg dirmngr — skipped (touches existing ~/.gnupg; low value)
25
+- ⏸️ §4.7 Firefox policies / fontconfig / libalpm guard — system layer, out of scope per confirmed scope
26
+- ⏸️ migrations decision — still open (vendor vs remove runner)
27
+- Deploy of everything above rides on the next `sudo bash install.sh` / runtime sync (same pending sudo as the bar-style + notification work)
28
+
29
+## Verdict in one paragraph
30
+
31
+The fork tracks upstream unusually closely: all 22 themes, `applications/`,
32
+`shell/services`, `shell/Ui`, all popup panels, and ~411 of 431 shared CLI
33
+commands are byte-identical. `bin/` and `config/` are strict supersets
34
+(fork adds 10 commands, 7 shell plugins). The real gaps concentrate in
35
+`default/` (119 missing paths — mostly distro/installer machinery, but three
36
+user-facing features among them), the eight absent top-level dirs
37
+(`docs/ manual/ migrations/ install/ etc/ test/ agents/ plans/`), and one
38
+**broken-by-reference** case: Chromium extension installers whose asset
39
+files were never copied over.
40
+
41
+---
42
+
43
+## 1. Confirmed parity (no action needed)
44
+
45
+| Area | Evidence |
46
+|---|---|
47
+| Themes | All 22 identical (except `icons.theme` in 8 light-ish themes: Yaru-* → `breeze`, deliberate Dolphin/Papirus change) |
48
+| Applications (.desktop + icons) | Identical |
49
+| Shell core (`shell/services/`, `shell/Ui/`) | Identical file-for-file |
50
+| Popup panels (audio/bluetooth/clock/network/power/tailscale/dropbox/weather/wifiqr/speedtest/disk-speedtest/monitor) | Identical under `shell/plugins/panels/` |
51
+| Plugin lifecycle CLIs | `plugin add/clone/update/remove/enable/disable/list/validate` byte-identical |
52
+| Bar gestures & engine | Identical except deliberate bar-style additions |
53
+| Toggles/hooks/menu/theme-set plumbing | Identical |
54
+
55
+## 2. Fork-only additions (not gaps — inventoried for completeness)
56
+
57
+- `bin`: `omarchy-plugins` (marketplace via omarchyplugins.com catalog),
58
+ `omarchy-plugin-manager`, `omarchy-plugin-library`, `omarchy-keybindings`,
59
+ `omarchy-monitor-manager`, `omarchy-monitormgr`, `omarchy-bar-style-{list,set,cycle,menu}`
60
+- Shell plugins: `plugin-manager`, `plugin-library`, `notification-center`,
61
+ `power-profile`, `docker-status`, `system-overview`, `wallpaper-manager`
62
+- Config: NvChad nvim config, starship, zshrc.d layer, PAM lock config,
63
+ `deo-layer/bindings/autostart.lua` additive Hyprland layer
64
+- Defaults: `bar.transparent: true`, sysmon widget, notification-center widget
65
+
66
+---
67
+
68
+## 3. GAPS — broken by reference (fix first)
69
+
70
+### 3.1 Chromium extensions & native messaging hosts — `default/chromium/` missing entirely
71
+Upstream ships `default/chromium/{extensions/{copy-url,yt-dlp,whatsapp-slim},native-messaging-hosts/}`.
72
+The fork kept the CLIs but lost the assets they load:
73
+
74
+- `bin/omarchy-install-chromium-copy-url:9` → `$OMARCHY_PATH/default/chromium/native-messaging-hosts/$HOST_NAME.json` — **file does not exist at runtime**
75
+- `bin/omarchy-install-chromium-ytdlp:9` → same pattern
76
+- Consequence: "Copy tab URL" (Alt+Shift+L) and "Download video" (Alt+Shift+D)
77
+ integrations cannot be installed. `omarchy-chromium-copy-url-host` /
78
+ `omarchy-chromium-ytdlp-host` (the hosts themselves) DID survive — only the
79
+ registration templates and extension sources are gone.
80
+
81
+Fix: copy `default/chromium/` from upstream into the fork (paths already
82
+match; `omarchy-upgrade-to-quattro` even references the expected runtime
83
+path `/usr/share/de-omarchy/default/chromium/extensions/copy-url`).
84
+
85
+## 4. GAPS — user-facing features upstream has, fork lacks
86
+
87
+Ordered by how much a daily user would notice.
88
+
89
+| # | Feature | Upstream location | Notes |
90
+|---|---|---|---|
91
+| 4.1 | **AI agent skill bundling** | `default/agents/skills/omarchy/` (SKILL.md + capture/contributing/hooks/hyprland/plugins/theming md) and `skills/diagnose-crash/` | Manual ch 17: skills are symlinked into Claude Code/Codex/etc. skill dirs so agents can drive Omarchy natively and diagnose crashes. Fork has `omarchy-agent*` usage CLIs but no bundled skills. High leverage, cheap to port. |
92
+| 4.2 | **CapsLock compose: emoji sequences & completions** | `default/xcompose/` (+ `~/.XCompose`, `omarchy-restart-xcompose` exists in fork) | Manual ch 34: `CapsLock M <letter>` emoji insertion. Fork has the restart command and fcitx5 mentions in bindings but no default XCompose payload. |
93
+| 4.3 | **Dictation (Voxtype) config** | `default/voxtype/config.toml` | Fork has the whole `omarchy-voxtype-*` command family but no shipped config; first-run experience depends on it. |
94
+| 4.4 | **Screenshot annotation state** | `default/tensaku/state.toml` | Annotation editor (manual ch 12). Check whether tensaku itself is in packages/ui.packages before porting. |
95
+| 4.5 | **Screensaver terminal configs** | `default/{foot/screensaver.ini, alacritty/screensaver.toml, ghostty/screensaver}` | The ASCII-logo screensaver renders in the configured terminal; without per-terminal screensaver styling it falls back ugly. Fork user runs kitty — verify kitty path covers them, then decide. |
96
+| 4.6 | **Audio filter chain + per-device tunings** | `default/audio/filter-chain-host.conf`, `audio/tunings/<device>/` | `omarchy-audio-tuning` command exists in fork; its data does not. Affects only tuned devices (e.g. dell-xps-2026 profile present upstream). |
97
+| 4.7 | **Firefox policies** | `default/firefox/policies.json` | Wayland flags/policies if the user switches browsers. Low priority. |
98
+| 4.8 | **fontconfig overrides** | `default/fontconfig/conf.avail/` | Font substitution/aliasing guarantees. Low priority on an existing system that already renders fine. |
99
+| 4.9 | **xdg-terminal-exec mapping** | `default/xdg-terminal-exec/hyprland-xdg-terminals.list` | Terminal autodiscovery for XDG callers. Small but trivial to copy. |
100
+| 4.10 | **GPG dirmngr config** | `default/gpg/dirmngr.conf` | Keyserver hygiene. Trivial. |
101
+
102
+Not applicable by design: `nautilus-python/extensions` (fork replaced
103
+Nautilus with Dolphin in commit fc10361).
104
+
105
+## 5. GAPS — distro/installer machinery (intentional, documented for completeness)
106
+
107
+These exist upstream because Omarchy IS a distro. de-omarchy installs onto an
108
+existing Arch/CachyOS system, so their absence is policy — but each carries a
109
+consequence worth knowing:
110
+
111
+| Upstream area | Fork consequence |
112
+|---|---|
113
+| `install/` (ISO, provisioning, hardware drivers) | No assisted install — `install.sh` layers UI only. Accepted scope. |
114
+| `etc/` + `default/pacman/` (mirrors per channel, repo signing, `libalpm/hooks` blocking direct `pacman -Syu`) | Nothing stops a direct pacman full-upgrade from racing omarchy's own update flow. Consider re-adding just the libalpm guard hook. |
115
+| `default/limine/` + `snapper/` | No automatic pre-update snapshots, no boot-into-snapshot rollback (manual ch 30/47). Mitigate via CachyOS's own snapper/grub-btrfs if present. |
116
+| `default/plymouth/` (boot splash + unlock art incl. per-theme unlock designs) | Style > Unlock feature is dead; `omarchy plymouth preview/set` will fail. Also means theme `preview-unlock.png` assets are unused. |
117
+| `default/sddm/` | SDDM stays unthemed (system-level; install.sh explicitly doesn't touch it). Accepted. |
118
+| `default/systemd/{zram-generator.conf.d, faster-shutdown.conf, [email protected]}` | No zram/shutdown tuning. Usually already sensible on CachyOS. |
119
+| `udev/framework16-qmk-hid.rules` | Only matters on Framework 16 keyboards. |
120
+| `default/bashrc`, bash env stack | Replaced by zsh (`config/zshrc.d/50-de-omarchy.zsh`). Intentional. |
121
+
122
+## 6. GAPS — developer experience & update safety
123
+
124
+| Missing dir | Impact |
125
+|---|---|
126
+| `docs/` | The 9 internal docs (omarchy-shell, theming, cli-router, file-layout, menu, notifications, audio-tuning, testing, update-process). We read them from the upstream clone; consider vendoring with fork-specific amendments so they stop drifting. |
127
+| `manual/` | The 51-chapter user manual shown by the About/help flows upstream. Fork users have KEYMAP.md only. |
128
+| `test/` | `test/cli` + `test/shell` regression suites (upstream runs `commands --check` inside them). Fork currently relies on ad-hoc checks — we ran `omarchy commands --check` manually today. |
129
+| `migrations/` | **Subtle risk:** fork keeps `bin/omarchy-migrate` but deleted the migration scripts directory, so updates run zero migrations. Any future layout change (like upstream's shell.json v1 migration) must be handled manually. Either vendor the dir or delete the runner to avoid a silent no-op. |
130
+| `agents/` | Agent-facing command metadata guide referenced by cli-router.md. Docs-only. |
131
+| `plans/` | Design notes. Docs-only. |
132
+
133
+## 7. Deliberate divergences in shared files (audit trail)
134
+
135
+20 bin scripts differ; all trace to the port or to fork features:
136
+
137
+- **Distro machinery rewritten**: `omarchy`, `apply-hardware`, `apply-system`,
138
+ `channel-current/set`, `migrate`, `provision-owner/user`,
139
+ `system-factory-reset`, `theme-set-gnome`, `update-available`,
140
+ `update-dev`, `update-system-pkgs`, `upgrade-to-quattro`, `version`,
141
+ `version-branch`, `dev-status`, `dev-unlink`
142
+- **Fork features**: `plugin-add`, `plugin-remove` (registry.json integration)
143
+- **QML**: `shell.qml` (+46 lines), `Bar.qml` (style presets/islands),
144
+ `notifications/Service.qml` (focused-monitor + finite expiries)
145
+- **Hyprland Lua**: `bootstrap.lua` (reload_prefixes), `windows.lua`,
146
+ `paths.lua`; `uwsm/env.d/10-omarchy`; `bash/env*` (zsh); `kitty/kitty.conf`;
147
+ `config/omarchy/shell.json` defaults
148
+
149
+## 8. Recommended action order
150
+
151
+1. Port `default/chromium/` (unbreaks two shipped commands) — minutes.
152
+2. Vendor `docs/` + `manual/` (with a fork README noting deltas) — hours, stops doc drift.
153
+3. Port `default/agents/skills/` and wire the symlink step into install.sh — high value for this user's AI-heavy workflow.
154
+4. Decide migrations policy (vendor or remove runner) before the next big change.
155
+5. Add the libalpm pacman-guard hook adapted for CachyOS.
156
+6. Port xcompose + voxtype + tensaku + xdg-terminal-exec payloads (small files, complete features).
157
+7. Screensaver/audio-tuning/fontconfig/firefox — opportunistic.
0
158
▼docs/FORK-NOTES.md
+57-0
1
+# FORK NOTES — how de-omarchy differs from upstream Omarchy
2
+
3
+The `docs/`, `manual/`, and `agents/` trees are vendored from upstream
4
+Omarchy so the reference material travels with the fork. They describe
5
+upstream faithfully except for the deltas below. When this file and a
6
+vendored doc disagree, this file wins.
7
+
8
+## Paths
9
+
10
+| Upstream says | Here |
11
+|---|---|
12
+| `/usr/share/omarchy` | `/usr/share/de-omarchy` (`OMARCHY_PATH`) |
13
+| `github.com/omarchy/omarchy` | this repo (de-omarchy) |
14
+| bash login stack | zsh: `~/.config/zshrc.d/50-de-omarchy.zsh` |
15
+
16
+## Not present by design (no ISO — UI/shell/theme/application layer only)
17
+
18
+Installer machinery: ISO build, LUKS provisioning, Limine bootloader +
19
+snapshot boot entries, snapper, Plymouth boot splash/unlock art, SDDM theme,
20
+pacman mirrors/repo signing, `libalpm` guard hooks, systemd zram/shutdown
21
+tunings, udev rules, Firefox policies, system fontconfig, wayland-sessions
22
+entry, `etc/skel`.
23
+
24
+Consequences: no pre-update snapshot rollback, Style > Unlock is dead,
25
+direct `pacman -Syu` is not blocked.
26
+
27
+## Fork additions
28
+
29
+- Plugin marketplace: `registry.json` + `omarchy plugins …` CLI + Plugin
30
+ Library/Manager windows (upstream installs plugins from git URLs only)
31
+- Bar style presets: `shell/plugins/bar/BarStyles.js`,
32
+ `omarchy bar style list|set|cycle|menu`, SUPER+CTRL+Y, persisted as
33
+ `bar.styleName` in shell.json
34
+- Extra shell plugins: plugin-manager, plugin-library, notification-center
35
+ (SUPER+ALT+N), power-profile, docker-status, system-overview,
36
+ wallpaper-manager
37
+- Standalone keybindings window: SUPER+K → `omarchy-keybindings`
38
+- Notifications: toasts render only on the Hyprland focused monitor; all
39
+ urgencies expire (3s normal / 6s critical); hover pauses the countdown
40
+- Install model: `install.sh` layers onto an EXISTING Arch/CachyOS system
41
+ additively (backs up first, appends one marked block to hyprland.lua,
42
+ never overwrites user files) instead of owning the machine
43
+
44
+## Diverged shared files
45
+
46
+See `audit/PARITY-AUDIT.md` §7 for the full audit trail of files that
47
+differ deliberately (update/channel/provisioning rewrites, hypr bootstrap
48
+reload prefixes, kitty config, default shell.json layout).
49
+
50
+## Vendoring workflow
51
+
52
+To refresh these trees from upstream:
53
+
54
+ cp -r /path/to/upstream/{docs,manual,agents} .
55
+
56
+…then re-apply nothing — keep deltas in THIS file only, never edit vendored
57
+files in place (except mechanical path rewrites noted here).
0
58
▼docs/audio-tuning.md
+158-0
1
+# Speaker tunings
2
+
3
+Laptop speakers ship voiced by the vendor's Windows DSP layer, which Linux does
4
+not get. A tuning restores that as a PipeWire filter-chain in front of the
5
+internal speaker sink: a declarative graph hosted by a small PipeWire client, with
6
+no GUI app and no binary blob.
7
+
8
+```
9
+default/audio/tunings/<vendor>-<model>/
10
+├── tuning.conf # description, match, provenance, measurements
11
+└── filter-chain.conf # the graph, with @SPEAKER_SINK@ substituted on install
12
+```
13
+
14
+`on` renders the graph into `~/.config/pipewire/omarchy-speaker-tuning.conf.d/`
15
+(plus the shared host config `omarchy-speaker-tuning.conf`, from
16
+`default/audio/filter-chain-host.conf`) and runs it as its own PipeWire client via
17
+`omarchy-speaker-tuning.service`, rather than
18
+loading it into the audio daemon. The daemon only reads its own config at startup,
19
+so a daemon-loaded tuning could only be switched by restarting PipeWire — which
20
+drops every PulseAudio client's connection, and applications that do not reconnect
21
+(Spotify) then have to be restarted by hand. Hosting it separately makes switching
22
+a start/stop of one small process, and contains failure: a malformed tuning breaks
23
+only that service instead of stopping PipeWire from starting at all.
24
+
25
+Tunings apply automatically: `install/hardware/speaker-tuning.sh` installs the
26
+LV2 dependency and `install/user/first-run/audio-tuning.sh` applies the tuning,
27
+both gated on the match. Machines without a matching tuning are untouched.
28
+
29
+Switching it on happens at first-run, not at finalize-user time, because finalize-user
30
+also runs in the ISO chroot where there is no audio server: the sink a tuning has
31
+to target does not exist there, so nothing could be written — and nothing would
32
+retry, since the finalizer marks all shipped migrations complete on a fresh
33
+install. Matching itself deliberately does not consult the audio graph, so the
34
+LV2 dependency is still installed in the chroot.
35
+
36
+```bash
37
+omarchy audio tuning on # install the matching tuning
38
+omarchy audio tuning off # remove it, back to raw speakers
39
+omarchy audio tuning status # installed? in use? what matches?
40
+```
41
+
42
+`match` and `fronted-sink` are also accepted; they exist for the install hooks
43
+and the sink-listing scripts rather than for daily use.
44
+
45
+`on` verifies its own work: it waits for the tuning sink to appear and confirms
46
+its output linked to the expected physical sink, and uninstalls everything again
47
+on either failure — so a broken tuning cannot be left half-applied. It also
48
+switches the default sink to the tuning and moves existing app streams onto it
49
+(`off` reverses both). When everything is already installed and linked, `on` is
50
+a no-op; pass `--force` when iterating on a tuning in place.
51
+
52
+## Adding a tuning
53
+
54
+Add a directory with a `tuning.conf` and a `filter-chain.conf`. No new command is
55
+needed: matching is data. A tuning declares how to recognise its hardware, plus the
56
+`sink_pattern` its graph targets:
57
+
58
+| Key | Matches on | Notes |
59
+|---|---|---|
60
+| `match_sku` | DMI product SKU, whole value | Most precise. Vendors key speaker firmware on it, so it identifies the hardware rather than a marketing name |
61
+| `match_dmi` | DMI product name or family, substring | Convenient, but a short string widens fast — `product_family` here is `Dell Laptops` |
62
+| `match_command` | Any predicate you name | For hardware needing a sharper test than either |
63
+
64
+`match_sku` and `match_dmi` are lists, so one tuning can cover several models it has
65
+been validated on:
66
+
67
+```bash
68
+match_sku=("0DB9" "0DBA") # XPS 14 and XPS 16
69
+```
70
+
71
+Only the first *defined* key is consulted, in the order `match_command`,
72
+`match_sku`, `match_dmi` — keys below a defined one are ignored, and a tuning
73
+defining none never matches.
74
+
75
+`sink_pattern` is required whichever method you use, since the graph's target sink
76
+is substituted from it. The graph must also keep two fixed properties: the sink
77
+node is named `omarchy_speaker_tuning` (the install checks for that exact name,
78
+so renaming it silently fails verification), and its output stream sets
79
+`node.dont-fallback` alongside `node.dont-move`, so WirePlumber cannot link it
80
+somewhere else when the target sink is absent at host start.
81
+
82
+Gate narrowly and widen as models are validated; a tuning aimed at the wrong
83
+drivers can sound worse than none and can stress them. When a tuning covers a model
84
+it was not measured on, say so in `tuning.conf` — the provenance fields are there to
85
+keep that distinction visible rather than implied.
86
+
87
+Two hard requirements:
88
+
89
+- **End in a limiter.** Peaks must stay under 0 dBFS with headroom.
90
+- **Do not boost what the drivers cannot deliver.** The XPS 14 tuning
91
+ deliberately *cuts* 40 Hz by around 18 dB. Excursion down there buys nothing
92
+ and costs distortion.
93
+
94
+## Building one
95
+
96
+Measuring a laptop and fitting a filter-chain to it is a separate job with its own
97
+tools, in [omarchy-audio-tuner](https://github.com/omacom-io/omarchy-audio-tuner).
98
+It is not installed by default — almost nobody authoring a tuning, and it needs
99
+python, ffmpeg and mpv.
100
+
101
+```bash
102
+omarchy pkg add omarchy-audio-tuner
103
+```
104
+
105
+Its README is the walkthrough, and covers both cases: copying a reference that
106
+already sounds right (how the XPS 14 tuning was made, no microphone needed), and
107
+designing from scratch, which needs a *calibrated* measurement mic and a target
108
+curve that measurement alone cannot give you.
109
+
110
+## What a tuning must report
111
+
112
+A tuning is not reviewable on "sounds better to me". Record these, measured, in
113
+`tuning.conf`:
114
+
115
+| Field | What it is |
116
+|---|---|
117
+| `magnitude_rms_db` | Deviation from the reference or target it was fitted to |
118
+| `bass_group_delay_swing_ms` | Max minus min group delay, 30–300 Hz |
119
+| `limiter_headroom_db` | Worst-case peak against the limiter threshold |
120
+| `dynamic_range_delta_lu` | LRA change against the reference |
121
+
122
+Measure electrically by capturing the physical speaker sink's monitor, which sits
123
+upstream of the volume control, so results are independent of listening level.
124
+
125
+## How this fits the audio graph
126
+
127
+Two things about the surrounding system are worth knowing, because both caused
128
+real bugs:
129
+
130
+- **Volume lives downstream of the tuning.** A tuning is a virtual sink that
131
+ becomes the default output, and changing *its* volume would alter the level
132
+ going into the processing — moving the display while the speakers stay put, and
133
+ changing the tone of anything with a compressor or limiter in it.
134
+ `omarchy-audio-output-sink` is the single definition of "which sink does this
135
+ output's volume really use": it resolves a sink through any DSP sink to the
136
+ physical one, and with no argument resolves the current default output. The
137
+ volume keys, the output switcher's OSD and the audio panel all use it, so they
138
+ cannot disagree. Resolving the *current default* rather than "whatever a tuning
139
+ fronts" is what keeps it correct when headphones or HDMI are selected while a
140
+ tuning still exists.
141
+- **The fronted sink is hidden.** The tuning and the physical speakers both exist
142
+ in the graph, and selecting the physical one would only bypass the tuning. So
143
+ `omarchy-audio-sink-availability` reports it unavailable and
144
+ `omarchy-audio-output-switch` skips it, leaving one speaker entry in the panel.
145
+ A WirePlumber smart filter would remove the need for both — it leaves the real
146
+ device as the default output — but on PipeWire 1.6.8 / WirePlumber 0.5.15 the
147
+ graph loads and links correctly as a smart filter and then passes audio through
148
+ unprocessed. Revisit when that is understood.
149
+- **EasyEffects cannot coexist with a tuning.** It moves any stream that follows
150
+ the default sink to its own sink, so it would grab audio back from a
151
+ filter-chain. `on` refuses while it is running rather than installing a graph
152
+ that would be bypassed.
153
+- **The tuning's own output must not be moved.** A filter-chain's output is a
154
+ playback stream like any other, so anything rerouting "all streams" to a newly
155
+ selected output would drag the processing with it — onto headphones, or into the
156
+ tuning's own sink, which is a cycle. The tuning sets `node.dont-move`, and
157
+ `omarchy-audio-output-set-default` moves only streams that carry an
158
+ `application.name`.
0
159
▼docs/cli-router.md
+130-0
1
+# The Omarchy CLI router
2
+
3
+`bin/omarchy` maps spaced commands onto the flat `bin/omarchy-*` namespace:
4
+`omarchy theme set foo` becomes `exec bin/omarchy-theme-set foo`. There is no
5
+registry to maintain — every executable `bin/omarchy-*` file is a command, and
6
+its filename is its default route. Metadata comments in the file header refine
7
+how it presents and routes; the keys are documented in
8
+[`agents/skills/command-metadata.md`](../agents/skills/command-metadata.md).
9
+This document covers what that guide does not: how resolution and dispatch
10
+actually work.
11
+
12
+## How a binary becomes routes
13
+
14
+The stem after `omarchy-` splits at the first hyphen: `omarchy-theme-set` gets
15
+group `theme` and name `set`, with remaining hyphens becoming spaces
16
+(`omarchy-hw-asus-rog` → group `hw`, name `asus rog`). A single-segment stem
17
+(`omarchy-update`) is the root command of its own group, with an empty name.
18
+
19
+Every command registers two routes: the canonical route `omarchy <group>
20
+<name>` after metadata overrides, and the filename route with *all* hyphens
21
+turned to spaces. When metadata moves nothing, they are the same route. When it
22
+does, both keep working — `# omarchy:name=gaming xbox-cloud` on
23
+`omarchy-install-gaming-xbox-cloud` keeps the hyphen inside the name, so
24
+`omarchy install gaming xbox-cloud` is canonical while the filename route
25
+`omarchy install gaming xbox cloud` still resolves. An explicitly *empty* `#
26
+omarchy:name=` makes a command the root of its group: `omarchy-menu-share` sets
27
+`group=share` and an empty name, so its canonical route is `omarchy share`
28
+while `omarchy menu share` remains as the filename route. Alias routes register
29
+the same way but are flagged, so listings show them as aliases rather than
30
+commands.
31
+
32
+Two routes claiming different binaries is a collision: the first registration
33
+wins, dispatch is unaffected, and the conflict is recorded for `omarchy
34
+commands --check` to report. Hidden commands (`# omarchy:hidden=true`) still
35
+register and dispatch normally — hiding only removes them from listings, which
36
+is how install-time plumbing like `omarchy apply hardware` stays callable
37
+without being browsable.
38
+
39
+Metadata is read from the comment header only: the first 80 lines, stopping at
40
+the first non-comment line, so metadata-shaped comments after code never take
41
+effect. Malformed `omarchy:` lines and unknown keys are ignored rather than
42
+fatal — a typo degrades a command to its filename route instead of breaking the
43
+router. The first plain comment line doubles as a fallback summary, and a
44
+command with no comments at all still gets a generated one, though `--check`
45
+demands the explicit form (below).
46
+
47
+## Dispatch
48
+
49
+Resolution is longest-prefix: the router tries the full argument list as a
50
+route, then drops trailing words until something matches. Whatever it drops is
51
+passed to the binary as arguments. This runs in two passes.
52
+
53
+The fast path joins argument prefixes with hyphens and checks for an
54
+executable file: `omarchy theme set foo` probes `omarchy-theme-set-foo`, then
55
+`omarchy-theme-set`, which exists — resolved without reading a single metadata
56
+header. This exists because plain dispatch is the hot path: parsing the
57
+headers of several hundred binaries on every invocation is measurable
58
+latency (`omarchy dev benchmark cli` tracks it), and a filename probe is a few
59
+stat calls. Metadata loads lazily, only for the resolved command when help is
60
+needed.
61
+
62
+When no filename matches — metadata-moved routes like `omarchy share`, and
63
+aliases like `omarchy screenshot` — the router falls back to loading all
64
+metadata and resolving against the registered route table, with the same
65
+longest-prefix rule.
66
+
67
+Both paths intercept `--help`/`-h` *anywhere* in the leftover arguments, not
68
+just the first one. Resolution can succeed with unresolved words still ahead of
69
+the flag — `omarchy update aur --help` resolves `update` with leftovers `aur
70
+--help` — and checking only the first leftover once let that invocation start a
71
+real update. A `--` ends the scan: everything after it belongs to the command,
72
+so `omarchy foo run -- --help` forwards the flag. `--json` alongside `--help`
73
+switches the help output to the command's JSON record; `--json` alone is just
74
+an argument for the command.
75
+
76
+Bare invocations are also guarded. If a command declares required arguments
77
+(its `args` metadata, minus `[bracketed]` optional parts, is non-empty) and
78
+none were given, the router shows help instead of executing — `omarchy theme
79
+set` prints usage rather than running an interactive setter. A bare group name
80
+with child commands shows the group help.
81
+
82
+Dispatch is `exec`: the router process is replaced, the binary sees only the
83
+leftover arguments, and the exit code is the binary's own. The router itself
84
+exits 127 for unknown routes or missing binaries.
85
+
86
+When nothing resolves, the router tries a prefix listing — `omarchy hw asus`
87
+prints every command whose usage starts with that prefix — and otherwise
88
+errors with a "did you mean" suggestion (a known route extending the first
89
+word) and a pointer to `omarchy commands --all`.
90
+
91
+## Groups and the top-level listing
92
+
93
+Group help is synthesized from metadata, not written anywhere. A command
94
+belongs to a group when either its metadata group or its filename group
95
+matches, listed under the route that fits the group being viewed: `omarchy
96
+menu --help` shows `omarchy-menu-share` as `omarchy menu share`, while its
97
+canonical `omarchy share` stands alone. On the fast path, group help loads
98
+only that group's filename-prefixed binaries rather than everything.
99
+
100
+The top-level `omarchy` listing is driven entirely by the hand-curated
101
+`GROUP_DESCRIPTIONS` table in `bin/omarchy`, which also titles each group's
102
+help. An entry there advertises the group even when every command in it is
103
+hidden — which is exactly why `apply` and `provision` have none: they route,
104
+but a listing entry would put install-time plumbing back in front of users
105
+(see the Command Naming section of `AGENTS.md`). Adding a browsable command
106
+group means adding its `GROUP_DESCRIPTIONS` entry; adding hidden plumbing
107
+means deliberately not doing so.
108
+
109
+## Introspection
110
+
111
+`omarchy commands` prints every non-hidden command with its summary, plus an
112
+alias table. `--all` includes hidden commands, `--markdown` emits a table, and
113
+`--json` emits full records: route, binary, group, name, summary, flags, args,
114
+examples, aliases, `filename_route`, and `routes` (the union of everything
115
+that resolves to the binary). Per-command JSON comes from `omarchy <route>
116
+--help --json`.
117
+
118
+`omarchy commands --check` is the metadata lint, run by `test/cli`. It fails
119
+on:
120
+
121
+- route collisions between binaries
122
+- a missing explicit `# omarchy:summary=` — a plain-comment fallback renders
123
+ in help but does not satisfy the check
124
+- invalid boolean metadata: `hidden` and `requires-sudo` must be `true` or
125
+ omitted, never `false`
126
+- a registered command whose binary is missing or not executable
127
+
128
+When debugging a routing surprise, `omarchy <route> --help` shows the resolved
129
+binary and, when it differs, the filename route; `omarchy commands --all
130
+--json` shows every route the router knows.
0
131
▼docs/file-layout.md
+357-0
1
+# File layout
2
+
3
+How `omarchy/` is organized and where everything ends up on an installed
4
+system.
5
+
6
+## Mental model
7
+
8
+Two Arch packages are built from this one repo (PKGBUILDs live in the
9
+separate `omarchy-pkgs` repository, under `pkgbuilds/`):
10
+
11
+- **`omarchy`** — runtime binaries (`bin/`, including `bin/omarchy-dev-*`),
12
+ install/finalize scripts (`install/`), migrations, themes, and the
13
+ Quickshell desktop (`shell/`). Depends on `omarchy-settings`.
14
+- **`omarchy-settings`** — everything that has to be on the target *before*
15
+ the omarchy package installs (specifically before `useradd -m` and the
16
+ limine bootloader install): all `/etc/skel/**`, `/etc/` drop-ins,
17
+ package-owned system files under `/usr/share` and `/usr/lib`, fonts,
18
+ plymouth theme, sddm theme, branding, plus the limine/snapper configs
19
+ (mkinitcpio hooks, limine-entry-tool drop-ins, snapper template, the
20
+ `default/limine/` and `default/snapper/` trees, and the boot/snapshot
21
+ story end-to-end). Also ships the three debug binaries
22
+ (`omarchy-debug`, `omarchy-debug-idle`, `omarchy-upload-log`) needed by
23
+ the live ISO env.
24
+
25
+Two other packages live in `omarchy-pkgs` but stand alone:
26
+`omarchy-keyring` (GPG keys for pacman) and `omarchy-nvim` (the Neovim
27
+setup; independently seeds `/etc/skel`).
28
+
29
+Some trees ship in neither package and exist only in the repo: `manual/`
30
+(user manual chapters), `agents/skills/` (contributor task guides), `docs/`,
31
+`test/`, and `plans/`.
32
+
33
+Three layers populate `$HOME`:
34
+
35
+1. **Seed** — `omarchy-settings` ships static defaults to `/etc/skel/`.
36
+ Arch's `useradd -m` copies that tree into a new user's `$HOME` at user
37
+ creation. This is the only mechanism that touches a brand-new user's home
38
+ for these files.
39
+2. **Finalize** — `omarchy-provision-user` (routed as `omarchy finalize
40
+ user`) runs once per user and handles the things `/etc/skel` can't do
41
+ because they need `$HOME` expansion, the live `$OMARCHY_PATH`, or runtime
42
+ detection of system state.
43
+3. **Resync** — `omarchy-reinstall-configs` is the explicit, destructive
44
+ command for an existing user to clobber their configs back to shipped
45
+ defaults.
46
+
47
+`/etc/skel` only fires at user creation. Existing users picking up new
48
+defaults must use the resync command.
49
+
50
+Deferred-provisioning installs (`omarchy-apply-system --defer-provisioning`)
51
+create no user at all: the ISO leaves `/var/lib/omarchy/provisioning/pending`
52
+behind, which arms `omarchy-provision-owner.service` (shipped from
53
+`install/provisioning/`, alongside the factory-reset finish unit and
54
+`setup-form.sh`). On first boot `bin/omarchy-provision-owner` creates the
55
+user on tty1 and runs the finalize step itself.
56
+
57
+Current generated theme state lives under
58
+`~/.local/state/omarchy/current/`. Keep `~/.config/omarchy/` for files a user
59
+may intentionally version in a dotfile manager, such as user themes, hooks,
60
+shell layout, plugins, and themed template overrides.
61
+
62
+## Build-time map (repo → installed paths)
63
+
64
+```
65
+omarchy/ built into installed at
66
+───────────────────────── ────────────── ────────────────────────────────────
67
+
68
+bin/omarchy-* ──► omarchy /usr/bin/omarchy-*
69
+ (and symlinks in /usr/share/de-omarchy/bin/)
70
+bin/omarchy-debug,
71
+bin/omarchy-debug-idle,
72
+bin/omarchy-upload-log ──► omarchy-settings /usr/bin/ (needed before omarchy is installed)
73
+
74
+default/libalpm/hooks/*.hook
75
+ ──► omarchy /usr/share/libalpm/hooks/*.hook
76
+
77
+install/** ──► omarchy /usr/share/de-omarchy/install/
78
+migrations/** ──► omarchy /usr/share/de-omarchy/migrations/
79
+themes/** ──► omarchy /usr/share/de-omarchy/themes/
80
+shell/** ──► omarchy /usr/share/de-omarchy/shell/
81
+version ──► omarchy /usr/share/de-omarchy/version
82
+ + /etc/skel/.local/state/omarchy/migrations/*
83
+
84
+config/** ──► omarchy-settings /etc/skel/.config/** (seeds new users)
85
+ /usr/share/de-omarchy/config/** (resync source)
86
+etc/fastfetch/config.jsonc ──► omarchy-settings /etc/fastfetch/config.jsonc
87
+
88
+applications/*.desktop ──► omarchy-settings /etc/skel/.local/share/applications/
89
+ /usr/share/de-omarchy/applications/
90
+default/applications/battlenet.desktop
91
+ ──► omarchy-settings /usr/share/de-omarchy/default/applications/
92
+ (installer-only launcher template)
93
+applications/icons/* ──► omarchy-settings /usr/share/icons/hicolor/{48,256,scalable}/apps/
94
+
95
+etc/** ──► omarchy-settings /etc/** (drop-ins we own outright)
96
+ ├─ mkinitcpio.conf.d/{omarchy_hooks,thunderbolt_module}.conf
97
+ ├─ limine-entry-tool.d/{omarchy-defaults,omarchy-uki}.conf
98
+ ├─ NetworkManager/, sudoers.d/, sysctl.d/, tmpfiles.d/,
99
+ │ profile.d/omarchy.sh, … (a summary — `ls etc/` for the full ~17-entry tree)
100
+ └─ security/faillock.conf, nsswitch.conf,
101
+ cups/cups-browsed.conf, plymouth/plymouthd.conf /usr/share/de-omarchy/etc-overrides/
102
+ → /etc/* (post_install cp -f, see below)
103
+
104
+default/limine/limine.conf ──► omarchy-settings /usr/share/de-omarchy/default/limine/limine.conf
105
+default/limine/default.conf ──► omarchy-settings /usr/share/de-omarchy/default/limine/default.conf
106
+ (template; ISO substitutes @@CMDLINE@@ → /etc/default/limine)
107
+default/snapper/root ──► omarchy-settings /etc/snapper/config-templates/omarchy
108
+ (+ /usr/share/de-omarchy/default/snapper/root)
109
+
110
+default/** ──► omarchy-settings /usr/share/de-omarchy/default/
111
+ ├─ bash/env-bootstrap /usr/share/de-omarchy/default/bash/env-bootstrap
112
+ │ (sourced by every shell/session entry point; see "Env bootstrap")
113
+ ├─ bashrc /usr/share/de-omarchy/etc-overrides/dot.bashrc
114
+ │ → /etc/skel/.bashrc (post_install cp -f)
115
+ ├─ hypr/toggles/*.lua (flags,
116
+ │ single-window-aspect-ratio, window-no-gaps) /etc/skel/.local/state/omarchy/toggles/hypr/
117
+ ├─ nautilus-python/extensions/*.py /etc/skel/.local/share/nautilus-python/extensions/
118
+ ├─ tensaku/state.toml /etc/skel/.local/state/tensaku/state.toml
119
+ ├─ uwsm/env.d/10-omarchy /usr/share/uwsm/env.d/
120
+ ├─ environment.d/*.conf /usr/lib/environment.d/
121
+ ├─ fontconfig/conf.avail/50-omarchy.conf /usr/share/fontconfig/conf.avail/
122
+ │ + symlink /etc/fonts/conf.d/50-omarchy.conf
123
+ ├─ xdg-terminal-exec/*.list /usr/share/xdg-terminal-exec/
124
+ ├─ applications/mimeapps.list /usr/share/applications/mimeapps.list
125
+ ├─ systemd/user/*.service /usr/lib/systemd/user/
126
+ ├─ systemd/user/app.slice.d/10-oomd.conf /usr/lib/systemd/user/app.slice.d/
127
+ ├─ systemd/system-sleep/{force-igpu,
128
+ │ keyboard-backlight,unmount-fuse} /usr/lib/systemd/system-sleep/
129
+ ├─ systemd/zram-generator.conf.d/90-omarchy.conf /usr/lib/systemd/zram-generator.conf.d/
130
+ ├─ fonts/omarchy/omarchy.ttf /usr/share/fonts/omarchy/
131
+ ├─ sddm/omarchy/ /usr/share/sddm/themes/omarchy/
132
+ ├─ sddm/hyprland.lua /usr/share/sddm/hyprland.lua
133
+ ├─ wayland-sessions/omarchy.desktop /usr/local/share/wayland-sessions/
134
+ └─ plymouth/ /usr/share/plymouth/themes/omarchy/
135
+
136
+logo.{txt,svg}, icon.{txt,png} ──► omarchy-settings /usr/share/de-omarchy/ (resync source)
137
+ /usr/share/pixmaps/omarchy.png
138
+ /usr/share/icons/hicolor/256x256/apps/omarchy.png
139
+ /etc/skel/.config/omarchy/branding/{about,screensaver}.txt
140
+```
141
+
142
+### Why `etc-overrides/` exists
143
+
144
+Some files under `/etc/` (`.bashrc` in `/etc/skel`, `nsswitch.conf`,
145
+`security/faillock.conf`, `cups/cups-browsed.conf`, `plymouth/plymouthd.conf`)
146
+are owned by upstream Arch packages, so we can't install over them via pacman
147
+without a file conflict. Instead their sources (under `etc/` in the repo;
148
+`.bashrc` from `default/bashrc`) ship at
149
+`/usr/share/de-omarchy/etc-overrides/` and the `omarchy-settings` `post_install`
150
+/ `post_upgrade` scriptlet `cp -f`'s them into place.
151
+
152
+Tradeoff: user edits to those files get clobbered on every `omarchy-settings`
153
+upgrade. This is documented in the PKGBUILD.
154
+
155
+## Env bootstrap (`default/bash/env-bootstrap`)
156
+
157
+Single source of truth for `OMARCHY_PATH` and dev-link-aware `PATH`. It:
158
+
159
+- Sources `/etc/omarchy.conf` (written by `omarchy-dev-link`, reset to the
160
+ package path by `omarchy-dev-unlink`) if present; otherwise forces
161
+ `OMARCHY_PATH=/usr/share/de-omarchy` so a stale inherited value can't survive
162
+ an `omarchy-dev-unlink`.
163
+- Prepends `$OMARCHY_PATH/bin` to `PATH` **only when** `OMARCHY_PATH` is
164
+ not `/usr/share/de-omarchy`. On a production install the binaries are
165
+ already on `PATH` as `/usr/bin/omarchy-*` via the `omarchy` package.
166
+- Appends `~/.local/share/mise/shims` and `~/.local/bin` so login shells and
167
+ the uwsm session find mise-managed tools — kept in sync with the PAM `PATH`
168
+ line written by `install/config/ssh-command-path.sh`, which covers SSH
169
+ commands that run no shell setup at all.
170
+
171
+Sourced by every entry point that needs the env set:
172
+
173
+```
174
+/etc/profile.d/omarchy.sh (system login shells)
175
+/etc/skel/.bashrc (interactive shells)
176
+/usr/share/uwsm/env.d/10-omarchy (Hyprland session via uwsm)
177
+/usr/share/de-omarchy/default/bash/envs (SSH / non-login bash)
178
+```
179
+
180
+Idempotent — safe to source more than once in the same shell.
181
+
182
+`PATH` covers everything the user runs, but not `sudo`, which resolves command
183
+names against `secure_path` from `/etc/sudoers`. So `omarchy-dev-link` also
184
+writes `/etc/sudoers.d/omarchy-dev-path`:
185
+
186
+```
187
+Defaults secure_path="<checkout>/bin:/usr/local/sbin:/usr/local/bin:/usr/bin"
188
+```
189
+
190
+Without it, `sudo omarchy-*` fails for a command the package has not shipped
191
+yet and silently runs the packaged copy of one it has. The drop-in is validated
192
+with `visudo -c` before install and removed by `omarchy-dev-unlink`; unlike
193
+`/etc/omarchy.conf`, it takes effect without a reboot.
194
+
195
+## Runtime finalization (`omarchy-provision-user`)
196
+
197
+Runs once per user. It does **not** copy `~/.config/**`, `~/.bashrc`,
198
+`flags.lua`, or the nautilus extensions — `/etc/skel` already seeded those.
199
+It only does the things `/etc/skel` can't:
200
+
201
+- Skill symlinks `~/.{agents,claude,codex,pi/agent}/skills/<name>` →
202
+ `$OMARCHY_PATH/default/agents/skills/<name>`, looping over every skill
203
+ directory there (currently `omarchy` and `diagnose-crash`) so new skills
204
+ need no edit. Symlinks (not copies) so `omarchy dev link` against a dev
205
+ checkout repoints them correctly.
206
+- `xdg-user-dirs-update` (Templates/Public/Desktop folded back into `$HOME`)
207
+ and `~/.config/gtk-3.0/bookmarks` (needs `$HOME` expansion).
208
+- Hyprland's package-owned default input reads `XKBLAYOUT` / `XKBVARIANT`
209
+ from `/etc/vconsole.conf`; no per-user Hyprland config rewrite is needed.
210
+- `xdg-settings set default-web-browser chromium.desktop` and
211
+ `xdg-mime default HEY.desktop x-scheme-handler/mailto` (XDG-aware paths).
212
+- `omarchy-refresh-applications` (composes generated `.desktop` launchers).
213
+- Sources `install/user/all.sh` — theme, chromium, git, xcompose, mise,
214
+ keyring, per-user hardware quirks (asus mic/mixer, framework f13 audio, …).
215
+- On `--first-install`, marks every shipped user migration as already applied
216
+ for the freshly-created user.
217
+
218
+Idempotency marker: `~/.local/state/omarchy/done/finalize-user`, managed
219
+by `omarchy-done`.
220
+
221
+The ISO calls it as `omarchy-provision-user --force --first-install` in the
222
+target chroot as the install user, after `omarchy-apply-system` has finished
223
+the root-side work. `omarchy-provision-owner` makes the same call (with
224
+`OMARCHY_SETUP_CONTEXT=provision-owner`) when it creates the user during
225
+deferred first-boot provisioning.
226
+
227
+## Migrations (`omarchy-migrate`)
228
+
229
+See [`migrations.md`](../agents/skills/migrations.md) for the full migration model, authoring
230
+guidelines, and troubleshooting notes.
231
+
232
+Omarchy migrations live in `migrations/*.sh` and run per-user through
233
+`omarchy-migrate`. Completion state lives in
234
+`~/.local/state/omarchy/migrations/`, so every user gets a chance to run every
235
+migration. Migrations run as the user; privileged work should invoke the
236
+appropriate helper or privilege prompt. Migrations must be idempotent;
237
+machine-wide repairs should no-op when another user already applied them.
238
+
239
+Each graphical user has `omarchy-migrate-notify.service`, started once per login
240
+through `WantedBy=graphical-session.target` and ordered after that target so
241
+notification actions can safely launch through UWSM. The `omarchy-pkgs`
242
+PKGBUILD has shipped `omarchy-update-user-notify.service` as a symlink onto
243
+it, so users enabled under the old unit name keep working before they reach
244
+migration `1785095882`.
245
+It runs `omarchy-migrate-notify` as
246
+that user, which checks `omarchy-migrate --pending`. If this user has missing
247
+migration state, it shows a notification that opens a terminal for
248
+`omarchy-migrate`. The notifier never runs migrations in the background.
249
+
250
+Login is the only trigger. Nothing watches the packaged migration directory: a
251
+watcher cannot tell a bypassed `pacman -Syu` from the package transaction inside
252
+a normal `omarchy update`, so it notified about migrations that `omarchy-migrate`
253
+was already applying in the visible update terminal.
254
+
255
+`omarchy-migrate` waits for any active pacman transaction to finish, then runs
256
+pending migrations. It does not need `--force`; migrations happen when state
257
+files are missing. `omarchy update` runs `omarchy-migrate` after the package
258
+transaction in the already-visible update terminal, then runs
259
+`omarchy-hook post-update`.
260
+
261
+## First-run (`omarchy-provision-first-run`)
262
+
263
+Runs once on first interactive login, after the user manager is live. It
264
+first runs `omarchy-provision-user || true` so finalize catches up if it
265
+never ran, then handles the steps that need a running graphical session
266
+and/or a working user systemd instance:
267
+
268
+- `omarchy-hook-install post-update` for the three shipped hooks
269
+ (`install-voxtype.hook`, `setup-fingerprint.hook`, `setup-agent.hook`).
270
+- `install/user/first-run/enable-user-units.sh` — daemon-reload, then
271
+ `systemctl --user enable --now` the shipped user units (`bt-agent`,
272
+ `omarchy-sleep-lock`, `omarchy-recover-internal-monitor`,
273
+ `omarchy-migrate-notify.service`, `omarchy-fcitx5.service`,
274
+ `omarchy-crash-watch.service`) so they run in the first session too.
275
+ Done here, not at finalize, because
276
+ the user manager isn't reachable from the ISO chroot; `ConditionPath*`
277
+ in the unit files keeps services inert when they don't apply.
278
+- `install/user/first-run/gnome-theme.sh`,
279
+ `install/user/first-run/gtk-primary-paste.sh` — GNOME/GTK settings that
280
+ need the dconf daemon.
281
+- `install/user/first-run/audio-tuning.sh` — apply speaker tuning.
282
+- `install/user/first-run/welcome.sh` — keybindings toast that greets the
283
+ first login and opens the cheatsheet when clicked. The caller runs
284
+ `omarchy-notification-wait` once before this and the Wi-Fi step, so both
285
+ toasts land on a live notification server.
286
+- `install/user/first-run/wifi.sh` — Wi-Fi/update toasts (waits detached on
287
+ `nm-online` so the update prompt only lands once there is a connection).
288
+
289
+The entire sequence has one idempotency marker:
290
+`~/.local/state/omarchy/done/first-run-user`, managed by `omarchy-done`.
291
+Completed users exit before any first-run step. On failure the marker is not
292
+written and the sequence retries next login.
293
+
294
+Completion markers live under `~/.local/state/omarchy/done/`. Use
295
+`omarchy-done check <name>` to check one and `omarchy-done mark <name>` to record it.
296
+Use `omarchy-done ensure <name>` as a conditional when the guarded work should
297
+run only once; it records completion before returning success.
298
+The Quattro upgrade completes graphical first-run for upgraded users and moves
299
+the legacy finalization marker from `~/.local/state/omarchy/` into `done/`.
300
+
301
+## Root-side install orchestration
302
+
303
+`omarchy-apply-system` (root, in chroot) runs target-side setup at ISO
304
+finalization. It sources:
305
+
306
+- `install/config/all.sh` — theme links, lockout limits, lockscreen PAM,
307
+ powerprofilesctl shebang fix, SSH command path and keepalive, docker setup,
308
+ Snapper retention, locate index tuning, service enablement, firewall.
309
+- `install/hardware/all.sh` via `omarchy-apply-hardware` — vendor- and
310
+ device-specific kernel modules, udev rules, microcode, wireless regdom,
311
+ ASUS / Framework / Intel / Apple / Lenovo quirks.
312
+- `install/login/all.sh` — SDDM theme/session config.
313
+- `install/post-install/all.sh` — final pacman/udev/localdb passes.
314
+
315
+Logging goes to `/var/log/omarchy-install.log` via
316
+`install/helpers/logging.sh`.
317
+
318
+The package lists the ISO pacstraps live at `install/omarchy-base.packages`
319
+and `install/omarchy-other.packages`; the ISO builder also reads them when
320
+constructing its offline mirror.
321
+
322
+## Explicit resync (`omarchy-reinstall-configs`)
323
+
324
+When an existing user wants to reset to shipped defaults:
325
+
326
+```
327
+~/ ← cp -af /etc/skel/.
328
+```
329
+
330
+Replaying `/etc/skel` over `$HOME` is exactly what `useradd -m` does for a
331
+brand-new user, so this one copy resyncs `.bashrc`, `.config/**`,
332
+`.local/share/applications/`, the nautilus-python extensions, hypr toggles,
333
+branding files, and the shipped migration markers in a single pass.
334
+
335
+Then it runs `omarchy-refresh-limine`, `omarchy-refresh-plymouth`, and the
336
+nvim refresh. Destructive: existing user files copied from `/etc/skel` are
337
+clobbered without backup. Fastfetch is package-owned at
338
+`/etc/fastfetch/config.jsonc`; delete `~/.config/fastfetch/config.jsonc` to
339
+return to the packaged default.
340
+
341
+## Quick reference: where does X live?
342
+
343
+| Goal | Touch |
344
+| --- | --- |
345
+| Default file at `~/.config/foo/` | `config/foo/` |
346
+| `/etc/` drop-in we own outright | `etc/` |
347
+| `/etc/` file owned by an upstream package | `etc/` (see `etc/security/faillock.conf`), then add to `etc-overrides` in `omarchy-settings` PKGBUILD + scriptlet |
348
+| Package-owned system file (e.g. systemd user service in `/usr/lib`) | `default/`, then add the `install -Dm644` line in `omarchy-settings` PKGBUILD |
349
+| Per-user file that's static but lives outside `~/.config` | `default/`, then add `install -Dm644 ... $pkgdir/etc/skel/...` in `omarchy-settings` PKGBUILD |
350
+| Runtime tweak that needs `$HOME` or live system state | extend `omarchy-provision-user`, or add a per-user leaf under `install/user/` and wire into `install/user/all.sh` |
351
+| One-time root-side setup step | `install/config/*.sh` or `install/hardware/*.sh`, wire into `install/config/all.sh` or `install/hardware/all.sh` |
352
+| One-time fix for existing installs | `migrations/<unix-timestamp>.sh` |
353
+| Package-owned path something else may already write | Prefer a path nothing else writes, such as a vendor drop-in under `/usr/lib`. Otherwise the `--overwrite` entry in `bin/omarchy-update-system-pkgs` has to ship a release before the file |
354
+| User-facing `omarchy-*` command | `bin/omarchy-<group>-<verb>` — see `GROUP_DESCRIPTIONS` in `bin/omarchy` |
355
+| New stock theme | `themes/<name>/` (+ matching templates under `default/themed/` if they need theme colors) |
356
+| User-installed theme | `~/.config/omarchy/themes/<name>/` |
357
+| Generated current theme/background state | `~/.local/state/omarchy/current/` |
0
358
▼docs/menu.md
+167-0
1
+# The Omarchy menu
2
+
3
+The menu is the `omarchy.menu` plugin of the Quickshell desktop, with its
4
+content defined as data in `default/omarchy/omarchy-menu.jsonc` (read at
5
+runtime from `$OMARCHY_PATH`) and overlaid by the user's
6
+`~/.config/omarchy/extensions/omarchy-menu.jsonc`. The shell parses both files
7
+at startup and watches them for changes, so the keybind → IPC → visible path
8
+never shells out to parse anything, and edits to either file take effect
9
+without restarting the shell. Rendering and behavior live in
10
+`shell/plugins/menu/Menu.qml`; the pure logic lives in
11
+`shell/plugins/menu/MenuModel.js`, which is plain JavaScript that Node can
12
+also load — the shell tests in `test/shell.d/menu-test.sh` and
13
+`menu-guards-test.sh` exercise it directly.
14
+
15
+JSONC here means JSON plus comments and trailing commas, stripped by the
16
+parser rather than a real JSONC grammar: only whole-line `//` comments are
17
+removed, so an inline trailing comment breaks the parse. A file that fails to
18
+parse contributes no entries — a broken user extension silently drops every
19
+user entry while the shipped menu keeps working.
20
+
21
+## Entry schema
22
+
23
+Entries are object keys. The dotted id is the tree: `trigger.share.file` is a
24
+child of `trigger.share`, and an id with no dot sits on the root menu. There
25
+is no separate parent field to keep in sync — where an entry appears follows
26
+from what it is called (an explicit `parent` is accepted but nothing shipped
27
+uses one).
28
+
29
+Kind is inferred rather than declared: an entry with `action` is an action,
30
+one with `target` is a link to another submenu, and anything else is a
31
+submenu. The fields:
32
+
33
+| Field | Meaning |
34
+|---|---|
35
+| `icon` | Glyph in the icon column (usually Nerd Font) |
36
+| `iconFont` | Font family for the glyph when it differs from the menu font — how the private `omarchy` font's brand glyphs render |
37
+| `label` | Visible row title; defaults to the id |
38
+| `title` | Header text when the submenu is open; defaults to `label`. Lets a row read "Browser" under Defaults while the open menu says "Default Browser" |
39
+| `action` | Shell command to run, detached, when selected |
40
+| `target` | Existing submenu id to open; makes the row a link |
41
+| `provider` | Runtime row source for this submenu (see Providers) |
42
+| `aliases` | Alternate `omarchy menu summon <name>` routes; also searchable |
43
+| `description` | Subtitle shown while searching, and extra search text matched by whole word |
44
+| `when` / `checked` / `disabled` | Shell conditions (see Guards) |
45
+
46
+Do not add `aliases` to new entries. They are reserved for established
47
+alternate names users already type (`power-menu`, `settings`), kept for
48
+compatibility — see `AGENTS.md`. Search does not need them: labels, the last
49
+id segment, and descriptions are all searchable.
50
+
51
+## Load and merge
52
+
53
+`mergeMenuSources` overlays user entries on the defaults per key: reusing a
54
+shipped id replaces only the fields you declare, so an extension can retitle
55
+or re-icon a row without re-declaring its action, and an overridden entry
56
+keeps its original position in the list. New ids append. A `root` entry is
57
+injected if neither file declares one.
58
+
59
+The sample extension at `config/omarchy/extensions/omarchy-menu.jsonc`
60
+(refreshed into `~/.config/`) documents the format in its header and ships
61
+only comments, so the default state adds nothing.
62
+
63
+## Guards
64
+
65
+`when`, `checked`, and `disabled` are bash conditions. The shell never
66
+evaluates them on the open path: all guards in the menu are batched into a
67
+single bash process per (re)load and per open, reporting `<id>:<w|c|d>:<0|1>`
68
+lines. The menu opens immediately on the previous evaluation's answers, so
69
+the batch's runtime is exactly how long a row can contradict the state it
70
+describes — which is why the batch works hard to be fast:
71
+
72
+- Package and command presence (`omarchy-pkg-present` and friends) are
73
+ answered in-process from one `pacman -Q` snapshot instead of a fork per
74
+ row. The snapshot resolves provides too, so gvim answers for vim.
75
+- Commands that several rows read a value from — every Defaults > Browser row
76
+ compares against `$(omarchy-default-browser)` — run once, with the captured
77
+ answer substituted into each expression. The reader list is
78
+ `GUARD_READERS` in `MenuModel.js`; a new `$(omarchy-...)` reader used by
79
+ more than one row must be added there, and `menu-guards-test.sh` fails the
80
+ build if it is not.
81
+
82
+The three guards differ in what failure means:
83
+
84
+- `when` hides the row when it fails. A submenu whose visible descendants
85
+ are all hidden disappears with them (provider-backed submenus stay, since
86
+ their rows load on demand).
87
+- `checked` appends ✓ when it succeeds — the "this is the current choice"
88
+ marker on defaults, DNS, channel rows.
89
+- `disabled` keeps the row listed but dims it, marks it ✓, and makes it
90
+ unselectable: cursor, pointer, and Enter all step over it, and search omits
91
+ it. The Install submenus use it so software already on the machine reads as
92
+ installed rather than vanishing from the list it was installed from — the
93
+ list stays a catalog of what Omarchy can install. Since a dimmed row means
94
+ "you already have this", it earns the same ✓ as `checked` does elsewhere.
95
+
96
+Install rows should therefore carry `disabled:` with the presence check, not
97
+`when:`; Remove rows are the opposite, hiding via `when:` what is not there
98
+to remove. `menu-test.sh` enforces the Install side of this convention.
99
+
100
+## Providers
101
+
102
+A submenu with `provider: "name"` gets its rows at runtime instead of from
103
+JSONC. The names are defined by the shell, not the menu file — an extension
104
+can point a submenu at an existing provider but cannot declare a new one:
105
+
106
+- `apps` is QML-native: rows come from the shared AppLibrary (desktop
107
+ entries), carrying image icons, launch feedback, and uninstall support like
108
+ the launcher. App rows are searchable by their desktop Keywords but never
109
+ routable, so an installed app cannot capture a menu route (htop ships
110
+ `Keywords=system;...`, and SUPER+ESCAPE must still open the system menu).
111
+- `fonts` and `power-profiles` are bash one-liners in the `providers` map in
112
+ `Menu.qml`. The contract is one tab-delimited line per row:
113
+ `label\tvalue\tcurrent`. The row whose value equals `current` gets the ✓
114
+ icon, and selection runs the spec's `actionFor(value)`. Row ids are
115
+ `<menuId>.<slugify(value)>`, with a `-` appended on collision so two values
116
+ that slugify alike cannot silently drop a row.
117
+
118
+A provider marked `volatile` re-runs every time its submenu is entered — a
119
+font installed since the shell started shows up without a restart — but not
120
+on search keystrokes, which would restart the same enumeration per key.
121
+
122
+`swapProviderRows` in `MenuModel.js` merges the results: rows carry the id of
123
+the submenu that produced them, so a provider that runs again drops its
124
+previous batch without disturbing static children declared in JSONC. Both it
125
+and the app merge return fresh item maps for the caller to assign in one go —
126
+writing into a map held by a QML `var` property occasionally loses the write,
127
+which used to duplicate launcher rows. Never mutate `root.items` in place.
128
+
129
+Adding a provider means adding an entry to the `providers` map in `Menu.qml`
130
+(script, icon, `actionFor`, optionally `volatile`) and pointing a submenu at
131
+it with `provider:`.
132
+
133
+## Driving the menu from the CLI
134
+
135
+`bin/omarchy-menu` is a thin wrapper over the standard plugin IPC surface:
136
+
137
+```bash
138
+omarchy menu # toggle the root menu
139
+omarchy menu toggle system # open at a route, or close if already open
140
+omarchy menu summon style.theme # always open (no close-if-visible)
141
+omarchy menu close
142
+omarchy menu refresh # re-parse the JSONC files
143
+omarchy menu ping
144
+```
145
+
146
+A route is an item id or a declared alias, case-insensitive, with
147
+underscores normalized to dashes. An exact id beats any alias; empty input,
148
+`go`, and `menu` mean root; an unknown string falls through as a literal id
149
+so a misspelling still attempts to open that id. Summoning a route that
150
+resolves to an action — an alias for a leaf, like `screenrecord-stop` — runs
151
+the action directly instead of opening an action with no children, and a
152
+link is followed to its target. The default Hyprland bindings in
153
+`default/hypr/bindings/utilities.lua` all go through this surface
154
+(SUPER+SPACE toggles root, SUPER+ESCAPE the system menu, and so on).
155
+
156
+## Select and input modes
157
+
158
+The same plugin doubles as the system's dmenu. `omarchy-menu-select` and
159
+`omarchy-menu-input` summon it with a `mode: select` or `mode: input`
160
+payload, then block on a tempfile handshake: the shell writes the selection
161
+to `selectionFile` and touches `doneFile`, and cancellation (empty
162
+selection) exits 1. A select option is `label`, `glyph\tlabel`, or
163
+`glyph\tlabel\tsubtext` — the glyph shows but never returns, the subtext
164
+renders under the label, filters with it, and comes back as
165
+`label\tsubtext` so callers with same-named rows get a stable key. This is
166
+how the pickers behind menu actions (`omarchy-menu-plugin`,
167
+`omarchy-menu-timezone`, ...) present lists without owning any UI.
0
168
▼docs/notifications.md
+143-0
1
+# Notifications
2
+
3
+The shell is the notification daemon: `shell/plugins/notifications/Service.qml`
4
+hosts a Quickshell `NotificationServer` that claims `org.freedesktop.Notifications`
5
+on the session bus. There is no dunst or mako — anything that speaks the
6
+freedesktop notification protocol (notify-send, libnotify apps, Chromium web
7
+apps) lands in the shell, which renders it as a toast card stacked in the
8
+top-right corner. The pure decision logic lives in `NotificationLogic.js`,
9
+which is also loadable from Node so `test/shell.d/` can exercise it without
10
+a compositor.
11
+
12
+The end-user view (hotkey notices for time, battery, weather) is in
13
+`manual/10-notices.md`; this document is the system shape behind it.
14
+
15
+## Toast lifecycle
16
+
17
+A toast lives on screen for at least 5s (low), 8s (normal), or forever
18
+(critical), stretched up to 30s if the sender asked for a longer
19
+`expire_timeout`. Hovering pauses the countdown, and a content update restarts
20
+it — new text deserves a full look. Left-click invokes the default action,
21
+right-click or the hover-revealed close button dismisses.
22
+
23
+Every on-screen popup is mirrored to its own file under
24
+`~/.local/state/omarchy/notifications/` (one JSON line per file, named
25
+`<timestamp>-<id>.json`), so live toasts survive the shell restart that
26
+`omarchy-update` performs. When a toast leaves the screen — expiry, dismissal,
27
+or click — its file moves into `notifications/history/`, trimmed to the newest
28
+ten. That directory *is* the history: `showHistory` replays exactly what has
29
+been moved in there. Referenced avatars/images are copied into
30
+`notifications/images/`, because senders delete their originals on close.
31
+
32
+`replaces_id` updates never produce a second notification signal: the server
33
+writes new content onto the object the service already holds, so the service
34
+watches the object's property-change signals and rewrites the row and its file
35
+in place, under the popup's original file identity. Restored rows carry ids
36
+from a dead server generation (ids restart from 1 each shell process), so
37
+they are keyed by timestamp+id and never matched against live objects — a
38
+fresh notification reusing an old id must not dismiss or replace them.
39
+
40
+## Silencing
41
+
42
+Do-not-disturb is a single boolean, persisted as the `dnd` key in
43
+`~/.local/state/omarchy/notifications.json` and toggled via shell IPC
44
+(`omarchy-shell notifications toggleDnd` / `setDnd` / `dndState`).
45
+`omarchy-toggle-notification-silencing` wraps the toggle and refreshes the
46
+bar's `omarchy.indicators` widget, whose Dnd indicator binds directly to the
47
+service's `doNotDisturb` property.
48
+
49
+Two kinds of notification punch through DND, chosen to be intentional and
50
+rare:
51
+
52
+- `app_name` = `omarchy-action` — Omarchy's own user-action confirmation
53
+ toasts ("Theme changed"). The user just did something; their feedback shows.
54
+- urgency critical *and* `app_name` = `notify-send` — bare-CLI emergency
55
+ alerts. Critical alone is not enough, because chat apps abuse it to force
56
+ visibility; they set `app_name` to their brand, which fails this rule.
57
+
58
+A silenced notification that anyone might look back at is written straight
59
+into history — "what did I miss while silenced" is what history is for.
60
+Ephemeral ones (the freedesktop `transient` hint, or an `app_name` of
61
+`notify-send`/`omarchy-action`) are dropped entirely.
62
+
63
+## The sender contract
64
+
65
+`bin/omarchy-notification-send` is the one way Omarchy code sends
66
+notifications — never raw `notify-send`. It translates its flags into
67
+notify-send arguments and passes any unrecognized options through:
68
+
69
+| Flag | Becomes | Meaning |
70
+|---|---|---|
71
+| `-g` / `--glyph` | `--hint=string:omarchy-glyph:` | Nerd Font glyph for the icon slot when no image icon resolves |
72
+| `--exec` | `--hint=string:omarchy-exec:` | shell command the card runs when clicked |
73
+| `--image` | `--hint=string:image-path:` | the standard freedesktop image hint |
74
+| `--app-name` | `-a` | defaults to `omarchy-action` |
75
+| `-u` / `--urgency` | `-u` | defaults to `low` |
76
+
77
+The defaults are the point: an unadorned `omarchy-notification-send "Done"`
78
+is a low-urgency user-action toast that pops through DND and is treated as
79
+ephemeral noise when silenced.
80
+
81
+`--exec` is deliberately not a libnotify action. An action keeps the sender
82
+blocked waiting for `ActionInvoked`, and dies unanswered whenever the shell
83
+restarts underneath it — the installer toasts restart the shell as their
84
+first act. Carrying the command as a hint means the shell executes the click
85
+itself (detached, so the command outlives the shell process) from the copy it
86
+keeps with the popup, which the persistence files preserve: a restored toast
87
+clicks through exactly like a live one, and oneshot senders can exit
88
+immediately. For third-party clients the click falls back to the libnotify
89
+`default` action while the sender is alive, then to focusing the sender's
90
+window by class via `omarchy-hyprland-focus-app` — chat apps rarely register
91
+an action and just expect click-to-jump.
92
+
93
+## Helper commands
94
+
95
+- `omarchy-notification-wait [timeout]` — polls until the shell answers IPC
96
+ *and* has claimed the bus name. Anything sending near session start or a
97
+ shell restart uses it, or the toast is sent into the void.
98
+- `omarchy-notification-dismiss <summary>` — dismiss by summary substring,
99
+ used by the first-run toasts once their action has been clicked.
100
+- `omarchy-notification-time` / `-battery` — the hotkey notices: one-line
101
+ low-urgency glyph toasts wrapping `date` and `omarchy-battery-status`.
102
+- `omarchy-notification-weather` — despite the name, not a sender: it toggles
103
+ the `omarchy.weather` shell panel.
104
+
105
+Keybindings live in `default/hypr/bindings/utilities.lua`: `Super+comma`
106
+variants map to the IPC methods `dismissOne`, `dismissAll`, `invokeLast`,
107
+`showHistory`, and the silencing toggle.
108
+
109
+## How subsystems plug in
110
+
111
+Everything goes through the same sender contract, so the pieces are small:
112
+
113
+- **Low battery** — `omarchy-battery-low` sends a critical toast and runs the
114
+ `battery-low` hook.
115
+- **Crash capture** — `omarchy-crash-watch` follows the systemd-coredump
116
+ journal stream and announces each crashed program (deduped per minute) as a
117
+ critical toast whose `--exec` runs `omarchy-agent-crash`. It waits for the
118
+ server first: a shell crash takes the notification server down with it, and
119
+ that crash is the one most worth reporting.
120
+- **Pending migrations** — `omarchy-migrate-notify` (from its user service
121
+ after `graphical-session.target`) waits for the server, then sends a
122
+ critical toast whose click opens a terminal running `omarchy-migrate`,
123
+ falling back to printing in the terminal if the hand-off fails.
124
+
125
+## Reminders
126
+
127
+Reminders ride on notifications rather than being their own daemon.
128
+`bin/omarchy-reminder <minutes> [message]` creates a transient systemd user
129
+timer via `systemd-run --user --collect --on-active=<minutes>m` under the
130
+unit name `omarchy-reminder-<minutes>m-<epoch>`; the timer's payload sends the
131
+reminder toast, deletes its message file, and refreshes the bar indicator.
132
+Custom messages are stashed in `$XDG_RUNTIME_DIR/omarchy-reminders/<unit>.message`
133
+since a unit name cannot carry arbitrary text. `--collect` means fired timers
134
+leave nothing behind.
135
+
136
+The state therefore lives entirely in systemd: `show` and `clear` enumerate
137
+`systemctl --user list-timers "omarchy-reminder-*.timer"` — `show` as a
138
+summary toast, `show --json` as the JSON the bar's Reminder indicator polls
139
+(refreshed by the same `omarchy-shell -q omarchy.indicators refresh` call the
140
+timers and mutations make). `omarchy-reminder -i` summons the
141
+`omarchy.reminders` overlay (`shell/plugins/reminders/ReminderFlow.qml`), a
142
+two-step minutes/message prompt that shells back out to `omarchy-reminder` to
143
+do the setting.
0
144
▼docs/omarchy-shell.md
+403-0
1
+# omarchy-shell
2
+
3
+A single long-running [Quickshell](https://quickshell.org/) instance
4
+that hosts the Omarchy desktop. The bar, panels, overlays, menus, and
5
+services all run inside as plugins. Hyprland autostart launches the
6
+shell via `omarchy-launch-shell`; restart it with `omarchy-restart-shell`.
7
+IPC is the canonical way for CLIs to talk to a running shell —
8
+`omarchy-shell` forwards a call and fails when the shell is not running
9
+(`-q` makes it quiet best-effort; `OMARCHY_SHELL_IPC_TIMEOUT` bounds the
10
+wait).
11
+
12
+## Plugin manifest
13
+
14
+```json
15
+{
16
+ "schemaVersion": 1,
17
+ "id": "my.org.cool-clock",
18
+ "name": "Cool clock",
19
+ "version": "1.0.0",
20
+ "author": "You",
21
+ "description": "A clock that does cool things",
22
+ "kinds": ["bar-widget"],
23
+ "entryPoints": { "barWidget": "Widget.qml" }
24
+}
25
+```
26
+
27
+`kinds` (a manifest may declare more than one):
28
+
29
+| Kind | What it is |
30
+|--------------|---------------------------------------------|
31
+| `bar-widget` | Component the active bar drops into a section |
32
+| `bar` | Full bar option that can replace `omarchy.bar` |
33
+| `panel` | Floating window (e.g. OSD) |
34
+| `overlay` | Fullscreen overlay (e.g. background picker) |
35
+| `menu` | Summoned menu surface |
36
+| `service` | Headless singleton, no UI |
37
+
38
+Only one full bar option is active at a time. The built-in `omarchy.bar` is
39
+used when `bar.id` is omitted or when a selected third-party bar cannot load.
40
+Panels, overlays, and menus are loaded when summoned. Plugins can set the
41
+top-level manifest key `keepLoaded: true` to survive between summons.
42
+First-party services are loaded at startup.
43
+
44
+Entry points are QML `Item`s. Panel, overlay, and menu entry points expose
45
+`open(payloadJson)` and `close()` for summon/hide; on load the host injects
46
+`omarchyPath`, `shell`, `manifest`, and the registries (`pluginRegistry` /
47
+`barWidgetRegistry`) as properties.
48
+
49
+Full schema: [`shell/services/PluginRegistry.qml`](../shell/services/PluginRegistry.qml).
50
+
51
+## Installing a third-party plugin
52
+
53
+A plugin is a **git repo** with a `manifest.json` at its root. Adding one
54
+clones it straight into `~/.config/omarchy/plugins/<id>/`; updating is a
55
+fast-forward pull:
56
+
57
+```bash
58
+omarchy plugin add https://github.com/acme/omarchy-weather.git
59
+omarchy plugin update # fetches, shows a diff, fast-forwards
60
+omarchy plugin remove acme.weather
61
+```
62
+
63
+**Setup › Plugins** offers Enable, Disable, Add, Clone, and Remove. Enable and
64
+Disable include built-ins as well as installed plugins. Clone is limited to
65
+built-ins, while Remove is limited to installed plugins since a built-in has
66
+no checkout to delete. Add, Clone, and Remove open a terminal so their warning,
67
+editor, confirmation, and output stay visible.
68
+
69
+Cloning `omarchy.clock`, for example, creates and switches to
70
+`~/.config/omarchy/plugins/<username>.clock/` (e.g. `dhh.clock`), names it
71
+`My Clock`, and preserves the built-in IPC identity so existing shortcuts keep
72
+working. The username prefix keeps a shared clone from colliding with anyone
73
+else's. Saving files in any installed plugin reloads its code automatically,
74
+and removing an active clone switches back to its built-in source.
75
+
76
+For a bar widget, on and off means its place in the bar. Everything else is
77
+loaded by default when it is built in, so `shell.json` records only the
78
+deviation: a third-party plugin you added under `plugins[]`, a built-in you
79
+switched off under `disabledPlugins[]`. A full bar has no off state: enabling
80
+one replaces the active bar, and it is therefore never offered under Disable.
81
+Bar widgets may set `barWidget.defaultSection` to `left`, `center`, or `right`;
82
+widgets that omit it default to `center`.
83
+
84
+Plugins run as **unsandboxed code** inside `omarchy-shell`. Adding warns you
85
+before cloning, plugins land disabled so you can review the code before
86
+`omarchy plugin enable`, and updates show a diff before touching anything.
87
+Commands confirm in a terminal even when given arguments; without one they
88
+refuse rather than guess. Add `--yes` to skip every prompt (the path for
89
+scripts and agents).
90
+
91
+You can still install by hand: drop a plugin into
92
+`~/.config/omarchy/plugins/<id>/`, run `omarchy-shell shell rescanPlugins`, then
93
+`omarchy plugin enable <id>`. A bar widget starts in its declared default
94
+section; enabling a full bar replaces the one in use. `omarchy bar` drives the
95
+bar from the CLI — `use | reset | defaults | position | transparent | put |
96
+move | set`, with placement flags such as `--section` and `--index`.
97
+The lower-level IPC methods remain available through `omarchy-shell shell ...`.
98
+
99
+## IPC
100
+
101
+The shell exposes a `shell` target (the host also registers
102
+`image-selector`) plus targets registered by individual plugins, named
103
+for the plugin rather than for where it appears: `background`, `osd`,
104
+`media`, `notifications`, and per-widget targets such as `omarchy.clock`
105
+or `omarchy.power`. There is no `bar` target.
106
+
107
+| Method | Effect |
108
+|---------------------------------------|---------------------------------|
109
+| `ping` | health check |
110
+| `summon <id> <payloadJson>` | load + open a plugin |
111
+| `hide <id>` | close a previously-summoned |
112
+| `toggle <id> <payloadJson>` | summon if closed, hide if open |
113
+| `togglePanelAt <section> <index>` | toggle the panel at a bar position |
114
+| `call <id> <method> <arg>` | call an already-loaded plugin |
115
+| `rescanPlugins` | re-walk plugin dirs and hot-reload plugin code |
116
+| `reloadConfig` | reload shell.json |
117
+| `applyTheme <colorsB64> <shellB64>` | push theme colors + shell.toml |
118
+| `toggleBarTransparency` | flip the bar background between solid and transparent |
119
+| `setPluginEnabled <id> <"true"\|…>` | flip enabled bit (`ok` / `unknown`) |
120
+| `enablePlugin <id> <placementJson>` | enable and place in one mutation |
121
+| `putBarWidget <id> <placementJson>` | place a widget only where absent (`omarchy bar put`) |
122
+| `moveBarWidget <id> <placementJson>` | move a configured widget |
123
+| `setBarWidget <id> <key> <valueJson> <selectorJson>` | set an inline widget option |
124
+| `listPlugins` | JSON of every discovered plugin |
125
+| `listShellConfig` | effective shell.json as JSON |
126
+| `debugBarGeometry` | bar geometry dump for debugging |
127
+
128
+`setPluginEnabled` takes a string; only literal `"true"` enables. Methods
129
+answer on stdout with exit 0 — `ok` on success, `unknown` or an error
130
+string on a miss.
131
+
132
+## shell.json
133
+
134
+```json
135
+{
136
+ "version": 1,
137
+ "idle": {
138
+ "screensaver": 150,
139
+ "lock": 300
140
+ },
141
+ "bar": {
142
+ "id": "omarchy.bar",
143
+ "position": "top",
144
+ "transparent": false,
145
+ "centerAnchor": "omarchy.clock",
146
+ "layout": {
147
+ "left": [ { "id": "omarchy.menu" } ],
148
+ "center": [ { "id": "omarchy.clock", "format": "HH:mm" } ],
149
+ "right": [ { "id": "omarchy.audio" } ]
150
+ }
151
+ },
152
+ "plugins": [
153
+ { "id": "community.weather-extra" }
154
+ ]
155
+}
156
+```
157
+
158
+Rules:
159
+
160
+1. The active bar option is `bar.id`. Omit it or set it to `omarchy.bar` for
161
+ the built-in bar; set it to a plugin whose manifest declares `kind: "bar"`
162
+ to replace the full bar.
163
+2. Every plugin instance is one entry — `bar.layout.<section>` for
164
+ bar widgets, `plugins[]` for everything else.
165
+3. Settings are inline on the entry. No `config:` sub-object, no
166
+ merge layers.
167
+4. Built-in bar widget ids are namespaced (`omarchy.clock`, `omarchy.audio`, …).
168
+5. Third-party enabled ⇔ present; for full bar options that means `bar.id`.
169
+ First-party non-bar plugins are enabled unless listed in `disabledPlugins[]`.
170
+6. `barWidget.allowMultiple: true` in the manifest permits multiple instances.
171
+7. `idle.screensaver` and `idle.lock` are seconds since user idle began.
172
+8. `version: 1` is required.
173
+
174
+`config/omarchy/shell.json` describes the fresh-install state. When no
175
+user `shell.json` exists, defaults are used verbatim. Once the user
176
+customizes, `shell.json` is canonical — there is no deep-merge.
177
+
178
+`shell.json` is shell configuration; theme tokens live in `shell.toml`
179
+(next section). Both are current — they answer different questions. A
180
+machine-level `~/.config/omarchy/shell.toml` is watched live by the
181
+shell and its keys win over the active theme's `shell.toml`, so
182
+overrides like `omarchy display text size` survive theme switches.
183
+
184
+## Theme tokens
185
+
186
+See [`theming.md`](theming.md) for the full theme/template workflow,
187
+including generated `*.tpl` files, gradient helpers, and shell border syntax.
188
+
189
+Themes ship colors in `themes/<name>/colors.toml` and surface roles +
190
+sizing in `themes/<name>/shell.toml`. Defaults are generated from
191
+`default/themed/shell.toml.tpl`; a theme may also drop a hand-written
192
+`shell.toml` next to its `colors.toml` to replace the generated file,
193
+or override a single section with `shell.<section>.toml`, merged in by
194
+`omarchy-theme-set-templates` (see [`theming.md`](theming.md)).
195
+
196
+`colors.toml` uses `foreground` and `background` for the foundational
197
+text/background palette, exposed to QML as `Color.foreground` and
198
+`Color.background`.
199
+
200
+The shell exposes these tokens to QML via three singletons in
201
+`qs.Commons`:
202
+
203
+- `Color` — palette (`foreground`, `background`, `accent`, `urgent`)
204
+ and per-surface roles (`Color.bar.*`, `Color.popups.*`,
205
+ `Color.tooltip.*`, `Color.notifications.*`, `Color.menu.*`,
206
+ `Color.polkit.*`, `Color.lock.*`, `Color.imagePicker.*`). Clipboard
207
+ and emojis share `Color.menu.*`; the `[launcher]` section is consumed
208
+ by the launcher outside shell QML.
209
+- `Style` — structural tokens (`cornerRadius`), shared interactive
210
+ state tokens/helpers, spacing (`Style.spacing.*` / `Style.space(px)`),
211
+ the type scale (`Style.font.*`), and bar dimensions
212
+ (`Style.bar.sizeHorizontal` / `Style.bar.sizeVertical`).
213
+- `Border` — border-spec helpers for QML surfaces. Use with
214
+ `BorderSurface` from `qs.Ui` when a border should honor shell theme
215
+ gradients or per-side widths. `Color.<section>.border` is only the
216
+ flat-color fallback for code that cannot render a real border.
217
+
218
+### Interactive states
219
+
220
+`[controls]` standardizes reusable control chrome (buttons, dropdowns,
221
+tab strips, etc.) around four states: `normal`, `hover-cursor`, `focus`,
222
+and `selected`. State colors and border tokens accept palette roles
223
+(`foreground`, `accent`, `urgent`, `background`) or hex strings; border
224
+values may also be gradients. Fill alpha applies to the state color;
225
+border alpha applies to the state's border token.
226
+
227
+Surfaces like `[menu]`, `[launcher]`, and `[image-picker]` define
228
+their own `selected-*` tokens and do **not** inherit from `[controls]`.
229
+`[controls]` only governs the shared button/dropdown chrome.
230
+
231
+| State | Color token | Fill alpha | Border token | Border width | Border alpha |
232
+|-------|-------------|------------|--------------|--------------|--------------|
233
+| Normal idle chrome | `normal-color` | `normal-fill-alpha` | `normal-border` | `normal-border-width` | `normal-border-alpha` |
234
+| Hover / keyboard cursor | `hover-cursor-color` | `hover-cursor-fill-alpha` | `hover-cursor-border` | `hover-cursor-border-width` | `hover-cursor-border-alpha` |
235
+| Qt activeFocus | `focus-color` | `focus-fill-alpha` | `focus-border` | `focus-border-width` | `focus-border-alpha` |
236
+| Persistent selected/current | `selected-color` | `selected-fill-alpha` | `selected-border` | `selected-border-width` | `selected-border-alpha` |
237
+
238
+The template ships `focus-*` adjacent to `hover-cursor-*` with the same
239
+values so mouse hover, keyboard cursor, and tab focus read identically.
240
+Themes that want focus to stand out override the `focus-*` keys.
241
+
242
+Border widths are the theme-level on/off switches for state borders; set
243
+a width to `0` to keep the fill while removing that state border. The
244
+default keeps selected borders off globally (`selected-border-width =
245
+0`); explicitly bordered controls keep their normal border when selected.
246
+
247
+```toml
248
+[controls]
249
+# Accent-tinted cursor/focus, foreground-tinted selected state.
250
+hover-cursor-color = "accent"
251
+focus-color = "accent"
252
+selected-color = "foreground"
253
+focus-border = "rgba(33ccffee) rgba(00ff99ee) 45deg"
254
+
255
+# Keep selected fills but remove selected-state borders.
256
+selected-border-width = 0
257
+```
258
+
259
+Momentary fills use `pressed-fill-alpha` for button press feedback and
260
+`selection-fill-alpha` for text selection. Themes may also provide
261
+`pressed-color` or `selection-color`; they fall back to hover-cursor and
262
+foreground respectively.
263
+
264
+The section was previously named `[style]`. Hand-written theme
265
+`shell.toml` files using the old name still apply — the parser accepts
266
+both `[controls]` and `[style]`.
267
+
268
+### Spacing
269
+
270
+`[spacing] scale` multiplies the shell's shared margins, gaps, padding,
271
+control sizes, and panel dimensions. The default is `1.0`; values above
272
+`1.0` create more breathing room while values below `1.0` make controls
273
+dense. By default `scale-with-font = true`, so increasing `[font]
274
+base-size` also scales buttons, popup widths, row heights, and panel
275
+padding proportionally.
276
+
277
+```toml
278
+[spacing]
279
+scale = 1.15
280
+scale-with-font = true # grow controls and panels with [font] base-size
281
+```
282
+
283
+QML components should prefer semantic tokens where possible:
284
+
285
+| Token | Default use |
286
+|-------|-------------|
287
+| `Style.spacing.controlPaddingX` / `controlPaddingY` | Button and tooltip padding |
288
+| `Style.spacing.inputPaddingY` | Text-field vertical padding |
289
+| `Style.spacing.controlHeight` / `popupRowHeight` | Dropdown and number-field row heights |
290
+| `Style.spacing.dropdownWidth` / `searchableDropdownWidth` / `numberFieldWidth` | Default field widths |
291
+| `Style.spacing.searchablePopupMinHeight` | Minimum searchable dropdown popup height |
292
+| `Style.spacing.controlGap` | Gap between icon and label inside controls |
293
+| `Style.spacing.labelGap` | Label-to-control and compact list gaps |
294
+| `Style.spacing.rowGap` / `rowPaddingX` | Form rows and list row content |
295
+| `Style.spacing.panelGap` / `panelPadding` | Panel section spacing and interior padding |
296
+| `Style.spacing.popupPadding` | Popout interior padding |
297
+
298
+Popout placement deliberately follows Hyprland's `general:gaps_out`
299
+(`Style.gapsOut`) so panels align with tiled windows. Use a theme's
300
+`hyprland.lua` to change that outer alignment; `[spacing]` controls the
301
+interior breathing room.
302
+
303
+For one-off proportional constants, use `Style.space(px)` to preserve the
304
+old default at scale `1.0` and `base-size = 12` while still responding to
305
+the theme scale and font scale. Use `Style.spaceReal(px)` only for
306
+fractional geometry that should not be rounded, such as bar widget text
307
+margins. Themes can override any semantic token directly in `[spacing]`,
308
+e.g.:
309
+
310
+```toml
311
+[spacing]
312
+scale = 1.0
313
+panel-padding = 22
314
+row-gap = 10
315
+```
316
+
317
+### Typography
318
+
319
+`[font] base-size` is the rem root for the scale. Every
320
+`Style.font.<token>` derives from it via a fixed multiplier, so
321
+bumping `base-size` rescales the whole shell proportionally:
322
+
323
+| Token | Multiplier | Default |
324
+|-----------------------|------------|---------|
325
+| `Style.font.caption` | 0.833 | 10 |
326
+| `Style.font.bodySmall` | 0.917 | 11 |
327
+| `Style.font.body` | 1.0 | 12 |
328
+| `Style.font.subtitle` | 1.083 | 13 |
329
+| `Style.font.title` | 1.167 | 14 |
330
+| `Style.font.heading` | 1.333 | 16 |
331
+| `Style.font.display` | 2.0 | 24 |
332
+| `Style.font.displayLarge` | 2.333 | 28 |
333
+| `Style.font.iconSmall` | bodySmall | 11 |
334
+| `Style.font.icon` | title | 14 |
335
+| `Style.font.iconLarge` | 1.5 | 18 |
336
+
337
+A theme can either scale everything by tweaking `base-size`:
338
+
339
+```toml
340
+[font]
341
+base-size = 13 # roomier
342
+```
343
+
344
+…or pin individual tokens for stylistic emphasis without affecting
345
+the rest of the scale:
346
+
347
+```toml
348
+[font]
349
+base-size = 12
350
+heading = 20
351
+display-large = 36
352
+```
353
+
354
+Recognized override keys: `base-size`, `caption`, `body-small`,
355
+`body`, `subtitle`, `title`, `heading`, `display`, `display-large`,
356
+`icon-small`, `icon`, `icon-large`.
357
+
358
+`base-size` has no upper clamp; the shell only floors it at **1px** to
359
+avoid nonsensical zero/negative sizes. Per-token overrides aren't clamped
360
+either. The shell font family is the fontconfig `monospace` alias —
361
+themes don't set it, the user does via `omarchy font set <name>`.
362
+
363
+### Bar size
364
+
365
+`[bar] size-horizontal` / `size-vertical` set the cross-axis dimension
366
+of top/bottom and left/right bars respectively, measured at the default
367
+12px font base. By default `scale-with-font = true`, so increasing
368
+`[font] base-size` also increases the bar's cross-axis size:
369
+
370
+```toml
371
+[bar]
372
+scale-with-font = true
373
+size-horizontal = 26 # top/bottom bar height at base-size 12
374
+size-vertical = 28 # left/right bar width at base-size 12
375
+```
376
+
377
+Set `scale-with-font = false` to keep those bar sizes as fixed pixels.
378
+
379
+## Custom bar modules
380
+
381
+If a full plugin is overkill, declare a one-off module inline in
382
+`bar.layout.<section>`:
383
+
384
+```json
385
+{ "id": "vpn", "type": "command", "exec": "~/.config/omarchy/bar/scripts/vpn-status",
386
+ "interval": 5, "tooltip": "VPN", "onClick": "nm-connection-editor" }
387
+```
388
+
389
+Output is plain text or Waybar-style JSON (`{ "text": ..., "tooltip": ..., "class": ... }`).
390
+
391
+For a custom QML widget:
392
+
393
+```json
394
+{ "id": "gpu", "type": "qml" }
395
+```
396
+
397
+Then `~/.config/omarchy/bar/modules/gpu.qml` (or set `source` to point
398
+elsewhere). The module is an `Item` and receives `bar`, `moduleName`,
399
+`settings` properties. `bar` exposes `foreground` / `background` /
400
+`urgent` / `fontFamily` / `position` / `vertical` / `barSize`, plus
401
+`run(cmd)`, `showTooltip(t, s)` / `hideTooltip(t)`,
402
+`requestPopout(o)` / `releasePopout(o)`. To shell-quote arguments for
403
+`run`, use `Util.shellQuote(v)` from `qs.Commons`.
0
404
▼docs/testing.md
+138-0
1
+# Testing
2
+
3
+How the non-graphical test suites are organized: what each runner owns, the
4
+protocol test files speak, and the conventions that keep them runnable on any
5
+machine — including headless CI sandboxes with no compositor. The graphical
6
+acceptance suite is a separate thing that drives a live session in a disposable
7
+VM; see [`agents/skills/acceptance-tests.md`](../agents/skills/acceptance-tests.md).
8
+
9
+## Suite map
10
+
11
+`./test/all` runs both suites below and keeps going when one fails, so a single
12
+failure cannot hide the other suite behind it. It reports the failed suites at
13
+the end and exits non-zero.
14
+
15
+- **`./test/cli`** — one big script, one suite. It owns the CLI router: help
16
+ and group rendering, route resolution, aliases, hidden commands, and the
17
+ guarantee that a trailing `--help` never executes the target. It also owns
18
+ the metadata lint — every `omarchy-*` executable under `bin/` is checked for a
19
+ `# omarchy:summary=` header and against removed or redundant fields — plus
20
+ the theme pipeline: template rendering (`omarchy-theme-set-templates`,
21
+ `omarchy-theme-color`, `omarchy-theme-osc`), the theme sync commands
22
+ (tmux, GNOME, VS Code, Pi, Claude) run against stub binaries and a fake
23
+ `$HOME`, and the theme-state migrations.
24
+- **`./test/shell`** — runs every `test/shell.d/*-test.sh` (except
25
+ `base-test.sh` itself). Each file is an independent suite covering one area:
26
+ a shell plugin, a `bin/` command, a config invariant, a migration. This is
27
+ where new tests go.
28
+- **Acceptance** — everything that needs a real desktop doing real things.
29
+ Deliberately excluded from `./test/all`; it runs in a VM, not the
30
+ development session.
31
+
32
+A new shell test only needs the right name: drop `<area>-test.sh` into
33
+`test/shell.d/` and `./test/shell` picks it up automatically. Shared fixtures
34
+live under `test/shell.d/fixtures/`.
35
+
36
+## The base-test.sh contract
37
+
38
+Every shell test starts the same way:
39
+
40
+```bash
41
+#!/bin/bash
42
+
43
+set -euo pipefail
44
+
45
+source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
46
+```
47
+
48
+`base-test.sh` refuses to be executed directly — it is a library. It discovers
49
+the repo root from its own location and exports it as `ROOT`, so tests
50
+reference files as `$ROOT/bin/...` and never depend on the caller's working
51
+directory or an installed Omarchy.
52
+
53
+Assertions are TAP-flavored and blunt:
54
+
55
+- `pass "description"` prints `ok - description`.
56
+- `fail "description" [detail]` prints the optional detail and
57
+ `not ok - description` to stderr, then **exits the file**. There is no
58
+ counting or continuing within a file: the first failed assertion ends it,
59
+ which keeps later assertions from reporting against state the failure
60
+ already invalidated.
61
+- `require_command <cmd>` fails the file when a needed tool is absent.
62
+
63
+The runner compensates for that early exit: `./test/shell` continues past a
64
+failing file and summarizes the failures at the end. Aborting the whole run at
65
+the first bad file once let a single packaging failure mask 114 of 134 files.
66
+Failure granularity is therefore per file inside a run, per assertion inside a
67
+file.
68
+
69
+## Compositor-dependent tests
70
+
71
+Some tests launch Quickshell or query Hyprland, but the suite must stay green
72
+on headless machines. `require_compositor "description"` handles this: when no
73
+compositor answers it prints `ok - no Wayland compositor; skipping ...` and
74
+exits 0 — a skip is a passing test — and otherwise returns so the file
75
+proceeds.
76
+
77
+The probe is more than an environment check, because `WAYLAND_DISPLAY` only
78
+proves the variable was inherited. Sandboxes pass the environment through
79
+while blocking `$XDG_RUNTIME_DIR`, so Quickshell clears a bare variable check
80
+and then aborts inside QGuiApplication — a core dump per launch where a skip
81
+belonged. So `compositor_reachable` checks the socket actually exists, then
82
+asks Hyprland itself (`hyprctl -j monitors`, retried, and only when
83
+`HYPRLAND_INSTANCE_SIGNATURE` makes it askable), since a compositor that died
84
+mid-session leaves its socket behind. When the compositor is reachable,
85
+`require_compositor` also sets `ulimit -c 0`: Quickshell leaves through
86
+`qFatal()` if its connection drops mid-run, and the test should fail without
87
+writing a core dump as debris.
88
+
89
+Gate only what needs gating — put `require_compositor` in files whose runtime
90
+half needs a live session, and keep static analysis of the same area in code
91
+that runs unconditionally before or beside it.
92
+
93
+## Unit-testing shell JavaScript from bash
94
+
95
+The Quickshell plugins keep their logic in plain `.js` modules
96
+(`shell/plugins/menu/MenuModel.js`, `bar/BarModel.js`, ...) that end in a
97
+guarded `if (typeof module !== "undefined") module.exports = {...}` block. QML
98
+imports them directly and ignores the guard; Node loads them as CommonJS. That
99
+dual citizenship is what makes the shell's model logic unit-testable without a
100
+compositor.
101
+
102
+`run_node_test` is the bridge: it prepends a JS prelude to a heredoc and pipes
103
+the result into `node`. The prelude mirrors the bash assertion protocol
104
+(`pass`, `fail`, `assert`, `assertEqual`, `assertDeepEqual` — same
105
+`ok`/`not ok` lines, same exit-on-first-failure) and provides `root` (from the
106
+exported `ROOT`), `path`, and `requireFromRoot(relativePath)`:
107
+
108
+```bash
109
+run_node_test <<'JS'
110
+const menu = requireFromRoot('shell/plugins/menu/MenuModel.js')
111
+
112
+const parsed = menu.parseMenuJsonc('{ "items": { "root": { "label": "Go" }, }, }')
113
+assertEqual(parsed.length, 1, 'menu parses JSONC with trailing commas')
114
+JS
115
+```
116
+
117
+Roughly a quarter of the shell test files use this to test parsing, merging,
118
+and layout logic as pure functions, reserving compositor-gated tests for what
119
+only a live session can prove.
120
+
121
+## Conventions worth copying
122
+
123
+- **Stub the world, run the real code.** Tests build a scratch `bin/` of stub
124
+ executables (`sudo`, `tmux`, `gsettings`, helper commands) that log their
125
+ arguments to a file, prepend it to `PATH`, and then run the real script
126
+ under test. Assertions grep the call log and the files the script wrote.
127
+- **Fake `$HOME`, real `$OMARCHY_PATH`.** Anything touching user state runs
128
+ with `HOME` pointed at a `mktemp -d` directory (cleaned up via
129
+ `trap ... EXIT`) and `OMARCHY_PATH="$ROOT"`, so tests exercise the checkout
130
+ without touching the developer's machine.
131
+- **Migrations run directly.** A migration test builds the legacy state in a
132
+ fake `$HOME`, runs `bash -euo pipefail "$ROOT/migrations/<ts>.sh"`, and
133
+ asserts the resulting state — including running it twice to prove
134
+ idempotence, and once against non-legacy state to prove it leaves user
135
+ customization alone.
136
+- **Assert the invariant, not the snapshot.** Config tests pin the property a
137
+ test is named for (this widget stays adjacent to that one) rather than whole
138
+ structures, so unrelated churn does not fail them.
0
139
▼docs/theming.md
+368-0
1
+# Omarchy theming
2
+
3
+Omarchy themes live under `themes/<name>/` in the source tree (installed at
4
+`/usr/share/de-omarchy/themes/<name>/`), with optional user themes under
5
+`~/.config/omarchy/themes/<name>/`. A theme normally starts with a
6
+`colors.toml`; Omarchy generates the active theme files from
7
+`default/themed/*.tpl` when `omarchy-theme-set <name>` runs.
8
+
9
+Beyond `colors.toml` and hand-written config overrides, a theme can ship
10
+`backgrounds/` (users overlay their own via
11
+`~/.config/omarchy/backgrounds/<name>/`; the active image is the
12
+`~/.local/state/omarchy/current/background` symlink), `preview.png` and
13
+`preview-unlock.png` for the theme switcher, `icons.theme`, `keyboard.rgb`,
14
+`unlock.png`, and a `light.mode` marker file.
15
+
16
+## Theme activation flow
17
+
18
+`omarchy-theme-set <name>` builds a clean staging directory at
19
+`~/.local/state/omarchy/current/next-theme`:
20
+
21
+1. Copy the first-party theme from `themes/<name>/`.
22
+2. Overlay any user theme files from `~/.config/omarchy/themes/<name>/`.
23
+3. If needed, generate `colors.toml` from `alacritty.toml`.
24
+4. Run `omarchy-theme-set-templates` to render templates into the staging
25
+ theme.
26
+5. Move the staging theme into `~/.local/state/omarchy/current/theme`, write
27
+ `~/.local/state/omarchy/current/theme.name`, and notify the running shell.
28
+
29
+Template rendering only happens when the staged theme has `colors.toml`.
30
+Existing files are never overwritten by a template, so a hand-written
31
+`themes/<name>/shell.toml` or `hyprland.lua` wins over
32
+`default/themed/shell.toml.tpl` or `hyprland.lua.tpl`.
33
+
34
+User templates in `~/.config/omarchy/themed/*.tpl` are processed before the
35
+built-in templates. If a user template has the same output filename as a
36
+built-in template, the built-in output is skipped.
37
+
38
+After activation, `omarchy-theme-set` fires the `theme-set` hook
39
+(`~/.config/omarchy/hooks/theme-set*`, theme name in `$1`) and dispatches a
40
+parallel retint of running apps — terminals, Hyprland, btop, browser, editors,
41
+and the rest of the `post_theme_commands` list in `bin/omarchy-theme-set`.
42
+Making a new app follow theme changes means adding its restart/retint command
43
+to that list. Runs serialize on a `flock`, so scripted theme changes queue
44
+instead of racing.
45
+
46
+## `colors.toml`
47
+
48
+`colors.toml` provides the palette keys used by templates. Keys are grouped
49
+semantic-first: accent/selection/muted, then the backgrounds, then the
50
+foregrounds, then the named colors:
51
+
52
+```toml
53
+mode = "dark"
54
+
55
+accent = "#7aa2f7"
56
+selection = "#292e42"
57
+muted = "#414868"
58
+
59
+background = "#1a1b26"
60
+dark_background = "#13141c"
61
+darker_background = "#0e0e14"
62
+lighter_background = "#24283b"
63
+
64
+foreground = "#a9b1d6"
65
+dark_foreground = "#565f89"
66
+light_foreground = "#b4bee6"
67
+bright_foreground = "#c0caf5"
68
+
69
+red = "#f7768e"
70
+blue = "#7aa2f7"
71
+```
72
+
73
+Any key can be referenced from a template with `{{ key }}`. The foundational
74
+shell palette is loaded from:
75
+
76
+- `foreground` — primary readable text color
77
+- `background` — primary background color
78
+- `accent` — preferred when present; otherwise some places fall back to
79
+ `color4`
80
+- `muted` — de-emphasized elements (comments, placeholders, dividers); also
81
+ serves as ANSI `color8`
82
+- `red` / `color1` — populate the shell's urgent role; there is no `urgent`
83
+ palette key (one defined in `colors.toml` is ignored)
84
+
85
+Themes and user templates using the legacy short names remain supported.
86
+Canonical names take precedence when both forms are defined, and resolved
87
+canonical values are also exposed through their legacy names:
88
+
89
+| Canonical | Legacy |
90
+|-----------|--------|
91
+| `background` | `bg` |
92
+| `dark_background` | `dark_bg` |
93
+| `darker_background` | `darker_bg` |
94
+| `lighter_background` | `lighter_bg` |
95
+| `foreground` | `fg` |
96
+| `dark_foreground` | `dark_fg` |
97
+| `light_foreground` | `light_fg` |
98
+| `bright_foreground` | `bright_fg` |
99
+
100
+The neutral ramp is centered on `background -> bright_foreground`. Dark themes
101
+should read from darkest to lightest; light themes should read from lightest to
102
+darkest. Terminal and editor cursors use `bright_foreground`; there is no
103
+separate cursor palette key. `selection` is the text-selection background stop
104
+in that ramp; Omarchy derives `selection_background = selection` and
105
+`selection_foreground = bright_foreground`. Use
106
+`omarchy dev theme-preview [theme]` to inspect that ramp, including
107
+`dark_background`, `darker_background`, and a selected-text sample.
108
+
109
+## Template placeholders
110
+
111
+Templates are plain files ending in `.tpl`. `omarchy-theme-set-templates`
112
+replaces placeholders with values from `colors.toml`.
113
+
114
+### Color placeholders
115
+
116
+For a color key such as `accent = "#7aa2f7"`:
117
+
118
+| Placeholder | Output |
119
+|-------------|--------|
120
+| `{{ accent }}` | `#7aa2f7` |
121
+| `{{ accent_strip }}` | `7aa2f7` |
122
+| `{{ accent_rgb }}` | `122,162,247` |
123
+
124
+### Color mixing
125
+
126
+`mix`, `mix_strip`, and `mix_rgb` blend two hex colors by a fraction or
127
+percentage:
128
+
129
+```text
130
+{{ mix background foreground 15% }}
131
+{{ mix_strip background accent 0.35 }}
132
+{{ mix_rgb color0 color7 50 }}
133
+```
134
+
135
+### Gradient helpers
136
+
137
+Some theme keys can be either a solid color or a Hyprland-style gradient:
138
+
139
+```toml
140
+hyprland_active_border = "rgba(33ccffee) rgba(00ff99ee) 45deg"
141
+```
142
+
143
+Gradient helper placeholders understand those values:
144
+
145
+| Helper | Use | Example output |
146
+|--------|-----|----------------|
147
+| `{{ hypr_gradient hyprland_active_border accent }}` | Hyprland Lua config | `{ colors = { "rgba(33ccffee)", "rgba(00ff99ee)" }, angle = 45 }` |
148
+| `{{ shell_gradient hyprland_active_border accent }}` | shell border tokens | `rgba(33ccffee) rgba(00ff99ee) 45deg` |
149
+| `{{ gradient_start hyprland_active_border accent }}` | flat-color-only consumers | `#33ccff` |
150
+
151
+The second argument is a fallback. For example,
152
+`{{ shell_gradient hyprland_active_border accent }}` means: use
153
+`hyprland_active_border` if the theme defines it; otherwise use `accent`.
154
+The helper does not choose the first color unless you use `gradient_start`.
155
+
156
+## `shell.toml`
157
+
158
+`shell.toml` contains shell surface roles, control states, spacing, typography,
159
+and bar sizing. The default generated file comes from
160
+`default/themed/shell.toml.tpl`.
161
+
162
+Themes can override the entire generated file by shipping `shell.toml`, or just
163
+one section by shipping `shell.<section>.toml`. For example,
164
+`shell.lock.toml` replaces only the `[lock]` section after the default
165
+`shell.toml` has been generated:
166
+
167
+```toml
168
+text = "#ffffff"
169
+placeholder = "#ffffff"
170
+border = "#ffffff"
171
+```
172
+
173
+The filename decides the target section, so the `[lock]` header is optional.
174
+
175
+The running shell reads `shell.toml` into two QML singletons:
176
+
177
+- `Color` for palette and surface roles like `Color.menu.border`.
178
+- `Style` for controls, spacing, font scale, corner radius, and bar sizing.
179
+
180
+### Borders
181
+
182
+Shell border tokens accept either a solid color or a gradient in the same key:
183
+
184
+```toml
185
+[notifications]
186
+border = "#7aa2f7"
187
+```
188
+
189
+or:
190
+
191
+```toml
192
+[notifications]
193
+border = "rgba(33ccffee) rgba(00ff99ee) 45deg"
194
+```
195
+
196
+Do not add a separate `border-gradient` key for new themes. The parser still
197
+accepts `border-gradient` and `*-border-gradient` for compatibility with older
198
+configs, but the canonical form is the border key itself.
199
+
200
+Border alphas apply to solid borders and to every gradient stop:
201
+
202
+```toml
203
+[notifications]
204
+border = "rgba(33ccffee) rgba(00ff99ee) 45deg"
205
+border-alpha = 0.8
206
+```
207
+
208
+If a color stop already includes alpha, the stop alpha and `border-alpha` are
209
+combined.
210
+
211
+### Border widths
212
+
213
+Border widths accept CSS-style lists:
214
+
215
+```toml
216
+border-width = 2 # all sides
217
+border-width = "2 4" # top/bottom, right/left
218
+border-width = "2 4 6" # top, right/left, bottom
219
+border-width = "2 4 6 8" # top, right, bottom, left
220
+```
221
+
222
+Per-side keys override the list:
223
+
224
+```toml
225
+[notifications]
226
+border-width = 2
227
+border-width-left = 6
228
+```
229
+
230
+That gives notifications a 2px border on the top, right, and bottom, and a 6px
231
+left edge.
232
+
233
+State-specific borders follow the same pattern. A selected menu row can use a
234
+different width from the card border:
235
+
236
+```toml
237
+[menu]
238
+selected-border = "accent"
239
+selected-border-width = "1 1 1 4"
240
+```
241
+
242
+For state-specific surfaces such as lock and polkit, the token name prefixes
243
+the width key:
244
+
245
+```toml
246
+[lock]
247
+border-active = "rgba(33ccffee) rgba(00ff99ee) 45deg"
248
+border-active-width-left = 6
249
+```
250
+
251
+### Control borders
252
+
253
+`[controls]` governs shared controls such as buttons, dropdowns, text fields,
254
+toggles, and cursor rows. Each state has a fill color, optional border value,
255
+border width, and border alpha:
256
+
257
+```toml
258
+[controls]
259
+normal-color = "#a9b1d6"
260
+normal-border = "#a9b1d6"
261
+normal-border-width = 1
262
+normal-border-alpha = 0.4
263
+
264
+hover-cursor-color = "#a9b1d6"
265
+hover-cursor-border = "#a9b1d6"
266
+hover-cursor-border-width = 1
267
+hover-cursor-border-alpha = 0.25
268
+```
269
+
270
+The `*-border` keys can also be gradients:
271
+
272
+```toml
273
+[controls]
274
+focus-border = "rgba(33ccffee) rgba(00ff99ee) 45deg"
275
+focus-border-width = "2 2 2 4"
276
+```
277
+
278
+Set a border width to `0` to keep the fill but remove that state border.
279
+
280
+### Surface sections
281
+
282
+Common shell sections include:
283
+
284
+- `[bar]`
285
+- `[controls]`
286
+- `[popups]`
287
+- `[tooltip]`
288
+- `[notifications]`
289
+- `[launcher]`
290
+- `[menu]`
291
+- `[polkit]`
292
+- `[lock]`
293
+- `[image-picker]`
294
+- `[spacing]`
295
+- `[font]`
296
+
297
+Clipboard and emojis inherit menu tokens. Popups are used by bar flyouts,
298
+dropdowns, OSD, and popup cards.
299
+
300
+## QML border API
301
+
302
+Plugin and shell QML should use `BorderSurface` for theme-aware borders:
303
+
304
+```qml
305
+import qs.Commons
306
+import qs.Ui
307
+
308
+BorderSurface {
309
+ color: Color.popups.background
310
+ borderSpec: Border.surfaceSpec("popups", "border", Color.popups.border, 2)
311
+ padding: Style.spacing.popupPadding
312
+
313
+ Item {
314
+ anchors.fill: parent
315
+ anchors.topMargin: parent.contentTopInset
316
+ anchors.rightMargin: parent.contentRightInset
317
+ anchors.bottomMargin: parent.contentBottomInset
318
+ anchors.leftMargin: parent.contentLeftInset
319
+ }
320
+}
321
+```
322
+
323
+Use `Border.surfaceSpec(section, token, fallbackColor, fallbackWidth, alphaKey)`
324
+for shell theme tokens (the optional `alphaKey` names the alpha token, e.g.
325
+`"border-alpha"`), `Border.controlSpec(state, foreground, accent, urgent)` for
326
+shared controls, and `Border.flat(color, width)` for a deliberate local border
327
+that should not be overridden by the active theme. `Color.<section>.border` is the
328
+flat first-stop color for consumers that cannot render full border specs.
329
+
330
+## Hyprland templates
331
+
332
+Hyprland theme output is generated from `default/themed/hyprland.lua.tpl`.
333
+Use `hypr_gradient` for border values because Hyprland's Lua config wants a
334
+Lua string for solid colors and a Lua table for gradients:
335
+
336
+```lua
337
+local active_border_color = {{ hypr_gradient hyprland_active_border accent }}
338
+```
339
+
340
+For a solid fallback this renders:
341
+
342
+```lua
343
+local active_border_color = "#7aa2f7"
344
+```
345
+
346
+For a gradient it renders:
347
+
348
+```lua
349
+local active_border_color = { colors = { "rgba(33ccffee)", "rgba(00ff99ee)" }, angle = 45 }
350
+```
351
+
352
+## Adding or overriding theme files
353
+
354
+- Add palette values to `themes/<name>/colors.toml`.
355
+- Prefer generated files when the theme can be expressed with templates.
356
+- Add a hand-written file in `themes/<name>/` only when that theme needs to
357
+ override the generated output entirely.
358
+- Add a new built-in template under `default/themed/<file>.tpl` when every
359
+ theme should generate that file.
360
+- Add a user-wide template under `~/.config/omarchy/themed/<file>.tpl` when a
361
+ local customization should apply across themes.
362
+
363
+When changing templates or theme helpers, run focused tests such as:
364
+
365
+```bash
366
+./test/cli
367
+./test/shell
368
+```
0
369
▼docs/update-process.md
+330-0
1
+# Omarchy update process
2
+
3
+This document describes the intended update behavior now that Omarchy is
4
+package-backed. It covers the blessed update path plus what happens when a user attempts to
5
+bypass it:
6
+
7
+1. `omarchy update` — the blessed interactive Omarchy update flow.
8
+2. `sudo pacman -Syu` — guarded by Omarchy and aborted with instructions unless
9
+ the user explicitly bypasses the guard.
10
+
11
+The design goal is:
12
+
13
+- `omarchy update` owns the visible update pipeline: package transaction,
14
+ migrations, post-update hooks, update-state refresh, and restart checks.
15
+- Migrations run per-user after pacman finishes, because they may need `$HOME`,
16
+ DBus/session state, a graphical session, sudo, or user interaction.
17
+- Users who bypass `omarchy update` are nudged back by the pacman guard; if they
18
+ explicitly bypass it, their session is notified when migrations are pending.
19
+
20
+## State and coordination files
21
+
22
+| Path | Owner | Purpose |
23
+| --- | --- | --- |
24
+| `${XDG_RUNTIME_DIR:-/tmp}/omarchy-update.lock` | user | Prevent overlapping update runs. Owned by `omarchy-update-lock`; compatibility wrappers inherit/respect it. |
25
+| `/tmp/omarchy-update.log` | user | Transcript of `omarchy update`, used by `omarchy-update-analyze-logs`. |
26
+| `~/.local/state/omarchy/current/` | user | Generated active theme, selected theme name, and current background symlink. |
27
+| `~/.local/state/omarchy/migrations/` | user | Per-user migration markers. |
28
+| `~/.local/state/omarchy/reboot-required` | user | Optional reboot marker checked by `omarchy-update-restart`. |
29
+| `~/.local/state/omarchy/restart-*-required` | user | Optional service/app restart markers checked by `omarchy-update-restart`. The shell needs no marker: it is restarted unconditionally after every update. |
30
+
31
+## Migration layout
32
+
33
+See [`migrations.md`](../agents/skills/migrations.md) for the full migration model, authoring
34
+guidelines, and troubleshooting notes.
35
+
36
+Migrations live in:
37
+
38
+```text
39
+migrations/*.sh
40
+```
41
+
42
+They run as the current user through:
43
+
44
+```bash
45
+omarchy-migrate
46
+```
47
+
48
+Completion state is per-user:
49
+
50
+```text
51
+~/.local/state/omarchy/migrations/<migration filename>
52
+```
53
+
54
+Every user gets a chance to run every migration. Migrations run as the user;
55
+privileged work should invoke the appropriate helper or privilege prompt.
56
+Migrations must be idempotent; if one user already applied a machine-wide repair,
57
+the migration should no-op for other users.
58
+
59
+For watchers and diagnostics, `omarchy-migrate --pending` prints pending
60
+migration names and exits `0` when any are pending. When no migrations are
61
+pending, it prints nothing and exits non-zero.
62
+
63
+## Raw pacman guard
64
+
65
+The `omarchy` package installs an ALPM pre-transaction hook alongside its guard
66
+binary:
67
+
68
+```text
69
+/usr/share/libalpm/hooks/00-omarchy-update-guard.hook
70
+/usr/bin/omarchy-update-pacman-guard
71
+```
72
+
73
+It triggers on package upgrades and runs:
74
+
75
+```bash
76
+omarchy-update-pacman-guard
77
+```
78
+
79
+The guard detects direct pacman system-upgrade commands like `pacman -Syu` or
80
+`pacman --sync --refresh --sysupgrade`. If the upgrade was not launched by an
81
+Omarchy update command, the hook exits non-zero with `AbortOnFail`, which stops
82
+the transaction before packages are changed.
83
+
84
+`omarchy-update-system-pkgs`, `omarchy-refresh-pacman`, `omarchy-reinstall-pkgs`,
85
+`omarchy-channel-set`, and the v4 upgrader run pacman through:
86
+
87
+```bash
88
+env OMARCHY_UPDATE_PACMAN=1 pacman ...
89
+```
90
+
91
+so the guard allows Omarchy-owned update flows. A user can intentionally bypass
92
+the guard with:
93
+
94
+```bash
95
+sudo env OMARCHY_ALLOW_DIRECT_PACMAN=1 pacman -Syu
96
+```
97
+
98
+The guard does not start `omarchy update` itself because pacman is already in a
99
+transaction setup path; it only aborts with instructions.
100
+
101
+The `omarchy` package also installs ALPM hooks for `omarchy-settings` /
102
+`omarchy-settings-dev` installs and upgrades. The pre-transaction hook runs
103
+`omarchy-hyprland-reload-guard pause` to disable live Hyprland config reloads
104
+while `/usr/share/de-omarchy/default/hypr/**` is replaced. The post-transaction
105
+hook runs `omarchy-hyprland-reload-guard resume`, forces one `hyprctl reload`,
106
+and restores the session's previous `misc.disable_autoreload` and
107
+`debug.suppress_errors` values.
108
+
109
+## Path 1: `omarchy update`
110
+
111
+High-level flow:
112
+
113
+```text
114
+omarchy-update
115
+ ├─ ensure transcript logging through script(1) → /tmp/omarchy-update.log
116
+ ├─ omarchy-update-lock
117
+ │ └─ acquire the update lock and run omarchy-update inside it
118
+ ├─ omarchy-update-requires-free-space
119
+ │ └─ abort below the configured free-space threshold on /
120
+ ├─ confirm unless -y
121
+ ├─ omarchy-update-pkg-prune
122
+ │ └─ trim the pacman cache to two versions per package, deliberately
123
+ │ before the snapshot since the cache lives on the snapshotted subvolume
124
+ ├─ create snapper snapshot (skipped silently without snapper; snapper
125
+ │ installed but unconfigured fails the snapshot loudly, pointing at
126
+ │ install/config/snapper.sh, and the update continues without one)
127
+ ├─ omarchy-update-stay-awake start
128
+ ├─ run package updates, migrations, hooks, and log analysis
129
+ ├─ omarchy-update-status
130
+ │ └─ refresh or clear the shell update indicator
131
+ ├─ omarchy-update-stay-awake stop
132
+ │ └─ release the sleep inhibitor and restore shell idle state, if changed
133
+ └─ omarchy-update-restart
134
+```
135
+
136
+Important behavior:
137
+
138
+- In dev-link mode, `omarchy update` fast-forwards the active checkout from its
139
+ configured upstream before changing system packages or running migrations.
140
+- `-y` exports `OMARCHY_UPDATE_UNATTENDED=1` — a promise not to ask anything.
141
+ Steps that would prompt (orphan removal, conflict handoff) report and skip
142
+ instead of blocking.
143
+- The free-space requirement uses a 10 GiB threshold and stops the update before
144
+ confirmation when it is not met. If free space cannot be determined, the
145
+ check is silently skipped. Set `OMARCHY_UPDATE_FORCE=1` to bypass the check.
146
+- `omarchy update` checks/runs migrations in the same visible terminal via
147
+ `omarchy-migrate` after pacman finishes.
148
+- A failure should leave enough output in `/tmp/omarchy-update.log` and the
149
+ terminal transcript to debug.
150
+
151
+## Path 2: direct `sudo pacman -Syu` attempt
152
+
153
+High-level flow:
154
+
155
+```text
156
+sudo pacman -Syu
157
+ ├─ pre-transaction guard aborts and tells the user to run omarchy update
158
+ └─ if explicitly bypassed, upgrades omarchy and related packages
159
+ └─ at that user's next login
160
+ ├─ graphical-session.target starts
161
+ ├─ omarchy-migrate-notify.service starts after it
162
+ ├─ omarchy-migrate-notify checks omarchy-migrate --pending
163
+ ├─ if this user has missing migration state, show notification
164
+ └─ click opens terminal: omarchy-migrate
165
+```
166
+
167
+Login is deliberately the only trigger. A watcher on the packaged migration
168
+directory cannot distinguish a bypassed `pacman -Syu` from the package
169
+transaction inside a normal `omarchy update`, so it fired notifications for
170
+migrations that `omarchy-migrate` was about to apply in the visible update
171
+terminal. The retired unit was `omarchy-update-user-notify.path`.
172
+
173
+Retiring that watcher through a migration cannot come in time for the update
174
+that retires it: pacman writes the migration directory, the watcher fires, and
175
+only then does `omarchy-migrate` reach the migration that stops it. So the
176
+notifier also refuses to run while `omarchy update` holds its
177
+`$XDG_RUNTIME_DIR/omarchy-update.lock`, which covers the stale watcher and any
178
+trigger added later — during an update, every pending migration is by
179
+definition already being applied a step away. It checks again after waiting for
180
+the notification server, since that wait is long enough for an update to start
181
+underneath it.
182
+
183
+The notifier reads only its own user's runtime directory, never the `/tmp` path
184
+`omarchy-update` falls back to when `XDG_RUNTIME_DIR` is unset. A shared lock
185
+file belongs to whoever created it first, so honouring it would let one user
186
+silence another user's notification. Missing an update and showing a redundant
187
+toast is the better failure.
188
+
189
+Suppression is why `omarchy-update-stay-awake` starts its sleep inhibitor with
190
+the lock descriptor closed. That inhibitor outlives the step that starts it, so
191
+an update killed before cleanup would otherwise leave it holding the flock
192
+indefinitely — blocking later updates and, now that the notifier reads the same
193
+lock, silencing migration notifications at every login.
194
+
195
+Fallbacks:
196
+
197
+- `omarchy-provision-first-run` enables `omarchy-migrate-notify.service`, which also
198
+ covers users created after install: their per-user migration markers are
199
+ missing, so their first login prompts them to run every shipped migration.
200
+- The package ships `omarchy-update-user-notify.service` as a symlink onto
201
+ `omarchy-migrate-notify.service`. Users set up before the rename hold an
202
+ absolute `graphical-session.target.wants` symlink to the old path, and the
203
+ migration that repoints it only runs for users who run an update — the
204
+ opposite of who the notifier is for. The alias can be dropped once installs
205
+ have run migration `1785095882`.
206
+- The notifier is ordered after `graphical-session.target`, so an action that
207
+ launches through `uwsm-app` cannot block the target that gates UWSM's app
208
+ daemon.
209
+- The notifier waits for a live notification server before sending, because
210
+ `graphical-session.target` can be reached before the shell claims
211
+ `org.freedesktop.Notifications`.
212
+- The notifier is only a prompt. It does not run migrations in the background.
213
+- A session that is already open when another user updates is not re-checked;
214
+ it picks the migrations up at its next login, or whenever that user runs
215
+ `omarchy-migrate` or `omarchy update`.
216
+- Direct pacman updates do not run `omarchy-hook post-update` unless the user
217
+ explicitly runs that hook; without a package-update marker, the only pending
218
+ state we can derive is missing per-user migration markers.
219
+
220
+## Shell update indicator
221
+
222
+The bar widget `omarchy.system-update` runs:
223
+
224
+```bash
225
+omarchy-update-available
226
+```
227
+
228
+`omarchy-update-available` checks the active Omarchy sources for updates:
229
+
230
+- new upstream commits for the active dev-linked checkout
231
+- `omarchy-dev`, when installed
232
+- otherwise `omarchy`, when installed
233
+
234
+The dev check fetches the checkout's configured upstream before comparing it
235
+with `HEAD`. A failed fetch is quiet and falls back to the existing remote-
236
+tracking state.
237
+
238
+Exit codes:
239
+
240
+- `0` — Omarchy updates are available; stdout is the update list.
241
+- non-zero — no Omarchy updates are available; stdout says Omarchy is up to date.
242
+
243
+The widget runs this check on shell startup and every six hours. Clicking the
244
+update icon launches `omarchy-update` in a floating terminal.
245
+
246
+## Channels and versions
247
+
248
+Updates install whatever the active channel points at. `omarchy-channel-set
249
+<stable|rc|edge|dev>` switches channels: the three package channels select
250
+which pacman repo the mirrorlist points at (and swap between the `omarchy` and
251
+`omarchy-dev` packages through a guard-allowed pacman run), while `dev` links
252
+the runtime to a git checkout via the dev-link mechanism, after which
253
+`omarchy update` fast-forwards that checkout instead of upgrading a package.
254
+
255
+There is no version file at runtime. `omarchy-version` derives the version from
256
+`pacman -Q` on whichever package is installed, or reports `dev (<hash>)` for a
257
+linked checkout, and `omarchy-version-channel` sniffs the mirrorlist and
258
+pacman.conf to answer which channel is active.
259
+
260
+## Update-related binaries
261
+
262
+This inventory is intentionally opinionated. Some commands are useful as stable
263
+leaf commands; others exist mostly because the old update flow accreted small
264
+scripts.
265
+
266
+| Binary | Current purpose | Keep? / Question |
267
+| --- | --- | --- |
268
+| `omarchy-update` | Public user command. Adds transcript logging, confirmation, snapshot, and restart checks around the locked, sleep-inhibited update pipeline. | **Keep.** This is the blessed entry point and orchestrates the update pipeline. |
269
+| `omarchy-update-lock` | Hidden command wrapper that holds the per-user update lock while its child runs. | **Keep internal/hidden.** Isolates update concurrency and lock descriptor handling. |
270
+| `omarchy-update-stay-awake` | Hidden helper that starts or stops update-owned sleep and idle inhibition, restoring only the state it changed. | **Keep internal/hidden.** Keeps inhibitor ownership and cleanup together. |
271
+| `omarchy-update-status` | Hidden helper that refreshes or clears the shell update indicator after rechecking available updates. | **Keep internal/hidden.** Keeps shell status synchronization out of the main pipeline. |
272
+| `omarchy-update-confirm` | Gum confirmation copy for `omarchy update`. | **Question.** Could be inlined into `omarchy-update`; separate file only helps keep copy isolated. |
273
+| `omarchy-update-dev` | Fast-forwards the active dev-linked checkout from its configured upstream; no-ops for package-backed installs. | **Keep.** Runs before package updates so a checkout conflict stops the update before system mutation. |
274
+| `omarchy-update-keyring` | Ensures Omarchy keyring and Arch keyring are current before the main transaction. | **Keep, but review.** It uses targeted `pacman -Sy` for keyring bootstrapping; acceptable for this special case but should remain tightly scoped. |
275
+| `omarchy-update-system-pkgs` | Runs `sudo env OMARCHY_UPDATE_PACMAN=1 pacman -Syu --noconfirm` with `--overwrite '/usr/share/de-omarchy/*'`, capturing stderr to a report file; on failure it execs `omarchy-update-system-pkgs-when-conflicted`. | **Keep for now.** Small leaf command, clear/testable. |
276
+| `omarchy-update-system-pkgs-when-conflicted` | Hidden conflict handler: quarantines unowned conflicting files under `/var/lib/omarchy/replaced`, retries the upgrade once, restores files the upgrade didn't claim, and hands package-vs-package conflicts to an interactive pacman run (never under `-y`). | **Keep internal/hidden.** Keeps conflict recovery out of the happy path. |
277
+| `omarchy-update-pkg-prune` | Trims the pacman cache to two versions per package (`paccache -rk2`) before the snapshot, keeping the offline downgrade path while capping snapshot growth. | **Keep internal/hidden.** |
278
+| `omarchy-update-requires-free-space` | Aborts the update below a 10 GiB free-space threshold on `/`; silently skipped when free space cannot be determined; `OMARCHY_UPDATE_FORCE=1` bypasses. | **Keep internal/hidden.** |
279
+| `omarchy-migrate` | Public migration command. Waits for pacman, then runs all pending migrations for the current user. Supports `--pending`. | **Keep.** This replaces the discarded `omarchy-update-user-finalize` name and no longer needs `--force`. |
280
+| `omarchy-update-pacman-guard` | ALPM pre-transaction guard that aborts direct `pacman -Syu` style upgrades unless Omarchy set `OMARCHY_UPDATE_PACMAN=1` or the user explicitly set `OMARCHY_ALLOW_DIRECT_PACMAN=1`. | **Keep internal/hidden.** This is what nudges users back to `omarchy update`. |
281
+| `omarchy-migrate-notify` | Internal login-time notification helper. Uses `omarchy-migrate --pending` and shows a notification only when this user has pending migrations. | **Keep internal/hidden.** Clear name now that the public command is `omarchy-migrate`. |
282
+| `omarchy-update-user-notify` | Hidden compatibility wrapper for `omarchy-migrate-notify`. | **Temporary.** Keep only for old callers. |
283
+| `omarchy-update-available` | Update checker for shell widget and post-update refresh. | **Keep.** Could eventually be renamed `omarchy-update-check`, but current name matches widget semantics. |
284
+| `omarchy-update-aur-pkgs` | Updates AUR packages with `yay -Sua` if foreign packages exist and AUR is reachable. | **Question.** Omarchy is package-backed now, but users may still install AUR packages. Keep for now. |
285
+| `omarchy-update-mise` | Runs `MISE_MINIMUM_RELEASE_AGE=0 mise up` for mise-managed tools — the override of mise's release-age cooldown is the point. | **Keep.** Mise-managed tools are intentionally part of the blessed update path. |
286
+| `omarchy-update-orphan-pkgs` | Lists orphans and prompts before removal; noninteractive mode never removes. | **Keep for now.** Safe because it is prompt-only. |
287
+| `omarchy-update-analyze-logs` | Scans `/tmp/omarchy-update.log` for known failure patterns, currently initramfs generation. | **Keep/expand.** Useful safety net; should grow only for high-signal checks. |
288
+| `omarchy-update-restart` | Prompts for reboot after kernel/Hyprland updates, restarts components with `restart-*-required` markers, and always restarts the shell. | **Keep.** Important final step; may eventually include service-restart checks. |
289
+| `omarchy-update-firmware` | Manual firmware update command using fwupd. Not part of the normal update pipeline. | **Keep separate.** Firmware is not a routine system update step. |
290
+| `omarchy-update-time` | Restarts `systemd-timesyncd`. | **Question.** Not really an update command. Consider renaming/moving under system/time maintenance. |
291
+
292
+## Closed decisions
293
+
294
+1. **Migrations run per-user from the update pipeline**
295
+ - `omarchy update` runs `omarchy-migrate` after pacman finishes.
296
+ - Package-time migration runners do not apply migrations inside pacman.
297
+ - Every user has per-user migration markers, and migrations must be
298
+ idempotent when they repair machine-wide state.
299
+
300
+2. **Migration notification naming**
301
+ - The real helper is `omarchy-migrate-notify`, started by
302
+ `omarchy-migrate-notify.service`.
303
+ - `omarchy-update-user-notify` remains only as a hidden compatibility wrapper.
304
+
305
+3. **Update pipeline ownership**
306
+ - `omarchy-update` owns the full update pipeline now.
307
+
308
+4. **Mise remains in the blessed update path**
309
+ - `omarchy-update-mise` intentionally runs as part of `omarchy update`.
310
+
311
+5. **Orphan cleanup stays in the update path for now**
312
+ - It is prompt-only and never removes packages noninteractively.
313
+
314
+6. **Direct pacman user follow-up is based on actual migration state**
315
+ - Direct `sudo pacman -Syu` no longer uses a fake user-update marker.
316
+ - User notifications are shown only when `omarchy-migrate --pending` finds
317
+ missing per-user migration state.
318
+
319
+## Remaining concerns
320
+
321
+1. **Pacman guard scope**
322
+ - The guard detects direct pacman sysupgrade invocations and allows Omarchy
323
+ commands that set `OMARCHY_UPDATE_PACMAN=1`.
324
+ - We may regret blocking some legitimate package-manager frontends or
325
+ maintenance flows. Keep an eye on what should be allowed versus redirected
326
+ to `omarchy update`.
327
+
328
+2. **Pacnew/pacsave handling is still missing**
329
+ - Package-backed Omarchy should warn about or help process `.pacnew` and
330
+ `.pacsave` files after updates.
0
331
▼manual/01-welcome-to-omarchy.md
+11-0
1
+# Welcome to Omarchy!
2
+
3
+Omarchy is an [omakase](https://manuals.omamix.org/3/omacom/76/omakase-computing) Linux distribution based on [Arch](https://archlinux.org/), the tiling window manager [Hyprland](https://hypr.land/), and the desktop construction-kit [Quickshell](https://quickshell.org/). It ships with everything a modern, savvy computer user needs to be productive immediately. From [Neovim](https://neovim.io/) (btw) to Chromium, [Obsidian](https://obsidian.md/) to LibreOffice, and Kdenlive to OBS Studio. Hell, even a retro Winamp-style music player is there!
4
+
5
+This isn't just a grab bag of preinstalled packages, though. It's a complete system designed with both aesthetics and productivity in mind. Because a _beautiful_ system is a _motivating_ system, and productivity has always been [downstream from motivation](https://world.hey.com/dhh/beautiful-motivations-6fef7c73). There's zero bloat here: Just everything I use.
6
+
7
+It's true that developing an eye for the beauty of a TUI-heavy, theme-delighted, tiling-window-managed system like Omarchy can be an acquired taste. But that's why you're here, isn't it? To experience something a little outside of your comfort zone? To embark on a little bit of an adventure into a new way of working with computers? I hope so.
8
+
9
+Omarchy isn't like Windows and it's not like macOS either. It's not trying to be as familiar as possible. It's trying to be beautiful and _better_. Embrace the Linux-ness of it all. Manually editing some config files, sure. Heavy on the terminal, definitely.
10
+
11
+Let's get started with the basics.
0
12
▼manual/02-getting-started.md
+39-0
1
+# Getting Started
2
+
3
+Omarchy is installed using an ISO. You can choose between a full-disk install, which takes over the entire drive, or a free-space install, which puts Omarchy in the unallocated space on a drive — that's how you dual boot alongside Windows or another OS (see [dual-boot install](50-dual-boot-install.md) — note that you'll need to turn off BitLocker in Windows first). Either way, the installation defaults to full encryption, and the full-disk option will wipe the selected drive, so be sure to take a backup before using an existing one!
4
+
5
+[Download the Omarchy ISO](https://omarchy.org/) first, put it on a USB stick (use [balenaEtcher](https://etcher.balena.io/) on Mac/Windows or [caligula](https://github.com/ifd3f/caligula) on Linux), and boot off the stick.
6
+
7
+_You must turn off Secure Boot and/or TPM in the BIOS. You have to turn these off to be able to install Omarchy. They're Microsoft security schemes meant for Windows and Microsoft-affiliated Linux distributions._
8
+
9
+Then answer the configuration questions, and confirm them like this:
10
+
11
+ ![install-config](images/install-config.webp)
12
+
13
+Then select a drive for your installation, and sit back and watch the installation show go. It can be done in under a minute on the fastest modern machines, but it shouldn't take more than 5 minutes even on an older computer.
14
+
15
+ ![install-done](images/install-done.webp)
16
+
17
+Now you're ready to Omarchy!
18
+
19
+### Use a wired or 2.4ghz keyboard!
20
+
21
+The full-disk encryption won't allow you to enter the password from a Bluetooth keyboard at startup. Just like you can't use a Bluetooth keyboard to enter the BIOS on a PC. You'll need a keyboard that either uses a 2.4ghz dongle or a cable (which is much nicer for latency anyway!). I personally love the [Lofree Flow84](https://www.lofree.co/products/lofree-flow-the-smoothest-mechanical-keyboard)!
22
+
23
+### Installing for another owner
24
+
25
+If you're setting up a machine for someone else — a family member, a new employee, a buyer — you shouldn't be answering the personal questions on their behalf. Hit `Ctrl + C` on the very first screen of the installer (the keyboard selection), and Omarchy will offer to prepare the machine for another owner instead. The system installs right away, but all the personal setup — keyboard layout, username, password — is deferred until the machine boots for the first time. The drive is still encrypted by default, and the password the new owner picks on that first boot becomes the encryption password too. (A machine you've already been using can be handed over without a reinstall too — see [resetting the computer](48-security.md).)
26
+
27
+### Unattended installs
28
+
29
+The ISO can also install completely on its own — no keyboard, no wizard — when it's handed its configuration on a second drive. That's the way to treat Omarchy as a base image for VMs and fleet machines. See [unattended installs](51-unattended-installs.md).
30
+
31
+### No-encryption installations
32
+
33
+Omarchy is installed with encryption by default. It's the safe, responsible choice for any computer that can possibly be lost or stolen. You don't want anyone with access to your hardware to be able to get your data!
34
+
35
+But in special circumstances, like remote Omarchy installs on protected computers or for throw-away installations without sensitive data, you may want to install without encryption. You can hit `Ctrl + C` on the disk formatting confirmation to switch to an encryption-less installation.
36
+
37
+### Help if you're stuck
38
+
39
+If you get stuck, you can usually find someone willing to help in the _#omarchy-help_ channel on [the community Discord](https://omarchy.org/discord).
0
40
▼manual/03-coming-from-mac-or-windows.md
+57-0
1
+# Coming From Mac or Windows
2
+
3
+If you've spent years on macOS or Windows, your fingers know a hundred things your brain has forgotten it ever learned. This chapter is the translation layer: where those instincts go in Omarchy. The features themselves are covered in depth elsewhere — this is just the map.
4
+
5
+### Super is the center of everything
6
+
7
+All the muscle memory you've built around Cmd or the Windows key transfers to one key: Super. That's the Windows key on a PC keyboard, and it's the anchor for nearly every hotkey in Omarchy.
8
+
9
+Your Spotlight or Raycast or Start-menu reflex becomes `Super + Space`. That opens the Omarchy menu, which launches apps, changes settings, installs software, captures the screen — just about everything. Start typing to filter. There's also a dedicated apps-only menu on `Super + Alt + Space`. See [navigation](04-navigation.md).
10
+
11
+### There's no dock and no desktop icons
12
+
13
+Nothing to click to launch things, no icons to arrange on the desktop. Apps start from a hotkey (`Super + Return` for the terminal, `Super + Shift + Return` for the browser, and `Super + K` for a list of everything that's mapped) or from the menu. The one persistent piece of UI is [the top bar](05-the-top-bar.md), which covers what the menu bar, system tray, and Notification Center did for you before — and nearly every widget on it does something on left, right, and middle click.
14
+
15
+### Windows place themselves
16
+
17
+The biggest mindset shift: you don't drag windows around or snap them to screen halves. Open a window and it takes the whole screen. Open a second and they split it. You never fish a window out from under another one, because windows don't overlap.
18
+
19
+When you genuinely need a floating window, `Super + T` toggles the active one out of the tiling (and back). But give the tiling a real chance first — it's the heart of the whole thing. [Navigation](04-navigation.md) walks you through it.
20
+
21
+Workspaces will feel familiar: they're macOS Spaces or Windows virtual desktops, except you'll actually use them, because `Super + 1/2/3/4` jumps straight to one and `Super + Shift + 1/2/3/4` sends the active window there. No animation delay, just instant jumps. This means that you might not even need multiple monitors, if you were used to that before.
22
+
23
+### Copy and paste just work
24
+
25
+On the Mac you had Cmd + C everywhere. On Windows you had Ctrl + C everywhere — except the terminal, where it kills your program. Omarchy gives you `Super + C`, `Super + X`, and `Super + V`, and they work everywhere, including the terminal. No separate reflex to learn for the shell.
26
+
27
+Windows folks: your Win + V clipboard history lives on `Super + Ctrl + V`, and it holds images as well as text. See [unified clipboard & history](08-unified-clipboard-history.md).
28
+
29
+### The translation table
30
+
31
+| You reach for | In Omarchy |
32
+| ------------- | ---------- |
33
+| Spotlight / Raycast / Start menu | `Super + Space` — the Omarchy menu |
34
+| AirDrop | LocalSend, via `Super + Ctrl + S` — see [GUIs](22-guis.md) |
35
+| Cmd + Shift + 4 / Win + Shift + S | `Print Screen` — see [screenshots & recording](12-screenshots-recording.md) |
36
+| Notification Center | Notification history on `Super + Shift + Alt + ,` |
37
+| Time Machine (for the system) | Automatic [system snapshots](47-system-snapshots.md) on every update |
38
+| App Store / downloading an installer | _Install_ in the menu, or `omarchy pkg add` — see [other packages](29-other-packages.md) |
39
+| System Settings / Control Panel | _Setup_ in the menu, which edits plain config files — see [dotfiles](31-dotfiles.md) |
40
+
41
+### Some things really are different
42
+
43
+A lot of settings live in text files you edit, not panels you click through. That sounds primitive until you realize it means every tweak can be seen, copied to your next machine, and put in version control. The _Setup_ menu drops you straight into the right file and restarts whatever needs restarting when you're done.
44
+
45
+Updates come through one command — _Update > Omarchy_ — that updates Omarchy itself and every package on the system, taking a snapshot first. No per-app updaters nagging you at random. See [updates](30-updates.md).
46
+
47
+Software comes from a package manager, not from downloaded installers.
48
+
49
+And when you close a window, the app actually quits. There's no macOS limbo where the program keeps running with no windows. `Super + W` means gone.
50
+
51
+### On Mac hardware
52
+
53
+Omarchy runs well on Intel Macs — see [Mac support](44-mac-support.md). And the keyboard is kind to you: Omarchy doesn't remap anything, and Linux treats the Command key as Super, so Super sits right where Cmd always was. Your thumb won't notice the move.
54
+
55
+### Give it two weeks
56
+
57
+The instincts transfer faster than you'd think. Skim the [hotkeys](07-hotkeys.md) chapter once, and whenever you blank on a binding, hit `Super + K` — it shows you all of them. That's the only hotkey you actually have to memorize.
0
58
▼manual/04-navigation.md
+71-0
1
+# Navigation
2
+
3
+Everything in Omarchy happens via the keyboard — _EVERYTHING!_ When the system first starts, you literally can't do a thing with the mouse alone. But you can hit `Super + Space` to reveal the Omarchy Menu and from here you to do just about everything.
4
+
5
+But the Omarchy menu is not even intended to be the main way to operate the system most of the time. We can get faster than that! All the most important applications are bound directly to individual hotkeys. You start the terminal with `Super + Return` and a browser with `Super + Shift + Return`. Try doing one after the other, and you'll see the magic of Hyprland's tiling in action:
6
+
7
+ ![navigation-browser-terminal](images/navigation-browser-terminal.webp)
8
+
9
+You can then hit `Super + J` to stack them on top of each other instead of side by side:
10
+
11
+ ![navigation-stacked](images/navigation-stacked.webp)
12
+
13
+Hit `Super + J` again to return them to their side-by-side positions. Then try `Super + Shift + Arrow Right` while on the browser to swap the windows.
14
+
15
+Now try `Super + Ctrl + T` to start the Activity monitor. That'll appears as a floating window. You can tile it using `Super + T` (and hit that again to make it floating again). Now press `Super + Shift + F` to open the files manager. You'll have a neat four-way setup:
16
+
17
+ ![navigation-fourway-tiling](images/navigation-fourway-tiling.webp)
18
+
19
+You navigate between the window you want to be active with `Super + Arrow`. This will switch focus and move the cursor to the center of the new application.
20
+
21
+If you hit `Super + Shift + 2`, you'll move the current focused application onto the second workspace. `Super + Shift + 1` moves it back. (And `Super + Shift + Alt + 2` will move the current focused application onto the second workspace without switching to it).
22
+
23
+If you hold down `Super` and use the mouse to click on a window, you'll be able to rearrange where it sits. If you hold `Super` and use the right button on the mouse, you can freely resize the window.
24
+
25
+You close a window on `Super + W` (and close all windows on `Ctrl + Alt + Delete`).
26
+
27
+You can also go full screen with `Super + F` or even just full-width (keeping the top bar) with `Super + Alt + F` or full-screen within a window with `Super + Ctrl + F` (good for YouTube!).
28
+
29
+### Dwindle vs scrolling layout
30
+
31
+Omarchy's default layout is called dwindle. It keeps all the windows you open on a single workspace visible at all time, even if it has to shrink them down.
32
+
33
+ ![navigation-dwindle-layout](images/navigation-dwindle-layout.webp)
34
+
35
+But you can also choose to turn a workspace into the scrolling layout where windows are lined up side-by-side, beyond the visible edge of the display. You turn a single workspace into this layout via `Super + L`.
36
+
37
+ ![navigation-scrolling-layout](images/navigation-scrolling-layout.webp)
38
+
39
+The choice is per workspace, and it sticks. So you can keep workspace 1 on dwindle for browsing and workspace 2 on scrolling for code, and they'll come back that way after a restart. (The same toggle is under _Trigger > Toggle > Workspace Layout_ in the Omarchy menu).
40
+
41
+If you wish to use the scrolling layout as the default, you can set that in `~/.config/hypr/looknfeel.lua`:
42
+
43
+```lua
44
+hl.config({
45
+ general = {
46
+ layout = "scrolling",
47
+ },
48
+})
49
+```
50
+
51
+### Grouping windows
52
+
53
+Windows can be grouped using `Super + G`. Once you're in a group, every window you start while that's active will belong to the group. You can move between these grouped windows using `Super + Ctrl + Arrow Left/Right` or `Super + Alt + 1/2/3/4` to go directly to grouped window in order.
54
+
55
+You can move a window out of the grouping with `Super + Alt + G` or disassemble the entire group by hitting `Super + G` again. Finally, you can move windows outside the group into it with `Super + Alt + Arrows`.
56
+
57
+### Popping windows
58
+
59
+You can pop a window out of its workspace allocation with `Super + O`. That'll pin it as a floating window that follows you on whatever workspace you go to. Great for video players and the like.
60
+
61
+ ![navigation-popped-window](images/navigation-popped-window.webp)
62
+
63
+### Scratchpad workspace
64
+
65
+Finally, there's a special scratchpad workspace that drops down over whatever workspace you're currently on, much like a Quake console. Toggle it with `Super + Grave` or `Super + S`, and place a window there using `Super + Shift + Grave` or `Super + Alt + S`.
66
+
67
+It works especially well for a terminal running an agent, or for controls you want to interact with quickly without leaving the current workspace. To move a window off the scratchpad, send it directly to another workspace with something like `Super + Shift + 1`.
68
+
69
+### It takes some getting used to!
70
+
71
+It takes a little while to get used to navigating your desktop like this, but once you do, it'll be hard to go back to a traditional mouse-driven desktop experience!
0
72
▼manual/05-the-top-bar.md
+134-0
1
+# The Top Bar
2
+
3
+The strip along the top of your screen is the Omarchy bar. It's not a bolted-on status bar but part of the Omarchy shell, the single long-running Quickshell process that also draws the menu, the notifications, the OSD popups, and the lock screen. That's why it themes perfectly with everything else and why a panel opens instantly instead of spawning a new app.
4
+
5
+It's also the one piece of the desktop that's always on screen, so it's worth knowing what all those little glyphs do.
6
+
7
+## What's on it by default
8
+
9
+The bar has three sections. On the left sits the Omarchy logo (the menu launcher) and the workspace indicators. In the center you get the status indicators, the clock, the keyboard layout, the weather, and an Omarchy update badge. On the right: the system tray, agents, bluetooth, network, audio, display, and power.
10
+
11
+A few of those only show up when they have something to say. The keyboard layout appears only if you've configured more than one layout. The update badge appears only when there's an Omarchy update waiting. And the agents icon appears the first time Omarchy finds AI coding usage on the machine (see [AI](17-ai.md)).
12
+
13
+## Clicking around
14
+
15
+Nearly every widget does something on left, right, and middle click, and several respond to scrolling. This is the part people miss — the right and middle buttons are where a lot of the good stuff hides.
16
+
17
+| Widget | Left | Right | Middle / scroll |
18
+| --- | --- | --- | --- |
19
+| Menu | Omarchy menu | New terminal | — |
20
+| Workspaces | Focus that workspace | — | — |
21
+| Clock | Calendar popup | Cycle the label format | Middle: timezone picker |
22
+| Weather | Forecast popup | Full weather as a notification | Middle: refresh |
23
+| Audio | Audio panel | Mute | Middle: panel · scroll: volume |
24
+| Microphone | Mute the mic | — | Middle: audio panel · scroll: input volume |
25
+| Network | Network panel | — | — |
26
+| Bluetooth | Bluetooth panel | Toggle the radio | — |
27
+| Display | Display panel | — | Scroll: brightness |
28
+| Power | Power panel | Toggle the battery percentage | — |
29
+| Media | Play/pause | Cover-art popup | Middle: next · scroll: prev/next |
30
+| Agents | Agents panel | Launch your agent | Middle: next subscription |
31
+| Tray | Hover to reveal the drawer | Right on the chevron to manage | — |
32
+| Omarchy update | Run the update | — | — |
33
+
34
+Not everything in that table is on your bar out of the box. The media widget (MPRIS now-playing, with a scrolling track and artist) and the microphone widget are both built in but off by default — add them if you want them, as described below.
35
+
36
+## The panels
37
+
38
+Clicking a bar icon opens a panel, which is a proper popup with sliders, lists, and keyboard navigation rather than a tooltip. Each one also has a hotkey, so you never have to aim at a 16-pixel glyph:
39
+
40
+| Hotkey | Panel |
41
+| --- | --- |
42
+| `Super + Ctrl + A` | Audio |
43
+| `Super + Ctrl + W` | Network |
44
+| `Super + Ctrl + B` | Bluetooth |
45
+| `Super + Ctrl + D` | Display |
46
+| `Super + Ctrl + P` | Power |
47
+| `Super + Ctrl + Alt + D` | Calendar |
48
+| `Super + Ctrl + 1-9` | Toggle the nth panel in the right section |
49
+
50
+The panels aren't read-outs. They're where you actually do the thing:
51
+
52
+- **Audio** has a master volume slider, an output-device picker, and a per-app mixer, so you can turn down that one browser tab without touching everything else.
53
+- **Network** scans for Wi-Fi, shows signal strength, connects, and lets you pick a DNS provider.
54
+- **Bluetooth** lists your devices with connect/disconnect and battery levels.
55
+- **Power** shows battery stats, switches power profiles (it remembers a separate choice for battery and AC), and prints some system info.
56
+- **Display** carries a brightness slider, text size, monitor scaling presets, and — when you have more than one screen — per-monitor controls. See [monitors](33-monitors.md) for the deeper story.
57
+- **Clock** opens a month grid with ISO week numbers and month stepping.
58
+
59
+Every panel takes the keyboard as well as the mouse: arrows move, Return activates, Tab steps to the neighbouring panel, and Escape closes.
60
+
61
+`Super + Ctrl + 1-9` counts panels left to right in the right section, skipping the tray since it has no panel of its own. So the number matches the icon you'd point at.
62
+
63
+### Tailscale and Dropbox
64
+
65
+Two more widgets appear on the bar only once you install the matching service from **Install → Service**, and both are worth knowing about because they do more than report status.
66
+
67
+The **Tailscale** panel connects and disconnects the tailnet, switches between accounts, and picks an exit node (your own machines and Mullvad regions both show up in that list). It also browses your machines — and with one selected, `s` sends files to it over Taildrop, which is the fastest way to move a file to your phone or another laptop. `c` copies the machine's IP, `n` its name, and `d` its full DNS name. There's a send button on each machine row too, if you'd rather click. The same thing from the terminal is `omarchy tailscale send <machine> [file...]`.
68
+
69
+The **Dropbox** panel handles login, shows how much storage you've used, and lists recently synced files.
70
+
71
+Removing either service takes its widget back off the bar.
72
+
73
+## Indicators
74
+
75
+The little cluster in the center is the indicators widget. These are status glyphs for modes you've turned on: do not disturb, night light, a queued [reminder](09-reminders.md), an active screen recording, stay awake, and [dictation](11-text-extraction-dictation.md). They light up when the mode is active and otherwise stay out of the way — hover the center of the bar to peek at the inactive ones. Clicking an indicator toggles that mode.
76
+
77
+If you'd rather they were always visible, set `alwaysShow` to `true` on the widget. And if you only care about some of them, list the ones you want in `items`: `["Dnd", "Reminder", "NightLight"]`. You can have more than one indicators widget, so different sections can show different subsets.
78
+
79
+## Rearranging the bar
80
+
81
+The bar configures itself. You don't have to open a config file to move things.
82
+
83
+Grab an empty patch of the bar around the center and drag it toward another screen edge, and the bar moves there — left, right, top, or bottom all work, and every widget adapts (vertical bars fall back to compact icon-only forms). A click-and-hold starts the same drag. Double-left-click that same empty space to toggle transparency. And drag any widget to reorder it or throw it into another section.
84
+
85
+If you'd rather pick from a menu, **Style → Menu Bar** has both position and transparency.
86
+
87
+The same things have commands, which is what you want for a [dotfiles](31-dotfiles.md) setup:
88
+
89
+```bash
90
+omarchy bar position bottom
91
+omarchy bar transparent toggle
92
+omarchy bar move omarchy.clock --section center --index 0
93
+omarchy bar set omarchy.clock format "HH:mm"
94
+omarchy bar defaults # back to the shipped layout
95
+```
96
+
97
+To add or remove a widget entirely, use the plugin commands. `omarchy plugin list` prints every widget the shell knows about with its id, and then:
98
+
99
+```bash
100
+omarchy plugin enable omarchy.media --section center
101
+omarchy plugin disable omarchy.weather
102
+```
103
+
104
+## Hiding the bar
105
+
106
+`Super + Shift + Space` toggles the bar off and back on without killing the shell — panels and hotkeys keep working, you just get the pixels back. It's also in the menu under **Trigger → Toggle → Menu Bar**.
107
+
108
+## The config file
109
+
110
+All of it is stored in `~/.config/omarchy/shell.json`, under the `bar` key. Here's a trimmed version:
111
+
112
+```json
113
+{
114
+ "version": 1,
115
+ "bar": {
116
+ "position": "top",
117
+ "transparent": false,
118
+ "centerAnchor": "omarchy.clock",
119
+ "layout": {
120
+ "left": [{ "id": "omarchy.menu" }, { "id": "omarchy.workspaces" }],
121
+ "center": [{ "id": "omarchy.clock", "format": "HH:mm" }],
122
+ "right": [{ "id": "omarchy.audio" }, { "id": "omarchy.power" }]
123
+ }
124
+ }
125
+}
126
+```
127
+
128
+Every widget is one entry in one of the three layout arrays, and its settings sit inline on that entry — there's no separate settings file and no `config` sub-object. The clock's `format`, `formatAlt` (what right-click cycles to), and `verticalFormat` all live right there on `{ "id": "omarchy.clock" }`.
129
+
130
+`centerAnchor` names the one center widget that gets pinned to the exact center of the screen, with the others flanking it. That's how the clock stays dead center even as the weather and update badge come and go. Set it to an empty string and the center list is just centered as a group instead.
131
+
132
+One rule worth internalizing: **once you have your own `shell.json`, it's canonical**. Until you customize anything, the shell reads Omarchy's default file. The moment you drag a widget, run `omarchy bar`, or edit the file yourself, you own it — there's no deep merge, so new default widgets in future Omarchy releases won't appear on your bar automatically. `omarchy bar defaults` puts the shipped layout back whenever you want a clean slate.
133
+
134
+The same file also holds your idle timings at the top level, outside the `bar` key: `idle.screensaver` and `idle.lock`, both in seconds since you went idle. So the default screensaver kicks in at 150 seconds and the lock at 300.
0
135
▼manual/06-themes.md
+127-0
1
+# Themes
2
+
3
+Omarchy comes with twenty-two beautiful themes. You can select between them via _Style > Theme_ in the Omarchy Menu (`Super + Space`) or hop directly to the theme selector using `Super + Ctrl + Shift + Space`.
4
+
5
+Each theme styles the desktop, terminal, neovim, activity screen (btop), Chromium, and the entire Omarchy shell: top bar, menu, notifications, OSD, and the lock screen. (For Obsidian, you must manually select the Omarchy theme via _Appearance > Themes_ inside the app).
6
+
7
+Themes have a set of background images that you can pick between using `Super + Ctrl + Space`.
8
+
9
+You can find even more themes on [the extra themes page](https://omarchy.org/themes/) or even [make your own theme](43-making-your-own-theme.md).
10
+
11
+ ![tokyo-night](../themes/tokyo-night/preview.png)
12
+_Tokyo Night_
13
+
14
+ ![catppuccin](../themes/catppuccin/preview.png)
15
+_Catppuccin_
16
+
17
+ ![lumon](../themes/lumon/preview.png)
18
+_Lumon_
19
+
20
+ ![ethereal](../themes/ethereal/preview.png)
21
+_Ethereal_
22
+
23
+ ![everforest](../themes/everforest/preview.png)
24
+_Everforest_
25
+
26
+ ![gruvbox](../themes/gruvbox/preview.png)
27
+_Gruvbox_
28
+
29
+ ![miasma](../themes/miasma/preview.png)
30
+_Miasma_
31
+
32
+ ![hackerman](../themes/hackerman/preview.png)
33
+_Hackerman_
34
+
35
+ ![osaka-jade](../themes/osaka-jade/preview.png)
36
+_Osaka Jade_
37
+
38
+ ![kanagawa](../themes/kanagawa/preview.png)
39
+_Kanagawa_
40
+
41
+ ![nord](../themes/nord/preview.png)
42
+_Nord_
43
+
44
+ ![matte-black](../themes/matte-black/preview.png)
45
+_Matte Black_
46
+
47
+ ![vantablack](../themes/vantablack/preview.png)
48
+_Vantablack_
49
+
50
+ ![ristretto](../themes/ristretto/preview.png)
51
+_Ristretto_
52
+
53
+ ![retro-82](../themes/retro-82/preview.png)
54
+_Retro 82_
55
+
56
+ ![flexoki-light](../themes/flexoki-light/preview.png)
57
+_Flexoki Light_
58
+
59
+ ![rose-pine](../themes/rose-pine/preview.png)
60
+_Rose Pine_
61
+
62
+ ![catppuccin-latte](../themes/catppuccin-latte/preview.png)
63
+_Catppuccin Latte_
64
+
65
+ ![white](../themes/white/preview.png)
66
+_White_
67
+
68
+### Unlocks
69
+
70
+Themes can also have a custom unlock design, which is used for the boot decryption process. You can select one of these under _Style > Unlock_. They look like this:
71
+
72
+ ![catppuccin](../themes/catppuccin/preview-unlock.png)
73
+_Catppuccin_
74
+
75
+ ![catppuccin-latte](../themes/catppuccin-latte/preview-unlock.png)
76
+_Catppuccin Latte_
77
+
78
+ ![ethereal](../themes/ethereal/preview-unlock.png)
79
+_Ethereal_
80
+
81
+ ![everforest](../themes/everforest/preview-unlock.png)
82
+_Everforest_
83
+
84
+ ![flexoki-light](../themes/flexoki-light/preview-unlock.png)
85
+_Flexoki Light_
86
+
87
+ ![gruvbox](../themes/gruvbox/preview-unlock.png)
88
+_Gruvbox_
89
+
90
+ ![hackerman](../themes/hackerman/preview-unlock.png)
91
+_Hackerman_
92
+
93
+ ![kanagawa](../themes/kanagawa/preview-unlock.png)
94
+_Kanagawa_
95
+
96
+ ![lumon](../themes/lumon/preview-unlock.png)
97
+_Lumon_
98
+
99
+ ![matte-black](../themes/matte-black/preview-unlock.png)
100
+_Matte Black_
101
+
102
+![miasma](../themes/miasma/preview-unlock.png)
103
+_Miasma_
104
+
105
+ ![nord](../themes/nord/preview-unlock.png)
106
+_Nord_
107
+
108
+ ![osaka-jade](../themes/osaka-jade/preview-unlock.png)
109
+_Osaka Jade_
110
+
111
+ ![retro-82](../themes/retro-82/preview-unlock.png)
112
+_Retro 82_
113
+
114
+ ![ristretto](../themes/ristretto/preview-unlock.png)
115
+_Ristretto_
116
+
117
+![rose-pine](../themes/rose-pine/preview-unlock.png)
118
+_Rose Pine_
119
+
120
+ ![tokyo-night](../themes/tokyo-night/preview-unlock.png)
121
+_Tokyo Night_
122
+
123
+ ![vantablack](../themes/vantablack/preview-unlock.png)
124
+_Vantablack_
125
+
126
+ ![white](../themes/white/preview-unlock.png)
127
+_White_
0
128
▼manual/07-hotkeys.md
+373-0
1
+# Hotkeys
2
+
3
+You can see all the main keyboard bindings with `Super + K` (Tmux bindings with `Super + Alt + K` and Herdr bindings with `Super + Ctrl + K`).
4
+
5
+## Navigating
6
+
7
+| Hotkey | Function |
8
+| ----------------------- | --------------------- |
9
+| `Super + Space` | Omarchy menu (apps and everything else) |
10
+| `Super + Alt + Space` | Apps menu |
11
+| `Super + Escape` | System menu (suspend, restart, etc) |
12
+| `Super + Ctrl + L` | Lock computer |
13
+| `Super + W` | Close window |
14
+| `Ctrl + Alt + Del` | Close all windows |
15
+| `Super + T` | Toggle window between tiling/floating |
16
+| `Super + J` | Toggle window position (horizontal/vertical) |
17
+| `Super + O` | Toggle popping window into sticky'n'floating |
18
+| `Super + L` | Toggle between dwindle and scrolling layout |
19
+| `Super + P` | Toggle pseudo window style (natural v stretch) |
20
+| `Super + F` | Go full screen |
21
+| `Super + Alt + F` | Go full width |
22
+| `Super + Ctrl + F` | Go full screen inside window |
23
+| `Super + 1/2/3/4` | Jump to specific workspace |
24
+| `Super + Tab` | Jump to next workspace |
25
+| `Super + Shift + Tab` | Jump to previous workspace |
26
+| `Super + Ctrl + Tab` | Jump to former workspace |
27
+| `Super + Shift + 1/2/3/4` | Move window to workspace |
28
+| `Super + Shift + Alt + 1/2/3/4` | Move window to workspace without following |
29
+| `Super + S` / `Super + Grave` | Toggle scratchpad |
30
+| `Super + Alt + S` / `Super + Shift + Grave` | Move window to scratchpad |
31
+| `Super + Shift + Alt + Arrows` | Move workspaces to directional monitor |
32
+| `Super + Arrow` | Move focus to window in direction of arrow |
33
+| `Super + Shift + Arrow` | Swap window with another in direction of arrow |
34
+| `Super + Minus` | Expand window left |
35
+| `Super + Equal` | Shrink window left |
36
+| `Super + Shift + Minus` | Shrink window up |
37
+| `Super + Shift + Equal` | Expand window down |
38
+| `Super + Alt + Minus/Equal` | Same resizing in smaller steps |
39
+| `Super + Ctrl + Minus/Equal` | Same resizing in bigger steps |
40
+| `Super + Alt + Home` | Save window width |
41
+| `Super + Home` | Restore saved window width |
42
+| `Super + Left Mouse` | Drag window around |
43
+| `Super + Right Mouse` | Resize window |
44
+| `Super + Scroll Wheel` | Scroll through workspaces |
45
+| `Super + G` | Toggle window grouping |
46
+| `Super + Alt + G` | Move window out of grouping |
47
+| `Super + Alt + Tab` | Cycle between windows in grouping |
48
+| `Super + Alt + Shift + Tab` | Cycle backward between windows in grouping |
49
+| `Super + Alt + 1/2/3/4/5` | Jump to specific window in grouping |
50
+| `Super + Alt + Arrow` | Move window into grouping in direction of arrow |
51
+| `Super + Ctrl + Left/Right` | Move between windows inside a tiling group |
52
+| `Super + Ctrl + Z` | Zoom in on screen (repeat for more zoom) |
53
+| `Super + Ctrl + Alt + Z` | Zoom fully out from screen |
54
+| `Super + /` | Step forward through monitor scaling options |
55
+| `Super + Alt + /` | Step backward through monitor scaling options |
56
+| `Alt + Tab` | Cycle forward through windows on the active workspace |
57
+| `Alt + Shift + Tab` | Cycle backward through windows on the active workspace |
58
+| `Ctrl + Alt + Tab`| Cycle focus forward through monitors |
59
+| `Ctrl + Alt + Shift + Tab`| Cycle focus backwards through monitors |
60
+
61
+## System controls
62
+
63
+| Hotkey | Function |
64
+| ----------------------- | --------------------- |
65
+| `Super + Ctrl + A` | Audio panel |
66
+| `Super + Ctrl + B` | Bluetooth panel |
67
+| `Super + Ctrl + W` | Wifi/network panel |
68
+| `Super + Ctrl + D` | Display panel |
69
+| `Super + Ctrl + P` | Power panel |
70
+| `Super + Ctrl + Alt + D` | Calendar panel |
71
+| `Super + Ctrl + 1-9` | Toggle bar panel by position |
72
+| `Super + Ctrl + S` | Share menu (via LocalSend) |
73
+| `Super + Ctrl + T` | Activity (btop) |
74
+| `Super + Ctrl + C` | Capture controls (screenshot/-recording/picker) |
75
+| `Super + Ctrl + O` | Toggle menu |
76
+| `Super + Ctrl + H` | Hardware menu |
77
+| `Super + Ctrl + Q` | Calculator |
78
+| `Super + Ctrl + E` | Emoji picker |
79
+| `Super + Ctrl + .` | Transcode media |
80
+| `Super + Shift + Ctrl + A` | Pick an AI agent |
81
+
82
+## Adjustments
83
+
84
+| Hotkey | Function |
85
+| ----------------------- | --------------------- |
86
+| `Shift + Brightness Up` | Maximum screen brightness |
87
+| `Shift + Brightness Down` | Minimum screen brightness |
88
+| `Alt + Brightness Up/Down` | Precise 1% brightness changes |
89
+| `Alt + Volume Up/Down` | Precise 1% volume changes |
90
+| `Keyboard Brightness Up/Down` | Keyboard backlight brighter/dimmer |
91
+| `Keyboard Backlight` | Cycle the keyboard backlight levels |
92
+| `Alt + Play` | Next track |
93
+| `Alt + Shift + Play` | Previous track |
94
+
95
+## Launching apps
96
+
97
+| Hotkey | Function |
98
+| ----------------------- | --------------------- |
99
+| `Super + Return` | Terminal |
100
+| `Super + Alt + Return` | Tmux terminal |
101
+| `Super + Ctrl + Return` | Herdr (agent manager) |
102
+| `Super + Shift + Return` | Browser |
103
+| `Super + Shift + Alt + B` | Browser (private/incognito) |
104
+| `Super + Shift + F` | File manager |
105
+| `Super + Shift + Alt + F` | File manager in cwd of terminal |
106
+| `Super + Shift + M` | Music (Spotify) |
107
+| `Super + Shift + Alt + M` | Music (cliamp) |
108
+| `Super + Shift + /` | Password manager (1password) |
109
+| `Super + Shift + N` | Editor (Neovim) |
110
+| `Super + Shift + C` | Calendar ([HEY](https://hey.com/)) |
111
+| `Super + Shift + E` | Email ([HEY](https://hey.com/)) |
112
+| `Super + Shift + Alt + E` | New email ([HEY](https://hey.com/)) |
113
+| `Super + Shift + A` | AI (ChatGPT) |
114
+| `Super + Shift + Alt + A` | AI (Grok) |
115
+| `Super + Shift + G` | Messenger (Signal) |
116
+| `Super + Shift + P` | Google Photos |
117
+| `Super + Shift + S` | Google Maps |
118
+| `Super + Shift + Alt + G` | Messenger (WhatsApp) |
119
+| `Super + Shift + Ctrl + G` | Messenger (Google) |
120
+| `Super + Shift + D` | Docker (LazyDocker) |
121
+| `Super + Shift + O` | Obsidian |
122
+| `Super + Shift + W` | Writing (Omawrite) |
123
+| `Super + Shift + X` | X |
124
+| `Super + Shift + Alt + X` | X Compose |
125
+| `Super + Shift + Y` | YouTube |
126
+
127
+Change/add bindings in `~/.config/hypr/bindings.lua`.
128
+
129
+## Universal clipboard
130
+
131
+| Hotkey | Function |
132
+| ----------------------- | --------------------- |
133
+| `Super + C` | Copy |
134
+| `Super + X` | Cut (not in terminal) |
135
+| `Super + V` | Paste |
136
+| `Super + Ctrl + V` | Clipboard manager |
137
+
138
+Usually on Linux, you need `Ctrl + Shift + C/V` to copy'n'paste in the terminal and `Ctrl + C/V` to do it everywhere else. These Omarchy unified clipboard hotkeys work everywhere.
139
+
140
+## Capture
141
+
142
+| Hotkey | Function |
143
+| ------------------- | ------------------------------ |
144
+| `Super + Ctrl + C` | Capture menu (for keyboards w/o PrintScr button) |
145
+| `Print Screen` | Screenshot |
146
+| `Alt + Print Screen` | Screenrecord |
147
+| `Super + Print Screen` | Color picker |
148
+| `Super + Ctrl + Print Screen` | Text extraction to clipboard |
149
+| `Super + Alt + [` | Make webcam overlay smaller while recording |
150
+| `Super + Alt + ]` | Make webcam overlay larger while recording |
151
+| `Alt + Shift + L` | Copy current URL from webapp or Chromium |
152
+| `Alt + Shift + D` | Download the video on the current page to `~/Videos` |
153
+| `Super + Ctrl + X` | Start/stop dictation (requires _Install > AI > Dictation_) |
154
+| `F9` | Push-to-talk dictation (requires _Install > AI > Dictation_) |
155
+
156
+With screenrecordings, the hotkey first asks which audio you want, then starts recording. Hit it again to stop. See [screenshots and recording](12-screenshots-recording.md) for the details.
157
+
158
+All capture options are also accessible under _Trigger > Capture_ in the Omarchy menu (`Super + Space`).
159
+
160
+## Notifications
161
+
162
+| Hotkey | Function |
163
+| ----------------------- | --------------------- |
164
+| `Super + ,` | Dismiss latest notification |
165
+| `Super + Shift + ,` | Dismiss all notifications |
166
+| `Super + Ctrl + ,` | Toggle silencing notifications |
167
+| `Super + Alt + ,` | Invoke most recent notification |
168
+| `Super + Shift + Alt + ,` | Open notification history |
169
+
170
+## Style
171
+
172
+| Hotkey | Function |
173
+| ----------------------- | --------------------- |
174
+| `Super + Ctrl + Shift + Space` | Pick a new theme |
175
+| `Super + Ctrl + Space` | Pick theme background |
176
+| `Super + Backspace` | Toggle transparency on a window |
177
+| `Super + Ctrl + Backspace` | Toggle single-window square aspect |
178
+
179
+Extra background images live in `~/.config/omarchy/backgrounds/<theme name>`. Also available via _Install > Style > Background_ in the Omarchy menu.
180
+
181
+All style options are also accessible under _Style_ in the Omarchy menu (`Super + Space`).
182
+
183
+## Toggles
184
+
185
+| Hotkey | Function |
186
+| ----------------------- | --------------------- |
187
+| `Super + Ctrl + I` | Toggle locking on idle |
188
+| `Super + Ctrl + N` | Toggle nightlight display temperature |
189
+| `Super + Ctrl + Delete` | Toggle laptop display on/off |
190
+| `Super + Ctrl + Alt + Delete` | Toggle laptop display mirroring |
191
+| `Super + Shift + Space` | Toggle the top bar |
192
+| `Shift + Mute` | Switch to next audio output |
193
+| `Shift + Play` | Switch to next media source |
194
+| `Super + Shift + Backspace` | Toggle window gaps |
195
+
196
+## Reminders
197
+
198
+| Hotkey | Function |
199
+| ----------------------- | --------------------- |
200
+| `Super + Ctrl + R` | Set a reminder |
201
+| `Super + Ctrl + Alt + R` | See all reminders |
202
+| `Super + Ctrl + Shift + R` | Clear all reminders |
203
+
204
+## Notices
205
+
206
+| Hotkey | Function |
207
+| ----------------------- | --------------------- |
208
+| `Super + Ctrl + Alt + T` | Show time as notification |
209
+| `Super + Ctrl + Alt + B` | Show battery as notification |
210
+| `Super + Ctrl + Alt + W` | Toggle weather as notification |
211
+
212
+## Tmux
213
+
214
+The prefix key is `Ctrl + Space` (`Ctrl + B` also works). You can change these bindings in `~/.config/tmux/tmux.conf`.
215
+
216
+### Panes
217
+
218
+| Hotkey | Function |
219
+| ----------------------- | --------------------- |
220
+| `Prefix + v` | Split pane beside (vertical) |
221
+| `Prefix + h` | Split pane below (horizontal) |
222
+| `Prefix + x` | Kill pane |
223
+| `Prefix + z` | Toggle pane zoom (fullscreen) |
224
+| `Alt + Enter` | Split pane below (no prefix) |
225
+| `Alt + Shift + Enter` | Split pane beside (no prefix) |
226
+| `Alt + Escape` | Kill pane (no prefix) |
227
+| `Ctrl + Alt + Arrows` | Move between panes |
228
+| `Ctrl + Alt + Shift + Arrows` | Resize panes |
229
+
230
+### Windows
231
+
232
+| Hotkey | Function |
233
+| ----------------------- | --------------------- |
234
+| `Prefix + c` | New window |
235
+| `Prefix + k` | Kill window |
236
+| `Prefix + r` | Rename window |
237
+| `Alt + 1-9` | Go to specific window |
238
+| `Alt + Arrow Left/Right` | Move between windows |
239
+| `Alt + Shift + Arrow Left/Right` | Move window left/right |
240
+
241
+### Sessions
242
+
243
+| Hotkey | Function |
244
+| ----------------------- | --------------------- |
245
+| `Prefix + C` | New session |
246
+| `Prefix + K` | Kill session |
247
+| `Prefix + R` | Rename session |
248
+| `Prefix + N` | Next session |
249
+| `Prefix + P` | Previous session |
250
+| `Alt + Arrow Up/Down` | Move between sessions |
251
+| `Prefix + s` | List sessions |
252
+| `Prefix + d` | Detach from session |
253
+
254
+### Copy mode (vi-style)
255
+
256
+| Hotkey | Function |
257
+| ----------------------- | --------------------- |
258
+| `Prefix + [` | Enter copy mode |
259
+| `v` | Begin selection (in copy mode) |
260
+| `y` | Copy selection (in copy mode) |
261
+
262
+### General
263
+
264
+| Hotkey | Function |
265
+| ----------------------- | --------------------- |
266
+| `Prefix + q` | Reload config |
267
+| `Prefix + ?` | Show Tmux keybindings |
268
+| `Prefix + :` | Command prompt |
269
+
270
+### Tmux layout functions
271
+
272
+These functions must be run inside a Tmux session.
273
+
274
+| Command | Function |
275
+| ------- | -------- |
276
+| `tdl <ai> [<second_ai>]` | Create dev layout with editor, AI, and terminal |
277
+| `tdlm <ai> [<second_ai>]` | Create dev layout per subdirectory |
278
+| `tsl <count> <command>` | Create multi-pane swarm layout |
279
+
280
+## Ghostty Terminal
281
+
282
+Ghostty terminal is installed using _Install > Terminal_ via the Omarchy menu.
283
+
284
+| Hotkey | Function |
285
+| ----------------------- | --------------------- |
286
+| `Ctrl + Shift + E` | New split below |
287
+| `Ctrl + Shift + O` | New split besides |
288
+| `Ctrl + Alt + Arrows` | Move between splits |
289
+| `Super + Ctrl + Shift + Arrows` | Resize split by 10 lines |
290
+| `Super + Ctrl + Shift + Alt + Arrows` | Resize split by 100 lines |
291
+| `Ctrl + Shift + T` | New tab |
292
+| `Ctrl + Shift + Arrows` | Move between tabs |
293
+| `Alt + Numbers` | Go to specific tab |
294
+| `Shift + Pg Up/Down` | Scroll the history |
295
+| `Ctrl + Left mouse` | Open link in browser |
296
+
297
+## File Manager
298
+
299
+| Hotkey | Function |
300
+| ------------------- | ------------------------------ |
301
+| `Ctrl + L` | Go to path |
302
+| `Space` | Preview file (arrows navigate) |
303
+| `Backspace` | Go back one folder |
304
+
305
+## Neovim (w/ lazyvim)
306
+
307
+### Navigation
308
+
309
+| Hotkey | Function |
310
+| ------------------------ | ------------------------------- |
311
+| `Space` | Show command options |
312
+| `Space Space` | Open file via fuzzy search |
313
+| `Space E` | Toggle sidebar |
314
+| `Space G G` | Show git controls |
315
+| `Space S G` | Search file content |
316
+| `Ctrl + W W` | Jump between sidebar and editor |
317
+| `Ctrl + Left/right arrow` | Change size of sidebar |
318
+| `Shift + H` | Go to left file tab |
319
+| `Shift + L` | Go to right file tab |
320
+| `Space B D` | Close file tab |
321
+
322
+### While in sidebar
323
+
324
+| Hotkey | Function |
325
+| ------------------------ | ------------------------------- |
326
+| `A` | Add new file in parent dir |
327
+| `Shift + A` | Add new subdir in parent dir |
328
+| `D` | Delete highlighted file/dir |
329
+| `M` | Move highlighted file/dir |
330
+| `R` | Rename highlighted file/dir |
331
+| `?` | Show help for all commands |
332
+
333
+[See all the Neovim hotkeys configured by LazyVim](https://www.lazyvim.org/keymaps).
334
+
335
+## Quick Emojis
336
+
337
+You can use `Super + Ctrl + E` to show a complete emoji picker that'll put the selection on the clipboard or you can use these quick access options.
338
+
339
+| Hotkey | EM | Clue |
340
+| ------------ | -- | ---------- |
341
+| `CapsLock M S` | 😄 | smile |
342
+| `CapsLock M C` | 😂 | cry |
343
+| `CapsLock M L` | 😍 | love |
344
+| `CapsLock M V` | ✌️ | victory |
345
+| `CapsLock M H` | ❤️ | heart |
346
+| `CapsLock M Y` | 👍 | yes |
347
+| `CapsLock M N` | 👎 | no |
348
+| `CapsLock M F` | 🖕 | fuck |
349
+| `CapsLock M W` | 🤞 | wish |
350
+| `CapsLock M R` | 🤘 | rock |
351
+| `CapsLock M K` | 😘 | kiss |
352
+| `CapsLock M E` | 🙄 | eyeroll |
353
+| `CapsLock M I` | 😉 | wink |
354
+| `CapsLock M P` | 🙏 | pray |
355
+| `CapsLock M D` | 🤤 | drool |
356
+| `CapsLock M M` | 💰 | money |
357
+| `CapsLock M X` | 🎉 | xellebrate |
358
+| `CapsLock M 1` | 💯 | 100% |
359
+| `CapsLock M T` | 🥂 | toast |
360
+| `CapsLock M O` |👌 | ok |
361
+| `CapsLock M G` |👋 | greeting |
362
+| `CapsLock M A` |💪 | arm |
363
+| `CapsLock M B` |🤯 | blowing |
364
+
365
+## Quick Completions
366
+
367
+| Hotkey | Completion |
368
+| ------------ | ---------- |
369
+| `CapsLock Space Space` | — (mdash) |
370
+| `CapsLock Space N` | Your name (as entered on setup) |
371
+| `CapsLock Space E` | Your email (as entered on setup) |
372
+
373
+You can add more of your own by editing `~/.XCompose`, then running `omarchy-restart-xcompose` in the terminal to get the changes picked up.
0
374
▼manual/08-unified-clipboard-history.md
+24-0
1
+# Unified Clipboard & History
2
+
3
+Usually on Linux, you need `Ctrl + Shift + C/V` to copy'n'paste in the terminal and `Ctrl + C/V` to do it everywhere else. That's hard to get used to for anyone who hasn't been born and bred on Linux! So too is the switch from super to ctrl, if you're coming from the Mac.
4
+
5
+Omarchy tackles both problems with unified clipboard hotkeys that work (almost) everywhere. They are:
6
+
7
+| Hotkey | Command |
8
+| ------- | ----------- |
9
+| Super + C | Copy |
10
+| Super + X | Cut |
11
+| Super + V | Paste |
12
+| Super + Ctrl + V | Clipboard history |
13
+
14
+_Note that most agent harnesses will use `Ctrl + V` for pasting images, but `Super + V` for pasting text._
15
+
16
+### Clipboard history
17
+
18
+The clipboard history is provided by the Omarchy shell and works for both text and images. You trigger it by `Super + Ctrl + V`, select your entry with return, and then that'll be placed on the clipboard ready to paste on `Super + V`.
19
+
20
+ ![clipboard-history](images/clipboard-history.webp)
21
+
22
+You can also search the history just by starting to type:
23
+
24
+ ![clipboard-history-search](images/clipboard-history-search.webp)
0
25
▼manual/09-reminders.md
+5-0
1
+# Reminders
2
+
3
+Omarchy has a built-in way to set simple reminders based on a countdown timer and with a message. You can do this via `Super + Ctrl + R`, seeing all the ones set via `Super + Ctrl + Alt + R`, and clearing all via `Super + Ctrl + Shift + R`. Everything also accessible via _Trigger > Reminder_. You can also use the cli with `omarchy reminder 7 'Tea ready'`.
4
+
5
+ ![reminders](images/reminders.webp)
0
6
▼manual/10-notices.md
+23-0
1
+# Notices
2
+
3
+You can quickly access the date and time, battery status, and current weather using the hotkey notices.
4
+
5
+### Date & Time
6
+
7
+`Super + Ctrl + Alt + T`
8
+
9
+ ![notice-datetime](images/notice-datetime.webp)
10
+
11
+### Weather
12
+
13
+`Super + Ctrl + Alt + W`
14
+
15
+ ![notice-weather](images/notice-weather.webp)
16
+
17
+The location is detected from your IP address, which is usually close enough, but not always. You can pin it down with `omarchy weather location --set Malibu`, or be exact about it by adding coordinates: `omarchy weather location --set Malibu 34.0259,-118.7798`. Run `omarchy weather location` on its own to see where it thinks you are, and `--clear` to go back to auto-detection.
18
+
19
+### Battery
20
+
21
+`Super + Ctrl + Alt + B`
22
+
23
+ ![notice-battery](images/notice-battery.webp)
0
24
▼manual/11-text-extraction-dictation.md
+15-0
1
+# Text Extraction & Dictation
2
+
3
+### Text Extraction
4
+
5
+Hit `Super + Ctrl + PrtScr` to select a region on the screen for text extraction. The tesseract open source OCR model will then quickly convert that selection into text and place it on the clipboard. Then you just hit `Super + V` to paste.
6
+
7
+This is very helpful for grabbing addresses out of image footers or phone numbers embedded in website headlines.
8
+
9
+ ![text-extraction](images/text-extraction.webp)
10
+
11
+### Dictation
12
+
13
+Omarchy offers AI dictation via [Voxtype](https://voxtype.io/). You install it via _Install > AI > Dictation_ through the Omarchy menu. By default, it'll load a base English model that takes up 150MB. But you can tweak which model you'd like to use by running `voxtype setup model` in the terminal. And you can tweak all the settings via `~/.config/voxtype/config.toml`.
14
+
15
+Once installed, you dictate by holding down `F9` or by toggling with `Super + Ctrl + X`, and the dictated text will appear in the focused input area.
0
16
▼manual/12-screenshots-recording.md
+78-0
1
+# Screenshots & Recording
2
+
3
+Everything you can grab off the screen hangs off the Print Screen key. One key on its own takes a picture, and the modifiers take a recording, a colour, or the text inside a region. If your keyboard doesn't have a Print Screen key at all, `Super + Ctrl + C` opens the same set as a menu.
4
+
5
+| Hotkey | Function |
6
+| ------ | -------- |
7
+| `Print Screen` | Screenshot |
8
+| `Alt + Print Screen` | Screenrecord (or stop the one that's running) |
9
+| `Super + Print Screen` | Colour picker |
10
+| `Super + Ctrl + Print Screen` | Extract text from a region |
11
+| `Super + Ctrl + C` | Capture menu |
12
+| `Super + Ctrl + .` | Transcode a picture or video |
13
+
14
+## Screenshots
15
+
16
+Hit `Print Screen` and the screen freezes so nothing shifts under you while you aim. Drag a box for a freeform region, or just click once and the shot snaps to whatever rectangle you clicked in — a window if you landed on one, the whole monitor if you landed on the bar or in a gap. Changed your mind? Hit `Print Screen` again to dismiss the picker.
17
+
18
+The result goes two places at once: a PNG in your pictures directory, and the clipboard, so you can paste it straight into a chat window with `Super + V`. A notification pops up with a thumbnail. Click it (or hit `Super + Alt + ,` to invoke the last notification) and the shot opens in Tensaku, the annotation editor, where you can draw arrows and boxes on it before you send it.
19
+
20
+Files land in `~/Pictures` by default, named `screenshot-2026-08-13_14-22-05.png`. If you'd rather keep them in their own folder, set `OMARCHY_SCREENSHOT_DIR` — see [the FAQ](46-faq.md) for where to put session environment variables. Omarchy creates the directory for you if it isn't there. You can swap the editor too with `OMARCHY_SCREENSHOT_EDITOR`.
21
+
22
+From the terminal, `omarchy screenshot` takes the same shot, and you can be explicit about it: `omarchy capture screenshot region` for freeform only, `windows` to snap to window and monitor rectangles, or `fullscreen` to skip the picker entirely and grab the focused monitor. A second argument of `copy` puts the shot only on the clipboard, and `save` only on disk.
23
+
24
+### Driving the picker from the keyboard
25
+
26
+While the selection is up, you don't have to use the mouse at all:
27
+
28
+| Key | Function |
29
+| --- | -------- |
30
+| `Return` | Capture the highlighted window |
31
+| `Ctrl + Return` | Capture the whole screen |
32
+| `Tab` / `Ctrl + Tab` | Highlight the next / previous window |
33
+| Arrow keys | Highlight the window in that direction |
34
+
35
+The arrows and Tab move the cursor to the window they pick, so the highlight follows along and you can see what you're about to capture. These bindings only exist while a selection is on screen, so they can't collide with anything in your own config.
36
+
37
+## Screen recording
38
+
39
+`Alt + Print Screen` opens _Trigger > Capture > Screenrecord_, which asks what you want on the soundtrack: no audio, desktop audio, desktop plus microphone, or desktop plus microphone plus webcam. That last one only shows up if you actually have a camera plugged in. Pick one and you get the same picker as a screenshot: drag a region, or click a window or monitor.
40
+
41
+Recording runs on gpu-screen-recorder, which encodes on the GPU at 60fps and falls back to the CPU if it has to. The result is an MP4 in `~/Videos`, named `screenrecording-2026-08-13_14-22-05.mp4`. Set `OMARCHY_SCREENRECORD_DIR` to change that — but note that unlike the screenshot directory, this one has to exist already, or the recording refuses to start.
42
+
43
+While you're recording, a little indicator shows up in the bar. Click it to stop. You can also stop with `Alt + Print Screen` again, or with the _Stop Screenrecording_ entry under _Trigger > Capture > Screenrecord_, which only appears while something is actually recording.
44
+
45
+Stopping does a bit of tidying before it hands you the file: the first frame gets trimmed, and if there's audio it's normalized to -14 LUFS with the PipeWire capture pop at the very start muted out. Then a notification appears with a thumbnail from the recording. Click it to play the file in mpv.
46
+
47
+### The webcam overlay
48
+
49
+When you record with a webcam, the camera appears as a pinned, cropped portrait window in the bottom-right corner of whatever you're recording. If it's sitting on top of something you need, resize it on the fly:
50
+
51
+| Hotkey | Function |
52
+| ------ | -------- |
53
+| `Super + Alt + [` | Make the webcam overlay smaller |
54
+| `Super + Alt + ]` | Make the webcam overlay larger |
55
+
56
+There are three sizes — small, medium, and large — and the hotkeys step between them. Medium is the default. They're proportional to the recording, so the camera takes up the same share of the frame whether you're recording a 1080p monitor or a 6K one. And if you recorded a region rather than a whole display, the overlay anchors to that region's corner rather than the monitor's, so it stays inside the shot.
57
+
58
+You can also call it directly with `omarchy-capture-webcam-resize small`, or `reset` to go back to medium.
59
+
60
+## Text, QR codes, and colours
61
+
62
+`Super + Ctrl + Print Screen` selects a region and OCRs it to the clipboard. That's covered properly in [Text Extraction & Dictation](11-text-extraction-dictation.md).
63
+
64
+_Trigger > Capture > QR Code_ does the same trick for QR codes. Select the region with the code in it, and the decoded value goes to the clipboard. It only looks for QR codes — dense screen content has a habit of false-positiving as a barcode otherwise. Worth knowing: the decoded value goes to the clipboard and nowhere else. It isn't printed, it isn't in the notification, and it's marked sensitive so it doesn't stick around in [clipboard history](08-unified-clipboard-history.md). QR codes routinely carry secrets — the `otpauth://` URI behind a 2FA setup code, for one — and you don't want that in a log. Pasting still works fine.
65
+
66
+`Super + Print Screen` (or _Trigger > Capture > Color_) turns the cursor into an eyedropper. Click anything on screen and the colour lands on the clipboard. Press the hotkey again to back out without picking.
67
+
68
+## Transcoding before you share
69
+
70
+A 4K screen recording or a raw HEIC off your phone is often too big to just send. `Super + Ctrl + .` (or _Trigger > Transcode_) fixes that. It offers you a fuzzy file picker over `~/Pictures` and `~/Videos`, then asks for a format and a size.
71
+
72
+Pictures go to jpg or png at high, medium, or low, which cap the width at 3160, 2160, and 1080 pixels. Videos go to mp4 or an animated gif at 4k, 1080p, or 720p. The converted file is written next to the original with the resolution in the name — `demo-1080p.mp4` — and the path is copied to the clipboard as a file URI, so you can paste it directly into an app that takes file drops.
73
+
74
+It works from the terminal too, if you already know what you want: `omarchy transcode ~/Videos/demo.mov mp4 1080p`. There's also `omarchy transcode ascii`, which turns an image into ASCII art — that one's mostly for [branding](41-branding.md).
75
+
76
+## Sending it somewhere
77
+
78
+Once you've got the file, `Super + Ctrl + S` opens the Share menu and sends it to another device on your network via LocalSend. See [GUIs](22-guis.md) for that.
0
79
▼manual/13-toggles-idle-screensaver.md
+101-0
1
+# Toggles, Idle & the Screensaver
2
+
3
+A lot of what you change day to day isn't really a setting. It's a mode you flip on for an hour and off again: night light while you're working late, do not disturb while you're presenting, stay awake while you're watching something. Omarchy calls those toggles, and they all work the same way — a hotkey, a menu entry, and a command, all hitting the same switch.
4
+
5
+### The toggle menu
6
+
7
+`Super + Ctrl + O` opens _Trigger > Toggle_ directly, or you can walk there from the Omarchy menu (`Super + Space`). Everything in that list is a switch you can flip without thinking about where the state lives.
8
+
9
+From the terminal, the same switches are `omarchy toggle <thing>`. Run `omarchy toggle` on its own to see the whole group.
10
+
11
+| Toggle | Hotkey | Command |
12
+| ------ | ------ | ------- |
13
+| Night light | `Super + Ctrl + N` | `omarchy toggle nightlight` |
14
+| Silence notifications | `Super + Ctrl + ,` | `omarchy toggle notification silencing` |
15
+| Stay awake (no idle lock) | `Super + Ctrl + I` | `omarchy toggle idle` |
16
+| Crash capture | — | `omarchy toggle crash-capture` |
17
+| Screensaver | — | `omarchy toggle screensaver` |
18
+| Menu bar | `Super + Shift + Space` | `omarchy toggle bar` |
19
+| Touchpad | `XF86TouchpadToggle` | `omarchy toggle touchpad` |
20
+| Touchscreen | — | `omarchy toggle touchscreen` |
21
+| Suspend | — | `omarchy toggle suspend` |
22
+| Hybrid GPU | — | `omarchy toggle hybrid gpu` |
23
+
24
+The touchpad, touchscreen, and hybrid GPU switches live under _Trigger > Hardware_ (`Super + Ctrl + H`) rather than under Toggle, since they only show up when you actually have that hardware. The touchpad and touchscreen ones survive a Hyprland reload — the disabled state is written back out as a small Lua file that Hyprland sources on startup.
25
+
26
+The Toggle menu also carries a few things that aren't `omarchy toggle` commands but behave the same: battery percentage in the bar, workspace layout (`Super + L`), window gaps (`Super + Shift + Backspace`), and the 1-window square aspect (`Super + Ctrl + Backspace`).
27
+
28
+Most of these are just a flag file under `~/.local/state/omarchy/toggles/`. If you want to branch on one in a script, `omarchy-toggle-enabled` gives you an exit code instead of making you go looking:
29
+
30
+```bash
31
+omarchy-toggle-enabled screensaver-off && echo "screensaver is off"
32
+```
33
+
34
+The flags are named for the off state — `screensaver-off`, `suspend-off`, `bar-off` — so their presence means the feature is disabled.
35
+
36
+### Indicators in the bar
37
+
38
+When a mode is on, you get a small glyph in the middle of the top bar next to the clock. That's the indicators widget, and it carries dictation, screen recording, pending reminders, night light, do not disturb, and stay awake.
39
+
40
+Inactive indicators are hidden. Hover the area around them and they fade in dimmed, so you can click one to turn it on without knowing its hotkey. Clicking an active one turns it back off. If you'd rather see all of them all the time, set `alwaysShow` to `true` on the `omarchy.indicators` entry in `~/.config/omarchy/shell.json` — see [the top bar](05-the-top-bar.md) for how bar widgets are configured.
41
+
42
+### Night light
43
+
44
+`Super + Ctrl + N` warms the screen to 4000K, and hitting it again puts it back to 6500K. It's driven by hyprsunset, which the toggle starts for you if it isn't already running.
45
+
46
+By default hyprsunset does nothing to your screen at all. `~/.config/hypr/hyprsunset.conf` ships with an identity profile precisely so the display stays untouched until you ask for warmth. If you'd rather have it switch by the clock, replace that with a time profile:
47
+
48
+```
49
+profile {
50
+ time = 20:00
51
+ temperature = 4000
52
+}
53
+```
54
+
55
+Then start hyprsunset at login by adding `o.launch_on_start("hyprsunset")` to `~/.config/hypr/autostart.lua`. The 4000K/6500K pair used by the toggle is fixed, so the config file is where you go if you want a different temperature.
56
+
57
+### Do not disturb
58
+
59
+`Super + Ctrl + ,` silences notifications. No toasts pop up while it's on, and the crossed-out bell indicator sits in the bar to remind you why the desktop has gone quiet.
60
+
61
+Nothing is lost, though. A silenced notification is written straight into your notification history, which is exactly the record you want when you come back and wonder what you missed. Open it with `Super + Shift + Alt + ,`. See [notices](10-notices.md) for the rest of the notification story.
62
+
63
+Two kinds of message still get through: Omarchy's own confirmation toasts for something you just did ("Theme changed", "Screenshot saved"), and critical alerts sent from the command line. Chat apps that mark everything critical to force their way in front of you don't qualify.
64
+
65
+### Idle
66
+
67
+The Omarchy shell owns idle behavior, and the timings are a top-level `idle` block in `~/.config/omarchy/shell.json`:
68
+
69
+```json
70
+{
71
+ "version": 1,
72
+ "idle": {
73
+ "screensaver": 150,
74
+ "lock": 300
75
+ }
76
+}
77
+```
78
+
79
+Both numbers are seconds counted from the moment you went idle — not from each other. So with the defaults, the screensaver comes up after two and a half minutes and the lock screen takes over at five minutes, whether or not the screensaver ran. Save the file and the shell picks up the new timings right away.
80
+
81
+If you dismiss the screensaver before the lock deadline, that counts as activity and the pending lock is cancelled. You don't get locked out for glancing at your machine.
82
+
83
+To stop locking on idle entirely, `Super + Ctrl + I` — or `omarchy toggle idle` — flips stay awake on, and the coffee cup indicator appears in the bar. That's the one to hit before a long presentation or a build you want to watch. Hit it again to go back to normal. `omarchy toggle idle status` prints the current state as JSON if you need it from a script.
84
+
85
+This is about locking and the screensaver, not power. Suspend and hibernation have their own setup in [system sleep](36-system-sleep.md).
86
+
87
+### The screensaver
88
+
89
+Omarchy's screensaver is ASCII art running through random text effects, one instance per monitor. Any key or mouse movement exits it.
90
+
91
+You can start it on demand from _System > Screensaver_ (`Super + Esc`), which forces it up even if you've turned the idle screensaver off. There's no hotkey bound to it by default.
92
+
93
+`omarchy toggle screensaver` is what turns the idle one off, if you'd rather go straight from working to locked. It needs a terminal it knows how to configure — Alacritty, Foot, Ghostty, or Kitty — and will tell you so if your default terminal is something else.
94
+
95
+The logo it draws is yours to change, under _Style > Screensaver_. Upload a png or svg and Omarchy converts it to ASCII. See [branding](41-branding.md).
96
+
97
+### The lock screen
98
+
99
+`Super + Ctrl + L` locks the machine. That runs the lock screen from the Omarchy shell, blanks the display, resets your keyboard layout to the first one so you're not typing your password in the wrong alphabet, and — if you have it running — locks 1Password on the way out.
100
+
101
+The lock screen takes a password, and it'll take a fingerprint too once you've set one up. That, and the other ways to authenticate, are covered in [hardware authentication](37-hardware-authentication.md).
0
102
▼manual/14-omarchy-cli.md
+62-0
1
+# Omarchy CLI
2
+
3
+Omarchy is usually controlled through the hotkeys and the Omarchy menu (`Super + Space`). But you can also control it through the `omarchy` CLI. This is particularly helpful when you're having an AI agent work with you on customization or configuration.
4
+
5
+The CLI has access to all the internal tooling that is used both via the menu and otherwise. You can see everything that's available by running `omarchy` in the terminal.
6
+
7
+It looks something like this:
8
+
9
+```
10
+~ ❯ omarchy
11
+Omarchy command center
12
+
13
+Usage:
14
+ omarchy <command> [args...]
15
+ omarchy commands [--all] [--json] [--check]
16
+ omarchy <group> --help
17
+ omarchy <group> <command> --help
18
+
19
+Common commands:
20
+ omarchy update Update Omarchy and system packages
21
+ omarchy theme list List available themes
22
+ omarchy theme set <name> Apply a theme
23
+ omarchy font list List available fonts
24
+ omarchy screenshot Take a screenshot
25
+ omarchy debug Print debugging information
26
+
27
+Groups:
28
+ agent AI coding agent usage data
29
+ audio Audio input and output controls
30
+ bar Omarchy shell bar layout and settings
31
+ battery Battery status helpers
32
+ bluetooth Bluetooth device controls
33
+ branch Omarchy git branch management
34
+ branding About and screensaver branding
35
+ brightness Display and keyboard brightness
36
+ capture Screenshots and screen recording
37
+ channel Omarchy release channel management
38
+ clipboard Clipboard helpers
39
+ cmd Command and shortcut helpers
40
+ config System configuration helpers
41
+ debug Diagnostics and support logs
42
+ ...
43
+```
44
+
45
+And you can dive deeper on every group:
46
+
47
+```
48
+~ ❯ omarchy capture
49
+Capture commands — Screenshots and screen recording:
50
+ omarchy capture qr Decode a QR code from a screenshot region
51
+ omarchy capture screenrecording [--fullscreen] [--with-desktop-audio] [--with-microphone-audio] [--with-webcam] [--webcam-device=<device>] [--webcam-size=<small|medium|large>] [--resolution=<size>] [--stop-recording] Start or stop screen recording
52
+ omarchy capture screenrecording with webcam Pick a webcam and start a screen recording with it
53
+ omarchy capture screenshot [smart|region|windows|fullscreen] [slurp|copy|save] [--editor=<name>] Take a screenshot
54
+ omarchy capture text Extract text from a screenshot region with OCR
55
+ omarchy capture webcam resize <smaller|larger|reset|small|medium|large> Resize the active webcam recording overlay
56
+```
57
+
58
+Every command takes `--help` too, whether you ask a whole group (`omarchy capture --help`) or a single command (`omarchy capture screenshot --help`).
59
+
60
+### Opening the menu from the terminal
61
+
62
+The Omarchy menu is scriptable as well, which is handy for your own keybindings. `omarchy menu` opens it at the root, and you can jump straight to any point in the tree by naming it: `omarchy menu summon style.theme` goes right to the theme picker, `omarchy menu toggle system` opens the system menu and closes it again if it's already up, and `omarchy menu close` puts it away.
0
63
▼manual/15-terminal.md
+39-0
1
+# Terminal
2
+
3
+[Foot](https://codeberg.org/dnkl/foot) is the default terminal for Omarchy. It's fast, lightweight, and compatible with even old computers. It does not, however, support native tabs or splits.
4
+
5
+If you use Tmux, you may not mind, but if not, we fully support _Alacritty_, _Ghostty_, and _Kitty_ as options as well. Pick your preference under _Install > Terminal_ in the Omarchy menu.
6
+
7
+You start a new terminal using `Super + Return`. (This binding will automatically point to whichever Terminal you've installed via _Install > Terminal_, and you can switch between installed terminals under _Setup > Defaults > Terminal_.)
8
+
9
+## Tmux
10
+
11
+Tmux provides a consistent, programmable interface for panes, windows (aka tabs), and resumable sessions regardless of your terminal. It even works on remote hosts, so when you're SSH'ing into a server, you can use the same approach.
12
+
13
+You start a new Tmux session in a fresh terminal using `Super + Alt + Return`, and because Tmux is a persistent process, you can resume your session even if you close that terminal. Just hit `Ctrl + Space` (called the prefix key) then `s` to see all your active sessions.
14
+
15
+Omarchy ships with an ergonomically-optimized Tmux configuration, which has a lot of keybindings to learn, so keep [the cheatsheet handy](07-hotkeys.md#tmux).
16
+
17
+## Tmux layout functions
18
+
19
+Because Tmux is programmable, we can use functions to create layouts. Omarchy ships with four different functions for common developer layouts.
20
+
21
+`tdl [agent]` starts a three-way split IDE-like interface with the `$EDITOR` on the left, your chosen AI agent on the right (like `c` for opencode or `cx` for Claude or `codex` for OpenAI), and then a terminal at the bottom.
22
+
23
+So `tdl c` would start this (or just `ic`):
24
+
25
+ ![tmux-tdl](images/tmux-tdl.webp)
26
+
27
+You can also start a second agent with `tdl c cx` (opencode + claude) (or just `icx`):
28
+
29
+ ![tmux-tdl2](images/tmux-tdl2.webp)
30
+
31
+There's also `tds`, which starts a four-way square with the editor top left, a live diff watcher top right, a terminal bottom left, and opencode bottom right.
32
+
33
+You can also start this layout configuration for every subdirectory in the current directory using `tdlm [agent]`, then navigate using `alt + 1/2/3/4/5/...`:
34
+
35
+ ![tmux-tdlm](images/tmux-tdlm.webp)
36
+
37
+Finally, you can start a swarm of agents using `tsl [panes] [command]`. So `tsl 4 c` will give you a four-way grid of opencode agents:
38
+
39
+ ![tmux-tsl](images/tmux-tsl.webp)
0
40
▼manual/16-neovim.md
+42-0
1
+# Neovim
2
+
3
+[Neovim](https://neovim.io/) is a modern implementation of [the vi editor](<https://en.wikipedia.org/wiki/Vi_(text_editor)>) created by Bill Joy all the way back in 1976. It's a modal editor where insert mode and command mode are separated, and it's a bit of a superpower once you learn even just a subset of the incredibly deep key command set. But it's also quite the learning curve!
4
+
5
+If you're totally new to vim-style editing, I recommend you checkout [ThePrimeagen's Vim As Your Editor series](https://www.youtube.com/watch?v=X6AR2RMB5tE&list=PLm323Lc7iSW_wuxqmKx_xxNtJC_hJbQ7R) on YouTube. That'll teach you the basics. Just know that unlike more similar mainstream editors, it's going to take you longer to get basic proficiency with vim. But once you do, the payoff is also larger.
6
+
7
+Now Neovim is basically infinitely configurable. If you really want to go nuts, you can create your own Neovim configuration from scratch. There's a great course from [Typecraft on setting up Neovim from scratch](https://www.youtube.com/watch?v=zHTeCSVAFNY). And [ThePrimeagen has one as well](https://www.youtube.com/watch?v=w7i4amO_zaE).
8
+
9
+But Omarchy ships with a complete Neovim setup — the `omarchy-nvim` package — that's been lovingly tuned to showcase the best of what's possible out of the box. Without you having to write a single line of configuration! It's built on [LazyVim](https://www.lazyvim.org/), a distribution of Neovim plugins and configurations. It's awesome.
10
+
11
+## LazyVim Basics
12
+
13
+As mentioned, I'm not going to teach you vim in this short introduction, but I can show you a few basics of LazyVim, and how to get around.
14
+
15
+First, Neovim has the idea of the leader key. That's basically the gateway to all the commands. LazyVim has set that to `Space`. So just press that, wait a second, and you'll see a bunch of options explained inline like this:
16
+
17
+Here are some basic commands I use all the time:
18
+
19
+- `Space Space` - Fuzzy-find any file in the current directory.
20
+- `Space S G` - Search all files using grep with a preview.
21
+- `Space E` - Toggle the file tree on/off.
22
+- `Ctrl + W W` - Hop from the file tree to the editor and back.
23
+- `Shift + H` - Move left between the open tabs (vim calls them buffers).
24
+- `Shift + L` - Move right between the open tabs.
25
+- `Space B D` - Close a tab.
26
+- `Space B O` - Close all other tabs but the current.
27
+- `Space G G` - Launch LazyGit in a floating pane from the current directory.
28
+- `Space U W` - Toggle soft wrap.
29
+
30
+While you're in the file tree (`Space E` to reveal, `Ctrl + W W` to hop over there), you can add a new file with `a` or a new directory with `A`. Press `?` while in the tree to see all commands.
31
+
32
+If you want to pickup the basic vim language, I've written about [the three-part syntax](https://world.hey.com/dhh/wonderful-vi-a1d034d3) and how to pull off those sick combo moves!
33
+
34
+You can see all the possible commands on [the LazyVim Keymaps page](https://www.lazyvim.org/keymaps).
35
+
36
+## Starting Neovim
37
+
38
+You can start Neovim using `Super + Shift + N` (the binding launches your default editor, which is Neovim out of the box), but it's usually easier to drive it from the terminal by navigating to the directory you wish to work in and typing `n`. The `n` is the alias for `nvim`, which will use the the present directory to open by default. You can open a single file with `n myfile.txt`.
39
+
40
+## Using Neovim for sudo edits
41
+
42
+If you need to edit files that you can only change as a super user, you can use neovim with all your plugins setup by running `sudoedit /etc/sudoers.d/00-sudo-only-file`.
0
43
▼manual/17-ai.md
+51-0
1
+# AI
2
+
3
+Omarchy treats AI coding agents as first-class citizens, but it doesn't pick a favorite for you. Instead, every major coding-agent CLI comes pre-wired as a lazy-loaded launcher. The launchers are tiny [mise](https://mise.jdx.dev/)-managed stubs in `~/.local/bin/`, so nothing is downloaded until the first time you actually run one. Invoke any of these and authenticate when prompted:
4
+
5
+| Command | Agent |
6
+|------------|------------------------------------------------------------------|
7
+| `claude` | [Claude Code](https://code.claude.com/docs/en/overview) |
8
+| `codex` | [OpenAI Codex](https://github.com/openai/codex) |
9
+| `opencode` | [OpenCode](https://opencode.ai/) |
10
+| `agy` | [Google Antigravity CLI](https://github.com/google-antigravity/antigravity-cli) |
11
+| `copilot` | [GitHub Copilot CLI](https://github.com/github/copilot-cli) |
12
+| `crush` | [Crush](https://github.com/charmbracelet/crush) |
13
+| `grok` | Grok CLI from xAI |
14
+| `pi` | [Mario Zechner's Pi](https://github.com/badlogic/pi-mono) |
15
+| `omp` | [Oh My Pi](https://github.com/can1357/oh-my-pi) |
16
+
17
+To wrap an additional CLI the same way, run `omarchy-mise-install <package> [command-name]`. The stubs are kept current along with everything else mise manages when you run `omarchy update` (or the `mup` alias).
18
+
19
+### The default agent
20
+
21
+Pick your default agent with `omarchy default agent <name>` or under _Setup > Defaults > Agent_ in the Omarchy Menu (`Super + Space`). If the agent isn't installed yet, picking it installs it first. A fresh Omarchy will invite you to make this choice with a one-time notification.
22
+
23
+Once you've chosen, `Super + Shift + Ctrl + A` launches the default agent in a dedicated terminal window (or brings up the picker if you haven't chosen yet). You can also launch it straight into a task with `omarchy agent prompt "Review this project"`. Agents launched this way run unattended in their respective don't-stop-to-ask modes, so be ready for them to actually do things! And since agents refuse to remember trust for your home directory, launches from `$HOME` start in `~/Work` instead.
24
+
25
+There are terminal shortcuts too: `a` runs the default agent inline in the current terminal, while `c`, `cx`, and `cy` start OpenCode, Claude Code, and Codex directly (again in their auto-approving modes). Theme changes sync to the agents as well: Claude Code, Pi, and OpenCode all follow along when you switch the Omarchy theme.
26
+
27
+### The agents panel
28
+
29
+The top bar grows an agents icon the first time Omarchy finds AI coding usage on the machine (and stays out of the way until then). The panel behind it tracks every subscription in one place: your plan, the percentage used of the 5-hour session and weekly limits (or the remaining prepaid balance), and token usage by day and by model. Claude Code, Codex, and Fireworks are covered out of the box.
30
+
31
+Left-click the bar icon for the panel, right-click to launch your default agent. The usage records behind it are regenerated every 15 minutes by `omarchy agent usage-update`, and the panel can even merge usage from your other machines via a synced folder. See the README under `$OMARCHY_PATH/shell/plugins/agents/` for the full settings.
32
+
33
+### Crash diagnosis
34
+
35
+Omarchy watches systemd-coredump for process crashes. When something segfaults, you'll get a "Process crashed" notification — click it, and the crash is handed to your default agent along with Omarchy's diagnose-crash skill, which walks the agent through establishing the facts from the core dump and deciding whether the crash is worth reporting upstream. You can also run it by hand against any PID from `coredumpctl list` with `omarchy agent crash <pid>`.
36
+
37
+The watching is on by default. Turn it off under _Trigger > Toggle > Crash Capture_ (or with `omarchy toggle crash-capture`) and the notifications stop; `omarchy agent crash <pid>` still works by hand.
38
+
39
+### Desktop apps
40
+
41
+The _Install > AI_ menu also carries a couple of graphical AI apps: the ChatGPT desktop app, and Grok Bot for chatting with xAI's models.
42
+
43
+### Local LLMs
44
+
45
+Omarchy recommends two ways of running local LLM models: LM Studio and Ollama. LM Studio provides a GUI interface for finding open-weight models, installing them, and running them. It's a great way to get going easily. Ollama offers a CLI for doing so similarly. But if you're new to local models, I'd start with LM Studio. You can install either under _Install > AI_ in the Omarchy Menu.
46
+
47
+### The Omarchy Skill
48
+
49
+Agent skills help AI use specific tools in a specific way, and Omarchy ships with a default skill for tailoring the system. Like tweaking your Hyprland config, adjusting the bar, or even creating a new theme from scratch. It's symlinked into the skill directories for Claude Code (`~/.claude/skills`), Codex (`~/.codex/skills`), Pi (`~/.pi/agent/skills`), Antigravity (`~/.gemini/config/skills`), and the generic `~/.agents/skills` location, so most harnesses pick it up automatically.
50
+
51
+But you should treat this skill as experimental. Different models will use it to different effect. It's best to run in plan mode first, so you have an idea of what the agent would like to change. And then be ready to rollback changes or even invoking `omarchy reinstall configs`, if the agent makes a mess of everything.
0
52
▼manual/18-development-tools.md
+33-0
1
+# Development Tools
2
+
3
+## Alternative Editors
4
+
5
+Omarchy ships with [Neovim](https://neovim.io/) by default, but if you'd like something a bit more mainstream and familiar, you can run the Omarchy Menu (`Super + Space`) and see the options under _Install > Editor_. We have VSCode, Cursor, Zed, Sublime Text, Helix, Vim, and Emacs listed there. If you don't find what you're looking for, checkout _Install > Package_, and see if it isn't in an Arch package (and if not, try _Install > AUR_ to check the AUR).
6
+
7
+Theme matching is offered for `VSCode`, `Cursor`, `VSCodium`, and `Helix`.
8
+
9
+You can set the system-wide default editor under `Setup > Defaults > Editor`.
10
+
11
+## Environment
12
+
13
+Omarchy supports setting up a whole host of development environments through the _Install > Development_ section of the Omarchy Menu (`Super + Space`). You'll of course find _Ruby on Rails_, but also all three major runtimes for JavaScript (Node.js, Bun, Deno), as well as popular PHP frameworks like Laravel and Symfony. Oh, and there's Go, Rust, Python, Java, Elixir (with Phoenix), .NET, OCaml, Zig, Clojure, and Scala too. It's a very broad selection!
14
+
15
+The majority of these environments are managed by [Mise](https://mise.jdx.dev/). It's a tool that lets you install and run multiple versions of a programming language on the same machine. It's like rbenv or rvm for Ruby or virtualenv for Python, but it works for a bunch of different environments.
16
+
17
+To install, say, Ruby, you'd run `mise use -g ruby`, which will both install Ruby and set it as the global default. Or, if your project has a .ruby-version file, you can just run `mise i` in the root of that project.
18
+
19
+## Docker
20
+
21
+[Docker](https://www.docker.com/) hardly needs any introduction. It allows you to run isolated containers, and Omarchy installs everything needed to run it well. This includes Docker itself, [Docker Compose](https://docs.docker.com/compose/), and the user group changes needed for you to run Docker as the normal user and not as root.
22
+
23
+Remember to checkout the Lazydocker command to manage your containers in a cool TUI using `Super + Shift + D`.
24
+
25
+You can setup the common databases for local development in Docker using _Install > Development > Docker DB_ in the Omarchy menu.
26
+
27
+## GitHub CLI
28
+
29
+[The GitHub CLI](https://cli.github.com/) let's you authenticate with your GitHub account and clone private repositories using it. It's wired up as one of the lazy-loading mise stubs, so the first time you run `gh`, it installs itself. To authenticate, run `gh auth login`. Then you can checkout private repositories using `gh repo clone org/repo`.
30
+
31
+You can also perform a bunch of other GitHub operations using this command. Just run `gh` to see everything that's possible.
32
+
33
+There's a lazy-installing stub for `ghui` for managing your pull requests in a TUI too. And [lazygit](https://github.com/jesseduffield/lazygit) is preinstalled, if you'd like to drive git itself from a TUI as well.
0
34
▼manual/19-shell-tools.md
+59-0
1
+# Shell Tools
2
+
3
+In addition to the standard Linux tools, Omarchy also ships with a bunch of enhanced shell tools. Here are the key ones.
4
+
5
+## fzf
6
+
7
+[fzf](https://junegunn.github.io/fzf/) gives you fuzzy finding of files via the `ff` alias. Go to any directory, type `ff`, and you'll be able to fuzzy find your way to any file in that tree, while seeing a preview of the files you're narrowing down on the right-hand side.
8
+
9
+You can use `Ctrl + R` to use fzf to fuzzy find through your command history.
10
+
11
+This tool is also used by Neovim when you type `Space Space`.
12
+
13
+The full manual can be found via `man fzf`.
14
+
15
+## Zoxide
16
+
17
+[Zoxide](https://github.com/ajeetdsouza/zoxide) is a replacement for cd. It remembers the directories you've been in, so you can more easily jump to them next time. Say you do `cd ~/.config/omarchy` once. Next time, you can just do `cd omarchy` (or even just `cd oma`), and Zoxide will take you directly there.
18
+
19
+The full manual can be found via `man zoxide`.
20
+
21
+## ripgrep
22
+
23
+[ripgrep](https://github.com/BurntSushi/ripgrep) searches the contents of files by using `rg <pattern> <path>`, like `rg Controller app/` to find all mentions of `Controller` in the directory app.
24
+
25
+This tool is also used by Neovim when you type `Space S G`.
26
+
27
+The full manual can be found via `man rg`.
28
+
29
+## eza
30
+
31
+[eza](https://eza.rocks/) is a replacement for ls. It gives you directory listings with more information, color, and icons. By default, eza has been aliased as ls. You can also use `lt` to get a listing of two-deep levels of nesting. `lsa` gives you a listing including hidden files. And `lta` a nested listing with hidden files.
32
+
33
+The full manual can be found via `man eza`.
34
+
35
+## fd
36
+
37
+[fd](https://github.com/sharkdp/fd) is an easier to use replacement for `find`. Use `fd person.rb` to find a file called `person.rb` within the current tree. `fd person.rb /` will search the entire file system. `fd person.rb / -H` searches the entire file system, including hidden directories.
38
+
39
+The full manual can be found via `man fd`.
40
+
41
+## bat
42
+
43
+[bat](https://github.com/sharkdp/bat) is `cat` with syntax highlighting, line numbers, and paging. Run `bat somefile.rb` and you'll see why it's hard to go back. It's also quietly doing work for you elsewhere: it's what colors your man pages, and what renders the previews in `ff`.
44
+
45
+The full manual can be found via `man bat`.
46
+
47
+## tldr
48
+
49
+[tldr](https://tldr.sh/) is the antidote to man pages that open with three screens of history before showing you a single example. `tldr tar` gives you the handful of invocations you actually wanted.
50
+
51
+## yt-dlp
52
+
53
+[yt-dlp](https://github.com/yt-dlp/yt-dlp) downloads video from YouTube and hundreds of other sites. `yt-dlp <url>` grabs the best quality available into the current directory.
54
+
55
+The full manual can be found via `man yt-dlp`.
56
+
57
+## try
58
+
59
+[try](https://github.com/tobi/try) makes it easy to manage programming experiments with date-stamped directories. All experiments live in `~/Work/tries` and you can access them via `try`.
0
60
▼manual/20-shell-functions.md
+49-0
1
+# Shell Functions
2
+
3
+Omarchy comes with a set of shell functions to simplify common tasks and encapsulate convoluted parameter calls.
4
+
5
+## Compression
6
+
7
+- `compress [file/dir]`: Create a tar.gz archive from the file/dir.
8
+- `decompress [file.tar.gz]`: Expand a tar.gz file.
9
+
10
+## Drives
11
+
12
+- `iso2sd [image.iso]`: Create a bootable drive on an SD card using the referenced iso file and picking the drive interactively.
13
+- `format-drive [device] [name]`: Format an entire disk with a single exFAT partition (which works on Windows and macOS too). Run it without arguments to see the available drives. Be careful!
14
+
15
+## Dev layouts
16
+
17
+Instant multi-pane development layouts for tmux:
18
+
19
+- `tdl [ai]`: Create a Tmux Dev Layout with your editor, an AI agent, and a terminal. Use the agent aliases, like `tdl c` for opencode or `tdl cx` for Claude Code, or pass a second agent to run both, like `tdl c cx`.
20
+- `tds`: Create a Tmux Dev Square with editor, diff watching (via `hunk diff --watch`), terminal, and opencode.
21
+- `tdlm [ai]`: Create a `tdl` window for every subdirectory in the current directory.
22
+- `tsl [count] [command]`: Create a swarm of panes tiled in a grid, all running the same command (great for AI agents).
23
+
24
+The same layouts are available for Herdr as `hdl`, `hds`, `hdlm`, and `hsl`.
25
+
26
+## Git worktrees
27
+
28
+- `ga [branch]`: Create a new worktree and branch next to the current repository and jump into it.
29
+- `gd`: Remove the current worktree and its branch (asks for confirmation first).
30
+
31
+## Rsync watchers
32
+
33
+- `rsw [source] [destination]`: Start a background watcher that rsyncs source to destination whenever anything changes. The destination can be a remote host, like `rsw ~/Work/app nyc-dev:Work/app`.
34
+- `lsw`: List all active watchers.
35
+- `dsw`: Stop all active watchers.
36
+
37
+## SSH Portforwarding
38
+
39
+Ideal for doing web development with localhost secure-context privileges against a remote box.
40
+
41
+- `fip`: Forward one or more ports from a remote host to localhost via SSH.
42
+- `dip`: Disconnect one or more forwarded ports.
43
+- `lip`: List all active SSH port forwards.
44
+
45
+Say you start a dev server on port `3000` on a machine accessible as `nyc-dev`, then you can run `fip nyc-dev 3000` to forward that port, so `localhost:3000` actually reaches `nyc-dev:3000`, but without the need for SSL certificates to establish the secure context needed for testing web sockets or the like.
46
+
47
+## SSH reconnection
48
+
49
+`ssh` itself is wrapped in a function that cleans up the terminal if a connection dies while a remote tmux, Herdr, or editor has claimed it, and then automatically reconnects when an interactive session drops (Ctrl-C stops the retry loop).
0
50
▼manual/21-tuis.md
+51-0
1
+# TUIs
2
+
3
+## Lazygit
4
+
5
+[Lazygit](https://github.com/jesseduffield/lazygit) is a delightful alternative to something like the GitHub Desktop application, and it runs inside the terminal.
6
+
7
+You can run it directly, by going to any directory managed by git and running `lazygit`. Or you can run it inside Neovim where it can be started with `Space G G`.
8
+
9
+You hop between the different panes using `Tab`. In the Files pane, you select files for staging using `Space`, and then you can create a new commit using `c`. You can see all the commands available using `?`.
10
+
11
+## Lazydocker
12
+
13
+[Lazydocker](https://github.com/jesseduffield/lazydocker) is made in the same spirit like Lazygit, and also gives you a terminal interface for managing your containers and images.
14
+
15
+You can start it with `Super + Shift + D`.
16
+
17
+You stop a container using `s` or start/restart it using `r`. See all commands using `?`.
18
+
19
+## Btop
20
+
21
+[Btop](https://github.com/aristocratos/btop) is a beautiful resource manager that shows memory, CPU, disk, and network usage. It also lists all active processes, and allows you to manage them.
22
+
23
+Omarchy calls it Activity, and you start it by hitting `Super + Ctrl + T`. It opens as a floating window, which you can tile with `Super + T`.
24
+
25
+## Herdr
26
+
27
+[Herdr](https://github.com/omacom-io/herdr) is a terminal workspace manager that gives you workspaces, tabs, and panes, and keeps them all running in a persistent session you can detach from and come back to later.
28
+
29
+You start it (or reattach to your existing session) with `Super + Ctrl + Return`. Omarchy ships a Herdr configuration that mirrors its Tmux config, so the prefix key is `Ctrl + Space` here too. You can browse all the keybindings with `Super + Ctrl + K`.
30
+
31
+## Fastfetch
32
+
33
+[Fastfetch](https://github.com/fastfetch-cli/fastfetch) shows system information, like kernel version, uptime, theme, CPU, memory, and more. It's a successor to the popular neofetch tool.
34
+
35
+Omarchy has packaged this as _About_ in the Omarchy menu (`Super + Space`).
36
+
37
+## Disk Usage
38
+
39
+When the drive fills up and you have no idea what's eating it, launch _Disk Usage_ from the app launcher (`Super + Space`). It's [dua](https://github.com/Byron/dua-cli) in interactive mode pointed at the whole file system, so you can walk down into whatever directory is the culprit, sorted biggest first, and delete from right inside it.
40
+
41
+## Cliamp
42
+
43
+[Cliamp](https://www.cliamp.stream/) is a retro terminal music player inspired by Winamp 2.x, complete with built-in radio stations for lo-fi beats. Launch it with `Super + Shift + Alt + M`, or from the Omarchy menu under _Apps_. Press `?` for the full keybinding list.
44
+
45
+## What about Wi-Fi and Bluetooth?
46
+
47
+You won't find TUIs for Wi-Fi and Bluetooth — those jobs belong to the Omarchy shell. Click the Wi-Fi icon in the top bar (or hit `Super + Ctrl + W`) to see networks and connect, and click the Bluetooth icon (or hit `Super + Ctrl + B`) to pair and connect devices. See [networking](35-networking.md) for the full story.
48
+
49
+## Adding your own
50
+
51
+Any terminal program can get the full app treatment. Go to _Install > TUI_ in the Omarchy menu (`Super + Space`), give it a name, a launch command, a window style, and an icon, and it'll show up in the app launcher like any other application. You can remove it again under _Remove > TUI_.
0
52
▼manual/22-guis.md
+96-0
1
+# GUIs
2
+
3
+## Files
4
+
5
+Files (Nautilus) is the graphical file manager. `Super + Shift + F` opens it, and `Super + Shift + Alt + F` opens it in the directory your terminal is sitting in, which saves a lot of clicking. `Ctrl + L` lets you type a path, and hitting `Space` on any file gives you a quick preview without opening anything.
6
+
7
+Plug in a USB stick or an SD card and it's mounted automatically, so it just shows up in the sidebar. For anything more involved — formatting a drive, checking SMART health, creating partitions — launch _Disks_ from the app launcher (`Super + Space`).
8
+
9
+Double-clicking follows sensible defaults: images open in imv, video in mpv, PDFs in Document Viewer, and plain text in Neovim.
10
+
11
+## Obsidian
12
+
13
+[Obsidian](https://obsidian.md/) is a free and highly extensible note taking application that uses simple Markdown files for storage.
14
+
15
+Obsidian is free for all purposes, including personal, commercial, and non-profit use.
16
+
17
+Obsidian also offers a [commercial add-on for syncing](https://obsidian.md/sync) with mobile apps on iOS and Android. (https://obsidian.md/pricing).
18
+
19
+You start Obsidian with `Super + Shift + O`. To use theme syncing, you must select the `Omarchy` theme under settings.
20
+
21
+## Omawrite
22
+
23
+[Omawrite](https://github.com/omacom-io/omawrite) is Omarchy's own dead-simple Markdown writing app. No vaults, no plugins, just you and the words.
24
+
25
+You start Omawrite with `Super + Shift + W`.
26
+
27
+## Pinta
28
+
29
+[Pinta](https://www.pinta-project.com/) is a basic image editing tool that's great for cropping, resizing, and other basic manipulations. Just don't expect a Photoshop alternative. But it's still got a Magic Wand and layers!
30
+
31
+You start Pinta via the application launcher (`Super + Space`).
32
+
33
+## Aether
34
+
35
+[Aether](https://github.com/bjarneo/aether) is a theming application that can extract colors from a background image and turn them into a complete, cohesive theme. It's the easiest way to [make your own theme](43-making-your-own-theme.md).
36
+
37
+You start Aether via the application launcher (`Super + Space`).
38
+
39
+## LocalSend
40
+
41
+[LocalSend](https://localsend.org/) lets you send files to other devices on the same network running the app, like Apple's AirDrop. It's cross-platform, though, so you can send files to and from Windows, macOS, Android, iOS, and of course Linux.
42
+
43
+You can open the Share menu on `Super + Ctrl + S` or under _Trigger > Share_ in the Omarchy menu. It gives you four options:
44
+
45
+- **Clipboard** sends whatever you've copied as a text file. Great for getting a link or a snippet onto your phone without emailing yourself.
46
+- **File** opens a file picker where you can select several at once.
47
+- **Folder** sends an entire directory.
48
+- **Receive** opens LocalSend proper so another device can send something to you.
49
+
50
+The same thing works from the terminal with `omarchy share clipboard`, `omarchy share file [path]`, and `omarchy share folder [path]`. Leave the path off and you get the picker.
51
+
52
+You can also send straight from the file manager: right-click any selection in Nautilus and pick _Send via LocalSend_.
53
+
54
+Omarchy's firewall is closed by default except for LocalSend's port, so this works out of the box on a fresh install. See [security](48-security.md).
55
+
56
+## LibreOffice
57
+
58
+[LibreOffice](https://www.libreoffice.org/) is a complete office package with word processor, spreadsheet, presentations, drawing application, and more. It's compatible with files from Microsoft Office, so this is a great way to be able to open those Word documents.
59
+
60
+You start LibreOffice via the application launcher (`Super + Space`).
61
+
62
+## Omacalc
63
+
64
+[Omacalc](https://github.com/omacom-io/omacalc) is Omarchy's own dead-simple calculator, which opens in a floating window.
65
+
66
+You start Omacalc with `Super + Ctrl + Q` (or the calculator key, if your keyboard has one).
67
+
68
+## Signal
69
+
70
+[Signal](https://signal.org/) is the pioneer of E2E encrypted messaging, and a great communication option for anyone who'd prefer not to go through one of the big tech conglomerates.
71
+
72
+You start Signal with `Super + Shift + G`. It's not part of the base install, so the first time you hit that, Omarchy will offer to install it for you (it's also under _Install > Service_ in the Omarchy menu).
73
+
74
+## mpv
75
+
76
+[mpv](https://mpv.io/) is a simple, fast media player that'll play almost anything from any source. Great for watching videos.
77
+
78
+You start mpv via the application launcher (`Super + Space`) or just double-click on a video in the file manager.
79
+
80
+## OBS Studio
81
+
82
+[OBS Studio](https://obsproject.com/) lets you record or stream video from multiple inputs. You can mix a screencast with a webcam with a microphone input. It's what was used to record the Omarchy screencasts.
83
+
84
+You start OBS Studio via the application launcher (`Super + Space`).
85
+
86
+## Kdenlive
87
+
88
+[Kdenlive](https://kdenlive.org/) is an excellent video editor. Perfect for working on video that comes out of OBS Studio before sharing it.
89
+
90
+You start Kdenlive via the application launcher (`Super + Space`).
91
+
92
+## Omacut
93
+
94
+[Omacut](https://github.com/omacom-io/omacut) is Omarchy's own dead-simple video trimmer. When all you need is to cut the start and end off a clip, it beats firing up a full video editor.
95
+
96
+You start Omacut via the application launcher (`Super + Space`).
0
97
▼manual/23-browsers.md
+39-0
1
+# Browsers
2
+
3
+Omarchy ships with [Chromium](https://www.chromium.org/) as the default browser. It's the plain open-source build, themed to match the rest of your system, and it's what `Super + Shift + Return` opens and what every [web app](25-web-apps.md) runs inside.
4
+
5
+If Chromium isn't your taste, you're not stuck with it. Under _Install > Browser_ in the Omarchy menu you'll find Chrome, Edge, Brave, Brave Origin, Firefox, and [Zen](https://zen-browser.app/). Pick one and Omarchy installs it, sets up its policy directory, and applies your current theme to it.
6
+
7
+## Making one the default
8
+
9
+Installing a browser doesn't promote it. Once it's on the machine, go to _Setup > Defaults > Browser_ and pick it — the menu only lists browsers you actually have installed, and marks the current default with a check.
10
+
11
+From the terminal it's:
12
+
13
+```bash
14
+omarchy default browser firefox
15
+```
16
+
17
+Run it with no argument and it tells you the current default. This sets the XDG handler, so it's not just Omarchy's hotkeys that follow along — anything that opens a link, from a chat app to a terminal command, goes to the browser you picked.
18
+
19
+## Copy URL and Download Video
20
+
21
+The Chromium-family browsers (Chromium itself, Chrome, Edge, and Brave) come with two Omarchy extensions that reach out of the browser and into the rest of your system.
22
+
23
+**Copy URL** puts the current tab's address on your clipboard with `Alt + Shift + L`. That's faster than clicking into the address bar and copying, and because it goes through the system clipboard rather than the browser's, you get an Omarchy notification confirming it and the URL is immediately available in [clipboard history](08-unified-clipboard-history.md) and every other app. There's a toolbar button too, if you prefer clicking.
24
+
25
+**Download Video** grabs the video playing on the page you're looking at with `Alt + Shift + D`. It hands the URL to [yt-dlp](https://github.com/yt-dlp/yt-dlp), so it works on far more than YouTube, and the download lands in `~/Videos`. Progress shows up in the same on-screen display that volume and brightness use, updating in place rather than stacking up notifications. Set `OMARCHY_YTDLP_DIR` if you'd rather the files went somewhere else — see the [FAQ](46-faq.md) for where to put environment variables.
26
+
27
+Both extensions talk to Omarchy through a small native messaging host, which gets installed for you along with the browser. That's the piece that lets a web page's video end up in your home directory and a URL end up in your clipboard manager, which a normal extension can't do on its own.
28
+
29
+These are Chromium-family only. Firefox and Zen don't get them.
30
+
31
+## Firefox and Zen
32
+
33
+Firefox and Zen are a different family, so they get different treatment: Omarchy installs a policies file for sensible defaults and switches them into native Wayland mode, which you want for fractional scaling and smooth trackpad scrolling.
34
+
35
+They don't get the Chromium extensions above, and they're not themed by Omarchy, so those parts of the experience are yours to set up.
36
+
37
+## Removing one again
38
+
39
+Anything you installed here can be taken back off under _Remove > Browser_. Chromium isn't in that list — it's part of the base system.
0
40
▼manual/24-commercial-apps-services.md
+37-0
1
+# Commercial apps/services
2
+
3
+Omarchy is mostly focused on providing free, open source software, but it's not religious about it. Sometimes the best solution is a commercial offering, and that's just fine. Here are some of the options we provide an easy installation for.
4
+
5
+## 1Password
6
+
7
+Keeping your passwords in a password manager is a best practice. Doubly so if you're working with a team. And [1password](https://1password.com/) is a great solution, which also comes with a command line tool for integrating key lookups in scripts.
8
+
9
+You start 1Password with `Super + Shift + /`. If it isn't installed yet, that hotkey kicks off the installation first (you can also use _Install > Service > 1Password_ from the Omarchy menu). The installer sets up the 1Password extension for Chromium as well.
10
+
11
+## Bitwarden
12
+
13
+[Bitwarden](https://bitwarden.com/) is the open source alternative in the password manager space, with a free tier that covers most personal use. Install it with _Install > Service > Bitwarden_ from the Omarchy menu, which brings along the Bitwarden command line tool as well.
14
+
15
+## Spotify
16
+
17
+[Spotify](https://spotify.com/) is the world's most popular streaming music service. And the Linux application provides everything you'd expect, including offline playing.
18
+
19
+You start Spotify using `Super + Shift + M`. Like 1Password, the hotkey kicks off the installation first if Spotify isn't installed yet (or use _Install > Service > Spotify_ from the Omarchy menu).
20
+
21
+## Dropbox
22
+
23
+[Dropbox](https://www.dropbox.com/) is a great way to sync files between machines while keeping a backup in the cloud. To set it up, select _Install > Service > Dropbox_ from the Omarchy menu. Once it's running, hover the tray in the top right of the bar and right-click the Dropbox icon to finish the setup.
24
+
25
+## Tailscale
26
+
27
+[Tailscale](https://tailscale.com/) is a mesh VPN that makes getting access to all your computers and servers over the internet securely super simple. To set it up, select _Install > Service > Tailscale_ from the Omarchy menu.
28
+
29
+It gets a panel in the bar, a web app for the admin console, and Taildrop for sending files between your machines — see [networking](35-networking.md).
30
+
31
+## ONCE
32
+
33
+[ONCE](https://once.com/) is 37signals' line of software you buy once and run on your own server, like the Campfire chat system. Select _Install > Service > ONCE_ from the Omarchy menu to install it, which enables its background service and drops you into the ONCE terminal interface to take it from there.
34
+
35
+## NordVPN
36
+
37
+[NordVPN](https://nordvpn.com/) is a standard VPN service that lets you exit your traffic from most regions around the world. To set it up, select _Install > Service > NordVPN_ from the Omarchy menu. After the reboot it asks for, run `nordvpn login` to authenticate.
0
38
▼manual/25-web-apps.md
+75-0
1
+# Web Apps
2
+
3
+You can add your own web apps using _Install > Web App_ in the Omarchy menu (`Super + Space`). It'll ask you for the app name, app URL, and the icon URL, if it can't retrieve it via favicon. You can get great PNG icons for many popular web apps on [Dashboard Icons](https://dashboardicons.com).
4
+
5
+They'll then be accessible through the app launcher (`Super + Space`), and use the beautiful frameless web-app window.
6
+
7
+If you wish to remove a web app, just go to _Remove > Web App_ in the Omarchy menu.
8
+
9
+It's best if you log into all your accounts using a regular browser before using the web app shortcuts. The thin wrapper frame doesn't work well with 1password, so just easier to be logged in directly first.
10
+
11
+All the keyboard hotkeys for these web apps can be changed in `~/.config/hypr/bindings.lua`.
12
+
13
+When you're in a web app, you can copy the current URL to the clipboard using `Shift + Alt + L`.
14
+
15
+By default, Omarchy already ships with an assortment of default apps:
16
+
17
+## HEY
18
+
19
+[HEY](https://www.hey.com/) is an email and calendar service that serves as a great alternative to people tired of Gmail, Outlook, or Apple Mail. It's made by [37signals](https://37signals.com/) where Omarchy originated.
20
+
21
+You can start HEY Email using `Super + Shift + E`, jump straight to composing a new email using `Super + Shift + Alt + E`, and start HEY Calendar using `Super + Shift + C`.
22
+
23
+## Basecamp
24
+
25
+[Basecamp](https://basecamp.com/) is a project management service that helps small teams move faster and make more progress. Instead of patching together a mishmash of Trello, Slack, Asana, Notion, or whatever, you can have it all in one place with Basecamp. It's made by [37signals](https://37signals.com/) where Omarchy originated.
26
+
27
+You can start Basecamp using the application launcher (`Super + Space`)
28
+
29
+## ChatGPT
30
+
31
+[ChatGPT](https://chatgpt.com) is the most popular AI chat bot in the world.
32
+
33
+You can start ChatGPT using `Super + Shift + A`.
34
+
35
+## Grok
36
+
37
+[Grok](https://grok.com) is xAI's chat bot.
38
+
39
+You can start Grok using `Super + Shift + Alt + A`.
40
+
41
+## WhatsApp
42
+
43
+[WhatsApp](https://www.whatsapp.com/) is one of the most popular messaging services in the world, and the web version is a great option for Linux.
44
+
45
+You can start WhatsApp using `Super + Shift + Alt + G`.
46
+
47
+## Google apps
48
+
49
+Google Messages, Google Photos, Google Maps, and Google Contacts are all included as web apps too.
50
+
51
+You can start Google Messages using `Super + Shift + Ctrl + G`, Google Photos using `Super + Shift + P`, and Google Maps using `Super + Shift + S`. Google Contacts is available through the app launcher (`Super + Space`).
52
+
53
+## X
54
+
55
+X is where news break.
56
+
57
+You can start X using `Super + Shift + X` and go straight to writing a new post with `Super + Shift + Alt + X`.
58
+
59
+## YouTube
60
+
61
+[YouTube](https://youtube.com/) is the most popular video platform in the world.
62
+
63
+You can start YouTube using `Super + Shift + Y`.
64
+
65
+## Zoom
66
+
67
+[Zoom](https://zoom.us/) is the most popular video chat system used in the US. Great connections across the world. And 40-minute meetings can be held without a paying account. Omarchy wraps Zoom's web client, and zoom meeting links will open straight into it.
68
+
69
+You start Zoom using the application launcher (`Super + Space`).
70
+
71
+## Discord
72
+
73
+[Discord](https://discord.com/) is where most gaming and open source communities hang out, including [Omarchy's own](https://discord.gg/tXFUdasqhY).
74
+
75
+You start Discord using the application launcher (`Super + Space`).
0
76
▼manual/26-gaming.md
+85-0
1
+# Gaming
2
+
3
+Omarchy isn't just for _pRoDUcTiVItY_, it's also for having fun, and what's more fun than gaming? Omarchy ships with a whole suite of gaming options — Steam and RetroArch for native and retro play, Battle.net, Lutris, and Heroic for non-Steam stores, Moonlight for PC streaming, Xbox Cloud Gaming + NVIDIA GeForce NOW for cloud, plus the evergreen Minecraft.
4
+
5
+Thanks to Valve's incredible work on [the proton compatibility layer](https://en.wikipedia.org/wiki/Proton_(software)), there are now tens of thousands of playable modern games on Linux. Oh, and did you know that the [Steam Deck](https://store.steampowered.com/steamdeck/) actually runs Arch!
6
+
7
+All gaming installers live under _Install > Gaming_ in the Omarchy menu (`Super + Space`). If you ever want to undo one, use _Remove > Gaming_.
8
+
9
+## Steam
10
+
11
+Install [Steam](https://store.steampowered.com/) by selecting _Install > Gaming > Steam_ from the Omarchy menu (`Super + Space`).
12
+
13
+After you've installed it, you'll be able to launch Steam with `Super + Space`.
14
+
15
+Note that Steam can take 10-20 seconds to start up, and it's not going to provide any visual feedback that it's loading.
16
+
17
+ ![gaming-steam](images/gaming-steam.webp)
18
+
19
+## RetroArch
20
+
21
+Install [RetroArch](https://www.retroarch.com/) by selecting _Install > Gaming > RetroArch_ from the Omarchy menu (`Super + Space`). It comes with the full set of libretro cores, so all the classic systems are covered.
22
+
23
+RetroArch is fully preconfigured with the beautiful CRT Royale shader for that perfect retro look.
24
+
25
+To get going:
26
+
27
+1. Drop your BIOS files into `~/Games/bios` and your ROMs into `~/Games/roms`.
28
+2. Launch RetroArch with `Super + Space` and typing `retro`.
29
+3. Scan the `~/Games/roms` directory and you're ready to play.
30
+
31
+You can also give a favorite game its own entry in the app launcher with _Install > Gaming > RetroArch Game Launcher_, which lets you pick a core and a ROM, and jump straight into the game from `Super + Space`.
32
+
33
+ ![gaming-retroarch](images/gaming-retroarch.webp)
34
+
35
+## Xbox Cloud Gaming
36
+
37
+Install the Xbox Cloud Gaming web app by selecting _Install > Gaming > Xbox Cloud Gaming_ from the Omarchy menu (`Super + Space`). It's "just" a web app for the service, but it's quick to start and runs great at 1080p.
38
+
39
+If you already have Xbox Game Pass, this is a solid way to play Fortnite and other titles you can't run natively on Linux.
40
+
41
+ ![gaming-xbox-cloud](images/gaming-xbox-cloud.webp)
42
+
43
+## NVIDIA GeForce Now
44
+
45
+Install the cloud-gaming service [NVIDIA GeForce NOW](https://www.nvidia.com/en-us/geforce-now/) by selecting _Install > Gaming > NVIDIA GeForce NOW_ from the Omarchy menu (`Super + Space`). Another great way to play titles that aren't available natively on Linux.
46
+
47
+ ![gaming-geforce-now](images/gaming-geforce-now.webp)
48
+
49
+## Minecraft
50
+
51
+Install Minecraft by selecting _Install > Gaming > Minecraft_ from the Omarchy menu (`Super + Space`).
52
+
53
+Like Steam, note that it can take a while after logging in or starting up for the next screen to appear, and you're not going to get any feedback while you're waiting.
54
+
55
+ ![gaming-minecraft](images/gaming-minecraft.webp)
56
+
57
+## Xbox Controllers
58
+
59
+Install support for Bluetooth Xbox controllers by selecting _Install > Gaming > Xbox Controllers_ from the Omarchy menu (`Super + Space`). Pair the controllers via Bluetooth (`Super + Ctrl + B`) and they'll work in all your games. You don't need this if you're just hardwiring your controller with a USB-C cable.
60
+
61
+## Moonlight (Game streaming from a PC)
62
+
63
+The [Moonlight client](https://github.com/moonlight-stream/moonlight-qt) comes preinstalled with Omarchy, so you can stream games from a Windows PC running [Sunshine](https://app.lizardbyte.dev/Sunshine/) right away. Launch Moonlight via `Super + Space`.
64
+
65
+If both your Omarchy machine and the remote gaming PC are hardwired, the experience is indistinguishable from playing locally. Crank the resolution up to native, set the refresh to 120Hz, and max the bitrate — this is the best way to play competitive shooters like Fortnite on Linux.
66
+
67
+You can also turn an Omarchy machine into the host by running `omarchy install service sunshine`, which installs Sunshine and opens the Moonlight streaming ports for your LAN and Tailscale.
68
+
69
+## Battle.net
70
+
71
+Install [Battle.net](https://eu.shop.battle.net/en-us) by selecting _Install > Gaming > Battle.net_ from the Omarchy menu (`Super + Space`). This gives you titles like Diablo, Starcraft, and World of Warcraft as a standalone install running under GE-Proton — no Steam, Lutris, or Heroic needed.
72
+
73
+ ![gaming-starcraft](images/gaming-starcraft.webp)
74
+
75
+## Lutris (Windows games)
76
+
77
+Install [Lutris](https://lutris.net/) by selecting _Install > Gaming > Lutris_ from the Omarchy menu (`Super + Space`). Lutris is the way to play Windows games from stores like EA and Ubisoft Connect that don't have their own installer above.
78
+
79
+Installation is a little janky and looks like nothing is happening at times — just be patient, it's working in the background.
80
+
81
+## Heroic Launcher (Epic Games)
82
+
83
+Install the [Heroic Launcher](https://heroicgameslauncher.com/) by selecting _Install > Gaming > Heroic (Epic Games)_ from the Omarchy menu (`Super + Space`). Heroic lets you run Epic Games titles, like OddSparks, that don't rely on anti-cheat — plus games from GOG and Amazon Prime Gaming. Sadly, that means no Fortnite and no Rocket League — until Tim Sweeney comes to Linux, this is as close as it gets.
84
+
85
+Like Lutris, it can feel slow and janky while installing games. Give it time.
0
86
▼manual/27-filling-out-pdfs.md
+9-0
1
+# Filling out PDFs
2
+
3
+Omarchy ships with a nice, basic PDF viewer called Document Viewer. This is the program that'll open any PDFs you just double click on.
4
+
5
+But you can only use Document Viewer to fill out PDFs that have been setup as forms. If you need to fill out PDFs that haven't, or you need to sign a PDF, you'll have to right-click the file, select _Open With..._, and pick Xournal++.
6
+
7
+Xournal++ will let you write anywhere on a PDF using the T tool. If you need to sign a document, you'll need an image of your signature, and you can use the Image tool to insert this signature and resize it.
8
+
9
+When you're done filling out the PDF, use _File > Export as PDF_ to save the final version.
0
10
▼manual/28-windows-vm.md
+43-0
1
+# Windows VM
2
+
3
+Omarchy offers an easy way to run Windows through a Docker VM. You can install it using _Install > Windows_ from the Omarchy menu (`Super + Space`).
4
+
5
+Your machine needs KVM virtualization for this, which most do — but it's sometimes switched off in the BIOS, and the installer will tell you if that's the case. You'll also want the disk space: whatever you give Windows, plus about 10GB for the image itself.
6
+
7
+The installer asks how much RAM, how many CPU cores, and how much disk to hand over (64GB or more is the sensible floor), then for a Windows username and password. Leave those blank and you get `docker` / `admin`. The download takes a while — 10-15 minutes is normal — and you can follow the progress in the browser at `http://127.0.0.1:8006`.
8
+
9
+ ![windows-vm](images/windows-vm.webp)
10
+
11
+## Using it
12
+
13
+Once it's installed, launch _Windows_ from the app launcher. That starts the VM if it isn't already running and connects you over RDP, full screen. Give it 15-30 seconds on a cold start.
14
+
15
+The RDP session carries sound, your microphone, and a shared clipboard, so copying text between Linux and Windows just works. The resolution follows your window, and Omarchy passes your display scaling through, so it's not a blurry mess on a HiDPI screen.
16
+
17
+When you close the RDP window, the VM shuts down automatically. If you'd rather leave it running — say you've got something working away in there — launch it with `omarchy windows vm launch --keep-alive` instead.
18
+
19
+The rest of the controls are on the same command:
20
+
21
+```bash
22
+omarchy windows vm status # is it running?
23
+omarchy windows vm stop # shut it down
24
+omarchy windows vm launch # start and connect
25
+```
26
+
27
+## Sharing files
28
+
29
+The directory `~/Windows` in your home directory is automatically shared with the VM. Put files there if you want them accessible to Windows. The VM has no access to any other part of your file system, so you're safe from anything nasty on the Windows side. Its own virtual disk lives in `~/.windows`.
30
+
31
+The VM's ports are bound to localhost only, so nothing on your network can reach the Windows machine.
32
+
33
+## Limits and licensing
34
+
35
+There's no GPU passthrough with this setup, so it's not suitable for gaming or video editing. It's a great way to run Microsoft Office or whatever else you absolutely must have.
36
+
37
+The version installed is Windows 11 Pro, unactivated. You'll need your own license key to use the gated features.
38
+
39
+If this computer shipped with Windows, the OEM key is still in firmware even after installing Omarchy. Print it with `omarchy windows key`. That key is bound to this machine — it will activate Windows reinstalled on this hardware, but it usually will not activate the VM.
40
+
41
+You can change the resource allocation later by editing `~/.config/windows/docker-compose.yml`, which is also where you'd mount a USB device. See all the options on [the Dockur Windows project](https://github.com/dockur/windows).
42
+
43
+To get rid of the whole thing, use _Remove > Windows_ from the Omarchy menu. That deletes the VM's disk and all its data, so make sure anything you care about is out of `~/Windows` first.
0
44
▼manual/29-other-packages.md
+9-0
1
+# Other Packages
2
+
3
+Arch has an amazing wealth of packages available for almost any type of software between the official repository and the Arch User Repository (AUR).
4
+
5
+It couldn't be easier to use either. You install a new Arch package by going to _Install > Package_ in the Omarchy menu (`Super + Space`) and typing the package you want. It'll automatically fuzzy filter the list of all packages. (You can also do it manually using `omarchy pkg add [package]` in the terminal).
6
+
7
+You can do the same with AUR, just use _Install > AUR_. Just remember that the AUR isn't vetted by the Arch team. It's like RubyGems or npm. Anyone can upload.
8
+
9
+If you want to remove a package, you can use _Remove > Package_ from the Omarchy menu. It'll remove package, config files, and dependencies. (You can also do it manually using `omarchy pkg drop [package]`).
0
10
▼manual/30-updates.md
+37-0
1
+# Updates
2
+
3
+Omarchy and your packages are kept up to date via _Update > Omarchy_ in the Omarchy menu (`Super + Space`).
4
+
5
+Omarchy itself is installed as regular pacman packages from the [Omarchy Package Repository](https://github.com/omacom-io/omarchy-pkgs), so an update installs [the latest Omarchy release](https://github.com/basecamp/omarchy/releases), runs any pending migrations to get your system in sync with the latest, and updates all system packages from the [Omarchy Arch Mirror](https://github.com/omacom-io/omarchy-mirror) and [AUR](https://aur.archlinux.org/) (if you have installed any AUR packages).
6
+
7
+When new releases are made, a circle arrow icon will appear to the right of your clock. Click it and the update process will start.
8
+
9
+![update-available](images/update-available.webp)
10
+
11
+### Four channels
12
+
13
+Omarchy is updated along four channels: stable, RC, edge, and dev. New installations start on the stable channel, which tracks the [official releases](https://github.com/basecamp/omarchy/releases/), as well as the [stable Omarchy Arch mirror](https://github.com/omacom-io/omarchy-mirror) that's running one month behind the latest, so we can catch any new incompatibilities that require config changes before they cause problems for people.
14
+
15
+But if you'd like to help spot those potential issues, you can run on the edge channel. That'll keep your Omarchy packages tracking the latest development builds, and lets you update to the latest Arch packages as soon as they're available. You should only do this if you're experienced with Linux, and know how to recover a system that has problems.
16
+
17
+Before any new major release, we'll be doing final validation using the RC channel. If you're interested in helping with final polishing, come hang out in #omarchy-release-candidates on the Discord.
18
+
19
+Finally, there's the dev channel, which links Omarchy directly to a git checkout of the source code in `~/omarchy`, combined with the edge packages. You should only use this channel if you're an experienced Linux user, working directly on Omarchy, and willing to tolerate breakage.
20
+
21
+You can switch between channels using _Update > Channel_ from the Omarchy menu (or `omarchy-channel-set` in the terminal).
22
+
23
+### Firmware updates
24
+
25
+Your packages aren't the only thing that goes stale. Many laptops and peripherals ship BIOS, SSD, and dock firmware through the Linux Vendor Firmware Service, and _Update > Firmware_ in the Omarchy menu will fetch and install whatever your hardware has waiting. It installs `fwupd` the first time you run it. Plenty of firmware can only be written during a reboot, so don't be surprised to be asked for one.
26
+
27
+### Warning about direct pacman/yay updates
28
+
29
+If you're already familiar with Arch, you might be tempted to just run `pacman -Syu` or `yay -Syu` yourself, but if you do that, you'll miss the snapshot, migrations, and configuration updates that Omarchy runs together with new packages. That's why Omarchy will actually stop a direct system upgrade and point you to `omarchy update` instead. (If you really know what you're doing, the guard will tell you how to bypass it for a single transaction.)
30
+
31
+### Rolling back bad updates
32
+
33
+If you ever have a problem after doing an update, you can rollback your system to the snapshot taken before the update. Just restart and pick the snapshot in the boot loading menu from before you started the update.
34
+
35
+![bootloader](images/bootloader.webp)
36
+
37
+If somehow your configuration files have been corrupted, you can also perform an Omarchy reinstall using `omarchy reinstall` in the terminal. This will reinstall all the default Omarchy packages, put you on stable and downgrade any packages that are too new, and reset all the configuration files. Note that all your user config changes to the Omarchy defaults will be overwritten doing this!
0
38
▼manual/31-dotfiles.md
+78-0
1
+# Dotfiles
2
+
3
+Omarchy is primarily configured through the so-called dotfiles that live in `~/.config`. Those are considered your files for your changes. The files that live in `/usr/share/de-omarchy` belong to Omarchy itself, and you shouldn't be messing with those. If you need to change anything in `/usr/share/de-omarchy`, you should be overwriting the value in `~/.config` instead.
4
+
5
+The key configs can be edited straight from the Omarchy menu (`Super + Space`), like _Setup > Monitors_, _Setup > Keybindings_, _Setup > Input_, and _Setup > Config > [file]_. When you do it this way, any process that needs restarting after config edits automatically will be after you quit the editor (Neovim by default — `:wq`, remember! — but you can change that via _Setup > Defaults > Editor_).
6
+
7
+Here's a list of the key files in `~/.config` and what they control:
8
+
9
+| File | Purpose |
10
+| ----------------------- | --------------------- |
11
+| `~/.config/hypr/hyprland.lua` | The main Hyprland config. Loads the Omarchy defaults plus your override files below. [Learn more about Hyprland configs](https://wiki.hypr.land/Configuring/). |
12
+| `~/.config/hypr/bindings.lua` | Your own keybindings and overrides of the defaults. |
13
+| `~/.config/hypr/monitors.lua` | Controls your monitors, resolution, and position. |
14
+| `~/.config/hypr/input.lua` | Controls your keyboard layout, mouse, and trackpad settings. |
15
+| `~/.config/hypr/looknfeel.lua` | Controls gaps, borders, animations, and the rest of the look. |
16
+| `~/.config/hypr/autostart.lua` | Controls extra processes started with the session. |
17
+| `~/.config/omarchy/shell.json` | Controls the Omarchy shell: bar position, layout, and widgets, plus screensaver, lock, and idle timings. |
18
+| `~/.config/foot/foot.ini` | Controls your terminal (foot is the default). |
19
+| `~/.XCompose` | Defines your quick-access emoji and name/email autocomplete. Make sure to run `omarchy-restart-xcompose` after making changes. |
20
+
21
+If you end up making a lot of changes to tweak your own setup, it's a good idea to backup all these dotfiles. [Stow is a great way to do that](https://www.youtube.com/watch?v=NoFiYOqnC4o).
22
+
23
+### Starting your own apps with the session
24
+
25
+If you want something to run every time you log in — a sync daemon, a chat app, your own script — put it in `~/.config/hypr/autostart.lua`:
26
+
27
+```lua
28
+o.launch_on_start("my-service")
29
+```
30
+
31
+That starts the command as part of the session, so it's properly cleaned up when you log out again.
32
+
33
+### Running scripts on system events
34
+
35
+Omarchy fires hooks at a handful of moments, and you can hang your own scripts off them. They live in `~/.config/omarchy/hooks/<event>.d/`, one directory per event, and every executable file in there runs when the event happens:
36
+
37
+| Event | When it runs |
38
+| ----- | ------------ |
39
+| `post-boot` | Right after the desktop has started |
40
+| `post-update` | During `omarchy update`, after packages and migrations |
41
+| `pre-refresh-pacman` | Before `omarchy refresh pacman` re-syncs the package config |
42
+| `theme-set` | After a theme change (theme name in `$1`) |
43
+| `font-set` | After a font change (font name in `$1`) |
44
+| `battery-low` | When the battery gets low (percentage in `$1`) |
45
+
46
+Each of those directories already holds a `.sample` file showing the shape of a hook — drop the `.sample` from the name to put it to work. To install a script you've written elsewhere, use `omarchy hook install post-boot ~/my-hook`, which copies it in and makes it executable.
47
+
48
+### Adding your own menu entries
49
+
50
+The Omarchy menu (`Super + Space`) can be extended with your own rows by editing `~/.config/omarchy/extensions/omarchy-menu.jsonc`. Entries are keyed by a dotted id, and the id is what places them in the tree, so `personal` shows up on the root menu and `personal.notes` shows up inside it:
51
+
52
+```jsonc
53
+"personal": {"icon":"","label":"Personal"},
54
+"personal.notes": {"icon":"󰎞","label":"Notes","action":"omarchy-launch-editor ~/notes"},
55
+```
56
+
57
+Reuse an existing id and you override that row instead of adding a new one. The file ships with all the available fields documented as comments.
58
+
59
+### Adding your own shell exports, functions, and aliases
60
+
61
+Omarchy ships with a bunch of ergonomic aliases and helpful functions, but it's very common to want to add your own. You should add both aliases, functions, and exports in `~/.bashrc`. This file will not be overwritten on updates. If you want to change any of the Omarchy defaults, you can also safely add them here.
62
+
63
+### Changing internal Omarchy files
64
+
65
+Look, this is your computer. You can do whatever you want with it, but I would advise against making changes to the files in `/usr/share/de-omarchy` directly. They belong to the Omarchy pacman package, so your changes will simply be overwritten on the next update. You're better off just overwriting any default values you don't like in the `~/.config/*` folder instead.
66
+
67
+You can change just about everything that way, like the default keybindings. Just edit `~/.config/hypr/bindings.lua` to, say, replace [Obsidian](https://obsidian.md/) with [Joplin](https://joplinapp.org/) (install with `omarchy-pkg-add joplin-bin`):
68
+
69
+```
70
+hl.unbind("SUPER + SHIFT + O")
71
+o.bind("SUPER + SHIFT + O", "Joplin", "joplin-desktop")
72
+```
73
+
74
+If you insist on hacking on the internal Omarchy files, switch to the dev channel via _Update > Channel > Dev_. That links Omarchy to a git checkout of the source code in `~/omarchy`, which you're free to change to your heart's content. Ain't nobody here to tell you what to do!
75
+
76
+### Resetting any changes
77
+
78
+If you end up making a mess of the configurations, you can always revert them to the defaults via _Update > Config_ in the Omarchy menu. Or by running `omarchy reinstall configs` to reset everything.
0
79
▼manual/32-shell-plugins.md
+102-0
1
+# Shell Plugins
2
+
3
+The Omarchy desktop runs as a single long-lived Quickshell process called `omarchy-shell`, and almost everything you see on screen is a plugin inside it. The bar is a plugin. So are the panels that drop down from it, the fullscreen overlays like the emoji picker and the clipboard manager, the Omarchy menu itself, the lock screen, the polkit dialog, and the headless services that watch your battery and warm your screen up at night.
4
+
5
+That's not just an implementation detail. It means you can turn pieces of the desktop off, swap them out, or write your own without touching a line of Omarchy's source.
6
+
7
+The first-party plugins ship with Omarchy and live in `$OMARCHY_PATH/shell/plugins/`. Anything you add yourself — your own experiments, or something you found on GitHub — lives in `~/.config/omarchy/plugins/`. Both are discovered the same way at startup; the only difference is where they sit on disk.
8
+
9
+## Seeing what you have
10
+
11
+```
12
+omarchy plugin list
13
+```
14
+
15
+That prints every discovered plugin with its id, whether it's enabled, whether it's first-party or third-party, its kinds, and its display name. Add `--json` if you're feeding it to something else.
16
+
17
+Plugin ids are namespaced. The built-ins all start with `omarchy.` — `omarchy.clock`, `omarchy.network`, `omarchy.notifications` — and that namespace is reserved, so a third-party plugin can never claim it.
18
+
19
+## Turning them on and off
20
+
21
+```
22
+omarchy plugin enable omarchy.tailscale
23
+omarchy plugin disable omarchy.weather
24
+```
25
+
26
+Or use the menu: _Setup > Plugins_ has Enable, Disable, Add, Clone, and Remove, each with a picker that only offers the plugins that make sense for that action.
27
+
28
+Enabled state is stored in `~/.config/omarchy/shell.json`, and the rule differs slightly for the two kinds of plugin. A third-party plugin is enabled exactly when its id appears somewhere in that file — as a bar layout entry, as an entry in `plugins[]`, or as `bar.id`. First-party plugins that aren't bar widgets are the other way around: they're on by default and only turn off by being listed in `disabledPlugins[]`.
29
+
30
+A full bar plugin has no off state at all. There's always exactly one bar, so you replace it by enabling another one. Bar widget placement is covered in [the top bar](05-the-top-bar.md).
31
+
32
+## Adding a plugin from git
33
+
34
+A third-party plugin is just a git repo with a `manifest.json` at its root.
35
+
36
+```
37
+omarchy plugin add https://github.com/acme/omarchy-weather.git --enable
38
+```
39
+
40
+Before it does anything, it tells you plainly that plugins run as arbitrary, unsandboxed code inside your long-lived shell process, shows you the URL, and asks you to confirm. Take that seriously. A plugin isn't a config file — it's code that runs for as long as your session does, with everything your user account can reach. Only add repos you're willing to run, and read them before you enable them.
41
+
42
+Then it clones the repo into a staging directory, validates the manifest, refuses the install if another plugin already claims that id, and moves it into `~/.config/omarchy/plugins/<id>/`. Without `--enable` it asks whether you want it on now, and you can say no and go read the code first. It never runs anything from the plugin, never executes an install hook, and never asks for sudo — it clones files, checks the manifest, and flips a bit over IPC.
43
+
44
+Updating is a fast-forward pull of that same checkout:
45
+
46
+```
47
+omarchy plugin update acme.weather
48
+omarchy plugin update
49
+```
50
+
51
+With no id it updates every git-managed plugin you have. It shows you the diff before applying it, refuses to update if you've got local changes it can't fast-forward past, and rolls back if the new revision fails validation.
52
+
53
+```
54
+omarchy plugin remove acme.weather
55
+```
56
+
57
+Removal disables the plugin first, then deletes it if it's a git checkout (the repo is still upstream) or unlinks it if it's a symlink. A hand-made plugin folder with no git repo gets moved to a timestamped backup inside the plugins directory instead of being deleted outright.
58
+
59
+## Cloning a built-in to modify it
60
+
61
+This is my favorite part. If you want to change how a built-in widget behaves, don't edit the files under `$OMARCHY_PATH` — those belong to the package and the next update will overwrite them. Clone it instead:
62
+
63
+```
64
+omarchy plugin clone omarchy.clock
65
+```
66
+
67
+That copies the whole plugin into `~/.config/omarchy/plugins/dhh.clock` (your username, not mine), renames it to "My Clock", enables it, and switches the shell over from the built-in to your copy — keeping an existing bar widget's position and settings. Add `--edit` to open the new directory in your `$EDITOR` right away, which is what the menu's _Setup > Plugins > Clone Plugin_ does for you.
68
+
69
+The username prefix keeps your clone's id yours, so sharing it doesn't collide with anyone else's. Calls made to the original built-in id get routed to your clone, so nothing that referred to `omarchy.clock` needs updating. And if you make a mess of it, `omarchy plugin remove dhh.clock` puts the built-in back.
70
+
71
+Saving a file anywhere under `~/.config/omarchy/plugins/` reloads the plugin code automatically, so you can leave the editor open and watch your changes land.
72
+
73
+## Writing your own
74
+
75
+A plugin is a directory with a `manifest.json` and some QML. The manifest declares `schemaVersion: 1`, an `id`, `name`, `version`, one or more `kinds`, and an `entryPoints` object pointing at the QML file for each kind:
76
+
77
+| Kind | What it is |
78
+|------|------------|
79
+| `bar-widget` | A component the active bar can drop into a section |
80
+| `panel` | A persistent or summoned floating window |
81
+| `overlay` | A fullscreen overlay |
82
+| `menu` | A summoned menu surface |
83
+| `service` | A headless singleton with no UI |
84
+| `bar` | A full bar that replaces the built-in one |
85
+
86
+A plugin can declare several kinds at once — the media plugin is both a `service` and a `bar-widget`. Bar widgets get an extra `barWidget` block with a display name, a category, an optional `defaultSection`, and `allowMultiple`, which says whether it makes sense to have more than one on the bar. Most widgets set it to `false`; spacers and indicators set it to `true`.
87
+
88
+Before you publish anything, check it:
89
+
90
+```
91
+omarchy plugin validate ./my-plugin
92
+```
93
+
94
+That runs the same checks the shell does at load time: the schema version, the required fields, an id that isn't reserved, entry points that are safe relative paths and actually exist, an entry point for every kind you claimed, and no symlinks anywhere inside the folder.
95
+
96
+For the full picture, the source is the documentation: `shell/README.md` in the Omarchy repo covers the manifest schema, the shell's IPC contract, and the exact shape of `shell.json`, and `shell/plugins/README.md` lists every first-party plugin with its id, kinds, and entry points.
97
+
98
+## Sharing yours with the world
99
+
100
+Once you've made something you like, put it in a public git repo. That's the whole distribution mechanism — anyone can then run `omarchy plugin add` against your URL and have it running in seconds.
101
+
102
+To help people actually find it, list it at [omarchyplugins.com](https://omarchyplugins.com). That's the community directory of Omarchy shell plugins, and it's the first place to look when you're wondering whether someone has already built the widget you're about to write. Browse it before you start!
0
103
▼manual/33-monitors.md
+55-0
1
+# Monitors
2
+
3
+Omarchy assumes you're running on a 2x-capable retina-class display by default. This is what you need to get those nice, crisp programmer fonts. It's what almost all new premium laptops with high-resolution screens are optimized for. It's what you'd want to run on a 27" 5K [Apple Studio Display](https://www.apple.com/studio-display/)/[ProArt PA27JCV](https://www.asus.com/us/displays-desktops/monitors/proart/proart-display-5k-pa27jcv/)/[Samsung S9](https://www.samsung.com/us/computing/monitors/5k/27-viewfinity-s9-5k-monitor-with-thunderbolt-4-matte-display-and-smart-features-ls27c900panxza/)/[Kuycon G27P](https://kuycon.us/monitors/G27P/) or 32" 6K [Apple XDR](https://www.apple.com/pro-display-xdr/)/[ProArt PA32QCV](https://www.asus.com/displays-desktops/monitors/proart/proart-display-6k-pa32qcv/)/[Kuycon G32P](https://kuycon.us/monitors/G32P/).
4
+
5
+But if you're not running a display with a PPI of 218 or above, you'll want to change the monitor settings. For example, if you have a 27" or 32" 4K, you can use fractional scaling by opening `~/.config/hypr/monitors.lua` (via _Setup > Monitors_ in the Omarchy menu) and switching to the recommendation for that combo:
6
+
7
+```lua
8
+local omarchy_gdk_scale = 2
9
+local omarchy_monitor_scale = 1.6
10
+```
11
+
12
+If you're using a 1080p or 1440p display, you'll probably just want to use 1x scaling, so you can use:
13
+
14
+```lua
15
+local omarchy_gdk_scale = 1
16
+local omarchy_monitor_scale = 1
17
+```
18
+
19
+Changes to `GDK_SCALE` apply to applications started after the change (and GTK only honors whole numbers, so keep it at the nearest integer of your monitor scale). So make sure you quit the windows that you have that are oversized after the change (or close all windows with `Ctrl + Alt + Del`!).
20
+
21
+You can also quickly step through the major monitor scaling ratios (1x, 1.25x, 1.6x, 2x, 3x, 4x) using `Super + /` to go higher and `Super + Alt + /` to go lower. If you have the default configuration, these changes will also persist past reboot.
22
+
23
+### Making text bigger or smaller
24
+
25
+Monitor scaling changes the size of everything. If all you want is bigger or smaller _text_, there's a single knob for that:
26
+
27
+```
28
+omarchy display text size 14
29
+```
30
+
31
+That takes a pixel size between 9 and 20, and moves the Omarchy shell, GTK applications, and your terminal together, so the whole desktop stays in proportion. Run it without an argument to see where you're at, and `omarchy display text size reset` to go back to the default. Foot is the one straggler: it has no way to reload its config, so running terminals keep their old size until you open a new one.
32
+
33
+### Extending and mirroring laptop displays
34
+
35
+When you connect an external screen to your laptop, the display is automatically extended. But you can change that to mirroring instead using _Trigger > Hardware_ in the Omarchy menu or `Super + Ctrl + Alt + Delete`. This is especially helpful if that external screen is a projector, and you want to show something while working.
36
+
37
+When you're extending, closing the lid on the laptop will automatically turn off the internal screen. Opening the lid will turn it back on. You can also control this manually using _Trigger > Hardware_ in the Omarchy menu or `Super + Ctrl + Delete`.
38
+
39
+### Arranging multiple screens
40
+
41
+Hyprland works great with multiple screens. Read more about how to lay them out in [the Hyprland monitor documentation](https://wiki.hypr.land/Configuring/Basics/Monitors/). You can [bind specific workspaces to specific monitors](https://wiki.hypr.land/Configuring/Basics/Workspace-Rules/) as well. In Omarchy, these rules go in `~/.config/hypr/monitors.lua` as `hl.monitor` entries — the file ships with commented examples for pinning a specific monitor to a resolution, position, and rotation.
42
+
43
+You can also checkout [Hyprmon](https://github.com/erans/hyprmon/), if you'd like a TUI to help you with the positioning of multiple screens.
44
+
45
+### Controlling brightness
46
+
47
+Monitor brightness is controlled by the dedicated function keys for brightness up/down. If you hold down shift while pressing these, you'll go to maximum or minimum brightness. The keys control the display you're focused on, so external monitors that speak DDC/CI are adjusted the same way as the laptop screen.
48
+
49
+### Apple Displays
50
+
51
+If you're using an Apple display, the regular keyboard brightness keys will also automatically work, if you're focused on the Apple display. This is done through the `asdcontrol` command.
52
+
53
+Note that if you're using an Apple 6K XDR display, you may see a phantom screen in your `hyprctl monitors` listing. You can turn this off with something like `hl.monitor({ output = "DP-2", disabled = true })` via _Setup > Monitors_.
54
+
55
+On Intel machines, you should be connecting to Apple displays using a regular Thunderbolt cable. On other machines without Thunderbolt, you'll typically have to use a [DP + USB-A -> USB-C cable](https://www.amazon.com/dp/B0BNX7MS6N) to make it work.
0
56
▼manual/34-keyboard-mouse-trackpad.md
+74-0
1
+# Keyboard, Mouse, Trackpad
2
+
3
+Hyprland lets you configure all your inputs in great detail. You can change the keyboard repeat to be supersonically fast or make the trackpad use natural scrolling. You change all of it in `~/.config/hypr/input.lua`, which you can also reach via _Setup > Input_ in the Omarchy menu (`Super + Space`). Anything you set there replaces Omarchy's defaults.
4
+
5
+Here's an example:
6
+
7
+```lua
8
+hl.config({
9
+ input = {
10
+ -- Use multiple keyboard layouts and switch between them with Left Alt + Right Alt
11
+ kb_layout = "us,dk",
12
+ kb_options = "compose:caps,shift:both_capslock_cancel,grp:alts_toggle",
13
+
14
+ -- Change speed of keyboard repeat
15
+ repeat_rate = 40,
16
+ repeat_delay = 600,
17
+
18
+ -- Increase sensitivity for mouse/trackpad (default: 0)
19
+ sensitivity = 0.35,
20
+
21
+ touchpad = {
22
+ -- Use natural (inverse) scrolling
23
+ natural_scroll = true,
24
+
25
+ -- Use two-finger clicks for right-click instead of lower-right corner
26
+ clickfinger_behavior = true,
27
+
28
+ -- Control the speed of your scrolling
29
+ scroll_factor = 0.3,
30
+ },
31
+ },
32
+})
33
+
34
+-- Scroll faster in the terminal
35
+o.window("(Alacritty|kitty|foot)", { scroll_touchpad = 1.5 })
36
+```
37
+
38
+You can [see all the input options](https://wiki.hypr.land/Configuring/Basics/Variables/#input) on the Hyprland wiki for inputs.
39
+
40
+By default, Omarchy uses CapsLock as the compose key for [quick emojis](07-hotkeys.md#quick-emojis) and [other completions](07-hotkeys.md#quick-completions). If you'd rather use CapsLock as Caps Lock, move the compose key elsewhere by changing `compose:caps` in `kb_options`. For example, this moves the compose key to Right Alt:
41
+
42
+```lua
43
+hl.config({
44
+ input = {
45
+ kb_options = "compose:ralt",
46
+ },
47
+})
48
+```
49
+
50
+### Trackpad gestures
51
+
52
+You can also turn on [touchpad gestures](https://wiki.hypr.land/Configuring/Advanced-and-Cool/Gestures/), like swiping with three fingers to change workspaces:
53
+
54
+```lua
55
+hl.gesture({ fingers = 3, direction = "horizontal", action = "workspace" })
56
+```
57
+
58
+On Dell XPS laptops with a haptic touchpad, you can also set the click strength to low, mid, or high under _Trigger > Hardware > Touchpad Haptics_.
59
+
60
+### Typing in Chinese, Japanese, and other languages
61
+
62
+Omarchy runs the [fcitx5](https://fcitx-im.org/) input method framework as part of every session — it's what powers the CapsLock compose sequences. That means the plumbing for non-Latin input is already in place: install an input engine like `fcitx5-mozc` (Japanese) or `fcitx5-chinese-addons` (Chinese) with `omarchy pkg add`, plus `fcitx5-configtool` to add the engine to your input methods and set the key that switches between them.
63
+
64
+### Use ALT as SUPER
65
+
66
+On some keyboards, it's not convenient to use the primary meta key (Windows/cmd key) as SUPER. You can change this to be ALT instead using this change:
67
+
68
+```lua
69
+hl.config({
70
+ input = {
71
+ kb_options = "compose:caps,shift:both_capslock_cancel,altwin:swap_alt_win",
72
+ },
73
+})
74
+```
0
75
▼manual/35-networking.md
+45-0
1
+# Networking
2
+
3
+Networking in Omarchy is handled by NetworkManager, and you drive it from the network icon in the [top bar](05-the-top-bar.md) or with `Super + Ctrl + W`.
4
+
5
+That panel scans for Wi-Fi networks, shows signal strength, and connects. Ethernet needs nothing at all — plug it in and it works. If you'd rather stay in the terminal, `nmtui` gives you the same controls, and there's an `omarchy network` command group too.
6
+
7
+## Sharing your Wi-Fi
8
+
9
+Rather than reading a long password out loud, run _Setup > Network > QR Code_ while you're on Wi-Fi. That puts a QR code on screen that any phone camera can scan to join. It's one of those things you'll use more than you'd expect once you know it's there.
10
+
11
+If you actually need the password itself, `omarchy network password <interface>` prints it.
12
+
13
+## DNS
14
+
15
+Omarchy uses whatever DNS your network hands out over DHCP. You can override that for the whole machine under _Setup > Network > DNS_, where Cloudflare and Google are one click away. Pick _Custom_ to type in your own servers.
16
+
17
+From the terminal, `omarchy dns` prints the current provider and `omarchy dns Cloudflare` sets one.
18
+
19
+## Pinning the Wi-Fi band
20
+
21
+If your router puts 2.4GHz, 5GHz, and 6GHz on the same network name, your laptop will sometimes cling to the slow one. `omarchy network band` shows which band you're on, and `omarchy network band 5` pins it. Use `auto` to let it choose again.
22
+
23
+This pins the band rather than a specific access point, so you keep roaming between APs normally.
24
+
25
+## How fast is it?
26
+
27
+_Trigger > Speed Test > Network Speed Test_ measures your actual up and down speed with a pair of dials. From the terminal it's `omarchy network speedtest down` or `up`. (There's a disk speed test sitting next to it in that menu, if you're benchmarking the other bottleneck.)
28
+
29
+## The firewall
30
+
31
+The firewall is on by default and blocks all incoming traffic, with one exception: port 53317, so [LocalSend](22-guis.md) works out of the box.
32
+
33
+SSH is off until you turn it on with _Setup > Security > SSHD_, which starts the daemon, opens port 22 rate-limited against brute force, and authorizes a key. Docker is locked down too, so containers can't accidentally expose themselves to the world. See [security](48-security.md) for the whole story.
34
+
35
+## Tailscale
36
+
37
+[Tailscale](https://tailscale.com/) is a mesh VPN that makes reaching all your computers and servers over the internet simple and secure. Install it with _Install > Service > Tailscale_.
38
+
39
+That gives you a Tailscale panel in the bar, which connects and disconnects the tailnet, switches accounts, and picks an exit node — your own machines and Mullvad regions both show up in the list. It also browses your machines, and that's where Taildrop lives: select a machine and press `s` to send it files, or `c`, `n`, and `d` to copy its IP, name, or full DNS name. The terminal equivalent is `omarchy tailscale send <machine> [file...]`, and files sent to you land in `~/Downloads` automatically.
40
+
41
+Installing it also adds a web app for the Tailscale admin console.
42
+
43
+## When it stops working
44
+
45
+Before rebooting, try restarting the offending piece on its own. _Update > Hardware_ has Wi-Fi, Bluetooth, Audio, and Trackpad, and reloading one of those clears up most "it worked five minutes ago" situations. See [troubleshooting](45-troubleshooting.md).
0
46
▼manual/36-system-sleep.md
+19-0
1
+# System sleep
2
+
3
+Omarchy enables suspend and hibernation by default, but if you're having issues with either on your machine, you can toggle them off.
4
+
5
+### Power profiles
6
+
7
+On a laptop, Omarchy remembers your power profile separately for plugged in and running on battery, and switches between the two as you plug and unplug. Out of the box that means performance on AC and balanced on battery.
8
+
9
+You can see what your machine offers with `omarchy powerprofiles list`, and set the one you want for the state you're currently in with `omarchy powerprofiles set autodetect power-saver`. To set the other state without unplugging anything, name it directly: `omarchy powerprofiles set battery power-saver`. Whatever you pick is what you'll get back the next time you're in that state.
10
+
11
+### Toggle suspend
12
+
13
+You toggle suspend by running `omarchy toggle suspend` from the terminal. That just reveals/hides the option under _System_ (or `Super + Esc`), and then you can see if it works consistently on your system. If not, you can hide it again with the same command.
14
+
15
+### Toggle hibernation
16
+
17
+You set up hibernation by running `omarchy hibernation setup` from the terminal. Hibernation creates a /swap subvolume on your boot drive the size of your physical RAM allocation, so make sure you have plenty of room to spare. On a 32GB machine, you'll always need 32GB+ free for this volume. Hibernation also requires the default Limine bootloader.
18
+
19
+When set up, you'll see the hibernate option under _System_ (or `Super + Esc`), and then you can see if it works consistently on your system. If not, you can remove it again by running `omarchy hibernation remove`.
0
20
▼manual/37-hardware-authentication.md
+17-0
1
+# Hardware authentication
2
+
3
+### Fingerprint authentication
4
+
5
+A lot of laptops come with a fingerprint sensor to do authentication. You can use this with Omarchy by running _Setup > Security > Fingerprint_ in the Omarchy menu (`Super + Space`).
6
+
7
+That'll install the fingerprint package, collect your print, verify it, and you'll be set to go using your fingerprint to unlock from the lock screen (which you can trigger with `Super + Ctrl + L`), enter sudo mode, and authorize system prompts.
8
+
9
+When your laptop lid is closed, the fingerprint prompt is automatically skipped, so you go straight to the password prompt instead of waiting on a sensor you can't reach. If you otherwise need to work on an external keyboard that doesn't have a sensor, just hit `CTRL + C`, when you're prompted for your fingerprint during `sudo`.
10
+
11
+You can remove the fingerprint authentication under _Remove > Security > Fingerprint_ in the Omarchy menu.
12
+
13
+### Fido2 authentication
14
+
15
+If you're using a Fido2 device, you can set it up for `sudo` authentication using _Setup > Security > Fido2_ in the Omarchy menu (`Super + Space`). It covers `sudo` and system authorization prompts, though, not unlocking your computer.
16
+
17
+You can remove the fido2 authentication under _Remove > Security > Fido2_ in the Omarchy menu.
0
18
▼manual/38-fonts.md
+9-0
1
+# Fonts
2
+
3
+Omarchy uses JetBrainsMono Nerd Font as both the terminal and system font by default.
4
+
5
+ ![fonts-jetbrainsmono](images/fonts-jetbrainsmono.webp)
6
+
7
+You can change this through the _Style > Font_ menu in the Omarchy menu (`Super + Space`). That sets the monospace font everywhere: the terminal, the bar, and anything else that asks for it.
8
+
9
+You can install other popular programming fonts via _Install > Style > Font_ in the Omarchy menu: Cascadia Mono, Meslo LG Mono, Fira Code, Victor Code, Bitstream Vera Mono, and Iosevka are all one click away, in their Nerd Font versions so the glyphs in the bar and terminal keep working. After installing one, pick it under _Style > Font_.
0
10
▼manual/39-backgrounds.md
+7-0
1
+# Backgrounds
2
+
3
+Every theme ships with its own set of backgrounds, and you can add extras of your own in `~/.config/omarchy/backgrounds/[theme]`. If you want to add an extra background image to, say, the nord theme, you just put the file in `~/.config/omarchy/backgrounds/nord`.
4
+
5
+You can do this most easily by going to _Install > Style > Background_ in the Omarchy Menu. That'll bring up the folder where the backgrounds for that theme is stored. Hit `Super + Shift + F` to start another file manager, find your background, copy it over. Now it'll be included in the choices of backgrounds you can select between using `Super + Ctrl + Space`.
6
+
7
+You can find a huge collection of cool curated backgrounds on https://github.com/dharmx/walls.
0
8
▼manual/40-prompt.md
+7-0
1
+# Prompt
2
+
3
+Omarchy ships with a minimal [Starship](https://starship.rs/) prompt by default. That's how I like to keep my prompt. I don't need to know the user, because it's always me, and I don't need to know the time, because it's always at the top.
4
+
5
+ ![prompt](images/prompt.webp)
6
+
7
+If you want more information or style, you can change the [Starship.rs](https://starship.rs/) configuration in `~/.config/starship.toml`. There's a lot you can do. Just don't go overboard (or do go overboard, do whatever you want, it's your computer!)
0
8
▼manual/41-branding.md
+43-0
1
+# Branding
2
+
3
+Omarchy allows you to set your company logo or personal image for both the boot unlock, the screensaver, and the about screen.
4
+
5
+### Boot unlock
6
+
7
+You can use `omarchy plymouth preview` to see what your custom logo and colors would look like. It takes a background color, a text color, a logo png, and a path for the preview image:
8
+
9
+```
10
+omarchy plymouth preview '#1d2021' '#ebdbb2' logo.png preview.png
11
+```
12
+
13
+Then apply the setup with `omarchy plymouth set '#1d2021' '#ebdbb2' logo.png`, which will also give the SDDM login screen the same colors and logo. If you want to revert, you can use `omarchy plymouth reset`.
14
+
15
+ ![branding-plymouth-shopify](images/branding-plymouth-shopify.webp)
16
+
17
+### Screensaver
18
+
19
+You can change the logo used for the screensaver under _Style > Screensaver_. It's an ASCII logo, so you can edit the text directly, but you can also hand it a png or svg image, and we'll convert that to ASCII. It looks pretty cool.
20
+
21
+ ![branding-screensaver](images/branding-screensaver.webp)
22
+
23
+There are three entries in that menu:
24
+
25
+- **Edit Text** opens `~/.config/omarchy/branding/screensaver.txt` in your editor. Type or paste whatever you like — ASCII art, your name, a rude word. Save and quit, and the screensaver fires up immediately so you can see it.
26
+- **Set From Image** opens a file picker for a png or svg, converts it to ASCII, and shows you the result. Logos with a clear silhouette work far better than photos.
27
+- **Restore Default** puts the Omarchy logo back.
28
+
29
+### About screen
30
+
31
+The same three options are under _Style > About_ for the _About_ screen you get from the Omarchy menu, and they work identically — the file is `~/.config/omarchy/branding/about.txt`, and the About window pops up after each change. The About art is converted to a smaller size than the screensaver's, since it has to fit in a window rather than fill your display.
32
+
33
+ ![branding-about](images/branding-about.webp)
34
+
35
+### Converting images yourself
36
+
37
+Both of the _Set From Image_ options are just calling `omarchy transcode ascii`, which you can run directly if you want control over the conversion:
38
+
39
+```
40
+omarchy transcode ascii ~/logo.svg ~/.config/omarchy/branding/screensaver.txt --width 100
41
+```
42
+
43
+It takes `--width` and `--height` in terminal columns and rows, a `--mode` of either `braille` (the default, and much finer) or `block`, a `--threshold` percentage for deciding which pixels count as part of the logo, and `--invert` for when your logo is light on a dark background. If a conversion comes out as a blob, the threshold is usually the knob to turn.
0
44
▼manual/42-common-tweaks.md
+37-0
1
+# Common tweaks
2
+
3
+This is a collection of common tailorings to the Omarchy setup. Know that it might occasionally be necessary for system updates to restore certain configs to their original condition. If this happens, your changes won't be lost, but put in a `.bak` file in the same directory.
4
+
5
+If you screw something up, you can restore individual configs to their original setup via _Update > Config_ in the Omarchy menu. If you _really_ screw everything up, you can reset all configs via `omarchy-reinstall`.
6
+
7
+### Reveal all tray icons all the time
8
+
9
+By default, tray icons, like Dropbox, 1password, or Steam, are hidden behind the tray expander arrow, which reveals them when you hover it. If you'd like to have them exposed all the time, right-click the expander arrow to open the tray icon manager, then pin the icons you want to keep visible (you can also hide the ones you never want to see).
10
+
11
+### Rounded window corners
12
+
13
+Omarchy's default design is one of square corners, but if you like to soften that up a bit, you can change `~/.config/hypr/looknfeel.lua` so rounding is no longer commented out:
14
+
15
+```
16
+hl.config({
17
+ decoration = {
18
+ -- Use round window corners.
19
+ rounding = 8,
20
+ },
21
+})
22
+```
23
+
24
+### Remove window gaps
25
+
26
+On laptop displays, some people prefer not to waste any pixels on window gaps (or even a top bar, which you can toggle off with `Super + Shift + Space`). You can toggle all gaps and borders off with `Super + Shift + Backspace`, or remove them permanently by removing the comments in this section of `~/.config/hypr/looknfeel.lua`:
27
+
28
+```
29
+hl.config({
30
+ general = {
31
+ -- No gaps between windows or borders.
32
+ gaps_in = 0,
33
+ gaps_out = 0,
34
+ border_size = 0,
35
+ },
36
+})
37
+```
0
38
▼manual/43-making-your-own-theme.md
+31-0
1
+# Making your own theme
2
+
3
+You can add your own themes to `~/.config/omarchy/themes`. Just copy one of the existing ones as a base (look in `/usr/share/de-omarchy/themes`), then tweak to your delight. As long as your theme is inside that folder, it'll be included in the theme selection menu.
4
+
5
+The main file you have to tweak is `colors.toml`. That defines the color set that's then used to generate configurations for the terminal (Foot/Alacritty/Ghostty/Kitty), btop, Chromium, Hyprland, Neovim, Helix, VSCode, Obsidian, and the entire Omarchy shell (top bar, menu, notifications, OSD, and lock screen).
6
+
7
+You can also use the included Aether application to create a new theme using a lovely GUI interface to play with colors and search for backgrounds. Just start it via the apps menu on `Super + Alt + Space`.
8
+
9
+### Light mode
10
+
11
+If you're making a light mode theme, set `mode = "light"` at the top of your `colors.toml`. Then it'll automatically be paired with light mode for all the apps. (The old way of dropping an empty file called `light.mode` in the root of your theme still works too.)
12
+
13
+### Icon colors
14
+
15
+If you'd like to color-match the file manager icons to your theme, add a file called `icons.theme` with the name of the icon set you want to use. By default, the options are: `Yaru Yaru-blue Yaru-dark Yaru-magenta Yaru-olive Yaru-prussiangreen Yaru-purple Yaru-red Yaru-sage Yaru-wartybrown Yaru-yellow`.
16
+
17
+### Unlock image
18
+
19
+Themes supplied with `unlock.png` and `preview-unlock.png` images will be listed under _Style > Unlock_. Your `unlock.png` should preferably be a transparent png. And you can create the preview image using `omarchy plymouth preview`.
20
+
21
+### Theming apps Omarchy doesn't cover
22
+
23
+If you use an app that isn't in that list, you can teach Omarchy to theme it yourself with a template. Drop a file in `~/.config/omarchy/themed/` named after the config it generates plus a `.tpl` extension, and write the config with `{{ background }}`, `{{ foreground }}`, `{{ accent }}`, `{{ red }}`, `{{ color0 }}` through `{{ color15 }}`, and the rest of the palette as placeholders. Every time you switch themes, the file is regenerated with that theme's colors.
24
+
25
+There's a fully commented `alacritty.toml.tpl.sample` in that folder to copy from — it lists every variable you can use, plus the `_strip` and `_rgb` modifiers for apps that want their colors without the `#` or as decimal RGB. Your templates take priority over Omarchy's own, so you can also use this to override how a built-in app gets themed.
26
+
27
+### Distributing your theme
28
+
29
+If you want to distribute your theme so others can use it, you need to put it on a public git server, like GitHub. Then people can install it using _Install > Style > Theme_ in the Omarchy menu using that URL. It's recommended that you follow the naming convention of `omarchy-[themename]-theme`, as the theme will show correctly as just `[themename]` in the theme selection menu after installation.
30
+
31
+You can have your theme added to [the extra themes page](https://omarchy.org/themes/) by sending a pull request to [the omarchy-site repo](https://github.com/omacom-io/omarchy-site).
0
32
▼manual/44-mac-support.md
+71-0
1
+# Mac support
2
+
3
+Omarchy has built-in support for **Intel Macs**. There are a couple of known limitations at the moment, but as long as you're aware and OK with those; you can breathe some new life into your old Macs by loading Omarchy.
4
+
5
+Please note that installing on an M-series Mac is not directly supported at this time. You can find out more about the state of this in #omarchy-on-other in our [Discord](https://discord.gg/tXFUdasqhY).
6
+
7
+In a simple test, we were able to achieve 36% performance gains on a 2019 MacBook Pro just by installing Omarchy.
8
+
9
+ ![macbook-omarchy](images/macbook-omarchy.webp)
10
+
11
+### Installing Omarchy on Mac
12
+
13
+Omarchy only supports being the **only** OS installed at the moment. During the installation, the drive will be wiped and MacOS will no longer be bootable.
14
+
15
+You can still restore it later via Internet Recovery if you'd like.
16
+
17
+For the sake of this part, we'll assume you've already reviewed [Getting Started](02-getting-started.md) and have your USB drive ready. If you don't go ahead and do that now.
18
+
19
+#### Disable Secure Boot
20
+
21
+It is necessary to disable Apple's Secure Boot in order to boot the bootable USB, as well as the OS. To disable it, perform the following:
22
+
23
+1. Turn off your Mac
24
+2. Turn it on and _immediately_ press and hold Command-R until you see the loading screen appear
25
+3. Select your user and enter your password if prompted
26
+4. Once in the recovery screen, choose **Utilities > Startup Security Utility** from the menubar
27
+5. Enter your password when prompted to authenticate
28
+6. Choose "No Security" from the Secure Boot options
29
+7. Choose "Allow booting from external or removable media" from the External Boot options
30
+
31
+#### Start the Installation
32
+
33
+1. Insert the USB drive
34
+2. Restart your Mac and _immediately_ press and hold Option until you see a screen of boot devices
35
+3. Select the orange EFI Boot device
36
+4. Proceed with the [install as normal](02-getting-started.md)
37
+
38
+The installer detects Mac hardware and applies the needed fixes automatically: Broadcom Wi-Fi drivers and firmware, the SPI keyboard driver on the MacBook models that need it, and an NVMe suspend fix for those same models.
39
+
40
+### Known Limitations
41
+
42
+Members of the community are constantly working on solutions to these challenges so if these are problematic for you, join #omarchy-on-other in our [Discord](https://discord.gg/tXFUdasqhY) and see if there's any up-to-date methods for resolving these.
43
+
44
+#### Devices with T1 Chip
45
+
46
+The Apple T1 chip was introduced in late 2016 and used exclusively in the first-generation MacBook Pro models with Touch Bar.
47
+- MacBook Pro 13-inch (2016, two Thunderbolt 3 ports) – Model: A1706
48
+- MacBook Pro 13-inch (2016, four Thunderbolt 3 ports) – Model: A1708
49
+- MacBook Pro 15-inch (2016) – Model: A1707
50
+
51
+#### Known Issues
52
+
53
+- Touch Bar is non-functional
54
+- Sound is not functioning
55
+
56
+#### Devices with T2 Chip
57
+
58
+The Apple T2 Security Chip was introduced in 2017. The T2 chip was discontinued with the transition to Apple silicon (M-series chips) starting in 2020.
59
+
60
+- iMac Pro (2017) – Model: A1862
61
+- MacBook Pro 13-inch (2018, four Thunderbolt 3 ports) – Model: A1989
62
+- MacBook Pro 15-inch (2018) – Model: A1990
63
+- MacBook Air (Retina, 13-inch, 2018) – Model: A1932
64
+- Mac mini (2018) – Model: A1998
65
+- MacBook Pro 13-inch (2019, two Thunderbolt 3 ports) – Model: A2159
66
+- MacBook Pro 13-inch (2019, four Thunderbolt 3 ports) – Model: A2178
67
+- MacBook Pro 15-inch (2019) – Model: A1990
68
+- MacBook Pro 13-inch (2020, two Thunderbolt 3 ports) – Model: A2265
69
+- MacBook Pro 15-inch (2020) – Model: A1990
70
+
71
+On these models, the installer automatically sets up the patched `linux-t2` kernel, the T2 audio configuration, Apple's Broadcom Wi-Fi/Bluetooth firmware, and fan control via `t2fanrd`. The Touch Bar runs on the kernel's built-in Boot Camp-style support.
0
72
▼manual/45-troubleshooting.md
+49-0
1
+# Troubleshooting
2
+
3
+### I broke my system with an update!
4
+
5
+First try to [rollback your system](47-system-snapshots.md) the version before your recent update. If that doesn't work, use `omarchy-debug` to share with your problem on #omarchy-help in the Discord. And if all that fails, you can reinstall the defaults configs and packages using `omarchy-reinstall`.
6
+
7
+### Why are some apps so large on my display?
8
+
9
+Omarchy assumes a 2x high-resolution display, which requires setting `GDK_SCALE` to 2 in `~/.config/hypr/monitors.lua`. But if you're on a 1x display, you can change `local omarchy_gdk_scale = 2` to 1 (and then restart any app that's oversized). See [the manual on monitors](33-monitors.md).
10
+
11
+For Spotify, you can use `Ctrl + Minus` to shrink the UI (and `Ctrl + Plus` to make it bigger).
12
+
13
+### Why isn't Caps Lock working?
14
+
15
+In Omarchy, Caps Lock has been designated to be the xcompose key. That's how you get [quick emojis](07-hotkeys.md#quick-emojis) and [other autocompletions](07-hotkeys.md#quick-completions) done. If you really miss using Caps Lock, you can remap the xcompose key to something else by editing `~/.config/hypr/input.lua`, like setting it to the right alt key:
16
+
17
+```
18
+hl.config({
19
+ input = {
20
+ kb_options = "compose:ralt",
21
+ },
22
+})
23
+```
24
+
25
+### My Wi-Fi, Bluetooth, audio, or trackpad just stopped working
26
+
27
+Before you reboot, try restarting the offending subsystem on its own. _Update > Hardware_ in the Omarchy menu has Wi-Fi, Bluetooth, Audio, and Trackpad, and reloading one of those clears up the majority of "it worked five minutes ago" situations — a Bluetooth headset that won't reconnect, a trackpad that went dead after a suspend, sound that vanished when you unplugged a monitor.
28
+
29
+### Why are my external speakers not playing?
30
+
31
+Probably because they're not set as the primary output. Click on the speaker icon on the right side of the bar, and it'll open the volume popup where you can pick the output device (and mix per-app volumes too).
32
+
33
+### My laptop speakers sound off
34
+
35
+On some laptops, Omarchy automatically applies a speaker tuning that corrects the built-in speakers' frequency response. `omarchy audio tuning status` tells you whether one is active on your machine, and `omarchy audio tuning off` turns it off if you'd rather hear the speakers raw.
36
+
37
+### Why can't I login or sudo with my password?
38
+
39
+You probably typed it wrong too many times and got locked out. If this is happening on the lock screen, you can hit `CTRL + ALT + F2` to start a new TTY where you can login as root, then run `faillock --reset --user [your-username]`. That'll reset the lockout, and you're good to go.
40
+
41
+### Why isn't my 1Password authorization prompts for 1Password SSH Agent / CLI appearing?
42
+
43
+This can happen for 2 reasons:
44
+
45
+In order for the rich approval prompt to appear, Settings > Advanced > Use Hardware Acceleration must be turned on. _Note: This requires a reboot to begin working._
46
+
47
+ ![troubleshooting-1password](images/troubleshooting-1password.webp)
48
+
49
+Or if you haven't launched 1Password since booting up, the prompt will not appear.
0
50
▼manual/46-faq.md
+79-0
1
+# FAQ
2
+
3
+### How do I switch between keyboard layouts?
4
+
5
+Edit your `~/.config/hypr/input.lua` file and add this to switch between layouts on `Left Alt + Right Alt`:
6
+
7
+```
8
+hl.config({
9
+ input = {
10
+ -- Use multiple keyboard layouts and switch between them with Left Alt + Right Alt
11
+ kb_layout = "us,fr",
12
+ kb_options = "compose:caps,shift:both_capslock_cancel,grp:alts_toggle",
13
+ },
14
+})
15
+```
16
+
17
+The bar will automatically show your current keyboard layout once you have multiple layouts configured (and you can click it to switch too).
18
+
19
+### How do I change the clock format to 12-hour?
20
+
21
+Right-click the clock in the bar to cycle through the common formats, including the 12-hour ones. You can also set the format directly:
22
+
23
+```
24
+omarchy bar set omarchy.clock format "dddd h:mm AP"
25
+```
26
+
27
+This will display Sunday 10:55 AM.
28
+
29
+### How do I change my timezone?
30
+
31
+Run _Update > Timezone_ in the Omarchy menu and pick from the list. If the timezone is right but the clock itself has drifted, _Update > Time_ restarts the time synchronization for you.
32
+
33
+### How do I change my DNS, share my Wi-Fi, or check my connection speed?
34
+
35
+Those all live in [networking](35-networking.md).
36
+
37
+### How do I check how fast my disk is?
38
+
39
+_Trigger > Speed Test > Disk Speed Test_ measures live read and write speed on your drive, or `omarchy disk speedtest` from the terminal.
40
+
41
+### Why can't I sign into my Google account in Chromium?
42
+
43
+The plain open source Chromium build doesn't ship with the OAuth credentials that Google requires for account sign-in. Run _Install > Service > Chromium Account_ in the Omarchy menu to add them, restart the browser, and the sign-in will go through.
44
+
45
+### How do I add a printer?
46
+
47
+Printing is set up and running out of the box, so a printer on your network is usually already discovered. Launch _Print Settings_ from the app launcher (`Super + Space`) to see what's there, add one by hand, or set the default. Printing to a PDF file works without any printer at all.
48
+
49
+### How do I change where screenshots or screenrecordings are saved?
50
+
51
+If you want screenshots to be saved to `~/Pictures/Screenshots` instead of just `~/Pictures`, you can add this to a file under `~/.config/uwsm/env.d/` (like `~/.config/uwsm/env.d/capture`):
52
+
53
+```
54
+export OMARCHY_SCREENSHOT_DIR="$HOME/Pictures/Screenshots"
55
+```
56
+
57
+You can do the same for screenrecordings using `OMARCHY_SCREENRECORD_DIR`.
58
+
59
+Just remember to create the directoy you want to save to and restart Omarchy for this to take effect.
60
+
61
+### How do I get the speakers + webcam working on my Apple Studio Display?
62
+
63
+You'd think that it should all work just plugging in USB C, but unfortunately that isn't the case. The solution I've found to make it work reliably is using [the WJESOG DisplayPort + USB-A => USB-C cable](https://www.amazon.com/WJESOG-DisplayPort-Adapter-Converter-Thunderbolt/dp/B0BNX7MS6N/). Then speakers and webcam work like a charm.
64
+
65
+Remember that you have built-in brightness control in Omarchy for the Apple Displays (both Studio and XDR) using the regular keyboard brightness buttons.
66
+
67
+### How do I get rid of all the extra software?
68
+
69
+If you don't want programs like Obsidian or LibreOffice or any of the other preinstalled stuff, you can very easily remove it.
70
+
71
+Run _Remove > Package_ to see every package that's installed. Then you can select any package you'd like to remove with tab, and start removing everything you've selected with return.
72
+
73
+And you can use _Remove > Web App_ from the Omarchy menu to remove any of the preinstalled web apps you don't want.
74
+
75
+Or run _Remove > Preinstalls_ to sweep out all the preinstalled extras — web apps, TUIs, and optional applications — in one go. The hotkeys that launched them go away with them, so you're left with a clean slate of bindings to fill with your own in `~/.config/hypr/bindings.lua`.
76
+
77
+---
78
+
79
+For errors and broken bits, see [the Troubleshooting section](45-troubleshooting.md).
0
80
▼manual/47-system-snapshots.md
+25-0
1
+# System snapshots
2
+
3
+We create snapshots automatically on every Omarchy update, but should you want to create your own, you can use `omarchy-snapshot create`.
4
+
5
+To boot and restore a snapshot, you select it from the Limine boot loader. (If you're currently booting straight into the Omarchy decryption screen, you'll need to select Limine as a boot option via the BIOS first).
6
+
7
+From that screen, choose the snapshot you'd like to boot into based on the date and version. The version of Omarchy at the time of the snapshot can be seen at the bottom left corner.
8
+
9
+ ![snapshots-bootloader](images/snapshots-bootloader.webp)
10
+
11
+When you arrive inside, a notification will popup notifying you that you're in a bootable snapshot and if you click it, will start the restoration process. Alternatively, you can utilize `omarchy-snapshot restore`.
12
+
13
+ ![snapshots-restore](images/snapshots-restore.webp)
14
+
15
+This will restore your root filesystem, but not your `/home`. So it works for reverting a broken system update, but not for recovering lost personal files.
16
+
17
+This also means that your `~/.config` directory is kept as-is. So if you're rolling back to an earlier version of a library or application that stores configuration files in a new format, you'll have to sort that out manually.
18
+
19
+_Note: This feature is only available on installations using the Limine boot loader, which has been the default since Omarchy 2.0. It's not available if you're on GRUB or systemd-boot._
20
+
21
+### Skipping the boot menu
22
+
23
+If you never touch the boot menu and just want the machine to go straight to the decryption screen, run _Setup > Direct Boot_ in the Omarchy menu. That adds an EFI entry pointing directly at Omarchy, so the firmware boots it without stopping at Limine.
24
+
25
+The trade-off is the one mentioned at the top: with direct boot on, getting to a snapshot means picking Limine from your BIOS boot menu first. Run _Setup > Direct Boot_ again to remove the entry and go back to booting through Limine. Some firmware doesn't take kindly to custom EFI entries, so the setup refuses to run on American Megatrends and Apple firmware.
0
26
▼manual/48-security.md
+31-0
1
+# Security
2
+
3
+Omarchy takes security extremely seriously. This is meant to be an operating system that you can use to do _Real Work_ in the _Real World_. Where losing a laptop can't lead to a security emergency. So here's what we do:
4
+
5
+1. *Full-disk encryption is mandatory*: This is the most important step to securing the physical protection of your data. If your computer is lost or stolen, the data is fully encrypted using standard LUKS (Linux Unified Key Setup).
6
+2. *Firewall is enabled by default*: All incoming traffic is blocked by default except for port 53317 for [LocalSend](https://localsend.org/). Even ssh is off until you turn it on via _Setup > Security > SSHD_, which opens port 22 (rate limited against brute force) as part of the setup. We even lock down Docker access using the [ufw-docker](https://github.com/chaifeng/ufw-docker) setup to prevent that your containers are accidentally exposed to the world.
7
+3. *Arch always have the latest updates*: Arch, the underlying distro that Omarchy is built on, is a rolling distribution. This means that any security vulnerability that's discovered and patched in any package is quickly available for install using `omarchy-update`. You're always running the latest, most secure versions of everything that way.
8
+4. *Omarchy maintains its own packages and mirror*: Omarchy only relies on packages from Arch's own core/extra/multilib repositories and its own Omarchy Package Repository by default. You can install software directly from AUR, but the base install doesn't — only a few optional installs, like the third-party browsers, pull from the AUR.
9
+5. *Cloudflare protects us from DDoS*: All the Omarchy distribution infrastructure — the ISOs, the Omarchy packages, the Arch mirror — is protected behind Cloudflare's formidable DDoS shield and hosted on their CDN. This provides superb availability.
10
+
11
+## Changing your passwords
12
+
13
+You have two passwords on an encrypted install: the one that unlocks the drive at boot, and the one you log in and `sudo` with. Both can be changed under _Update > Password_ in the Omarchy menu — _Drive Encryption_ for the first, _User_ for the second. Changing the drive password asks for the current one first, so have it handy.
14
+
15
+## Passing on a machine you've already used
16
+
17
+If you're handing your machine over to someone else, you don't have to reinstall it. Run _Setup > Reset Computer_ in the Omarchy menu, type `reset` to confirm, and reboot. That wipes every user account and everything in `/home`, throws away all the packages and system changes you made since installation, and clears the machine's identity — network connections, host keys, and all. What comes back up is the setup wizard from the first boot, ready for its new owner to enter their own name, password, and encryption password.
18
+
19
+It works by restoring the baseline snapshot the installer takes, so it's only available on machines installed from the Omarchy ISO. And on a drive without encryption, a reset is deletion rather than a secure erase, so if the data was sensitive, do a fresh install instead.
20
+
21
+## Passwordless sudo
22
+
23
+Sometimes you want `sudo` to stop asking, most often when an AI agent is doing a long stretch of system work for you. _Setup > Security > Passwordless Sudo_ turns that off for 15 minutes and then puts it back automatically. Run it again before the timer runs out to end it early, and pass your own number of minutes with `omarchy-sudo-passwordless 30` if 15 isn't enough.
24
+
25
+Be clear-eyed about this one: while it's on, anything running as your user can do anything as root without being asked. That's the whole point, and it's also the whole risk.
26
+
27
+## Signing Keys
28
+
29
+The public key for all ISO signatures and Omarchy repo package is `40DFB630FF42BCFFB047046CF0134EE680CAC571` ([verify at openpgp.org](https://keys.openpgp.org/search?q=pkgs%40omarchy.org)). The `omarchy/omarchy-keyring` package contains this as well and will be used to rollout any potential updates seamlessly.
30
+
31
+You can find the signature for any ISO release by adding .sig to the URL. Like https://iso.omarchy.org/omarchy-x.x.x.iso.sig.
0
32
▼manual/49-omarchy-on.md
+29-0
1
+# Omarchy on...
2
+
3
+### Apple M1/M2 chips
4
+
5
+[Asahi Alarm](https://asahi-alarm.org/) is a version of Arch for Apple M1/M2 computers built on top of [Asahi Linux](https://asahilinux.org/). You can get Omarchy running on top of that with some effort. See [the user-driven guide](https://codeberg.org/malik-na/omarchy-mac).
6
+
7
+### Apple Virtual Machine
8
+
9
+You can also install Omarchy inside a Parallels VM. Quite the cumbersome process, but there's [a user-driven guide](https://github.com/basecamp/omarchy/discussions/452) for that too.
10
+
11
+### VirtualBox
12
+
13
+VirtualBox is a popular VM runner. [You can run Omarchy inside that too](https://github.com/basecamp/omarchy/discussions/176). But performance probably won't be great.
14
+
15
+### VMware Workstation on Windows 11
16
+
17
+Another popular VM runner for Windows. [Omarchy has been setup inside of that as well](https://github.com/basecamp/omarchy/discussions/572).
18
+
19
+### Steam Deck
20
+
21
+The Steam Deck runs on Arch, which means you can run Omarchy on your Steam Deck. Altynbek Orumbayev has [a full setup script and explanation on how to do it](https://github.com/aorumbayev/deckarchy). How cool is that!
22
+
23
+### NixOS
24
+
25
+Omarchy is really Arch + Hyprland, but Henry Sipp has [ported the essence of the setup to NixOS](https://github.com/henrysipp/omarchy-nix). So if you've been nix-pilled, here's a good starting point. It may or may not stay up-to-date with the latest Omarchy changes, but it's pretty cool none the less!
26
+
27
+### Something else!
28
+
29
+If you're trying to get Omarchy running on a configuration that isn't the default, you should join the #omarchy-on-other channel on [our community Discord](https://discord.gg/tXFUdasqhY).
0
30
▼manual/50-dual-boot-install.md
+44-0
1
+# Dual Boot Install
2
+
3
+You're able to install Omarchy to a single partition alongside Windows or other installations.
4
+
5
+This installation method still comes with LUKS encryption for the partition by default so it's effectively no different than full drive and simply requires free space to be available on the disk.
6
+
7
+## Making Space on Windows
8
+
9
+To install alongside Windows, type `disk management` in the start menu and select the option for **Create and format hard disk partitions**.
10
+
11
+ ![dual-boot-1](images/dual-boot-1.webp)
12
+
13
+Find the appropriate partition, right click, and choose **Shrink Volume**.
14
+
15
+![dual-boot-2](images/dual-boot-2.webp)
16
+
17
+ Input the amount you'd like to shrink the volume by. Note that this will be the size of your future Omarchy install inclusive of the boot partition.
18
+
19
+ ![dual-boot-3](images/dual-boot-3.webp)
20
+
21
+When you're finished, you should see something like this where the 50GB section is where we'll install Omarchy in this example.
22
+
23
+ ![dual-boot-4](images/dual-boot-4.webp)
24
+
25
+## Installing Omarchy
26
+
27
+The install process for Omarchy is effectively the same as normal. After you select your disk, you'll be given the option of **Free space install**. Select that option to prevent wiping the full disk.
28
+
29
+ ![dual-boot-5](images/dual-boot-5.webp)
30
+
31
+Confirm that everything looks good and wait for the install to finish like normal. This is also where you could elect to install unencrypted (not recommended) just like on a full-drive install.
32
+ ![dual-boot-6](images/dual-boot-6.webp)
33
+
34
+## Adding Other Installs to the Bootloader
35
+
36
+When you finish your Omarchy install, you'll notice that the Limine bootloader is the default now. With this, you can also add options to Limine for your other installs such as Windows.
37
+
38
+In order to do that, run `limine-scan` and follow the prompts to add whichever items you'd like to your limine config. Then when you boot, you'll see your normal options for Omarchy, as well as Windows Boot Manager or others.
39
+
40
+## Bitlocker
41
+
42
+It's important to note that this install method is not compatible with Bitlocker as it encrypts the entire drive, not just the partition. If you encounter an error stating that Bitlocker is enabled, boot to Windows, go to **Settings -> Privacy & Security -> Device encryption** and toggle Bitlocker off. It may take some time to decrypt the drive.
43
+
44
+ ![dual-boot-7](images/dual-boot-7.webp)
0
45
▼manual/51-unattended-installs.md
+61-0
1
+# Unattended Installs
2
+
3
+The Omarchy ISO can install itself with nobody at the keyboard. If the installer finds a second drive labeled `cidata` carrying its configuration files, it copies them off, skips the setup wizard entirely, and reboots into the finished system on its own. No special ISO build, no extra boot menu entry — with no such drive attached, nothing changes and you get the normal wizard.
4
+
5
+This makes Omarchy great as a base image for disposable dev environments: create a VM in Proxmox or with Packer, boot it, walk away, SSH in. `cidata` is the cloud-init `NoCloud` label, so all the common virtualization tooling already knows how to attach such a drive.
6
+
7
+## The configuration files
8
+
9
+The files are exactly what the installer's own wizard writes, so the easiest way to get a starting set is to run one interactive install (in a VM, say) and copy what it wrote into `/root`:
10
+
11
+| File | Required | Purpose |
12
+|------|----------|---------|
13
+| `user_configuration.json` | Yes | Disk, hostname, timezone, keyboard |
14
+| `user_credentials.json` | Yes | Username and password hash |
15
+| `user_full_name.txt` | No | Git full name |
16
+| `user_email_address.txt` | No | Git email |
17
+| `user_encrypt_installation.txt` | No | `true` when the configuration carries a `disk_encryption` block |
18
+| `authorized_keys` | No | SSH public keys, one per line |
19
+| `tailscale_authkey` | No | Tailscale auth key for joining your tailnet on first boot |
20
+
21
+Generate the password hash for `user_credentials.json` with `openssl passwd -6 "yourpassword"`.
22
+
23
+You can also drop in an empty file named `defer-provisioning` in place of `user_credentials.json`. That runs the same [prepare-for-another-owner install](02-getting-started.md) you can trigger interactively: the machine installs with no personal details, and whoever boots it first picks their keyboard and creates their user. That's the mode for imaging rigs, where the drive shouldn't carry anyone's credentials at all.
24
+
25
+## SSH access
26
+
27
+When `authorized_keys` is present, the install sets the keys up as the user's `~/.ssh/authorized_keys`, enables `sshd`, and opens the firewall for it. (A stock Omarchy install ships openssh with the service disabled and the port closed, so an unattended machine would otherwise be unreachable.) The install only adds your keys — it doesn't loosen any of the SSH daemon's other authentication settings.
28
+
29
+When `tailscale_authkey` is present, the machine joins your tailnet on first boot instead: Tailscale is installed from the ISO's bundled packages, the firewall allows the tailnet interface, and a background job runs the join as soon as the machine actually has network, retrying until it succeeds. Use a reusable, pre-authorized key so one drive image can serve many machines.
30
+
31
+## Building the cidata drive
32
+
33
+Any filesystem with the right label works. A tiny ISO is the easy way:
34
+
35
+```bash
36
+mkdir cidata
37
+cp user_configuration.json user_credentials.json authorized_keys cidata/
38
+genisoimage -output cidata.iso -volid cidata -joliet -rock cidata/
39
+```
40
+
41
+Then attach it to the VM alongside the Omarchy ISO. Here's a full Proxmox example:
42
+
43
+```bash
44
+qm create 101 --name my-omarchy \
45
+ --bios ovmf --machine q35 --cpu host --cores 4 --memory 8192 \
46
+ --ostype l26 --scsihw virtio-scsi-single \
47
+ --efidisk0 local-lvm:0,efitype=4m,pre-enrolled-keys=0 \
48
+ --scsi0 local-lvm:40,discard=on,iothread=1 \
49
+ --net0 virtio,bridge=vmbr0 --vga virtio --serial0 socket \
50
+ --ide2 local:iso/omarchy.iso,media=cdrom \
51
+ --ide3 local:iso/cidata.iso,media=cdrom \
52
+ --boot order='scsi0;ide2'
53
+
54
+qm start 101
55
+```
56
+
57
+The boot order lists the disk first on purpose: the empty disk falls through to the ISO on the first boot, and the installed system boots from disk ever after.
58
+
59
+## Two caveats
60
+
61
+Encrypted unattended installs aren't fully unattended — someone still has to type the LUKS passphrase at the first boot. And the `disk_encryption` block in `user_configuration.json` carries that passphrase in plaintext, so treat a cidata drive built from an encrypted install as the secret it is.
0
62
▼manual/images/bootloader.webp
+0-0
Binary file not shown.
▼manual/images/branding-about.webp
+0-0
Binary file not shown.
▼manual/images/branding-plymouth-shopify.webp
+0-0
Binary file not shown.
▼manual/images/branding-screensaver.webp
+0-0
Binary file not shown.
▼manual/images/clipboard-history-search.webp
+0-0
Binary file not shown.
▼manual/images/clipboard-history.webp
+0-0
Binary file not shown.
▼manual/images/dual-boot-1.webp
+0-0
Binary file not shown.
▼manual/images/dual-boot-2.webp
+0-0
Binary file not shown.
▼manual/images/dual-boot-3.webp
+0-0
Binary file not shown.
▼manual/images/dual-boot-4.webp
+0-0
Binary file not shown.
▼manual/images/dual-boot-5.webp
+0-0
Binary file not shown.
▼manual/images/dual-boot-6.webp
+0-0
Binary file not shown.
▼manual/images/dual-boot-7.webp
+0-0
Binary file not shown.
▼manual/images/fonts-jetbrainsmono.webp
+0-0
Binary file not shown.
▼manual/images/gaming-geforce-now.webp
+0-0
Binary file not shown.
▼manual/images/gaming-minecraft.webp
+0-0
Binary file not shown.
▼manual/images/gaming-retroarch.webp
+0-0
Binary file not shown.
▼manual/images/gaming-starcraft.webp
+0-0
Binary file not shown.
▼manual/images/gaming-steam.webp
+0-0
Binary file not shown.
▼manual/images/gaming-xbox-cloud.webp
+0-0
Binary file not shown.
▼manual/images/install-config.webp
+0-0
Binary file not shown.
▼manual/images/install-done.webp
+0-0
Binary file not shown.
▼manual/images/macbook-omarchy.webp
+0-0
Binary file not shown.
▼manual/images/navigation-browser-terminal.webp
+0-0
Binary file not shown.
▼manual/images/navigation-dwindle-layout.webp
+0-0
Binary file not shown.
▼manual/images/navigation-fourway-tiling.webp
+0-0
Binary file not shown.
▼manual/images/navigation-popped-window.webp
+0-0
Binary file not shown.
▼manual/images/navigation-scrolling-layout.webp
+0-0
Binary file not shown.
▼manual/images/navigation-stacked.webp
+0-0
Binary file not shown.
▼manual/images/notice-battery.webp
+0-0
Binary file not shown.
▼manual/images/notice-datetime.webp
+0-0
Binary file not shown.
▼manual/images/notice-weather.webp
+0-0
Binary file not shown.
▼manual/images/prompt.webp
+0-0
Binary file not shown.
▼manual/images/reminders.webp
+0-0
Binary file not shown.
▼manual/images/snapshots-bootloader.webp
+0-0
Binary file not shown.
▼manual/images/snapshots-restore.webp
+0-0
Binary file not shown.
▼manual/images/text-extraction.webp
+0-0
Binary file not shown.
▼manual/images/tmux-tdl.webp
+0-0
Binary file not shown.
▼manual/images/tmux-tdl2.webp
+0-0
Binary file not shown.
▼manual/images/tmux-tdlm.webp
+0-0
Binary file not shown.
▼manual/images/tmux-tsl.webp
+0-0
Binary file not shown.
▼manual/images/troubleshooting-1password.webp
+0-0
Binary file not shown.
▼manual/images/update-available.webp
+0-0
Binary file not shown.
▼manual/images/windows-vm.webp
+0-0
Binary file not shown.