# Making Omarchy Comfortable

> Learn where Omarchy keeps your settings and how updates treat them, then change keybindings in Lua, tune keyboard, trackpad and monitor scaling, and restyle themes, fonts, and the bar without breaking anything.


---

# Making Omarchy Comfortable

Checked against Omarchy 4.0.4. You have a working desktop, and a dozen small things feel wrong: a key you reach for does nothing, the scroll direction is backwards, the text is tiny on your 4K screen, the bar shows things you never use. On Windows or macOS you would open a settings app. On Omarchy you edit plain-text files, and the fear is real: what if I break it, and what if the next update wipes my work?

This guide removes both fears. First you learn which files are yours and exactly how updates treat them, including the safety nets that undo a bad edit. Then you change things in order of how often people need them: keybindings, keyboard and trackpad, monitors, and finally the look.

## Prerequisite

You should be able to open a terminal and a file in it. If not, read [The Terminal and Shell](/guides/the-terminal-and-shell) and [Editing in the Terminal](/guides/editing-in-the-terminal) first (Omarchy opens config files in Neovim by default, and `:wq` is how you save and quit). The menu and hotkey basics are in [Omarchy Menus, Panels, and the CLI](/guides/omarchy-menus-panels-and-cli).

## How to read this

- **One specific itch?** Keybinding: jump to [Phase 2](02-changing-and-adding-keybindings.md). Scroll direction, layout, or key repeat: [Phase 3](03-keyboard-mouse-and-screens.md). Colors, fonts, or the bar: [Phase 4](04-themes-fonts-and-the-bar.md).
- **Want to edit without fear?** Read [Phase 1](01-whose-files-are-whose.md) first. That phase saves you from the one real mistake: editing a file Omarchy owns.

## The phases

1. **[Whose Files Are Whose](01-whose-files-are-whose.md)** - what Omarchy owns, what you own, how updates treat each, and how to undo a bad edit.
2. **[Changing and Adding Keybindings](02-changing-and-adding-keybindings.md)** - `bindings.lua` in Lua: add, change, and disable bindings.
3. **[Keyboard, Mouse, and Screens](03-keyboard-mouse-and-screens.md)** - `input.lua` and `monitors.lua`: layouts, repeat rate, natural scrolling, scaling, and text size.
4. **[Themes, Fonts, and the Bar](04-themes-fonts-and-the-bar.md)** - themes, backgrounds, fonts, the prompt, the bar, and `looknfeel.lua` tweaks.

Where Omarchy's sibling guides go deeper: the terminal itself is in [The Omarchy Terminal Workflow](/guides/the-omarchy-terminal-workflow), installing software is in [Installing and Updating Software on Omarchy](/guides/installing-and-updating-software-on-omarchy), recovery after a bad update is in [When Omarchy Breaks](/guides/when-omarchy-breaks), and writing code that extends the bar is in [Building Your Own Omarchy Plugin](/guides/building-your-own-omarchy-plugin).


---

# Whose Files Are Whose

On Windows, settings hide behind a gear icon. On Omarchy most of them are plain-text files, and the first question every newcomer asks is: what happens to my edits when the next update lands? The answer is a clean split. Some files belong to Omarchy and get replaced during updates. Others belong to you and are never replaced by the package manager. Once you know which is which, editing stops being scary.

## Two owners, two places

Omarchy installs itself as ordinary pacman packages. Everything it ships lives under `/usr/share/omarchy`. The manual's rule is blunt: files there belong to Omarchy, and your changes to them are overwritten on the next update. Your own settings live in dotfiles under `~/.config`, and those are yours.

Think of a printed map with a sheet of tracing paper laid on top. Omarchy can reprint the map whenever it likes. Your pencil marks are on the tracing paper, so they survive. Hyprland (the window manager) is configured exactly this way. Its main file loads Omarchy's defaults first and your files after them, so whatever you set wins:

```mermaid
flowchart LR
  A["Omarchy defaults"] --> B["monitors.lua"]
  B --> C["input.lua"]
  C --> D["bindings.lua"]
  D --> E["looknfeel.lua"]
  E --> F["autostart.lua"]
```

The relevant part of `~/.config/hypr/hyprland.lua` looks like this (comments trimmed):

```lua
-- Load Omarchy defaults.
require("default.hypr.omarchy")

-- Your personal overrides, loaded after the defaults.
require("hypr.monitors")
require("hypr.input")
require("hypr.bindings")
require("hypr.looknfeel")
require("hypr.autostart")
```

Since v4, Hyprland's config is written in Lua, a small scripting language, so every one of those files ends in `.lua`. Old guides that show `hyprland.conf` or lines starting with `bind =` describe Omarchy 3 and do not apply.

> 💡 **Key point**: you never edit the defaults. You write the one setting you want different, in your file, and it overrides the default underneath.

## The files you will actually touch

| File | What it controls |
|---|---|
| `~/.config/hypr/hyprland.lua` | The main Hyprland config. Loads the defaults plus your override files. |
| `~/.config/hypr/bindings.lua` | Your keybindings and overrides of the defaults. |
| `~/.config/hypr/monitors.lua` | Monitors, resolution, scaling, and position. |
| `~/.config/hypr/input.lua` | Keyboard layout, mouse, and trackpad. |
| `~/.config/hypr/looknfeel.lua` | Gaps, borders, rounding, animations. |
| `~/.config/hypr/autostart.lua` | Extra programs started with your session. |
| `~/.config/omarchy/shell.json` | The bar (position, layout, widgets) plus screensaver, lock, and idle timings. |
| `~/.config/foot/foot.ini` | The default terminal, Foot. |
| `~/.config/tmux/tmux.conf` | Tmux. |
| `~/.config/starship.toml` | The shell prompt. |
| `~/.XCompose` | Quick-access emoji and name or email autocomplete. Run `omarchy-restart-xcompose` after editing. |

## Open files the Omarchy way

Press `Super + Space` to open the Omarchy menu, then pick one of these:

- _Setup > Monitors_ opens `monitors.lua`.
- _Setup > Keybindings_ opens `bindings.lua`.
- _Setup > Input_ opens `input.lua`.
- _Setup > Config_ offers Hyprland (`hyprland.lua`), Hyprsunset (the night-light config), and XCompose.
- _Style > Hyprland_ opens `looknfeel.lua`.

The file opens in your default editor, which is Neovim until you change it under _Setup > Defaults > Editor_. When you quit the editor (`:wq` in Neovim), Omarchy restarts whatever needs restarting for that file. That is the reason to prefer the menu over opening files by hand: it finishes the job.

Files with no menu entry, like `shell.json`, you open from a terminal. Omarchy defines `n` as an alias for `nvim`, so `n ~/.config/omarchy/shell.json` works.

## What an update does to each layer

- **Package files in `/usr/share/omarchy`** are replaced with the new release. This is how defaults improve without touching your files.
- **Your files in `~/.config`** are not overwritten by the package update. A seed copy of the shipped configs (kept in `/etc/skel`) only goes into a home folder when a user account is created, which is why existing users do not get new defaults pushed onto them.
- **Migrations** are the exception to know about. After the packages, `omarchy update` runs one-time repair scripts as your user, and a migration may touch `~/.config` when a new release needs a config changed. The manual's own warning: occasionally an update restores a config to its original condition, and then your version is saved next to it as a `.bak` file.
- **`shell.json` is yours once you change it.** Until you customize, the shell reads Omarchy's default file. After you drag a widget or run an `omarchy bar` command, your file is the only one that counts, with no merging. New default widgets in future releases will not appear on your bar on their own.

## The undo ladder

Every mistake has a rung, from gentle to drastic:

| You want to | Do this | What happens |
|---|---|---|
| Undo one bad edit | Edit it back, or `omarchy refresh config hypr/bindings.lua` | Copies Omarchy's shipped version of that one file into place and saves yours as a backup |
| Reset every Hyprland file | _Update > Config > Hyprland_ | Replaces `autostart.lua`, `bindings.lua`, `input.lua`, `looknfeel.lua`, `hyprland.lua`, and `monitors.lua` (plus a `.luarc.json` helper file), backing each up |
| Reset the bar | _Update > Config > Shell_ | Resets `shell.json` and the bar to defaults |
| Reset tmux | _Update > Config > Tmux_ | Replaces `tmux.conf` and reloads tmux |
| Reset everything | `omarchy reinstall configs` | Destructive: copies the shipped defaults over your home folder |

The single-file command prints what it did, using the path relative to `~/.config`:

```console
$ omarchy refresh config hypr/bindings.lua
Replaced /home/you/.config/hypr/bindings.lua with new Omarchy default.
Saved backup as /home/you/.config/hypr/bindings.lua.bak.1791100000.

Changes:
...
```

*What just happened:* Omarchy copied your file to a backup named with a Unix timestamp (the number differs every time), put its shipped version in place, and printed a diff of what changed. If your file already matched the default, it makes no backup and prints nothing.

> ⚠️ **Gotcha**: `omarchy reinstall configs` replays the shipped home-folder defaults over your files, same-named files included. That covers `~/.bashrc`, where your own aliases live. It is the last rung for a reason. Copy anything you care about somewhere safe before you use it.

## Four more places that are yours

- `~/.config/hypr/autostart.lua`: start something with every login, for example `o.launch_on_start("my-service")`.
- `~/.bashrc`: your own shell aliases, functions, and exports. The manual says Omarchy does not overwrite it on updates, and that you can safely override Omarchy's aliases here.
- `~/.config/omarchy/hooks/<event>.d/`: scripts that run on events: `post-boot`, `post-update`, `pre-refresh-pacman`, `theme-set`, `font-set`, and `battery-low`. Each folder ships a `.sample` file; remove the `.sample` ending to switch it on. `omarchy hook install post-boot ~/my-hook` copies a script in and makes it executable.
- `~/.config/omarchy/extensions/omarchy-menu.jsonc`: add rows to the Omarchy menu. A row's dotted id decides its place, so `personal.notes` appears inside the `personal` submenu:

```jsonc
"personal": {"icon":"","label":"Personal"},
"personal.notes": {"icon":"󰎞","label":"Notes","action":"omarchy-launch-editor ~/notes"},
```

The manual suggests GNU Stow for backing up your dotfiles once you have made a lot of changes. If you would rather keep them in version control yourself, [Git From Zero](/guides/git-from-zero) teaches the tool.

> 📝 **Terminology**: if you really want to change Omarchy's own files, the manual points to _Update > Channel > Dev_, which links Omarchy to a git checkout in `~/omarchy`. It is meant for people working on Omarchy itself and comes with the breakage that implies. Overriding in `~/.config` covers nearly everything.

## Your turn: recover one file

You edited `bindings.lua`, regretted it, and want Omarchy's shipped version of only that file back.

```exercise
[
  {
    "type": "predict",
    "task": "Type the command that restores only ~/.config/hypr/bindings.lua to Omarchy's shipped version (and saves yours as a backup). The argument is the path relative to ~/.config.",
    "accept": ["/^omarchy[ -]refresh[ -]config\\s+hypr\\/bindings\\.lua$/i"],
    "hint": "It starts with omarchy refresh config, then the path hypr/bindings.lua."
  }
]
```

