Skip to content

Instantly share code, notes, and snippets.

@IgorWarzocha
Created August 20, 2026 21:26
Show Gist options
  • Select an option

  • Save IgorWarzocha/b17278e1de9dedf17a3032730d7567cb to your computer and use it in GitHub Desktop.

Select an option

Save IgorWarzocha/b17278e1de9dedf17a3032730d7567cb to your computer and use it in GitHub Desktop.
Agent skill for preserving personal customisations when migrating Omarchy 3 to Omarchy 4 (Quattro)

Omarchy 3 → 4 migration skill

A slightly more personalised version of this skill helped me migrate three machines from Omarchy 3 to Omarchy 4 (Quattro), so I thought the generic version might help someone else.

This is an agent skill, not a migration script. It gives an AI coding agent a cautious workflow and practical heuristics for preserving personal customisations across Quattro's major changes. It deliberately does not choose your terminal, editor, coding agents, package manager, or preferred desktop setup for you.

It covers the failure shapes that were easiest to miss:

  • Hyprland .conf → Lua, including bindings, rules, submaps and scripts;
  • Waybar/Walker/Mako → the Quickshell-based Omarchy shell;
  • the move from a user Omarchy checkout to package-owned /usr/share/omarchy;
  • GUI-session PATH versus interactive-shell PATH;
  • Herdr launchers containing old absolute paths;
  • mise wrappers shadowing an existing CLI and installing a second copy;
  • custom scripts, hooks, themes, terminal/editor defaults, coding agents and iwd → NetworkManager risks;
  • staged validation and cleanup instead of restoring an old config wholesale.

Files and installation

GitHub Gists are flat, but the skill's intended directory structure is:

omarchy-v4-migration/
├── SKILL.md
└── references/
    ├── hyprland-lua.md
    ├── path-and-programs.md
    └── shell-and-scripts.md

Clone this Gist, then put SKILL.md at the skill root and the other three Markdown files under references/. For Pi's lazy skill layout, for example:

git clone https://gist.github.com/b17278e1de9dedf17a3032730d7567cb.git /tmp/omarchy-v4-migration
target="$HOME/.pi/agent/lazy-skills/operations/omarchy-v4-migration"
mkdir -p "$target/references"
cp /tmp/omarchy-v4-migration/SKILL.md "$target/"
cp /tmp/omarchy-v4-migration/{hyprland-lua,path-and-programs,shell-and-scripts}.md \
  "$target/references/"

Other agents can use the same structure in their own skill directory. If your agent only supports a single skill file, start with SKILL.md and provide the three reference files as additional context when their topics arise.

Notes

  • Read the current Omarchy command metadata and packaged source: Quattro is evolving, and live behaviour outranks examples.
  • Review the official upgrade route before starting; do not reuse an old beta command from a post or chat log.
  • Keep upgrade backups until the replacement behaviours work.
  • Treat linked bug reports as useful diagnostic shapes, not proof that a bug is still present.

Use and adapt freely. This is independent community guidance, not an official Omarchy migration tool.

Porting Hyprland .conf Intent to Lua

Hyprland 0.55 deprecated hyprlang configuration in favour of Lua. Omarchy 4 generates a Lua entry point and user modules. Do not translate text mechanically without first reading the generated Quattro files and current packaged defaults.

Official references:

Loader first

Start with ~/.config/hypr/hyprland.lua. A current Omarchy-generated loader bootstraps the packaged Lua path, loads Omarchy defaults, then requires user modules. Exact helper names and ordering can change.

Do not reconstruct an old loader from snippets. Existing loaders have broken after packaged modules began relying on helper globals that an older user file did not initialize. Compare with the current generated default and helpers.lua migration issue #5911 when errors mention a nil global such as o.

Add custom modules after defaults so user overrides win:

require("hypr.monitors")
require("hypr.input")
require("hypr.bindings")
require("hypr.looknfeel")
require("hypr.autostart")
require("hypr.my_rules")

The last line corresponds to ~/.config/hypr/my_rules.lua when the generated Lua package path includes the user config root.

Conversion map

Nested settings

