Motrix 贡献者指南:开发环境搭建、分层架构边界与提交前验证门禁
本文以 Motrix 仓库的 CONTRIBUTING.md 为主体,完整还原参与该开源下载管理器的全流程:从开发环境搭建(Git、Node.js 22+、pnpm 版本锁定)、独立用户数据目录的 dev 运行时,到 renderer/main/server/core/shared 分层架构与传输协议约定,再到提交前必须通过的 check:boundaries、lint、类型检查等验证门禁与分支/提交/PR 规范。读完后你可以独立完成一次符合项目标准的贡献提交,并理解其架构约束在源码层面如何被自动检查强制落地。
选择正确的贡献渠道
Motrix 接受代码、测试、文档、翻译、issue 报告和设计反馈等多种形式的贡献。在提交之前,项目明确要求:
- 创建新报告前,先检索已打开和已关闭的 issues,避免重复;
- 可复现的 bug 和聚焦的功能请求使用仓库的 issue 表单;
- 支持类问题、使用指导以及尚未成熟的想法,应放到 GitHub Discussions 而非 issue;
- 重大功能、架构变更、新依赖和破坏性变更,需要先讨论再投入实现;
- 每个 issue 和 PR 只聚焦一个问题或一项能力。
参与本项目受 行为准则 约束;疑似安全漏洞必须按 安全策略 私下报告,严禁在公开的 issue、讨论或 PR 中披露。
准备开发环境
工具链与版本锁定
开发需要 Git、Node.js 22 或更高版本,以及 package.json 中 packageManager 字段声明的 pnpm 版本。查看 package.json 可知当前锁定为 pnpm@11.22.0,建议通过 corepack 或 pnpm self-update 对齐该版本,避免锁文件协议不一致导致的安装差异。
克隆、安装与启动
没有写权限时先 Fork 仓库,然后克隆自己的 fork 并安装依赖:
git clone https://github.com/<your-account>/Motrix.git
cd Motrix
pnpm install
pnpm start
pnpm start 并非直接拉起 Electron。查看 package.json 中的脚本链可以发现,start 前会执行 prestart,即 ensure:electron-runtime 加 scripts/ensure-native-abi.mjs(针对 electron 目标重建 better-sqlite3 等原生模块的 ABI),随后由 scripts/dev.mjs 接管整个开发运行时。从 dev.mjs 的头部注释可以看到它的职责:
- 先通过
pnpm run build:builtin把内置插件打包到dist/builtin-plugins(源码注释明确指出:缺失该目录时 bilibili/youtube 链接会退化为普通 HTTP 下载); - 在固定端口(默认 5173,可用
VITE_DEV_PORT覆盖)启动 renderer 的 Vite dev server; - 以 watch 模式构建 main 和 preload 两份 bundle,两者首次产出后才注入
VITE_DEV_SERVER_URL启动 Electron; - 后续 main/preload 重新构建后自动重启 Electron,renderer 侧热更新由 Vite HMR 完成,无需重启。
用户数据目录隔离:dev 不污染正式版数据
文档说明 pnpm start 默认使用独立的用户数据目录(通常是 Motrix-dev)。这一行为的确切实现在 src/main/platform/services.ts:
const isDev = !app.isPackaged
const userDataOverride = process.env.MOTRIX_USER_DATA
const defaultUserDataDir = app.getPath('userData')
const userDataDir =
userDataOverride ||
(isDev ? `${defaultUserDataDir}-dev` : defaultUserDataDir)
即:开发态下目录在默认 userData 路径后追加 -dev 后缀。若要指定其他目录,在运行 pnpm start 前设置 MOTRIX_USER_DATA 为绝对路径即可;src/main/platform/services.test.ts 中的测试证实了相关契约:
MOTRIX_USER_DATA在开发态优先于-dev默认值;- 空字符串值会被忽略,回落到默认行为;
- 打包后(非开发态)的
MOTRIX_USER_DATA同样生效; - 相对路径会在创建目录前被直接拒绝,抛出
MOTRIX_USER_DATA must be an absolute path。
此外,dev 模式还会把 extra 资源目录解析为项目根下的 extra/(如 extra/aria2.conf),打包后则来自 process.resourcesPath/extra。
分支策略与分支命名
- 开发分支必须基于最新的
main创建,PR 也以main为目标; - 遗留的
master分支只保留 v1 代码库且已冻结,不要向它提交任何新变更; - 分支名格式为
<type>/<snake_case_topic>_<YYYYMMDD>,有对应 issue 时可在主题前加 issue 编号,例如fix/1970_conduct_links_20260826。
理解分层架构
Motrix Turbo 在两个应用外壳(Electron 桌面应用与 Node/Web 服务器)背后共享一个宿主无关(host-neutral)的产品核心,同一套 renderer 代码在两种宿主中运行。这种分离保证产品行为可复用、Electron 关注点不会泄漏进服务端,并允许下载引擎在稳定适配器之后被替换。
各层职责与依赖边界
| 目录 | 职责 | 依赖边界 |
|---|---|---|
| src/renderer/ | 共享的 Electron/浏览器用户界面 | 只导入 @shared/ 和 renderer 本地模块;产品行为统一经 @renderer/lib/transport 访问 |
| src/preload/ | 狭窄的 Electron context bridge | 使用 Electron 和 src/shared/ 中的纯协议值/类型,不含产品行为 |
| src/main/ | Electron 外壳、IPC、窗口、菜单与系统集成 | 可组合 src/core/、src/shared/ 和 Electron 特定适配器 |
| src/server/ | Node/Docker 外壳、HTTP/WebSocket 端点与服务端平台集成 | 可组合 src/core/、src/shared/ 与服务端库;禁止导入 Electron 或 src/main/ |
| src/core/ | 宿主无关的应用服务、领域行为、引擎编排与插件策略 | 可用 src/shared/ 和宿主无关库;禁止导入任一应用外壳 |
| src/shared/ | 跨层 schema、协议常量、类型、locale 数据与纯工具 | 不得包含 I/O、定时器、网络访问、Electron API 或 Node 特定 API |
| packages/native-host/ | 供浏览器扩展配对接入的独立 Rust native-messaging 宿主 | 通过已发布的 bridge 契约通信,不依赖系统 Node.js 或 Electron |
| src/test-utils/ | 仅供测试的 fixtures 与 helpers | 严禁被生产代码导入 |
这套边界在仓库目录结构中可以一一对应:例如 src/server/ 下是 Fastify 路由与 src/server/http/、src/server/bridge/ 等服务端实现,而 src/core/ 下则是 download、engine、plugin、session 等宿主无关领域模块。
传输与协议流
renderer 在两种宿主下使用同一套 command、query、event 契约:
Electron: renderer -> ElectronTransport -> preload -> main IPC -> core
Browser: renderer -> HttpWsTransport -> server RPC/events -> core
从源码结构看,这个契约确实被物理落实:
- 传输层实现在 src/renderer/lib/transport/,
electron.ts与http-ws.ts分别对应两条链路,renderer 功能代码只应经由该模块访问产品行为,直接访问window.motrix仅限于 Electron 传输层和窄范围的平台适配器; - 通道名与 payload 契约集中在 src/shared/protocol/(
commands.ts、queries.ts、events.ts及bridge.ts),应使用Commands、Queries、Events及其Bridge*常量而非裸通道字符串。
引擎、Bridge 与插件边界
- 产品级代码面向 src/core/engine/engine-adapter.ts 中定义的
EngineAdapter接口。从源码可以看到,该接口刻意保持“引擎中立”:例如AddTorrentParams中注释说明 16 位十六进制 GID、1-based 文件索引、checkIntegrity语义等均由具体 aria2 适配器负责翻译。aria2 RPC 类型与转换逻辑留在具体 aria2 适配器内,而引擎生命周期由 src/core/engine/engine-supervisor.ts 中的EngineSupervisor独占管理。 - MDXP 协议基于 HTTP 与 WebSocket 上的 JSON-RPC 2.0。
@motrix/mdxp包(见 package.json 依赖@motrix/mdxp@^0.5.0)是 wire schema、方法常量、错误码与连接行为的唯一事实来源,不得在本地重复实现这些契约。 - 宿主无关的插件状态、策略、安装、能力与沙箱编排位于 src/core/plugin/;Electron 与 Node/Docker 的接线分别在 src/main/plugin/ 和 src/server/plugin/。
- 插件 guest 代码在独立的 QuickJS worker 中运行(对应
quickjs-emscripten依赖),只能通过类型化能力桥(typed capability bridge)触达宿主行为;新增宿主特定能力时,必须在两个能力宿主中都实现并测试。
边界检查的自动化落地
文档要求:任何导入或层职责变化时都运行 pnpm run check:boundaries。该脚本对应 scripts/check-boundaries.mjs,其规则表(L4-L52)正是上述架构边界的机械化表达,例如:
core must not import electron:src/core/内禁止from 'electron';core must not import fastify:src/core/内禁止 fastify 导入;shared must not use Node-specific APIs or globals:src/shared/内禁止node:导入、动态import('node:...')、process.与NodeJS.命名空间;renderer must not import core or main:src/renderer/内禁止直接导入 core/main 层;server must not import electron、server must not import src/main。
脚本通过 grep -rnE 逐条检查,支持按文件白名单豁免,任一条失败即以非零码退出。文档同时提醒:自动化检查只是基线,不能替代对依赖方向的人工审查。
遵循实现规范
代码与文件
- 代码、注释、标识符、文件名、commit message 与 PR 标题一律使用英文;
- JavaScript/TypeScript/TSX/样式文件使用
kebab-case命名(与仓库现状一致,如 engine-supervisor.ts、http-ws.ts); - 类型专用导入使用
import type,Node.js 内建模块使用node:前缀; - 优先使用已配置的 alias 而非深层相对导入,但需确认该 alias 在目标运行时可用;
- 行为变更必须伴随新增或更新测试;生产代码不得依赖测试 helper 或生成的构建产物。
用户可见文本与国际化
- 所有用户可见的应用与运维文本必须走既有 i18next 资源(仓库依赖
i18next与react-i18next),禁止硬编码界面字符串; - 新增或变更翻译 key 时,必须更新每一个已注册 locale,且各 locale 的占位符集合必须完全一致。从 src/shared/locales/ 可见当前注册的 locale 为
en-US.json、zh-CN.json与zh-TW.json三个; - 编辑英文/简体中文文档对中的一份时,同一变更中必须同步另一份,保持标题、命令、路径与示例对齐,同时允许各版本使用地道表达;
- 禁止提交凭据、私有 URL、个人路径、私有计划、本地生成的状态或无关变更。
提交信息
使用 Conventional Commits 格式:
<type>(<optional-scope>): <imperative summary>
允许的 type 为 feat、fix、refactor、perf、test、docs、chore、ci、style。summary 用小写开头、结尾不加句号、控制在 72 字符以内;动机不明显时补充 body,适用时添加 BREAKING CHANGE: footer。
验证门禁
每次提交前必须运行以下三项强制门禁:
pnpm run check:boundaries
pnpm run lint
pnpm exec tsc --noEmit
其中 lint 对应 package.json 的 biome check .(配套 lint:fix、format 脚本),test 对应 vitest run,test:e2e 对应 playwright test。
然后按变更类型运行匹配的检查:
- 行为或逻辑变更:运行聚焦的 Vitest 测试;跨切面大范围改动运行
pnpm test; - 覆盖浏览器或 Electron 用户流程:
pnpm test:e2e; - locale 资源或国际化行为:
pnpm run check:i18n(实现为 scripts/check-i18n.mjs); - 新增或重命名文件:
pnpm run check:file-names(对应 scripts/check-file-names.mjs); - 插件 manifest 契约:
pnpm run check:schema-parity; - 依赖、打包资产或 license 元数据:
pnpm run check:third-party-notices; - native-host Rust 代码:运行下面一组 cargo 命令。
native-host 的验证命令(针对 packages/native-host/Cargo.toml):
cargo fmt --manifest-path packages/native-host/Cargo.toml --all -- --check
cargo clippy --manifest-path packages/native-host/Cargo.toml --all-targets --locked -- -D warnings
cargo test --manifest-path packages/native-host/Cargo.toml --locked --all-targets
-D warnings 表示 clippy 警告即失败,--locked 保证不漂移 Cargo.lock。最后,审查最终 diff、运行 git diff --check,并在 PR 中如实记录执行过的命令与结果;不得压制失败或丢弃命令退出码。
提交 Pull Request
- 目标分支为
main,关联相关 issue,同时说明问题本身与所选方案; - 完整填写 PR 模板,包含确切的验证命令、环境与结果;
- 可见界面变更必须附截图或录屏;
- 生成文件与依赖变更严格限制在 PR 所需范围内;
- 以追加 commit 的方式回应 review 意见;维护者合并时通常会对 feature PR 做 squash。
许可证与第三方声明
贡献以仓库的 MIT License 被接受;第三方资产可能有不同条款,记录在 THIRD_PARTY_NOTICES.md 中(对应 THIRD_PARTY_LICENSES/ 下维护的各组件许可文本)。涉及依赖或许可元数据变更时,记得运行 pnpm run check:third-party-notices 门禁保持其同步。
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 StartedRust0624
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