跳转至

01 · 全景与心智模型

如果只看到 432 个 omarchy-* 文件,Omarchy 很容易显得像一袋互不相关的脚本。更准确的理解是:它用 430 个被 router 注册的窄命令维护同一个桌面系统的声明、生成状态和副作用。

先把它想成控制面

Hyprland、Quickshell、pacman、systemd、PipeWire、NetworkManager 才是实际执行工作的“数据面”。Omarchy 不重新实现它们,而是把用户动作翻译成这些系统已有的接口:

flowchart TB
    Intent[用户动作<br/>命令/菜单/快捷键] --> Control[Omarchy 控制面]
    Control --> Package[pacman / AUR]
    Control --> Service[systemd / D-Bus]
    Control --> WM[Hyprland / UWSM]
    Control --> Desktop[Quickshell IPC]
    Control --> Config[配置编译与链接]
    Package --> Machine[可运行的桌面状态]
    Service --> Machine
    WM --> Machine
    Desktop --> Machine
    Config --> Machine

这带来一个很实用的判断:一条命令是否“完成”,不能只看它有没有返回 0,还要看下游系统接收了什么、状态写在哪里、失败后能否重放。

六层架构

层 主要位置 责任 生命周期
发行内容 /usr/share/omarchy 默认配置、脚本、主题、Shell 随包升级
系统集成 /etc、/usr/lib 登录、PAM、systemd、pacman hook root 管理
用户意图 ~/.config/omarchy 等 显式定制和扩展 用户持有
生成状态 ~/.local/state/omarchy 当前主题、模块、完成标记 可重建或迁移
图形运行时 Hyprland + Quickshell UI、通知、面板、IPC 每次会话
瞬态协调 $XDG_RUNTIME_DIR、/tmp 锁、握手、日志、选择结果 进程/启动周期

层之间不是随意互写。比如主题源属于发行内容或用户意图;omarchy-theme-set 把它编译到生成状态;Shell 再读取活动结果。直接修改生成目录会在下次切换时丢失,这是设计使然。

三条主生命周期

生命周期 A:机器变成 Omarchy

stateDiagram-v2
    [*] --> Packages: 安装包
    Packages --> SystemApplied: root 应用系统配置
    SystemApplied --> UserProvisioned: 创建/确定 owner
    UserProvisioned --> Finalized: 用户目录 finalization
    Finalized --> FirstRun: 首次图形登录
    FirstRun --> Ready: 会话服务就绪

root 阶段不能可靠操作用户 D-Bus、DConf、通知与音频会话,所以安装被刻意切成系统应用、用户 finalization 和图形 first-run。这里的“多阶段”不是历史包袱,而是权限和可用性边界。

生命周期 B:用户操作桌面

sequenceDiagram
    participant U as 用户
    participant C as omarchy CLI
    participant S as Quickshell
    participant O as OS 服务
    U->>C: 快捷键/菜单/终端命令
    alt 需要桌面 UI
      C->>S: IPC 调用
      S-->>U: panel/overlay/toast
    else 需要系统副作用
      C->>O: hyprctl/systemctl/pacman/配置写入
      O-->>C: 状态/退出码
    end

CLI 与 Shell 并非两套产品。CLI 是稳定的动作边界,Shell 是常驻 UI 和服务宿主。菜单、快捷键和终端最终可以复用同一动作。

生命周期 C:系统持续演进

flowchart LR
    Lock[更新锁] --> Space[空间检查]
    Space --> Snapshot[创建快照]
    Snapshot --> Packages[系统包事务]
    Packages --> Migrations[顺序迁移]
    Migrations --> Hooks[用户 post-update hook]
    Hooks --> Extras[AUR / mise / 清理]
    Extras --> Restart[必要时重启服务]

包事务是迁移前的屏障:新脚本和新默认值先到位,迁移才开始改变用户/系统状态。每个迁移只有成功后才写 marker,因此失败可以续跑。

两种扩展哲学

Omarchy 同时采用了两种扩展方式:

  1. 数据扩展:菜单 JSON、主题 TOML、desktop 文件。这类更容易验证和合并;
  2. 代码扩展:插件 QML、用户 Lua、hook 脚本。这类能力更强,也需要明确的信任边界。

最新快照恰好强化了这个区别:远程下载的主题只能被当作数据,不得借主题安装执行 Lua 或终端配置。用户主动维护的本地工作副本则被视为另一种信任级别。

五个反复出现的设计原则

1. 小入口,大组合

每个 omarchy-* 命令尽量只做一件事;顶层流程通过 source 或子命令组合它们。代价是文件多,收益是动作可从 CLI、菜单、迁移和测试复用。

2. 成功才留事实

finalization、first-run 和 migration 都用 marker 表示完成。关键不是“有 marker”,而是 marker 写入必须晚于全部必要副作用。

3. 生成物与手写配置分离

~/.config 表达意图,~/.local/state 保存编译/选择结果。这个区分让原子切换、回退和重建成为可能。

4. 快路径服务日常,慢路径服务发现

CLI 正常执行通过文件名做最长前缀匹配,不扫描所有命令;只有 help、list、alias 和检查才建立完整元数据注册表。

5. 失败边界要看得见

Shell IPC 不自动启动 Shell,迁移不吞掉失败,升级验证失败明确阻止 reboot。这些选择牺牲了一点“看起来总能工作”,换来真实状态不被掩盖。

关键源码索引

下一章把这张逻辑图落到真实目录和包边界:02 · 仓库地图与安装边界。