Hyprland AGENTS.md 深度解读:Hyprland 代码审查、编码风格与核心代码规范的完整指南
本文基于 Hyprland 仓库根目录的 AGENTS.md,系统讲解该项目面向 AI Agent 与人类贡献者制定的三层工程规范——代码审查准则(Review guidelines)、代码风格准则(Style guidelines)和核心代码准则(Core code guidelines)。读完本文,你将完整掌握 Hyprland 的 C++ 编码约定:clang-format 格式规则、C/S/I/m_ 命名体系、基于 hyprutils 的 UP<> 单例模式、rc/sc/cc 类型转换与测试覆盖要求,并能对照仓库中的真实源码(如 动画管理器)逐条验证这些规范的实际落地方式。
一、AGENTS.md 的定位:一份面向"Agent 与人类"的双用工程契约
AGENTS.md 位于仓库根目录,是 Hyprland 社区为代码评审(Code Review)过程定义的成文标准。它的目标读者既包括参与 PR 审查的人类维护者,也包括被接入仓库的 AI 编码 Agent——后者在执行修改、生成代码、发起评审时必须以该文档为准绳。文档由三大章节构成,层层递进:
- Review guidelines:审查者"看什么"——正确性、无回归、性能、API 稳定性、可读性;
- Style guidelines:代码"长什么样"——clang-format 格式、命名规范、include 规则等;
- Core code guidelines:代码"怎么组织"——设计模式、内存管理、类型转换、测试要求。
仓库当前版本见 VERSION(0.56.0),构建入口为 CMakeLists.txt。需要说明的是:AGENTS.md 本身不描述任何运行时功能,它约束的是开发过程,因此本文所有"实现事实"均以源码文件路径为准进行印证。
二、Review guidelines:审查者的六项检查清单
文档第一章节列出了审查时的优先级与必须标记的问题类型,完整继承如下:
| 审查关注点 | 具体含义(依据 AGENTS.md) |
|---|---|
| 正确性、无回归 | 优先级最高的综合标准,同时关注性能、API 稳定性、代码清晰度与可读性 |
| 性能敏感路径 | 必须标出明显的算法回退或慢路径(obvious algorithmic regressions or slow paths) |
| 测试覆盖 | 对变更或新增行为,只要测试框架有能力测,就应标记缺失的覆盖 |
| 配置变更 | 新增/移除配置项时,若作者未关联 wiki PR,应提醒其单独提交 wiki 文档 PR |
| 静默配置破坏 | 例如改变已有配置项的行为——明确不允许(This is not allowed) |
| 风格与核心规范 | 标记违反下方 Style / Core 准则的代码,并给出修复建议 |
其中两条规则值得展开:
- "静默配置破坏"是红线。Hyprland 是高度可配置的组合器,用户配置(
hyprland.conf)中的既有选项行为若被悄悄改变,属于破坏性变更,不允许通过。审查者必须在 PR 中显式拦截这类改动。 - 测试覆盖与仓库的双测试体系对应。文档要求"为 Unit(
tests/)或 Integration(hyprtester/)测试能测到的代码写测试"。仓库中确实存在两个测试体系:单元测试位于 tests/(按模块划分,如 tests/render/、tests/keybinds/、tests/helpers/ 等),集成测试位于 hyprtester/,其 CMakeLists.txt 定义了测试客户端(clients/下含 child-window、pointer-scroll、shortcut-inhibitor 等多个 Wayland 协议交互客户端)与测试主程序。
三、Style guidelines:从 clang-format 到命名规范
3.1 格式化基线:clang-format
文档要求"代码必须按照 .clang-format 进行 clang-format 格式化"。仓库根目录的 .clang-format 提供了可验证的格式基线,关键条目包括:
BasedOnStyle: LLVM
AccessModifierOffset: -2
BreakBeforeBraces: Attach
ColumnLimit: 180
IndentWidth: 4
PointerAlignment: Left
AllowShortBlocksOnASingleLine: true
SpaceAfterCStyleCast: false
几个与风格条款直接呼应的细节:BreakBeforeBraces: Attach 决定了大括号紧跟语句的排版;PointerAlignment: Left 即 UP<Foo> *ptr 写法的对齐依据;ColumnLimit: 180 说明 Hyprland 允许较长的单行,配合下文"空函数体内保留 ;"等条款共同维持 diff 稳定。静态分析层面则由 .clang-tidy 约束(Core guidelines 中明确"不得违反 clang-tidy")。
3.2 逐条风格规则解析
以下规则完整继承自 AGENTS.md 的 Style guidelines 章节,并结合仓库实例说明:
(1)单行 if / else 不加大括号,且仅限 if / else。
if (mgr())
mgr()->frameTick();
真实示例见 Animation::mgr 的 tick 回调——单行函数体、单行 if 均无大括号。注意该规则不适用于 do / while 等其他语句,这是文档特意限定的边界。
(2)头文件中尽量避免函数体(Avoid function bodies in headers)。 目的是控制头文件依赖面、加快编译。观察 src/animation/AnimationManager.hpp,类声明中方法均只声明不定义(唯一的内联模板 createAnimation 属于模板特化场景,因为模板必须在头文件中展开,这属于合理的例外)。
(3)源文件中避免用匿名 namespace {} 包裹局部函数,优先使用 static。 仓库中大量采用 static 局部函数,例如 AnimationManager.cpp 中的 wlTick 与 updateVariable 均以 static 修饰,符合该条款。
(4)优先使用卫语句(guard clauses): if (!cond) continue;。提前退出、减少嵌套深度是文档鼓励的控制流写法。
(5)头文件中优先前向声明(forward declaration)而非完整 include。 头文件包含越少,编译依赖图越小;能从源码结构看,Hyprland 的头文件普遍只包含真正需要的最小依赖集。
(6)大括号列表末尾保留逗号(trailing comma)。 这是为了后续增删元素时 diff 更干净,是纯工程性约定。
(7)空函数体内保留一个 ;。 同样服务于格式化与 diff 稳定性。
3.3 命名约定:C / S / I / m_ 四件套
文档给出了四条硬性的类型命名规则,仓库中可以逐一对应找到实例:
| 约定 | 规则 | 仓库实证 |
|---|---|---|
| 类 | CMyClass |
CHyprAnimationManager,见 AnimationManager.hpp |
| 结构体 | SMyStruct |
SAnimationPropertyConfig、SAnimationContext 等 S 前缀结构体遍布 src/helpers/AnimatedVariable.hpp |
| 接口 | IMyInterface |
IConfigManager,见 src/config/ConfigManager.hpp |
| 类(非结构体)成员变量 | m_variable |
m_animationTimer,见 AnimationManager.cpp |
这一命名体系使读者仅凭类型名前缀即可判断其种类(类/结构体/接口),是大型 C++ 项目降低认知成本的有效手段。审查时若发现 Foo(无 C 前缀的类)或 data(无 m_ 前缀的成员变量),即属风格违规。
3.4 include 规则:src/ 头文件内禁用绝对路径式 include
文档规定:不要从 src/ 写绝对式 include,例如应使用 #include "../a/b.hpp" 而非 #include "a/b.hpp"(协议头文件除外)。仓库源码严格遵守这一点,AnimationManager.hpp 的头部即为典型:
#include "../defines.hpp"
#include "../helpers/AnimatedVariable.hpp"
#include "../desktop/DesktopTypes.hpp"
#include "../helpers/time/Timer.hpp"
#include "../managers/eventLoop/EventLoopTimer.hpp"
全部使用相对路径回溯,而非依赖 include 搜索路径的"绝对"写法。协议(Wayland protocol)头文件由于由生成工具统一管理,不受此规则约束。
四、Core code guidelines:设计、内存与测试的底线
4.1 好的工程实践
文档要求遵循常规软件工程准则,具体列出:
- 避免复杂类/函数,倾向单一职责(SRP);
- 在合适处使用 hyprutils 的 Signals 实现观察者模式(事件解耦);
- 在合适处使用经典 OOP 模式:Strategy、Singleton、Proxy 等;
- 警惕典型坏味道:feature envy(依恋情结)、违反 LSP 等;
- 在合适处使用模板与继承简化代码。
4.2 单例模式:UP<CClass>& myClass();
文档给出了 Hyprland 单例的标准实现范式——在命名空间内声明 UP<CClass>& myClass();,在源文件中用静态局部智能指针实现并返回。仓库中该模式有严格一致的落地,例如 src/animation/AnimationManager.cpp:
UP<CHyprAnimationManager>& Animation::mgr() {
static UP<CHyprAnimationManager> p = makeUnique<CHyprAnimationManager>();
return p;
}
对应头文件 AnimationManager.hpp 中声明 UP<CHyprAnimationManager>& mgr();。同样的范式还见于 ConfigManager.cpp(static UP<IConfigManager> g_mgr;)以及 CActionState、CAnimationTreeController、CConfigWatcher、CMonitorRuleManager、CWorkspaceRuleManager、CExecutor 等多个管理器。这一写法的优点是:调用侧统一通过引用获取,生命周期由静态对象托管,同时避免了全局裸指针的初始化顺序问题(静态局部变量的 C++11 magic statics 保证线程安全的惰性初始化)。
4.3 绝对禁止项
文档用 "Do not, under any circumstance" 表述了两条硬性禁令:
- 禁止
using namespace std;; - 禁止留下未初始化的原始类型(int、float 等)。
后者在数值计算密集的组合器代码中尤其重要——未初始化变量会导致不可复现的行为差异。
4.4 尽量避免:C 库、malloc、C 风格指针与 C 风格转换
文档规定:
- 尽量使用 C++ STL 而非 C 标准库;
- 避免
malloc/free; - C 风格指针应避免,改用 hyprutils 的
SP<>、WP<>、UP<>——分别对应 Shared、Weak、Unique 指针。C 风格指针仅在"不可能出错"的极个别场景(如 destroy 回调函数)中允许; - C 风格转换应避免,改用 hyprutils 的
rc<>、sc<>、cc<>——它们是等价 C++ 转换的简写。
仓库源码印证了这套指针体系的实际使用:前文 AnimationManager.cpp 中的 wlTick 回调参数即为 SP<CEventLoopTimer> self,而管理器本体由 UP<> 托管。审查时若看到裸 new/delete 或 static_cast 长写法混入新功能代码,即可对照本条款给出修改建议。
4.5 避免:违反 clang-tidy 与手动 C 风格清理
两条"避免"条款:
- 不得违反 .clang-tidy 的检查项;
- 手动成对的 C 风格申请/释放(
some_c_thing_new()/some_c_thing_free())应当用 RAII 包装,避免在多处散落手工free调用。
4.6 测试要求:tests/ 与 hyprtester/ 双轨覆盖
文档最后一句是明确的测试义务:"Make sure to write tests for code which our Unit (tests/) 或 Integration (hyprtester/) tests can test." 结合仓库结构:
- 单元测试 tests/:覆盖纯逻辑模块,如
config/(配置解析、Lua 绑定)、helpers/(字节操作、颜色、数学变换、表达式)、keybinds/(Bind、Resolver、Registry)、render/(BlurUV、TransformerList)、state/(MonitorQueryCore 等核心状态查询); - 集成测试 hyprtester/:以真实 Wayland 客户端驱动组合器,
clients/目录包含 child-window、keyboard-modifiers、pointer-scroll、pointer-warp、shortcut-inhibitor 等协议级测试客户端,src/tests/下则按 main/clients/misc 组织测试主流程。
审查者据此可判断"该行为是否可测":能被上述任一框架覆盖的行为却没有测试,即应在 Review guidelines 第一条"缺失覆盖"项下被标记。
五、把规范落进工作流:一份可执行的审查对照表
综合三大章节,对 Hyprland 任意 PR 的审查可按以下顺序执行(全部条目均可追溯至 AGENTS.md):
- 正确性与回归:行为是否改变?是否存在静默的配置破坏(已有选项行为变更 → 直接拦截)?
- 配置项变更:新增/移除选项是否关联了独立的 wiki 文档 PR?
- 性能路径:帧循环、布局、渲染等热点路径是否有算法回退?
- 测试:新行为是否被 tests/ 或 hyprtester/ 覆盖?
- 风格:clang-format(对照 .clang-format)、单行 if/else 无大括号、
C/S/I/m_命名、src/头文件相对 include、头文件无函数体、static代替匿名 namespace。 - 核心实践:是否存在
using namespace std、未初始化原始类型、C 风格指针/转换(应换为SP/WP/UP与rc/sc/cc)、违反 .clang-tidy 的写法、未包装的 C 风格 new/free 对。
六、小结
AGENTS.md 用约 50 行文本完整定义了 Hyprland 的工程质量基线:以"正确性优先、禁止静默配置破坏"为核心的审查准则,以 clang-format + C/S/I/m_ 命名 + 相对 include 为骨架的风格准则,以及以 hyprutils 智能指针(SP/WP/UP)、rc/sc/cc 转换、UP<CClass>& 命名空间单例和双轨测试体系为底线的核心代码准则。仓库中的真实源码——如 src/animation/AnimationManager.cpp 的单例实现、src/animation/AnimationManager.hpp 的头文件组织方式——逐条印证了这些规范并非纸面约定,而是整个代码库统一执行的开发契约。无论是人类贡献者还是接入仓库的 AI Agent,遵守这份契约是保证 PR 通过审查的前提。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00