Old:

input {
  kb_layout = pl
  repeat_rate = 40
  touchpad {
    natural_scroll = true
  }
}

Lua:

hl.config({
  input = {
    kb_layout = "pl",
    repeat_rate = 40,
    touchpad = {
      natural_scroll = true,
    },
  },
})

Lua types matter: booleans are true/false, strings are quoted, and table entries use commas. Keys containing punctuation may need bracket syntax such as ["col.active_border"] = "...".

Monitors and environment

Old:

env = GDK_SCALE,1
monitor = DP-1,1920x1080@60,0x0,1

Lua:

hl.env("GDK_SCALE", "1")
hl.monitor({
  output = "DP-1",
  mode = "1920x1080@60",
  position = "0x0",
  scale = 1,
})

Discover live output names and supported modes with hyprctl monitors all. Do not copy another machine's output name or scale. Check both monitor scale and toolkit variables such as GDK_SCALE; a correct live Hyprland scale can still coexist with an oversized application environment.

Bindings

Native Lua:

hl.unbind("SUPER + RETURN")
hl.bind("SUPER + RETURN", hl.dsp.exec_cmd("my-terminal"))
hl.bind("F24", hl.dsp.exec_cmd("my-recorder stop"), { release = true })

Omarchy's descriptive helper, when present in the generated loader:

hl.unbind("SUPER + RETURN")
o.bind("SUPER + RETURN", "Terminal", "my-terminal")
o.bind("F24", nil, "my-recorder stop", { release = true })

Preserve intent from old variants rather than their spelling:

Old form Lua option/behaviour
bind plain hl.bind
bindr { release = true }
binde { repeating = true }
bindl { locked = true }
bindm mouse binding with { drag = true } where appropriate
bindd preserve the description with Omarchy's o.bind

Check the current Hyprland bind reference for combined flags. Unbind inherited keys before replacing them; otherwise both the old default and custom action may fire.

Autostart

Old:

exec-once = my-service --flag

Typical Omarchy Lua:

o.launch_on_start("my-service --flag")

Verify the helper in the current packaged defaults. Preserve ordering, backgrounding, environment, and single-instance assumptions rather than blindly wrapping every old line.

Window rules

Old rules should become structured Lua rules. Prefer current generated examples because match and action schemas evolve:

hl.window_rule({
  name = "project-terminal",
  match = { class = [[^org\.example\.Terminal$]] },
  workspace = "2 silent",
  float = true,
})

Omarchy may also expose a concise o.window(...) helper. Use it only after reading its current call sites. Give custom rules unique names and validate regular expressions against actual hyprctl clients -j classes.

Submaps and press/release flows

Port both halves of push-to-talk, hold, drag, or modal workflows. A press bind without its release bind is not equivalent.

hl.define_submap("temporary_mode", function()
  hl.bind("Escape", hl.dsp.submap("reset"))
end)

Check current API names for no-op keys, dispatchers, and submap reset. Validate the live submap after use so a failed script cannot strand the user in a mode.

Dispatches inside external scripts

Shell scripts may contain old dispatcher spelling even after Lua config is clean. For current Hyprland, dispatch Lua expressions through hyprctl:

hyprctl dispatch 'hl.dsp.layout("togglesplit")'
hyprctl dispatch 'hl.dsp.submap("reset")'

Translate the semantic action with the current dispatcher documentation. Do not assume every old hyprctl dispatch <name> <arg> maps by string substitution.

Files that may still be .conf

The Hyprland compositor's user configuration is Lua. Separate programs can still own .conf files, including display portals, night-light services, or other daemons in a given Omarchy release. Trace the process and packaged source before deleting every .conf under ~/.config/hypr.

Validation loop

