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
| @@ -0,0 +1,125 @@ | ||
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
| @@ -0,0 +1,46 @@ | ||
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
| @@ -0,0 +1,31 @@ | ||
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
| @@ -0,0 +1,79 @@ | ||
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
| @@ -0,0 +1,19 @@ | ||
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
| @@ -0,0 +1,167 @@ | ||
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
| @@ -0,0 +1,49 @@ | ||
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
| @@ -0,0 +1,44 @@ | ||
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
| @@ -0,0 +1,157 @@ | ||
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
| @@ -0,0 +1,57 @@ | ||
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
| @@ -0,0 +1,158 @@ | ||
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
| @@ -0,0 +1,130 @@ | ||
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
| @@ -0,0 +1,357 @@ | ||
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
| @@ -0,0 +1,167 @@ | ||
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
| @@ -0,0 +1,143 @@ | ||
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
| @@ -0,0 +1,403 @@ | ||
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
| @@ -0,0 +1,138 @@ | ||
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
| @@ -0,0 +1,368 @@ | ||
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
| @@ -0,0 +1,330 @@ | ||
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
| @@ -0,0 +1,11 @@ | ||
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
| @@ -0,0 +1,39 @@ | ||
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 | +  | |
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 | +  | |
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
| @@ -0,0 +1,57 @@ | ||
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
| @@ -0,0 +1,71 @@ | ||
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 | +  | |
8 | + | |
9 | +You can then hit `Super + J` to stack them on top of each other instead of side by side: | |
10 | + | |
11 | +  | |
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 | +  | |
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 | +  | |
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 | +  | |
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 | +  | |
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
| @@ -0,0 +1,134 @@ | ||
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
| @@ -0,0 +1,127 @@ | ||
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 | +  | |
12 | +_Tokyo Night_ | |
13 | + | |
14 | +  | |
15 | +_Catppuccin_ | |
16 | + | |
17 | +  | |
18 | +_Lumon_ | |
19 | + | |
20 | +  | |
21 | +_Ethereal_ | |
22 | + | |
23 | +  | |
24 | +_Everforest_ | |
25 | + | |
26 | +  | |
27 | +_Gruvbox_ | |
28 | + | |
29 | +  | |
30 | +_Miasma_ | |
31 | + | |
32 | +  | |
33 | +_Hackerman_ | |
34 | + | |
35 | +  | |
36 | +_Osaka Jade_ | |
37 | + | |
38 | +  | |
39 | +_Kanagawa_ | |
40 | + | |
41 | +  | |
42 | +_Nord_ | |
43 | + | |
44 | +  | |
45 | +_Matte Black_ | |
46 | + | |
47 | +  | |
48 | +_Vantablack_ | |
49 | + | |
50 | +  | |
51 | +_Ristretto_ | |
52 | + | |
53 | +  | |
54 | +_Retro 82_ | |
55 | + | |
56 | +  | |
57 | +_Flexoki Light_ | |
58 | + | |
59 | +  | |
60 | +_Rose Pine_ | |
61 | + | |
62 | +  | |
63 | +_Catppuccin Latte_ | |
64 | + | |
65 | +  | |
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 | +  | |
73 | +_Catppuccin_ | |
74 | + | |
75 | +  | |
76 | +_Catppuccin Latte_ | |
77 | + | |
78 | +  | |
79 | +_Ethereal_ | |
80 | + | |
81 | +  | |
82 | +_Everforest_ | |
83 | + | |
84 | +  | |
85 | +_Flexoki Light_ | |
86 | + | |
87 | +  | |
88 | +_Gruvbox_ | |
89 | + | |
90 | +  | |
91 | +_Hackerman_ | |
92 | + | |
93 | +  | |
94 | +_Kanagawa_ | |
95 | + | |
96 | +  | |
97 | +_Lumon_ | |
98 | + | |
99 | +  | |
100 | +_Matte Black_ | |
101 | + | |
102 | + | |
103 | +_Miasma_ | |
104 | + | |
105 | +  | |
106 | +_Nord_ | |
107 | + | |
108 | +  | |
109 | +_Osaka Jade_ | |
110 | + | |
111 | +  | |
112 | +_Retro 82_ | |
113 | + | |
114 | +  | |
115 | +_Ristretto_ | |
116 | + | |
117 | + | |
118 | +_Rose Pine_ | |
119 | + | |
120 | +  | |
121 | +_Tokyo Night_ | |
122 | + | |
123 | +  | |
124 | +_Vantablack_ | |
125 | + | |
126 | +  | |
127 | +_White_ | |
0 | 128 | |
▼manual/07-hotkeys.md
+373-0
| @@ -0,0 +1,373 @@ | ||
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
| @@ -0,0 +1,24 @@ | ||
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 | +  | |
21 | + | |
22 | +You can also search the history just by starting to type: | |
23 | + | |
24 | +  | |
0 | 25 | |
▼manual/09-reminders.md
+5-0
| @@ -0,0 +1,5 @@ | ||
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 | +  | |
0 | 6 | |
▼manual/10-notices.md
+23-0
| @@ -0,0 +1,23 @@ | ||
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 | +  | |
10 | + | |
11 | +### Weather | |
12 | + | |
13 | +`Super + Ctrl + Alt + W` | |
14 | + | |
15 | +  | |
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 | +  | |
0 | 24 | |
▼manual/11-text-extraction-dictation.md
+15-0
| @@ -0,0 +1,15 @@ | ||
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 | +  | |
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
| @@ -0,0 +1,78 @@ | ||
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
| @@ -0,0 +1,101 @@ | ||
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
| @@ -0,0 +1,62 @@ | ||
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
| @@ -0,0 +1,39 @@ | ||
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 | +  | |
26 | + | |
27 | +You can also start a second agent with `tdl c cx` (opencode + claude) (or just `icx`): | |
28 | + | |
29 | +  | |
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 | +  | |
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 | +  | |
0 | 40 | |
▼manual/16-neovim.md
+42-0
| @@ -0,0 +1,42 @@ | ||
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
| @@ -0,0 +1,51 @@ | ||
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
| @@ -0,0 +1,33 @@ | ||
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
| @@ -0,0 +1,59 @@ | ||
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
| @@ -0,0 +1,49 @@ | ||
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
| @@ -0,0 +1,51 @@ | ||
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
| @@ -0,0 +1,96 @@ | ||
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
| @@ -0,0 +1,39 @@ | ||
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
| @@ -0,0 +1,37 @@ | ||
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
| @@ -0,0 +1,75 @@ | ||
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
| @@ -0,0 +1,85 @@ | ||
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 | +  | |
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 | +  | |
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 | +  | |
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 | +  | |
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 | +  | |
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 | +  | |
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
| @@ -0,0 +1,9 @@ | ||
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
| @@ -0,0 +1,43 @@ | ||
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 | +  | |
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
| @@ -0,0 +1,9 @@ | ||
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
| @@ -0,0 +1,37 @@ | ||
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 | + | |
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 | + | |
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
| @@ -0,0 +1,78 @@ | ||
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
| @@ -0,0 +1,102 @@ | ||
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
| @@ -0,0 +1,55 @@ | ||
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
| @@ -0,0 +1,74 @@ | ||
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
| @@ -0,0 +1,45 @@ | ||
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
| @@ -0,0 +1,19 @@ | ||
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
| @@ -0,0 +1,17 @@ | ||
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
| @@ -0,0 +1,9 @@ | ||
1 | +# Fonts | |
2 | + | |
3 | +Omarchy uses JetBrainsMono Nerd Font as both the terminal and system font by default. | |
4 | + | |
5 | +  | |
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
| @@ -0,0 +1,7 @@ | ||
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
| @@ -0,0 +1,7 @@ | ||
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 | +  | |
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
| @@ -0,0 +1,43 @@ | ||
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 | +  | |
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 | +  | |
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 | +  | |
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
| @@ -0,0 +1,37 @@ | ||
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
| @@ -0,0 +1,31 @@ | ||
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
| @@ -0,0 +1,71 @@ | ||
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 | +  | |
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
| @@ -0,0 +1,49 @@ | ||
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 | +  | |
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
| @@ -0,0 +1,79 @@ | ||
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
| @@ -0,0 +1,25 @@ | ||
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 | +  | |
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 | +  | |
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
| @@ -0,0 +1,31 @@ | ||
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
| @@ -0,0 +1,29 @@ | ||
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
| @@ -0,0 +1,44 @@ | ||
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 | +  | |
12 | + | |
13 | +Find the appropriate partition, right click, and choose **Shrink Volume**. | |
14 | + | |
15 | + | |
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 | +  | |
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 | +  | |
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 | +  | |
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 | +  | |
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 | +  | |
0 | 45 | |
▼manual/51-unattended-installs.md
+61-0
| @@ -0,0 +1,61 @@ | ||
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.