跳转至

05 · 元数据驱动的 CLI

430 个注册命令若手写成一棵 case/switch,帮助文本、别名、权限提示和真实文件很快会失去同步。Quattro 反过来:可执行文件就是命令,文件头元数据就是目录。

一个命令如何声明自己

router 只读取 omarchy-* 文件前 80 行的注释元数据,字段包括:

字段 作用
@omarchy-group 命令分组
@omarchy-name 规范路由名
@omarchy-summary 单行帮助摘要
@omarchy-args 参数提示与必填判断
@omarchy-examples 例子
@omarchy-requires-sudo 帮助中标注权限
@omarchy-hidden 从常规列表隐藏
@omarchy-aliases 额外路由

缺省时,router 从文件名推导路由:omarchy-theme-set 对应 omarchy theme set。规范元数据可以覆盖该映射,alias 再增加额外入口。

为什么有两条路由路径

每次运行都扫描数百个文件会让最常用的 CLI 付出发现成本。router 因此分成快慢两条路径:

flowchart TD
    Args[argv] --> MetaNeed{help/list/check/alias?}
    MetaNeed -->|否| Prefix[最长前缀文件匹配]
    Prefix --> Found{找到可执行文件?}
    Found -->|是| Exec[exec 目标命令]
    Found -->|否| Registry[建立完整注册表]
    MetaNeed -->|是| Registry
    Registry --> Resolve[规范名/别名/部分路由解析]
    Resolve --> Exec

快路径:最长前缀

给定:

omarchy theme set catppuccin

router 从最长前缀开始尝试:

omarchy-theme-set-catppuccin
omarchy-theme-set
omarchy-theme

找到 omarchy-theme-set 后,把剩余的 catppuccin 作为参数传入。日常执行只做少量文件存在/可执行检查,不解析全库元数据。

慢路径:完整注册表

帮助、命令列表、alias、歧义解析和一致性检查需要知道所有命令。此时 router 扫描元数据,构造规范路由、别名与显示信息。

这种“双路径”设计把性能优化限定在不改变语义的地方:普通 filename route 快;复杂发现功能仍由统一注册表给出确定答案。

参数与帮助拦截

router 在 -- 之前发现 --help 时拦截,并展示目标命令的结构化帮助。-- 后的同名参数属于下游命令,不应被 router 吃掉。

若元数据声明必填参数而调用没有提供,router 展示帮助而不是启动一个注定失败的脚本。这只是一层可用性防线;真正的命令仍应校验参数,因为它也可能被直接执行。

exec 是一个重要细节

最终 dispatch 使用 exec 替换 router 进程,而不是 fork 后等待:

  • 调用者收到的退出码就是目标命令退出码;
  • SIGINT/SIGTERM 直接送到真实命令;
  • process tree 中没有无意义的 shell wrapper;
  • 需要前台终端和 sudo 的程序行为更自然。
sequenceDiagram
    participant T as 终端/systemd/菜单
    participant R as bin/omarchy
    participant C as omarchy-theme-set
    T->>R: omarchy theme set nord
    R->>R: fast resolve
    R->>C: exec ... nord
    Note over R,C: PID/信号/退出状态直接交接
    C-->>T: exit status

帮助本身也是可检查的接口

omarchy commands 可输出人读格式、JSON 和 Markdown,也能运行 --check。检查覆盖:

  • 路由或 alias 是否冲突;
  • 文件是否可执行;
  • 摘要与关键元数据是否缺失;
  • 声明的路由是否能解析到唯一目标。

这让 CLI 目录成为一个可以在 CI 中验证的数据模型,而不是依赖人工发现的文档漂移。

规模与分组

固定快照有 432 个 omarchy-* 命名文件,其中 430 个具有 executable bit,因而被 router 注册:361 条常规可见、69 条隐藏、84 条声明 sudo,分布在 72 个组。两个非可执行文件 omarchy-remove-service-dropbox 与 omarchy-remove-service-tailscale 不会被 router 发现;它们也解释了“按文件名计数”和“按真实命令计数”的差异。最大组包括 install、theme、hw、hyprland、remove、launch 和 update。

隐藏不等于私有或不安全,只表示不希望污染日常发现界面。内部 helper、兼容入口或机器调用命令仍可以通过完整路径使用。

新增命令的最小契约

  1. 在 bin/ 新建可执行的 omarchy-* 文件;
  2. 在前 80 行给出准确摘要与必要元数据;
  3. 参数校验仍写在命令自身;
  4. 运行 omarchy commands --check;
  5. 为路由、关键副作用或输出添加 CLI 测试。

文件名仍是 API

即使元数据可覆盖规范路由,快路径依赖文件名。随意重命名可能改变启动性能、直接调用与兼容性;需要保留旧入口时应明确使用 alias 或 wrapper。

边界案例

情况 处理
--help 在 -- 后 传给下游命令
多个前缀都存在 最长前缀胜出
alias 不能从文件名发现 回退完整 registry
route 冲突 commands --check 报错
文件存在但不可执行 不作为可 dispatch 命令
command 自身失败 exec 原样传播退出码

关键源码索引

所有命令的自动生成索引见 CLI 命令全集。下一章先厘清它们共同读写的状态:06 · 配置、状态与覆盖层。