Check yourself before moving on:

```quiz
[
  {
    "q": "You change a default by editing a file under /usr/share/omarchy. What happens at the next Omarchy update?",
    "choices": [
      "Your change is kept, because Omarchy merges it",
      "The file is replaced, because it belongs to the Omarchy package",
      "Omarchy asks you which version to keep"
    ],
    "answer": 1,
    "explain": "/usr/share/omarchy belongs to Omarchy's packages and your changes there are overwritten. Put overrides in ~/.config instead.",
    "why": ["Nothing merges package files; they are replaced.", null, "Package files are replaced; there is no prompt. Overrides belong in ~/.config."]
  },
  {
    "q": "You dragged a bar widget, so you now have your own shell.json. A new Omarchy release adds a default widget. What happens to your bar?",
    "choices": [
      "The new widget appears automatically",
      "Nothing changes: once you own shell.json it is the only file that counts, with no merging",
      "Your shell.json is deleted and replaced"
    ],
    "answer": 1,
    "explain": "Your file is canonical once you customize. Run omarchy bar defaults, or Update > Config > Shell, to return to the shipped layout."
  },
  {
    "q": "Which command resets one config file to Omarchy's version and keeps a backup of yours?",
    "choices": [
      "omarchy reinstall configs",
      "omarchy refresh config hypr/bindings.lua",
      "sudo pacman -Syu"
    ],
    "answer": 1,
    "explain": "omarchy refresh config takes one path relative to ~/.config. Reinstall configs resets everything and is destructive.",
    "why": ["That resets all your configs, not one file.", null, "That is a system upgrade, which Omarchy guards and sends through omarchy update. It does not reset a config file."]
  }
]
```

## Recap

1. `/usr/share/omarchy` is Omarchy's and is replaced by updates; `~/.config` is yours.
2. `hyprland.lua` loads Omarchy's defaults first and your `monitors`, `input`, `bindings`, `looknfeel`, and `autostart` files after, so yours win.
3. Open files through _Setup_ or _Style > Hyprland_ in the Omarchy menu so Omarchy restarts what needs it after you save.
4. Package updates leave `~/.config` alone. Migrations may change it, and when they do your version is saved as `.bak`.
5. Undo from small to large: one file with `omarchy refresh config`, a group with _Update > Config_, everything with `omarchy reinstall configs`.

Next up, [Changing and Adding Keybindings](02-changing-and-adding-keybindings.md): your first real edit, in `bindings.lua`.


---

# Changing and Adding Keybindings

Every Omarchy hotkey is one line of Lua, and the file where yours go is almost empty: it ships with comments only. That is good news, because you can read the whole thing in a minute and make your first change safely. By the end of this phase you will add a hotkey, take a key away from an app, and remove a default you never use.

## See what is bound first

Press `Super + K` to open a searchable list of every keybinding. `Super` is the Windows key (the Command key on a Mac keyboard). The same list prints into a terminal with `omarchy menu keybindings --print`, so you can search it with `grep`. Check a key here before you claim it, because binding a key that is already taken needs one extra step (below).

Tmux has its own list on `Super + Alt + K`, and Herdr on `Super + Ctrl + K`.

## A one-minute tour of Lua

You need five things from Lua to read and write bindings:

- `--` starts a comment. Everything after it on that line is ignored.
- Text goes in double quotes: `"SUPER + SHIFT + R"`.
- A call is a name followed by parentheses with comma-separated arguments: `o.bind("...", "...", "...")`.
- Curly braces make a table, a bundle of `name = value` pairs: `{ webapp = "https://reddit.com" }`.
- A dot reaches inside something: `hl.unbind` is the `unbind` function that Hyprland (`hl`) provides, and `o.bind` is the `bind` helper that Omarchy (`o`) provides.

Lua is strict. A missing quote or parenthesis stops the whole file from loading, so change one thing at a time.

## Anatomy of a binding

```lua
o.bind("SUPER + SHIFT + R", "Reddit", { webapp = "https://reddit.com" })
```

`o.bind` takes the key combination, a description, and what to do:

1. **The keys**: modifiers and one key, joined by ` + `. The modifiers are `SUPER`, `SHIFT`, `CTRL`, and `ALT`.
2. **The description**: the label you see in the `Super + K` list.
3. **The action**: a shell command as a string, or a table that Omarchy turns into a command for you. The tables used by the defaults are `{ omarchy = "terminal" }` (an Omarchy launcher), `{ webapp = "https://..." }` (a site in its own app-like window), `{ tui = "btop" }` (a terminal program in a terminal window), and `{ launch = "obsidian", focus = "^obsidian$" }` (start the app, or jump to its window if it is already open). Hyprland actions like `hl.dsp.window.close()` also work.

A fourth, optional argument is a table of settings. You will see `{ locked = true, repeating = true }` on the volume keys in the defaults, but you rarely need it.

> 📝 **Terminology**: a *binding* connects a key combination to an action. *Unbinding* removes that connection. Omarchy's own bindings are the *defaults*, and yours sit on top of them as described in [Phase 1](01-whose-files-are-whose.md).

## Add, change, disable

Open the file with `Super + Space`, then _Setup > Keybindings_. Here is a complete example with all three moves:

```lua
-- Add: a new key that opens a web app.
o.bind("SUPER + SHIFT + R", "Reddit", { webapp = "https://reddit.com" })

-- Add: a key that runs any command (here, an SSH session in a terminal window).
o.bind("SUPER + SHIFT + Z", "Work server", "omarchy-launch-tui ssh your-server")

-- Change: give a key that Omarchy already uses to a different app.
-- Install it first with: omarchy-pkg-add joplin-bin
hl.unbind("SUPER + SHIFT + O")
o.bind("SUPER + SHIFT + O", "Joplin", "joplin-desktop")

-- Disable: remove a default and leave the key empty.
hl.unbind("SUPER + SHIFT + B")
```

The Joplin lines come straight from the manual, which swaps the preinstalled Obsidian note app for Joplin. The rule behind them: **to change a key that is already bound, unbind it first, then bind it again.** Omarchy's own instructions for this file say to unbind first, so that your binding replaces the default instead of competing with it.

> 💡 **Key point**: disabling `Super + Shift + B` costs you nothing here. The browser is also bound to `Super + Shift + Return`, so only the duplicate key is gone.

Habits from other systems are one line each. Windows users who reach for `Alt + F4` can add it:

```lua
o.bind("ALT + F4", "Close window", hl.dsp.window.close())
```

That reuses the same action Omarchy gives `Super + W`.

## Key names: copy the spelling

Letters and digits are what you expect. A few keys have names you would not guess:

| Key | How the defaults spell it |
|---|---|
| Enter | `RETURN` |
| Space bar | `SPACE` |
| Escape | `ESCAPE` |
| `/` | `SLASH` |
| `.` | `PERIOD` |
| `,` | lowercase `comma` |
| Number row (1 to 0) | `code:10` through `code:19` |

The comma is a trap. A comment in Omarchy's own bindings file says the underlying keyboard library names that key `comma`, and the upper-case `COMMA` does not match. A `code:` number refers to a physical key position on the keyboard, which is how the defaults handle the number row.

You are allowed to read Omarchy's default binding files even though you must not edit them. They sit in `/usr/share/omarchy/default/hypr/bindings/`, and copying the spelling of a similar key is the safest way to get yours right.

## Turn off whole groups of defaults

Two switches live in `~/.config/hypr/hyprland.lua`, as comments near the top. They must come before the line that loads the defaults:

```lua
-- Disable only the bindings for preinstalled apps and web apps,
-- keeping core window-manager bindings:
omarchy_preinstalled_bindings = false

-- Disable every Omarchy default binding (you then add your own):
-- omarchy_default_bindings = false

require("default.hypr.omarchy")
```

Use the first if you removed the preinstalled apps and want their keys back for yourself. Use the second only if you are prepared to rebuild every binding you rely on, window closing included.

## Check your work

Hyprland reloads its config when you save. Omarchy's own guidance for editing these files is to force a reload and ask for errors afterwards:

```console
$ hyprctl reload
$ hyprctl configerrors
```

*What just happened:* the first command makes Hyprland re-read every config file. The second lists any errors it found, so a typo shows up there instead of as a mystery. If a binding does nothing, run both and read what comes back.

If you cannot find your mistake, rewind only this file with `omarchy refresh config hypr/bindings.lua` and start again from a known-good state.

## Your turn: two small edits

```exercise
[
  {
    "type": "predict",
    "task": "Type the one line that disables the default Super + Shift + B binding without replacing it.",
    "accept": ["/^hl\\.unbind\\(\\s*[\"']SUPER \\+ SHIFT \\+ B[\"']\\s*\\)$/"],
    "hint": "It is an hl.unbind call with the key string inside the parentheses."
  },
  {
    "type": "task",
    "task": "Add a binding on Super + Shift + H that opens https://news.ycombinator.com as a web app, then confirm it appears in the Super + K list.",
    "reveal": "o.bind(\"SUPER + SHIFT + H\", \"Hacker News\", { webapp = \"https://news.ycombinator.com\" })",
    "checklist": ["I checked Super + K first and the key was free", "I edited ~/.config/hypr/bindings.lua, not a file under /usr/share/omarchy", "The new line shows up in the keybinding list with my description"]
  }
]
```

Check yourself before moving on:

```quiz
[
  {
    "q": "You want Super + Shift + O to open Joplin instead of Obsidian. What goes in bindings.lua?",
    "choices": [
      "Only the new o.bind line; the later binding wins automatically",
      "hl.unbind(\"SUPER + SHIFT + O\") first, then the new o.bind line",
      "An edit to the default file under /usr/share/omarchy"
    ],
    "answer": 1,
    "explain": "A key that is already bound must be unbound before you bind it again. The defaults are Omarchy's files and are replaced on update.",
    "why": ["The template's rule is to unbind first, then bind the key again.", null, "Files under /usr/share/omarchy are overwritten by updates. Overrides belong in ~/.config."]
  },
  {
    "q": "Your binding on the comma key never fires. Which is the most likely cause?",
    "choices": [
      "You wrote COMMA in capitals, but the key is named comma in lowercase",
      "Comma cannot be used in bindings at all",
      "You forgot to add SHIFT"
    ],
    "answer": 0,
    "explain": "Omarchy's own bindings use lowercase comma and note that the upper-case form does not match."
  },
  {
    "q": "You removed the preinstalled apps and want their key combinations free for your own use. Where do you switch off the app bindings?",
    "choices": [
      "In bindings.lua, with omarchy_preinstalled_bindings = false",
      "In hyprland.lua, setting omarchy_preinstalled_bindings = false before require(\"default.hypr.omarchy\")",
      "In monitors.lua"
    ],
    "answer": 1,
    "explain": "The switch must be set in hyprland.lua before the defaults load, because it decides which default files load."
  }
]
```

## Recap