luac -p ~/.config/hypr/*.lua
hyprctl reload
hyprctl configerrors
hyprctl monitors
hyprctl getoption input:kb_layout
hyprctl getoption input:kb_variant
hyprctl binds -j

luac -p proves syntax only. hyprctl configerrors proves loading, and live queries prove that the intended value won after defaults and overrides.

Finish each tranche clean before deleting its .conf source.

PATH, Program Ownership, Herdr, and Coding Agents

Quattro changes package ownership, executable locations, the GUI shell, and mise-backed convenience wrappers. Many apparent application failures are selection failures: the intended program still exists, but another path wins.

Treat PATH as several environments

Compare at least:

  1. a login/interactive shell;
  2. the systemd user-manager/GUI session;
  3. the running parent process that launches the failing child;
  4. a remote SSH command, if remote launchers are involved.

Examples:

zsh -lic 'print -r -- $PATH; type -a pi'       # substitute the real login shell
systemctl --user show-environment | grep '^PATH='
pgrep -a herdr
tr '\0' '\n' </proc/<pid>/environ | grep '^PATH='
readlink -f /proc/<pid>/cwd

A shell can work while a menu, keybinding, service, or Herdr server cannot. Interactive shell initialization does not retroactively change an existing GUI or service process.

Durable GUI environment sources commonly include ~/.config/uwsm/default and ~/.config/uwsm/env.d/. Read the current Omarchy/UWSM load path before editing. A new login is the reliable activation boundary. systemctl --user set-environment can aid a current-session test but is not durable state.

Do not solve precedence bugs by repeatedly appending directories. Choose the canonical executable and put its owning bin directory in the smallest correct environment.

Package-root transition

Omarchy 3 commonly appeared as a user checkout under ~/.local/share/omarchy. Quattro's canonical package tree is normally /usr/share/omarchy, and the old-looking home path may be a compatibility symlink.

For every custom script or launcher containing an Omarchy path:

command -v omarchy
readlink -f "$(command -v omarchy)"
readlink -f ~/.local/share/omarchy
rg -n '/home/.*/\.local/(share/omarchy|bin)' ~/.config ~/.local/bin

Use $OMARCHY_PATH inside Omarchy-aware code when current packaged examples do so. Use command -v for external executables. Do not patch the package tree to preserve an old absolute path.

Herdr path heuristic

An old launcher may run:

~/.local/bin/herdr

while the Quattro package provides:

/usr/bin/herdr

This is not universal. On every machine or SSH target involved, discover:

command -v herdr
readlink -f "$(command -v herdr)"
pacman -Qo "$(command -v herdr)" 2>/dev/null || true

Then inspect:

  • keybindings and terminal commands;
  • focus-or-launch helpers;
  • tab cyclers and pgrep -f expressions;
  • remote commands such as ssh -t host /old/path/herdr;
  • user services and desktop entries.

Update both the command and any process-matching expression. A correct launch with a stale matcher can create duplicate Herdr windows. Preserve Herdr's session file and live workspaces; path repair does not require deleting them.

Diagnose a shadowed command

For any important tool:

type -a <tool>
selected=$(command -v <tool>)
printf '%s -> %s\n' "$selected" "$(readlink -f "$selected")"
file "$selected"
mime=$(file -Lb --mime-type "$selected")
[[ $mime == text/* ]] && sed -n '1,8p' "$selected"
pacman -Qo "$selected" 2>/dev/null || true
mise current 2>/dev/null
mise which <tool> 2>/dev/null || true
mise where <tool> 2>/dev/null || true

Also inspect the actual package-manager locations the user chose: npm global, Bun global, pipx, cargo, AUR/pacman, vendor installer, or a project-authored installation. Version equality does not mean two installations have the same runtime behaviour.

Mise lazy-wrapper trap

Quattro can place wrappers under ~/.local/bin using omarchy-mise-install. A wrapper may call mise use -g on first run. That is intentional for an uninstalled stock tool, but harmful when it shadows an existing installation the user wants to keep.

Typical symptoms:

  • a tool unexpectedly announces that it is installing;
  • ~/.config/mise/config.toml gains a new entry after first launch;
  • the selected binary changes from a JavaScript/Python/Rust install to a standalone mise backend;
  • a wrapper recurses because it resolves its own command name through PATH;
  • an aqua-backed wrapper fails attestation even though a system binary exists.

Relevant reports:

Do not remove every wrapper by policy. For each tool, ask whether the user wants the old authored/system install or Omarchy's mise-managed install.

When preserving the old install:

  1. prove the old executable and package are intact;
  2. ensure its bin directory is visible to both shell and GUI launchers;
  3. remove only the shadowing wrapper;
  4. remove the unwanted mise config/tool version if it was installed;
  5. run mise reshim;
  6. remove broken version-alias symlinks left by the uninstaller;
  7. test resolution again in every relevant environment.

When adopting the mise install, make sure the wrapper resolves the installed binary rather than itself and validate the backend/runtime before deleting the old installation.

Pi-specific diagnostic, not a preferred install method

Pi can be installed as an npm/Bun global JavaScript package whose CLI shebang selects Node, or as a mise-provided standalone executable built with Bun. A user may legitimately prefer either.

If an upgraded system prints a Bun crash mentioning a NAPI module and uv_async_init, check whether a new ~/.local/bin/pi wrapper selected a standalone Bun build over an existing Node-run package. Compare:

type -a pi
file "$(command -v pi)"
pi_target=$(readlink -f "$(command -v pi)")
[[ $(file -Lb --mime-type "$pi_target") == text/* ]] && sed -n '1p' "$pi_target"
mise current pi 2>/dev/null || true
find ~/.local/share/mise/installs ~/.cache/.bun/install/global \
  -path '*/pi-coding-agent/package.json' -print 2>/dev/null

Preserve the user's chosen Pi installation. The lesson is ownership and runtime selection, not “Node is always correct” or “mise is always correct.”

Terminals and editors are choices

Quattro may install or select a different default without removing the user's old tool. Distinguish:

  • installed package;
  • Omarchy launcher default;
  • XDG terminal preference;
  • EDITOR and VISUAL;
  • MIME handlers;
  • terminal command embedded in a keybinding or desktop file.

Discover the current routed commands with omarchy commands --json; common routes include:

omarchy default terminal
omarchy default editor
xdg-terminal-exec --print-id
xdg-mime query default text/plain

Ask whether to keep the old preference, adopt Quattro's, or retain both. Only then set defaults and remove packages/config directories.

Coding agents are choices too

For each agent, establish:

  • whether the user still wants it;
  • which installation is canonical;
  • whether it should be the Omarchy default;
  • whether shell/menu launchers can see it without installing another copy;
  • whether a stock wrapper is useful, redundant, or harmful.

omarchy default agent <name> may install the agent if Omarchy believes it is missing. Inspect the current implementation before using it with a non-mise installation. Do not assume the user's preferred roster, remove ordinary gh when cleaning a Copilot agent, or erase agent data merely because a launcher is retired.

Validation

Test both non-interactive metadata and real startup:

<tool> --version
<tool> --help

For TUIs with native modules, add an ephemeral PTY startup test when safe. A version flag may exit before loading the failing module. Disable session saving and use a temporary working directory when supported. Do not send prompts or trigger external actions merely for a smoke test.

Quickshell, Custom Scripts, Hooks, Themes, and Network

Omarchy 4 replaces the old collection of bar, launcher, notification, and OSD processes with one Quickshell-based Omarchy shell. Treat this as a product surface change, not a directory rename.

References:

Shell ownership

Common Quattro user surfaces:

~/.config/omarchy/shell.json
~/.config/omarchy/extensions/omarchy-menu.jsonc
~/.config/omarchy/plugins/<plugin-id>/

shell.json is authoritative once present; it is not deep-merged with later packaged defaults. Read the current packaged default and the live user file before changing it. Preserve unknown entries and host-specific ordering.

The shell hot-reloads user JSON, JSONC, and plugins. Validate with:

omarchy-shell shell ping
omarchy plugin validate ~/.config/omarchy/plugins/<plugin-id>

Use omarchy restart shell only when hot reload fails or a changed component requires a process restart. omarchy refresh shell is replacement/recovery, not a routine reload.

Do not start a second Quickshell process for a custom widget. Extend the running Omarchy shell through its plugin model.

Porting Waybar modules

Inventory each custom module as a behaviour bundle:

  • command or long-running process;
  • polling interval and signal handling;
  • click, scroll, and alternate-click actions;
  • JSON/text schema;
  • icons, fonts, CSS, and visibility conditions;
  • state files and secrets;
  • package and environment dependencies.

Then choose with the user:

  1. map it to a built-in Quickshell widget;
  2. create a user plugin with manifest.json and QML;
  3. replace it with a menu action or simpler script;
  4. retire it.

Do not assume everything under ~/.config/waybar was presentation-only. Users often store module state there. Upgrade backups can contain small data files that a script silently falls back from when missing.

Plugin validation may reject symlinked plugin folders. If so, keep canonical source in the user's dotfiles repository but deploy a real copied plugin tree under ~/.config/omarchy/plugins/; do not bypass validation or patch the packaged shell.

Menus, launchers, and notifications

Old Walker menu scripts, Waybar menus, and Mako rules do not automatically become Quickshell behaviour.

  • Put static menu additions and overrides in ~/.config/omarchy/extensions/omarchy-menu.jsonc.
  • Use providers only when the current menu API expects dynamic JSON rows.
  • Port hidden/default rows deliberately; an old script file existing does not make it active.
  • Map notification intent to current Omarchy shell controls or hooks rather than attempting to restart Mako alongside Quickshell.

Never test a suspend, reboot, shutdown, purchase, message, or other consequential menu action merely to prove that it appears. Validate structure and let the user exercise the live action.

Custom script audit

Search user scripts and call sites:

find ~/.local/bin ~/.config -type f -perm -u+x -print 2>/dev/null
rg -n '/home/|\.local/share/omarchy|hyprctl dispatch|waybar|walker|mako|foot|alacritty' \
  ~/.local/bin ~/.config 2>/dev/null

For each retained script, check:

  • package-owned absolute paths that changed;
  • commands removed or renamed by Quattro;
  • old Hyprland dispatcher syntax;
  • terminal-specific options and app IDs;
  • window classes changed by new launch helpers;
  • state files moved into an upgrade backup;
  • execute bits and interpreter shebangs;
  • GUI environment variables unavailable outside an interactive shell;
  • process matchers that still recognize only an old executable path.

Port the script and every caller together. A fixed command with an old pgrep -f expression can create duplicates; a fixed script with an old keybinding remains inert.

Static validation examples:

bash -n ~/.local/bin/my-script
python -m py_compile ~/.local/bin/my-script.py
luac -p ~/.config/hypr/my_rules.lua
command -v <dependency>

Remove generated __pycache__ when it was created only for migration validation.

Hooks and themes

Current user hooks live under ~/.config/omarchy/hooks/. Generated theme state commonly lives under ~/.local/state/omarchy/current/, while user theme sources belong under ~/.config/omarchy/themes/.

Audit old hooks for:

  • calls into a user Git checkout that became /usr/share/omarchy;
  • writes into packaged/default trees;
  • references to old generated state under ~/.config/omarchy/current;
  • restarts for Waybar, Walker, Mako, or terminal components no longer used;
  • custom templates that still work and should remain user-owned.

Edit the source/template/hook, not generated current-theme output. Use current routed Omarchy commands to reapply a theme or restart an affected component.

Network transition

Some Omarchy 3 installations used iwd directly while Quattro uses NetworkManager. Community reports show iwd credentials may not be converted. Before an upgrade—especially away from home—record how to reconnect and confirm that remote access will survive.

Relevant paths/services can include:

/var/lib/iwd/
iwd.service
NetworkManager.service

Do not print or copy wireless secrets into chat or migration notes. Use a secure local transfer if conversion is required.

If the upgrade aborts during the system transition, check that it did not leave both network stacks enabled before rebooting. An incomplete-upgrade report is documented in issue #6575; use it as a failure-shape heuristic and follow the current official recovery path rather than copying an old workaround.

Common symptom map

Symptom First place to look
Bar/module disappeared Waybar backup, shell.json, available shell plugins
Menu script exists but does nothing Active JSONC extension and current menu API
Notification rules vanished Mako backup versus Quickshell notification controls
Script says command not found GUI/user-manager PATH, not only interactive shell
Script runs twice old process matcher, duplicate autostart, second Quickshell instance
Layout script errors after Hyprland update old dispatcher syntax and Lua API
Theme change no longer affects app old generated-state path or packaged file edit
Wi-Fi gone after reboot iwd credentials and NetworkManager state

Cleanup boundary

After the replacement works and the user approves cleanup:

  • remove inactive Waybar/Walker/Mako config and old autostart entries;
  • remove superseded scripts and their callers together;
  • remove old generated theme links, not current user theme sources;
  • remove upgrade backups only after every needed state file and behaviour has been accounted for.
name omarchy-v4-migration
description Omarchy 3 to 4 (Quattro) migration stewardship: preserve user intent across Hyprland Lua, Quickshell, package-path, GUI-environment, script, and CLI-wrapper changes.

Omarchy 3 → 4 Migration

Use this skill to assess, perform, or finish an Omarchy 3 to Omarchy 4 (Quattro) migration. It is a behaviour-preserving migration, not a recipe for making every machine use the same terminal, editor, shell, or coding agent.

Current Omarchy command metadata, packaged source, and live runtime state outrank examples here. Quattro changes quickly.

Non-negotiable boundaries

  • Use the current official upgrade route. Discover it from the installed Omarchy command surface or current upstream documentation; do not replay an old beta curl command from memory.
  • Do not delete Omarchy 3 configuration while Omarchy 3 is still the live session. Upgrade, reach a successful completion, reboot, then port and clean.
  • Treat /usr/share/omarchy as package-owned and read-only. A ~/.local/share/omarchy compatibility path may resolve there.
  • Inventory user intent before changing defaults or removing packages.
  • Ask which terminal, editor, coding agents, package managers, and custom services the user wants to keep. Never substitute a personal allowlist.
  • Do not restore an old config tree wholesale over Quattro. Port one behaviour at a time into the current user-owned surface.
  • Confirm package removal, config refresh/reset, network-stack repair, logout, reboot, and other disruptive actions unless already explicitly authorized.
  • Keep the upgrade-created backups until the migrated behaviours validate. Their eventual deletion is a separate user decision.

Read selectively

  • references/hyprland-lua.md — .conf to Lua mapping and validation.
  • references/path-and-programs.md — package-root, PATH, Herdr, mise wrapper, Pi, terminal/editor, and coding-agent diagnostics.
  • references/shell-and-scripts.md — Waybar/Walker/Mako to Quickshell, custom scripts, hooks, themes, and network transition.

Migration workflow

1. Establish the phase

Identify one of these states before touching anything:

  1. Pre-upgrade: Omarchy 3 is live.
  2. Upgrade incomplete: the transition command failed or never reached its final success/reboot boundary.
  3. Quattro booted, personal behaviour missing: the normal porting phase.
  4. Quattro works, cleanup remains: validate, then remove superseded state.

If the upgrade failed, preserve its first error and inspect the current upgrade implementation and logs. Do not reboot a partially switched system merely because package installation appeared to finish. Pay particular attention to network services and whether both the old and new stacks are enabled.

2. Build a behaviour inventory

Describe what the user expects, not just which files exist:

  • monitor arrangement, scale, refresh rate, transforms;
  • keyboard layout/variant/options, pointer and touchpad tuning;
  • keybindings, window rules, submaps, autostart jobs, and custom dispatches;
  • terminal, editor, MIME handlers, shell, multiplexer, and launcher defaults;
  • coding agents and how each was installed;
  • Waybar modules, launcher/menu extensions, notification rules, and scripts;
  • themes, templates, hooks, generated state, and user plugins;
  • GUI-session environment, PATH additions, language/version managers;
  • Wi-Fi/network state and remote-access dependencies.

Useful evidence before upgrade includes:

find ~/.config/hypr -maxdepth 2 -type f -print
find ~/.config/waybar ~/.config/walker ~/.config/mako -maxdepth 3 -type f -print 2>/dev/null
find ~/.local/bin -maxdepth 1 -type f -o -type l
type -a <important-command>
readlink -f "$(command -v <important-command>)"
systemctl --user show-environment | grep '^PATH='

For each terminal/editor/agent, record four separate facts:

  1. the user's preferred tool;
  2. the executable selected in an interactive shell;
  3. the executable selected by the GUI/user-manager environment;
  4. the package manager or authored installation that owns it.

3. Locate Quattro's durable surfaces

After a successful upgrade and reboot, inspect the generated files before editing:

~/.config/hypr/hyprland.lua
~/.config/hypr/{bindings,input,monitors,looknfeel,autostart}.lua
~/.config/omarchy/shell.json
~/.config/omarchy/extensions/omarchy-menu.jsonc
~/.config/omarchy/plugins/
~/.config/omarchy/hooks/
~/.local/state/omarchy/

Upgrade evidence commonly uses names such as:

*.omarchy-upgrade-to-quattro.<timestamp>.bak

Resolve symlinks. Do not assume a file is user-owned because it is visible under the home directory.

4. Port in dependency order

Use small tranches:

  1. Access and environment: network, remote access, login shell, PATH.
  2. Display and input: enough to use the workstation comfortably.
  3. Terminal/editor/agent choices: preserve the user's choices and install methods unless they ask to change them.
  4. Hyprland behaviours: bindings, rules, layouts, submaps, autostart.
  5. Shell behaviours: bar, menus, notifications, plugins, idle controls.
  6. Themes, hooks, and peripheral scripts.
  7. Package and file cleanup.

Validate after every tranche. A clean reload is evidence; copying files is not.

5. Review choices instead of imposing them

Before final cleanup, present independent findings with disposition choices. Typical decisions are:

  • keep the old preferred terminal, adopt Quattro's default, or retain both;
  • keep the old editor and MIME ownership, adopt a new one, or split CLI/GUI;
  • preserve each coding agent's authored install, replace it with a mise-backed install, or remove it;
  • port a custom Waybar module to a Quickshell plugin, drop it, or defer it;
  • port an old script/hook, retire it, or leave it inert until later.

The right result is the user's chosen canonical stack, not the smallest or most stock stack.

6. Validate the final system

Match validation to the changed layer:

luac -p ~/.config/hypr/*.lua
hyprctl reload
hyprctl configerrors
hyprctl monitors
hyprctl getoption input:kb_layout
ghostty +validate-config                 # or the chosen terminal's validator
omarchy-shell shell ping
omarchy plugin validate ~/.config/omarchy/plugins/<id>
systemctl --user show-environment | grep '^PATH='
zsh -lic 'type -a <important-command>'   # use the actual login shell

For a TUI that failed only during interactive startup, --version is not a sufficient test. Use an ephemeral PTY smoke test with session saving disabled when the program supports it, and remove any temporary output afterwards.

Do not launch social stacks, record audio, rearrange workspaces, or trigger power actions merely to prove config structure. Ask before a disruptive visual or behavioural test.

7. Clean only proved superseded state

Once the active replacement works:

  • remove inactive Hyprland .conf overrides, not unrelated daemon configs;
  • remove old Waybar/Walker/Mako files only when no current process loads them;
  • remove lazy wrappers only after the canonical executable is selected and visible to both shell and GUI environments;
  • remove duplicate packages/config directories only after the user chooses a canonical terminal/editor/agent;
  • run mise reshim after changing mise-managed tools and remove broken alias symlinks left behind by uninstallers;
  • keep current user configuration and delete migration notes that no longer affect behaviour only when the user wants the historical record gone.

Completion criteria

  • The preferred behaviours are represented in active Quattro user files.
  • Hyprland and Quickshell validate cleanly.
  • Interactive shells, GUI launchers, remote launchers, and service processes resolve important programs to the intended installations.
  • No wrapper silently installs a second copy of an already-owned tool.
  • Custom scripts use current paths, commands, and dispatcher syntax.
  • Network and remote access survive a reboot.
  • Old packages and files remain only by deliberate user choice.

Sources

Issue reports linked in the references are diagnostic heuristics, not claims that the same bug remains in the current release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment