Skip to content

Omarchy tweaks

Set up DNS, configs, deps, programming languages, displays, and some AI stuff.

11 min read

System configuration

DNS

Select Setup -> Network -> DNS -> Cloudflare from the Omarchy menu.

Confirm the active DNS configuration with:

Shell command
resolvectl status

Shell aliases and PATH

Add these aliases and environment variables:

~/.bashrc
# CUSTOM
# non-omarchy alias for real ls
# alias la="ls -lahF"

# omarchy alias for replaced-by-eza ls
alias la="ls -lah --classify=auto"

export PATH=~/bin:$PATH
export ERL_AFLAGS="-kernel shell_history enabled"

Reset UFW

To discard the current UFW rules and enable a fresh firewall configuration:

Shell command
sudo ufw reset
sudo ufw enable

Extend desktop idle timeouts

The default idle timeouts are too short for my desktop. I replace them with the following one-hour screensaver and lock sequence:

~/.config/omarchy/shell.json
{
  // ...
  "idle": {
    "screensaver": 3600,
    "lock": 3601
  }
  // ...
}

Omarchy bar

Add detail to the clock, and show the active network interface:

~/.config/omarchy/shell.json
{
  // ...
  "bar": {
    // ...
    "layout": {
      // ...
      "center": {
        // ...
        {
          "id": "omarchy.clock",
          "format": "☀️ dddd  'w'ww  📅 yyyy / MM / dd  🕑 HH:mm:ss",
          // ...
        },
        // ...
      }
    }
  }
}

To make the clock update every second:

Bash
omarchy plugin clone omarchy.clock

This will create a $USER.clock file in ~/.config/omarchy/plugins. Let's change the precision in it from SystemClock.Minutes to SystemClock.Seconds:

~/.config/omarchy/plugins/$USER.clock/BarWidget.qml
// ...
SystemClock {
  // ...
  precision: SystemClock.Seconds
}

Restart the shell to apply the changes immediately:

Shell command
omarchy restart shell

Enable fstrim for an encrypted SSD

Run a manual trim check:

Shell command
sudo fstrim / -v

If it returns fstrim: /: the discard operation is not supported, add :allow-discards immediately after some-id:root:

/etc/default/limine
KERNEL_CMDLINE[default]="cryptdevice=PARTUUID=some-large-uuid:root:allow-discards ...

Regenerate the Limine configuration after saving the file:

Shell command
sudo limine-update

Then enable the periodic trim timer:

Shell command
sudo systemctl enable --now fstrim.timer

Restart the system to apply the kernel command-line change.

Software

Restore your backup

Remount the encrypted partition , then restore the files from your full-disk-encrypted backup drive.

Remove software I do not use

The following command removes packages that are not part of my workflow. Review the list before running it, especially on a system you have already configured:

Shell command
sudo pacman -Rns xournalpp docker docker-buildx docker-compose ufw-docker lazydocker
# codex might not be present at first until you do `omarchy update`
mise remove codex

Remove each unused web app through:

Omarchy menu -> Remove -> Web App

I also like to clear any entries in ~/.local/bin, and only add the ones I explicitly install:

Shell command
ls -la ~/.local/bin
rm ~/.local/bin/*

Update the system

Shell command
sudo pacman -Syy
omarchy update

Install desktop and command-line software

This is the software I typically need on a workstation:

Shell command
sudo pacman -S nethogs transmission-gtk nmap \
darktable gimp inkscape krita godot \
blender calibre obs-studio shotcut \
colordiff python-gobject python-xdg yt-dlp \
qgis python-gdal python-owslib python-psycopg2 python-pygments \
ansible inotify-tools jq \
simple-scan audacity base-devel \
libvips openslide firefox iotop \
vlc vlc-plugins-base vlc-plugins-extra \
podman pass

yt-dlp

If the normal extractor cannot download a video, try the generic extractor:

Shell command
yt-dlp --force-generic-extractor URL
# or install python-curl_cffi

Install Erlang, Elixir, Node.js, and Go with mise

List the language runtimes already installed:

Shell command
mise ls

Choose and install an Erlang version:

Shell command
mise ls-remote erlang
mise use erlang@29.1.2 --global

Choose an Elixir build that matches the installed Erlang/OTP version, then install the Hex, Rebar, Phoenix, and Nerves tooling:

Shell command
mise ls-remote elixir
mise use elixir@1.20.4-otp-29 --global

mix local.hex
mix local.rebar

mix archive.install hex phx_new
mix archive.install hex nerves_bootstrap

Choose and install a Node.js version, then install the npm and pnpm tools:

Shell command
mise ls-remote node
mise use node@26.12.0 --global

npm i -g npm

#pnpm setup
# npm i -g pnpm
# pnpm self-update

Set a minimum package release age so newly published versions are not installed immediately:

Shell command
# npm in days
npm config set min-release-age 2 --location=global

# pnpm in minutes
#pnpm config set minimumReleaseAge 2880

Choose and install a Go version:

Shell command
mise ls-remote go
mise use go@1.27.2 --global

Install PostgreSQL

Shell command
sudo pacman -S postgresql postgresql-libs postgis

sudo -i -u postgres
initdb --locale $LANG -E UTF8 -D '/var/lib/postgres/data/'
exit

Enable PostgreSQL now and on future system starts:

Shell command
sudo systemctl enable --now postgresql.service

Workstation fixes and desktop settings

Add fonts

Place your font files in ~/.local/share/fonts.

Prevent Bluetooth audio lag after inactivity

Disable WirePlumber's node suspension:

~/.config/wireplumber/wireplumber.conf.d/bluetooth-disable-suspension.conf
wireplumber.profiles = {
  main = {
    hooks.node.suspend = disabled
  }
}

Then restart the audio services:

Shell command
systemctl --user restart wireplumber.service pipewire.service

Install GPU utilities

For NVIDIA:

Shell command
sudo pacman -S nvtop nvidia-utils

For AMD:

Shell command
sudo pacman -S vulkan-radeon

Code editor

Zed

Install -> Editor -> Zed

Extensions:

  • Catppuccin
  • Catppuccin Icons
  • Dockerfile
  • Elixir
  • Emmet
  • Git Firefly
  • HTML
  • Rainbow CSV
  • SCSS & SASS
  • SQL
  • TOML
  • Vue

If Ctrl+Enter opens the assistant panel instead of inserting a cursor on the next line, add these bindings:

~/.config/zed/keymap.json
[
  {
    "context": "Editor && mode == full",
    "bindings": {
      "ctrl-enter": "editor::NewlineBelow",
      "ctrl-shift-enter": "editor::NewlineAbove",
    },
  },
]

My Zed settings:

~/.config/zed/settings.json
{
  "autosave": "on_window_change",
  //"buffer_font_size": 12,
  "buffer_line_height": "comfortable",
  "cursor_blink": true,
  "cursor_shape": "bar",
  "file_finder": { "modal_max_width": "large" },
  "file_types": {
    "HTML": ["*.svg"],
  },
  "icon_theme": "Catppuccin Mocha",
  "indent_guides": {
    "coloring": "indent_aware",
  },
  "languages": {
    "CSS": {
      "language_servers": [
        "tailwindcss-intellisense-css",
        "!vscode-css-language-server",
        "...",
      ],
    },
    "Elixir": {
      "language_servers": [
        "expert",
        "tailwindcss-language-server",
        "emmet-language-server",
        "!elixir-ls",
        "!next-ls",
        "!lexical",
        "...",
      ],
    },
    "HEEx": {
      "language_servers": [
        "expert",
        "tailwindcss-language-server",
        "emmet-language-server",
        "!elixir-ls",
        "!next-ls",
        "!lexical",
        "...",
      ],
    },
  },
  "prettier": {
    // "plugins": ["prettier-plugin-tailwindcss"],
    "semi": false,
    "singleQuote": false,
  },
  // "lsp": {
  //   "vscode-css-language-server": {
  //     "settings": {
  //       "css": {
  //         "lint": {
  //           "unknownAtRules": "ignore",
  //         },
  //       },
  //     },
  //   },
  // },
  "show_whitespaces": "all",
  "soft_wrap": "editor_width",
  "tab_size": 2,
  "tabs": {
    "file_icons": true,
  },
  "telemetry": {
    "diagnostics": true,
    "metrics": false,
    "anthropic_retention": false
  },
  "theme": {
    "mode": "dark",
    "light": "Catppuccin Latte",
    "dark": "Catppuccin Mocha",
  },
  //"ui_font_size": 14,
}

Configure two desktop monitors

List the connected monitors and note their output names:

Shell command
hyprctl monitors

My configuration assigns workspaces 1-5 to the landscape display and 6-10 to the rotated display:

~/.config/hypr/monitors.lua
-- when working with scales, you need to adjust the positioning of the second monitor accordingly
-- for a scale of 1.5 3840x2160 -> 2560x1440
-- if you want your second monitor to the right, vertical and centered you'd need to:
hl.monitor({
  output = "HDMI-A-2",
  mode = "3840x2160@60",
  position = "0x0",
  scale = 1.5,
})

hl.monitor({
  output = "HDMI-A-1",
  mode = "3840x2160@60",
  position = "2560x-560",
  scale = 1.5,
  transform = 3,
})

for i = 1, 5 do
  hl.workspace_rule({
    workspace = tostring(i),
    monitor = "HDMI-A-2",
    persistent = true,
  })
end

for i = 6, 10 do
  hl.workspace_rule({
    workspace = tostring(i),
    monitor = "HDMI-A-1",
    persistent = true,
  })
end


-- for a scale of 1.2 3840x2160 -> 3200x1800
-- if you want your second monitor to the right, vertical and centered you'd need to:
hl.monitor({
  output = "HDMI-A-2",
  mode = "3840x2160@60",
  position = "0x0",
  scale = 1.2,
})

hl.monitor({
  output = "HDMI-A-1",
  mode = "3840x2160@60",
  position = "3200x-700",
  scale = 1.2,
  transform = 3,
})

Configure laptop monitor

I like to keep all ten workspaces visible:

~/.config/hypr/monitors.lua
-- custom scale for 2.8k laptop display
local omarchy_gdk_scale = 1.8
local omarchy_monitor_scale = 1.8

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

for i = 1, 10 do
  hl.workspace_rule({
    workspace = tostring(i),
    persistent = true,
  })
end

Add laptop touchpad gestures

Add three-finger workspace and full-screen gestures:

~/.config/hypr/input.lua
hl.gesture({ fingers = 3, direction = "horizontal", action = "workspace"})

hl.config({
  gestures = {
    workspace_swipe_invert = false,
  },
})

hl.gesture({ fingers = 3, direction = "up", action = "fullscreen" })

Reduce window gaps

Set smaller inner gaps and remove outer gaps:

~/.config/hypr/looknfeel.lua
hl.config({
  general = {
    gaps_in = 2,
    gaps_out = 0,
    border_size = 1,
  },
})

Hyprland reloads these files automatically after each save. To check the active configuration for errors do:

Shell command
hyprctl reload
hyprctl configerrors

AI stuff

AI tools

Install OpenCode, Pi, and agent-browser with npm:

Shell command
npm install -g --allow-scripts=@opencode/cli @opencode/cli
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
npm install -g agent-browser

# your might need to reshim to pickup new executables
mise reshim

I have this set up for Pi:

~/.pi/agent/APPEND_SYSTEM.md
# CLI Tools

* You have access to the `agent-browser` CLI tool. You can use it as a "browser automation" tool.


# Special instructions

* When done and about to hand-off to the user terminate all outstanding processes started during your turn.
* When working on Phoenix apps, use Tailwind CSS utility classes instead of BEM style opaque classes.

Set OpenCode to notify before updating and keep optional MCP server configurations ready:

~/.config/opencode/opencode.json
{
  // ...
  "autoupdate": "notify",
  "default_agent": "plan",
  // "mcp": {
  //   "chrome-devtools": {
  //     "type": "local",
  //     "command": ["npx", "chrome-devtools-mcp@latest", "--executablePath=/usr/bin/chromium", "--isolated=true"],
  //     "enabled": false
  //   },
  //   "context7": {
  //     "type": "local",
  //     "command": ["npx", "-y", "@upstash/context7-mcp@latest"]
  //   },
  //   "playwright": {
  //     "type": "local",
  //     "command": ["npx", "@playwright/mcp@latest", "--executable-path=/usr/bin/chromium"],
  //     "enabled": false
  //   }
  // }
}

Opencode 2.0 starts a service whenever you run the TUI client, to see the status or stop it afterwards:

Bash
opencode service status
opencode service stop

Fabric

Install Fabric from its repository, then run its setup flow:

Shell command
# Install Fabric directly from the repo
go install github.com/danielmiessler/fabric/cmd/fabric@latest

# Configure your directories and keys
fabric --setup

AI sandbox

Need this code in phoenix apps if using the sandbox script:

config/runtime.exs
if System.get_env("AI_SANDBOX") == "true" do
  config :my_app, MyAppWeb.Endpoint, http: [ip: {0, 0, 0, 0}]
  config :my_app, MyApp.Repo, hostname: "postgres"
end

Agent skills

The way I set up agent skills is to clone the repo in a dev dir, for example for the Impeccable skill:

Bash
# the directory that will contain all the skills I want to install
mkdir -p ~/development/agent-skills
cd ~/development/agent-skills

# create a directory for the author (some skills are named the same, this serves as a namespace)
mkdir pbakaus
cd pbakaus

# clone the skill repository under the author
git clone https://github.com/pbakaus/impeccable.git

Then to have the skill available to agents:

Bash
cd ~/.agents/skills
ln -s ~/development/agent-skills/pbakaus/impeccable/.pi/skills/impeccable/
# you can link to something else in case you're using some other harness, for example:
# ln -s ~/development/agent-skills/pbakaus/impeccable/.opencode/skills/impeccable/
# ln -s ~/development/agent-skills/pbakaus/impeccable/.claude/skills/impeccable/
# ln -s ~/development/agent-skills/pbakaus/impeccable/.codex/skills/impeccable/

With this setup you can update skills with a git pull.

Some good baseline skills:

Misc

Running out of space

If mysteriously running out of space, it might be a faulty snapshot process.

A good starting point is to check the list of existing snapshots (shouldn't be there more than 5 or so, at some point I had more than 1000):

Bash
sudo snapper -c root list
# sudo snapper list

If you find a large number of snapshots and need to delete them, you can use something like:

Bash
sudo snapper -c root delete 32-105

Other commands to try:

Bash
findmnt -t btrfs
sudo btrfs subvolume list -t /
sudo btrfs filesystem usage -T /

sudo snapper list-configs
sudo snapper -c root get-config
# sudo snapper get-config

systemctl status snapper-cleanup.timer
systemctl status snapper-cleanup.service

Disable IPv6

To temporarily disable IPv6:

Bash
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1

More posts connected by shared tags.