1. `Super + K` lists every live binding; check it before you pick a key.
2. A binding is `o.bind(keys, description, action)` in `~/.config/hypr/bindings.lua`; the action is a command string or a table like `{ webapp = "..." }`.
3. To change a key that is already bound, call `hl.unbind` on it first, then `o.bind`. To disable one, call `hl.unbind` alone.
4. Copy key spellings from the defaults: `RETURN`, `SLASH`, `PERIOD`, and lowercase `comma`.
5. `omarchy_preinstalled_bindings = false` and `omarchy_default_bindings = false` go in `hyprland.lua`, before the defaults load.
6. After an edit, `hyprctl reload` then `hyprctl configerrors` shows what went wrong.

Next up, [Keyboard, Mouse, and Screens](03-keyboard-mouse-and-screens.md): layouts, repeat rate, natural scrolling, and monitor scaling.


---

# Keyboard, Mouse, and Screens

These are the settings you notice in the first hour: scrolling feels backwards, Caps Lock does something odd, the text is microscopic on a sharp monitor. All of it lives in two files, `~/.config/hypr/input.lua` and `~/.config/hypr/monitors.lua`. Open them with `Super + Space`, then _Setup > Input_ and _Setup > Monitors_.

## What Omarchy sets for you

Omarchy's defaults for input are worth knowing, because your file only needs to list what you want different:

- **Layout**: read from the system keyboard setting in `/etc/vconsole.conf` (`XKBLAYOUT`), or `us` when none is set.
- **Key repeat**: `repeat_rate = 40` and `repeat_delay = 250`. The delay is how many milliseconds a key is held before it starts repeating, and the rate is how many repeats per second follow.
- **Touchpad**: `natural_scroll = false`, two-finger click for right-click (`clickfinger_behavior = true`), and `scroll_factor = 0.4`.
- **Mouse**: `sensitivity = 0`, and `follow_mouse = 1`, which moves window focus to whatever is under the pointer as you move it (no click needed).
- **Caps Lock**: this one catches Windows and macOS users. The default `kb_options` is `compose:caps,shift:both_capslock_cancel`, which turns the Caps Lock key into the **compose key**. Pressing it, then a short sequence, types special characters, and Omarchy's `~/.XCompose` file defines quick-access emoji and name or email autocomplete on top. The real Caps Lock moved to pressing **both Shift keys together**, and the `_cancel` part releases it on the next lone Shift, so an accidental press fixes itself.

> ⚠️ **Gotcha**: `kb_options` is a single string. If you write your own, it replaces the default string entirely. Anything you want to keep from the default (`compose:caps`, `shift:both_capslock_cancel`) must be repeated in yours.

## input.lua in practice

Here is the manual's example, with each line explained. Uncomment or add only what you want:

```lua
hl.config({
  input = {
    -- Two layouts, switched with Left Alt + Right Alt.
    kb_layout = "us,dk",
    kb_options = "compose:caps,shift:both_capslock_cancel,grp:alts_toggle",

    -- Key repeat: wait 600 ms, then 40 repeats per second.
    repeat_rate = 40,
    repeat_delay = 600,

    -- Pointer speed (0 is the default).
    sensitivity = 0.35,

    touchpad = {
      -- Natural (inverse) scrolling, like a phone or a Mac.
      natural_scroll = true,

      -- Two-finger click for right-click.
      clickfinger_behavior = true,

      -- Scrolling speed.
      scroll_factor = 0.3,
    },
  },
})

-- Scroll faster in the terminal.
o.window("(Alacritty|kitty|foot)", { scroll_touchpad = 1.5 })
```

Most people want a much shorter file. Natural scrolling alone is this:

```lua
hl.config({
  input = {
    touchpad = {
      natural_scroll = true,
    },
  },
})
```

Other options from Omarchy's template file, all commented out until you remove the `--`:

- `accel_profile = "flat"` turns off mouse acceleration.
- `numlock_by_default = true` starts with Num Lock on (already the default).
- `touchpad.disable_while_typing = false` keeps the touchpad live while you type.
- `kb_variant = "intl"` selects a keyboard variant, such as the international one.

The full list of options is on the [Hyprland wiki's input page](https://wiki.hypr.land/Configuring/Basics/Variables/#input). Touchpad gestures work too. This line makes a three-finger horizontal swipe change workspaces:

```lua
hl.gesture({ fingers = 3, direction = "horizontal", action = "workspace" })
```

### Two layouts, one trap

Once you list more than one layout, a keyboard-layout widget appears in the bar. Put a Latin layout first. Omarchy's own default input file explains why: Hyprland matches keybindings against the first layout in `kb_layout`, not the one that is active right now, so `Super + W` and friends only fire when a Latin layout leads. If you installed with a layout that cannot type Latin letters, Omarchy adds `us` in front for you.

### Using Alt as Super

On some keyboards the Windows or Command key is awkward to hold. The manual's fix swaps Alt and Super, and it keeps the default compose and Caps Lock options in the same string:

```lua
hl.config({
  input = {
    kb_options = "compose:caps,shift:both_capslock_cancel,altwin:swap_alt_win",
  },
})
```

### Typing Chinese or Japanese

Omarchy already runs the fcitx5 input framework in every session. Install an engine such as `fcitx5-mozc` (Japanese) or `fcitx5-chinese-addons` (Chinese) with `omarchy pkg add`, plus `fcitx5-configtool` to add it to your input methods.

## Screens: scale is one idea

Omarchy assumes a high-density screen, what the manual calls a 2x retina-class display (218 pixels per inch or more). On such a screen, a scale of 2 draws everything twice as large, so text is crisp and readable. On a 27-inch 4K monitor that is too big, and on a 1080p monitor it would be enormous. Two numbers at the top of `monitors.lua` fix it:

```lua
local omarchy_gdk_scale = 2
local omarchy_monitor_scale = "auto"

hl.env("GDK_SCALE", tostring(omarchy_gdk_scale))
hl.monitor({ output = "", mode = "preferred", position = "auto", scale = omarchy_monitor_scale })
```

`omarchy_monitor_scale` is Hyprland's scale for the screen itself, and `"auto"` lets it choose. `GDK_SCALE` tells GTK apps how big to draw, and GTK only honors whole numbers, so keep it at the nearest integer of your scale. The last line applies to every monitor that has no rule of its own, because its output name is empty.

The manual's recommendations:

| Your screen | `omarchy_gdk_scale` | `omarchy_monitor_scale` |
|---|---|---|
| 27 or 32 inch 4K | `2` | `1.6` |
| 1080p or 1440p | `1` | `1` |
| 218 PPI or more (such as a 27 inch 5K) | `2` | `"auto"` (the default) |

`GDK_SCALE` only applies to apps you start after the change. Quit the oversized windows and reopen them, or press `Ctrl + Alt + Delete` to close every window.

To try a scale without editing a file, press `Super + /` to step up through 1, 1.25, 1.6, 2, 3, and 4, and `Super + Alt + /` to step down. With the default configuration the change survives a reboot. The command-line version is `omarchy hyprland monitor scaling 1.6`, or `up` and `down`.

### Text only

Scaling changes the size of everything. If only the text is wrong, use one command:

```console
$ omarchy display text size 14
```

*What just happened:* the Omarchy shell, GTK apps, and your terminal all moved to a 14 pixel text size together, so the desktop stays in proportion. Sizes run from 9 to 20. Without an argument it shows the current size, and `omarchy display text size reset` goes back to the default. Foot cannot reload its config, so terminals that are already open keep their old size until you open a new one.

### More than one screen

An external monitor extends your desktop by default. Mirror it with `Super + Ctrl + Alt + Delete` (or _Trigger > Hardware_), which is useful for a projector. With the screens extended, closing the laptop lid turns the internal display off. Toggle it yourself with `Super + Ctrl + Delete`.

For a specific monitor, list what Hyprland sees, then add a rule to `monitors.lua`:

```console
$ hyprctl monitors all
```

```lua
-- A 1440p monitor at 144 Hz, placed at the origin.
hl.monitor({ output = "DP-2", mode = "2560x1440@144", position = "0x0", scale = 1 })

-- A portrait (rotated) monitor: transform 1 is 90 degrees, 3 is 270.
hl.monitor({ output = "DP-2", mode = "preferred", position = "auto", scale = 1, transform = 1 })
```

Use the output name that `hyprctl monitors all` prints (`DP-2` is an example). The brightness keys adjust the display you are focused on, external monitors that speak DDC/CI included. Hold `Shift` for maximum or minimum, or `Alt` for 1 percent steps.

## Your turn: fix your screen and your scroll

```exercise
[
  {
    "type": "predict",
    "task": "You have a 27-inch 4K monitor. What value does the manual recommend for omarchy_monitor_scale?",
    "accept": ["1.6"],
    "hint": "It is a fractional scale between 1 and 2."
  },
  {
    "type": "predict",
    "task": "Type the command that sets the text size to 14 across the shell, GTK apps, and your terminal.",
    "accept": ["/^omarchy[ -]display[ -]text[ -]size\\s+14$/i"],
    "hint": "It starts with omarchy display text size."
  }
]
```

Check yourself before moving on:

```quiz
[
  {
    "q": "You add kb_options = \"grp:alts_toggle\" to input.lua to switch layouts. What else happens?",
    "choices": [
      "Nothing; it is added to the default options",
      "It replaces the default string, so compose:caps and shift:both_capslock_cancel are gone unless you repeat them",
      "Hyprland refuses to load the file"
    ],
    "answer": 1,
    "explain": "kb_options is one string, and yours replaces the default. The manual's own example repeats the defaults and appends grp:alts_toggle."
  },
  {
    "q": "On a 27-inch 4K monitor everything is too big at the default settings. What do you set in monitors.lua?",
    "choices": [
      "omarchy_gdk_scale = 2 and omarchy_monitor_scale = 1.6",
      "omarchy_gdk_scale = 1 and omarchy_monitor_scale = 1",
      "omarchy_gdk_scale = 3 and omarchy_monitor_scale = 3"
    ],
    "answer": 0,
    "explain": "The manual recommends 2 and 1.6 for a 27 or 32 inch 4K. The 1 and 1 pair is for 1080p and 1440p.",
    "why": [null, "That is the manual's setting for 1080p and 1440p screens, which would make a 4K screen's text tiny.", "Neither value is a manual recommendation for this screen, and it would make everything larger still."]
  },
  {
    "q": "Why should a Latin layout come first in kb_layout?",
    "choices": [
      "It makes typing faster",
      "Hyprland matches keybindings against the first layout, so Super-key shortcuts only fire when a Latin layout leads",
      "Omarchy refuses to start otherwise"
    ],
    "answer": 1,
    "explain": "Omarchy's default input file documents this: bindings resolve against the first entry in kb_layout, not the active layout."
  }
]
```

## Recap

1. Edit `input.lua` and `monitors.lua` via _Setup > Input_ and _Setup > Monitors_; list only what you want different from the defaults.
2. Caps Lock is the compose key by default, and the real Caps Lock is both Shift keys. `kb_options` is one string, so repeat the defaults you keep.
3. Natural scrolling is `touchpad = { natural_scroll = true }` inside `hl.config({ input = { ... } })`.
4. Put a Latin layout first in `kb_layout`, because bindings match the first layout.
5. Scale with two numbers: `omarchy_gdk_scale` and `omarchy_monitor_scale` (`2` and `1.6` for a 27 or 32 inch 4K, `1` and `1` for 1080p or 1440p). Try scales live with `Super + /` and `Super + Alt + /`.
6. For text size alone, use `omarchy display text size 14`.

Next up, [Themes, Fonts, and the Bar](04-themes-fonts-and-the-bar.md): the look.


---

# Themes, Fonts, and the Bar

Omarchy's look is the first thing people love and the first thing they want to adjust. The good news is that nearly every visual setting follows the same pattern from [Phase 1](01-whose-files-are-whose.md): a menu or command for the common case, and a file in `~/.config` for the rest. You will not edit anything Omarchy owns.

## Themes and backgrounds

A theme is a coordinated set of colors. Omarchy ships twenty-two, according to the manual, and one theme styles the desktop, terminal, Neovim, the activity monitor (btop), Chromium, and the whole shell: bar, menu, notifications, on-screen display, and lock screen. (Obsidian is the exception: pick the Omarchy theme once inside the app, under _Appearance > Themes_.)

Change it three ways:

- `Super + Ctrl + Shift + Space` opens the visual theme picker.
- _Style > Theme_ in the Omarchy menu does the same.
- In a terminal: `omarchy theme list`, then `omarchy theme set "Tokyo Night"`. Both `"Tokyo Night"` and `tokyo-night` work.

Every theme comes with a set of backgrounds. `Super + Ctrl + Space` picks between them. To add your own image, copy it into `~/.config/omarchy/backgrounds/<theme-name>/`, for example `~/.config/omarchy/backgrounds/nord`. The quickest route is _Install > Style > Background_, which opens that folder; `Super + Shift + F` opens a second file manager to copy from. Your image then appears in the `Super + Ctrl + Space` picker.

### Tweaking a theme without losing it

Never edit a stock theme under `/usr/share/omarchy/themes`, because an update replaces it. Omarchy's official customization guide gives two safe routes:

- **Overlay** (best for small changes): make a folder with the same name under `~/.config/omarchy/themes` containing only the files you change. When the theme is applied, the stock theme is copied first and your files win on top.

```console
$ mkdir -p ~/.config/omarchy/themes/catppuccin
$ cp /usr/share/omarchy/themes/catppuccin/colors.toml ~/.config/omarchy/themes/catppuccin/
$ n ~/.config/omarchy/themes/catppuccin/colors.toml
$ omarchy theme set catppuccin
```

*What just happened:* you copied the one file that defines the colors, edited your copy (with `n`, the Neovim alias), and re-applied the theme so Omarchy regenerates the terminal, bar, and app colors from it.

- **Fork**: copy the whole stock theme to a new name (`cp -r /usr/share/omarchy/themes/catppuccin ~/.config/omarchy/themes/catppuccin-custom`) and apply that.

The main file is `colors.toml`. A light theme sets `mode = "light"` at the top of it, which pairs every app with light mode. The Aether app (from the apps menu, `Super + Alt + Space`) can generate a theme from a background through a graphical editor.

### Installing someone else's theme

_Install > Style > Theme_ takes a git URL. The naming convention is `omarchy-<themename>-theme`, which then shows up in the picker as `<themename>`. One safety rule is worth knowing: a theme installed from a repo keeps its colors but loses anything that could run code on your machine. That means any `.lua` file, the terminal config files (`alacritty.toml`, `foot.ini`, `ghostty.conf`, `kitty.conf`), and `vscode.json`. Installing a theme should change what your desktop looks like, never what it runs. A theme you write yourself in `~/.config/omarchy/themes` is not restricted.

## Fonts and the prompt

The default font is JetBrainsMono Nerd Font for both the terminal and the system. _Style > Font_ changes the monospace font everywhere. _Install > Style > Font_ adds Cascadia Mono, Meslo LG Mono, Fira Code, Victor Code, Bitstream Vera Mono, or Iosevka, in Nerd Font versions so the icons in the bar and terminal keep working. After installing one, pick it under _Style > Font_. From a terminal:

```console
$ omarchy font list
$ omarchy font set "CaskaydiaMono Nerd Font"
```

For text size, remember `omarchy display text size 14` from [Phase 3](03-keyboard-mouse-and-screens.md). It moves the shell, GTK apps, and terminal together.

The shell prompt is a minimal [Starship](https://starship.rs/) prompt, configured in `~/.config/starship.toml`. The Foot terminal's own settings live in `~/.config/foot/foot.ini`, which starts by including the current theme's Foot file. That is why the colors come from the theme and not from `foot.ini` itself.

## The bar

The strip along the top is part of the Omarchy shell, so it follows the theme. You can rearrange it without opening a file:

- Drag an empty part of the bar toward another screen edge to move it. Double-left-click empty space to toggle transparency. Drag a widget to reorder it. _Style > Menu Bar_ offers position and transparency from the menu.
- `Super + Shift + Space` hides and shows the bar.
- Right-click the small arrow that hides your tray icons to pin the ones you always want visible.
- Right-click the clock to cycle formats. For a 12-hour clock that reads like `Sunday 10:55 AM`, run `omarchy bar set omarchy.clock format "dddd h:mm AP"`.

The same moves exist as commands, which is what you want for a dotfiles backup:

```console
$ omarchy bar position bottom
$ omarchy bar transparent toggle
$ omarchy bar move omarchy.clock --section center --index 0
$ omarchy bar defaults
```

To add or remove a widget, use `omarchy plugin list` to see ids, then `omarchy plugin enable omarchy.media --section center` or `omarchy plugin disable omarchy.weather`.

All of it lands in `~/.config/omarchy/shell.json`, which reloads when you save it. The same file holds your idle timings, in seconds since you went idle:

```json
{
  "version": 1,
  "idle": {
    "screensaver": 150,
    "lock": 300
  }
}
```

Those are the shipped values: screensaver at 150 seconds, lock at 300. "Lock after ten minutes" is `"lock": 600`. (The file also holds the `bar` section; this excerpt shows only the idle part.)

> 💡 **Key point**: once you change anything about the bar, your `shell.json` is canonical and nothing merges. `omarchy bar defaults` (or _Update > Config > Shell_) brings the shipped layout back, and new default widgets in future releases will not appear on their own.

## Gaps, corners, and layout in looknfeel.lua

Open it with _Style > Hyprland_. Everything in it ships commented out. Remove the `--` on what you want. These are the manual's two common tweaks plus others from the same template:

```lua
hl.config({
  general = {
    -- No gaps between windows or borders.
    gaps_in = 0,
    gaps_out = 0,
    border_size = 0,
  },
  decoration = {
    -- Round the window corners (Omarchy's default is square).
    rounding = 8,

    -- Dim windows that are not focused (0.0 is no dim, 1.0 is fully dimmed).
    dim_inactive = true,
    dim_strength = 0.15,
  },
})
```

If you only want to try gaps off, `Super + Shift + Backspace` toggles all gaps and borders without editing anything. Two more quick toggles: `Super + Backspace` toggles transparency on the focused window, and `Super + L` switches the current workspace between the default dwindle layout and a side-scrolling one. To make side-scrolling the layout everywhere, set `layout = "scrolling"` inside `general`. To turn animations off, set `animations = { enabled = false }` in its own `hl.config` block.

## Keep your work

Once you have tuned things, back them up. The manual suggests GNU Stow. The files worth keeping are the ones you edited: the `~/.config/hypr` folder, `~/.config/omarchy` (your themes, hooks, `shell.json`, and plugins), `~/.config/foot`, `~/.config/tmux`, `~/.config/starship.toml`, `~/.bashrc`, and `~/.XCompose`. The generated theme state under `~/.local/state/omarchy/current` is rebuilt for you and not worth saving.

## Your turn: make it yours

```exercise
[
  {
    "type": "predict",
    "task": "You want the screen to lock after ten minutes of idle time. What number goes in idle.lock in shell.json? (It is measured in seconds.)",
    "accept": ["600"],
    "hint": "Ten minutes times sixty seconds."
  },
  {
    "type": "task",
    "task": "Restyle your desktop in four steps, all without editing a file Omarchy owns.",
    "reveal": "Theme: Super + Ctrl + Shift + Space. Background: copy an image into ~/.config/omarchy/backgrounds/<theme-name>/ and press Super + Ctrl + Space. Font: omarchy font set \"CaskaydiaMono Nerd Font\" (after installing it under Install > Style > Font). Corners: in looknfeel.lua, set decoration = { rounding = 8 } inside hl.config.",
    "checklist": ["I switched to a different theme", "I added one background image of my own and selected it", "I changed the font under Style > Font", "I enabled rounded corners in looknfeel.lua"]
  }
]
```

Check yourself before moving on:

```quiz
[
  {
    "q": "You like Catppuccin but want one color changed, and you do not want an update to undo it. What is the safe route?",
    "choices": [
      "Edit colors.toml in /usr/share/omarchy/themes/catppuccin",
      "Make ~/.config/omarchy/themes/catppuccin containing only the files you change, then re-apply the theme",
      "Edit foot.ini, because it holds the terminal colors"
    ],
    "answer": 1,
    "explain": "A user theme folder with the same name overlays the stock theme: the stock files are copied first and yours win on top. Files in /usr/share/omarchy are replaced by updates.",
    "why": ["That folder belongs to Omarchy and is overwritten on update.", null, "foot.ini pulls its colors from the current theme, so the colors come from colors.toml, not from foot.ini."]
  },
  {
    "q": "You install a theme from a stranger's git repo and it ships a hyprland.lua and a foot.ini. What does Omarchy do with them?",
    "choices": [
      "Applies them, since they are part of the theme",
      "Drops them, because files that can run code are not allowed in an installed theme, and keeps the colors",
      "Refuses to install the theme at all"
    ],
    "answer": 1,
    "explain": "An installed theme keeps its colors but loses .lua files, terminal configs, and vscode.json. Those are regenerated from colors.toml."
  },
  {
    "q": "After you dragged a widget on the bar, a new Omarchy release adds a default widget. What happens to your bar?",
    "choices": [
      "The new widget is merged in automatically",
      "Your shell.json is canonical, so the new widget does not appear unless you add it",
      "Your changes are reset"
    ],
    "answer": 1,
    "explain": "There is no deep merge once you own shell.json. omarchy bar defaults restores the shipped layout."
  }
]
```

## Recap

1. Switch themes with `Super + Ctrl + Shift + Space` or `omarchy theme set`; add backgrounds under `~/.config/omarchy/backgrounds/<theme-name>/`.
2. To tweak a stock theme, overlay a same-named folder in `~/.config/omarchy/themes`. Installed themes lose code-running files.
3. Change fonts under _Style > Font_ or with `omarchy font set`; the prompt is `~/.config/starship.toml`.
4. The bar is configured in `~/.config/omarchy/shell.json` through drags, `omarchy bar` commands, or the file, and it reloads on save. Idle timings live there in seconds.
5. Gaps, rounding, dimming, and layout go in `looknfeel.lua`; `Super + Shift + Backspace` toggles gaps without editing.
6. Back up the files you edited, not the generated theme state.

When something does go wrong, [When Omarchy Breaks](/guides/when-omarchy-breaks) covers snapshots and recovery, and [Omarchy Plugins and the Marketplace](/guides/omarchy-plugins-and-the-marketplace) shows how to add bar widgets that others wrote.
