Bruno 开源 API 客户端的本地开发环境搭建与开源贡献指南(基于德语贡献文档)
Bruno 是一款开源的 API 探索与测试 IDE(Postman / Insomnia 的轻量级替代品),其官方仓库以 npm workspaces 组织的 monorepo 形式维护全部代码。本文以仓库中的德语贡献指南 docs/contributing/contributing_de.md 为核心骨架,完整覆盖技术栈、Node 环境要求、依赖安装、React 前端与 Electron 桌面端的双进程开发启动流程、常见错误排查、测试命令与 Pull Request 提交流程,并结合当前仓库源码逐项佐证。读完本文,你将能够在一台干净的机器上把 Bruno 跑起来、修改代码并规范地向社区提交贡献。
说明:文中所有文件路径均以仓库根目录为起点,便于直接查阅对应源码。
Bruno 项目是什么
Bruno 是一款面向 API 开发者的开源桌面应用(仓库自述为 "Opensource IDE For Exploring and Testing API's",轻量级 Postman / Insomnia 替代方案)。与绝大多数在线同步的 API 工具不同,Bruno 强调"数据留在本地":它以桌面应用形态运行,直接在文件系统上读写请求集合,从而天然支持 Git 版本管理。开发者不必再依赖云账号,也可以让整个集合文件夹直接进入 Git 仓库。
仓库采用 monorepo 结构,核心两大运行载体分别是 React 渲染层(负责 UI 与交互)与 Electron 主进程/外壳(负责桌面窗口与本地文件能力)。德语贡献文档中提到的技术栈细节是理解整套工程的起点。
Bruno 的技术栈与关键依赖
德语版贡献指南明确给出了当前工程依赖的核心技术:
- 桌面外壳:Electron(让"本地集合"成为可能)
- 前端渲染:React(配合构建与开发服务器工具链)
- CSS:Tailwind
- 代码编辑器:CodeMirror
- 状态管理:Redux
- 图标:Tabler Icons
- 表单:Formik
- Schema 校验:Yup
- 请求客户端:axios
- 文件系统监听:chokidar
以上描述都能在当前仓库源码中得到验证:例如 packages/bruno-app/package.json 的 dependencies 中可看到 @reduxjs/toolkit、codemirror、formik、@tabler/icons、yup、i18next、react 19 等依赖;packages/bruno-electron/package.json 中则包含 electron ~37.6.1、axios 1.18.0、chokidar、express、simple-git 等桌面端与本地集合管理所需依赖。
需要留意的一个版本差异:德语文档与简体中文版 docs/contributing/contributing_cn.md 都提到 Web 层基于 "Next.js" 构建,但对照当前仓库实际脚本(packages/bruno-app/package.json 中 dev 为 rsbuild dev),当前前端渲染层已改用 React + rsbuild(仓库根目录 contributing.md 的英文版也注明 "We use React for the frontend and rsbuild for build and dev server")。这说明各语言翻译版贡献文档撰写时代略有差异,实际开发请以仓库内脚本与英文主文档为准。
Monorepo 与 npm workspaces 布局
德语文档强调项目使用 npm workspaces(多工作区)。仓库根目录 package.json 中声明了 16 个工作区包,构建与测试大量依赖 workspace 机制在包之间调度。其中与"跑起来"直接相关的有:
| 工作区目录 | 包职责(从目录结构与 package.json 归纳) |
|---|---|
| packages/bruno-app | React 渲染层应用(UI、编辑器、各面板),开发/构建均基于 rsbuild |
| packages/bruno-electron | Electron 桌面外壳:主进程、IPC、本地集合、代理、模拟服务等 |
| packages/bruno-cli | 命令行版 Bruno(bru),支持无界面运行集合 |
| packages/bruno-common | 前后端共享的公共逻辑(运行时、schema 校验、codegen 等) |
| packages/bruno-schema | 集合/环境/请求等对象的 Yup 数据模型定义 |
| packages/bruno-schema-types | 与 schema 对应的 TypeScript 类型 |
| packages/bruno-query | 集合查询索引逻辑 |
| packages/bruno-js | 脚本沙箱(req/res 对象、测试断言等执行环境) |
| packages/bruno-lang | .bru 语言解析器 |
| packages/bruno-converters | Postman / Insomnia / OpenAPI / WSDL 等格式转换器 |
| packages/bruno-graphql-docs | GraphQL 文档浏览器 |
| packages/bruno-requests | 请求发送、鉴权、WebSocket 等请求层实现 |
| packages/bruno-filestore | 集合在文件系统中的存储、索引格式 |
| packages/bruno-sqlite | Web/Node 侧的 SQLite 数据层 |
| packages/bruno-toml | TOML 解析工具 |
| packages/bruno-tests | 各类集成测试用例与脚本库 |
这种布局意味着:开发时通常需要先在 bruno-app 等包内完成代码修改,再将编译产物提供给 Electron 主进程加载。
环境要求:Node 与 npm
德语文档列出的硬性前提是 Node v22.x 或最新 LTS,以及 npm 8.x。仓库在根目录维护了 .nvmrc 文件(当前内容为 v22.12.0),因此使用 nvm 管理 Node 版本时,只需在仓库根目录执行:
nvm use
该命令会读取 .nvmrc 并自动切换到你需要的 Node v22 环境,避免因版本过新/过旧导致的构建或运行时兼容问题。
安装依赖:为什么要用 --legacy-peer-deps
德语文档给出的第一步是安装依赖:
npm i --legacy-peer-deps
--legacy-peer-deps 的作用是忽略 npm 的 peerDependencies 自动解析规则(改用旧版 npm 的宽松处理),绕过某些第三方库 peer 依赖版本冲突导致的安装失败。这一点与仓库根 package.json 中大量 overrides 字段(例如将 axios 强制覆盖为 1.18.0、tar 为 7.5.22 等)相互印证——Bruno 依赖链很长,出于安全与兼容考虑做了大量版本锁定,开发者日常安装请务必保留 --legacy-peer-deps 参数。
构建依赖包子产物
Bruno 的多个 workspace 包之间通过编译产物互相引用。直接运行桌面端前,需要先把相关包构建出来。德语文档给出的最小构建步骤是:
# 构建 graphql 文档组件
npm run build:graphql-docs
# 构建 bruno 查询索引包
npm run build:bruno-query
对照英文版 contributing.md 与 scripts/setup.js,完整的依赖包构建清单还包括:
npm run build:bruno-common
npm run build:bruno-converters
npm run build:bruno-requests
npm run build:schema-types
npm run build:bruno-filestore
npm run build:bruno-sqlite
# 打包 JS 沙箱运行库
npm run sandbox:bundle-libraries --workspace=packages/bruno-js
这些构建脚本的映射都定义在根 package.json 的 scripts 区(如 "build:bruno-query": "npm run build --workspace=packages/bruno-query")。如果你希望一条命令完成全部工作,仓库还提供了自动化脚本:
npm run setup
它由 scripts/setup.js 实现,会依次执行:清理各子目录 node_modules → npm i --legacy-peer-deps 安装依赖 → 按操作系统强制安装平台相关二进制依赖(scripts/setup.js 中根据 darwin/win32/linux 分别安装对应架构的 @lydell/node-pty-*)→ 依次构建上述所有前置包 → 打包 bruno-js 沙箱库。
启动本地开发环境(双进程架构)
德语文档明确指出:Bruno 以桌面应用形态开发,需要在两个终端分别启动 React 层与 Electron 层。
先确认 node 版本并装好依赖(上文已述),然后构建前置产物,最后分别运行:
# 终端 1:启动 React(rsbuild)开发服务器
npm run dev:web
# 终端 2:启动 Electron 桌面壳
npm run dev:electron
从根 package.json 的脚本定义可以看出 dev:web 实际是 npm run dev --workspace=packages/bruno-app,而 packages/bruno-app 的 dev 脚本为 rsbuild dev,即启动 rsbuild 开发服务器托管 UI;dev:electron 则进入 packages/bruno-electron 执行 electron .,主入口为 packages/bruno-electron/src/index.js。
如果不想手动开两个终端,仓库还提供了一条并发启动命令:
npm run dev
该命令由 scripts/dev.js 实现:它会以子进程方式启动 rsbuild 开发服务器,并通过正则 Local:\s+http://localhost:(\d+) 从 rsbuild 输出中自动探测实际端口,然后把端口号通过 BRUNO_DEV_PORT 环境变量传给 Electron 子进程(见 scripts/dev.js)。也就是说,即使 3000 端口被占用导致 rsbuild 自动换端口,Electron 也能正确连上 Web 开发服务器。此外仓库还提供了带热更新的 dev:watch(npm run dev:watch,见根 package.json,实现位于 scripts/dev-hot-reload.js),适合需要跨包联动热重载的场景。
自定义 Electron 的 userData 目录(开发调试技巧)
英文版 contributing.md 补充了一个非常实用的开发期技巧,同样得到源码支持:在 packages/bruno-electron/src/index.js 中,当处于开发模式且设置了 ELECTRON_USER_DATA_PATH 环境变量时,应用会调用 app.setPath('userData', ...) 重定向 Electron 的用户数据目录。利用这一点,你可以让一次本地开发会话使用一个全新的、可随意清理的沙盒数据目录,避免污染日常使用的配置:
ELECTRON_USER_DATA_PATH=$(realpath ~/Desktop/bruno-test) npm run dev:electron
运行后桌面会生成 bruno-test 目录,并作为本次会话的 userData 使用。Bruno 的许多本地状态(例如 packages/bruno-electron/src/ipc/sqlite.js 中的 bruno.db、packages/bruno-electron/src/services/mount/file-index.js 中的挂载快照索引)都存放在 userData 下,通过该技巧可以隔离开发数据,也方便排查与"干净状态"相关的 bug。
Troubleshooting:Unsupported platform 错误
德语文档专门提醒了一个高频坑:执行 npm install 时可能遇到 Unsupported platform 错误。这类错误通常与平台相关的可选依赖(optional dependency,如上面提到的 @lydell/node-pty-*)或 peer 依赖解析冲突有关。官方给出的修复方式是从子目录中彻底删除 node_modules 与 package-lock.json 后重新安装:
# 删除所有子目录下的 node_modules
find ./ -type d -name "node_modules" -print0 | while read -d $'\0' dir; do
rm -rf "$dir"
done
# 删除所有子目录下的 package-lock.json
find . -type f -name "package-lock.json" -delete
清理完成后,回到仓库根目录再次执行:
npm i --legacy-peer-deps
如果仍然遇到平台相关依赖问题,可以运行仓库内置的 npm run setup,其内部会按你的操作系统强制安装对应架构的二进制依赖(参见 scripts/setup.js 中 forceInstallPlatformDeps 实现)。
如何运行测试
德语文档给出了两个层级的测试命令:先针对单个工作区,再全量运行所有工作区测试。
针对 bruno-schema(集合/环境/请求模型包):
npm test --workspace=packages/bruno-schema
该包的测试位于源码目录内的 *.spec.js 文件中(例如 packages/bruno-schema/src/collections/requestSchema.spec.js、packages/bruno-schema/src/collections/environmentSchema.spec.js 等),它们验证 Yup schema 对 .bru 集合对象的约束行为,是理解"集合/环境/请求模型"底层定义最直接的入口。
对仓库内所有声明了 test 脚本的工作区执行测试:
npm test --workspaces --if-present
--if-present 会跳过那些没有定义 test 脚本的工作区(例如 bruno-schema 的 package.json 中 "test": "jest" 才会被调用),避免全量运行时因缺失脚本而报错。如果只想针对某一个包迭代,可以参照根 package.json 及英文版 contributing.md 中的方式逐个运行,例如 bruno-app、bruno-electron、bruno-lang、bruno-toml 等均有独立的 jest 测试入口。
仓库还维护了一套基于 Playwright 的端到端测试(脚本位于根 package.json 的 test:e2e 等,配置见 playwright.config.ts 与 tests/ 目录下大量 .spec.ts),适合在完成 UI 改动后做回归验证,不过它属于进阶内容,第一次贡献时可以先用上文的工作区单元测试验证核心逻辑。
提交 Pull Request 的约定
德语文档对协作规范做了三点明确要求,这也是评审者最在意的"提交卫生":
- 保持 PR 小而聚焦:一个 PR 只做一件事,便于 review、降低合入风险;
- 分支命名遵循格式:
feature/[feature name]:只包含某个新功能的改动。例如feature/dark-mode;bugfix/[bug name]:只包含针对某个 bug 的修复。例如bugfix/bug-1。
这些约定与仓库配套的工程化约束是一致的:根 package.json 中配置了 husky + nano-staged,会在提交前对暂存的 *.{js,ts,jsx} 文件自动执行 npm run lint:fix;仓库根目录还维护了 eslint.config.js 与 CODING_STANDARDS.md(编码规范),建议在提交前阅读并保持代码风格一致。
更多参考资源
- 主语言贡献指南(内容最完整、最新):contributing.md
- 简体中文翻译版:docs/contributing/contributing_cn.md(与德语版同属官方维护的翻译集,见 contributing.md 顶部的语言切换列表)
- 发布相关文档见 docs/publishing/(对应根目录 publishing.md)
- 项目主文档:readme.md
最后再提醒一句:德语文档中"技术栈为 Next.js"的表述属于翻译版写作时的旧信息,动手开发前请以根目录英文 contributing.md、各 package.json 中的实际脚本和 .nvmrc 中锁定的 Node v22.12.0 为准。依照本文的流程,你就可以在本地完成 Bruno 的搭建、修改与提交,参与到"让 Bruno 变得更好"的共建中来。
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 StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00