资讯详情 openGym 开发者指南:读懂这份 CLAUDE.md 里的仓库架构、开发命令与工程约定
📅 2026/10/9 5:14:43
后端前端移动开发MCP 服务【免费下载链接】openGymSelf-hosted gym body-weight tracker — plan routines, log workouts (supersets, warm-ups, cardio), see which muscles are trained, fatigued or detrained, import from FitNotes/Strong/Hevy, passkey login. Your data, your server.项目地址https://gitcode.com/GitHub_Trending/op/openGym点击查看免费下载CLAUDE.md 是 openGym 仓库为 Claude Codeclaude.ai/code编写的仓库级工作指引但它本身就是一页高质量的项目架构速览它说明了这个自托管self-hosted健身与体脂记录 PWA 由哪些模块组成、日常开发该跑哪些命令、前后端与 MCP 服务器各自的架构要点以及贡献代码前必须知道的硬性约定。读完本文并结合文中标注的源码路径你可以直接上手本地搭建、运行三套测试套件并理解 passkey 认证、原子写状态文件等关键实现背后的设计约束。一、项目定位一个两个容器 一个数据目录的自托管 PWACLAUDE.md 开篇给出了项目的完整定义openGym 是一个自托管的健身房与体重追踪 PWA部署形态是apiweb两个容器外加一个用户自有的./data文件夹——没有第三方账号、没有遥测telemetry。功能上支持 PasskeyWebAuthn登录、可安装为主屏幕应用并可选用 Capacitor 壳打包独立的 Android/iOS 版本。许可证为 AGPL-3.0-or-later见 api/package.json 与 frontend/package.json 中的license字段。从架构图源文件 docs/diagrams/architecture.mmd可以确认这个边界划分手机/浏览器端只与webnginx建立 HTTPS 连接web负责托管静态前端并把/api代理到apiapi是唯一读写./data的进程可选的 media 服务是一次性下载动作素材MCP 服务器则只读同一份数据目录。单源single origin不是架构偏好而是 passkey 的硬要求——详见后文。二、目录结构每个目录解决什么问题CLAUDE.md 的 Project layout 一节是整个仓库的地图原文如下本文在其基础上补充了验证过的文件级证据frontend/ React 19 Vite app (src/views, src/components, src/store, src/lib). Builds to static files. android/ ios/ are the Capacitor shells for the standalone mobile app (docs/MOBILE.md). api/ backend — server.js (Node, no framework), deps: simplewebauthn/server, web-push. coach/ is the optional AI coach; openapi.yaml documents every route. web/ multi-stage Dockerfile (builds frontend → nginx) nginx.conf.template (serves app, proxies /api). mcp/ optional MCP server — read-only stdio bridge exposing a users workouts/1RM/muscle balance to LLM clients (Claude Desktop, Cursor…). Not part of the Docker build; only runs when an LLM client spawns it. media/ exercise img/gif, gitignored, fetched at runtime by the media compose service. website/ static project site (plain HTML/CSS/JS), deployed separately. kubernetes/ example manifests (docs/SELF_HOSTING_KUBERNETES.md). docs/ guides indexed in docs/README.md (FAQ, SELF_HOSTING*, MOBILE, AI_COACH, DATA_IMPORTS, API); docs/dev/ holds feature design notes (SET_TYPES: drop sets/rest-pause, LIST_VIEW, COMBINE_ROUTINES).逐目录核对仓库可以补充几点实用细节frontend/核心代码在src/下的四个分区——views/每个屏幕一个文件Home、Workout、Plan、Library、Stats、History、Settings、Admin、Login、RoutineEdit 等、components/图表、弹窗、计时器等共享 UI、store/状态管理、lib/纯函数领域逻辑。android/与ios/是 Capacitor 原生壳配套文档是 docs/MOBILE.md。api/后端就是 api/server.js 这一个文件当前约 2460 行基于原生node:http无框架。api/openapi.yaml 是所有路由的 OpenAPI 规范coach/子目录是可选的 AI 教练模块内含 Anthropic/OpenAI/Gemini 等 provider 适配与 prompt 模板。web/多阶段 Dockerfile 构建前端并交给 nginxweb/nginx.conf.template 在容器启动时由环境变量渲染。mcp/可选 MCP 服务器mcp/package.json 描述其职责——让外部 LLM 从你的自托管数据中读取训练计划、训练记录、体重日志、估算 1RM 与肌肉平衡只读、stdio 传输、无需额外容器。kubernetes/与 docs/SELF_HOSTING_KUBERNETES.md 对应的示例清单。docs/文档索引在 docs/README.md其中明确把 CLAUDE.md 定位为你想一页看懂架构时的入口docs/dev/存放与代码并置的功能设计笔记。三、日常开发命令完整继承并逐条说明CLAUDE.md 给出的命令区块如下可直接复制执行# 本地全栈api web media可用预构建镜像或从源码构建 cp .env.example .env docker compose up -d --build # 前端开发服务器热重载/api 代理到 :3000 cd frontend npm install npm run dev # 前端测试训练逻辑progression、1RM、session 回读 cd frontend npm test # vitest run cd frontend npm run test:watch npx vitest run src/lib/progression.test.js # 只跑单个文件 npx vitest run -t some test name # 按测试名只跑单个测试 # API 与 MCP 服务器测试 cd api npm test cd mcp npm test # 生产构建 cd frontend npm run build cd frontend npm run build:mobile # 额外执行 cap sync素材指向 CDN 数据集结合三个 package.json 可以精确说明这些命令背后的实际行为三套独立测试前端npm test即vitest run测试框架为 vitest happy-dom/linkedom见 frontend/package.json 的 devDependenciesAPI 的npm test是node --test test/*.test.js即 Node 内置 test runner零额外依赖api/package.jsonMCP 用vitest run。前端 dev 服务器npm run dev即vitefrontend/vite.config.js 配置了/api→:3000的代理因此本地只需同时把 API 跑在 3000 端口cd api npm start。build:mobile的差异该脚本以VITE_MOBILE1环境变量构建并把图片/GIF 基地址指向 jsDelivr 上的 exercises-dataset CDN而非本地 media 卷随后执行cap sync同步 Capacitor 壳——这正是 CLAUDE.md 注释points media at the CDN dataset的来源。风格约定CLAUDE.md 特别指出仓库没有配置 linter/formatter无 ESLint/Prettier 配置也没有 TypeScript——贡献代码时只能靠人工对齐现有风格。四、CI 与发布流水线GitHub 做门禁GitLab 做构建CLAUDE.md 明确了两段式发布流程仓库内可直接验证对应文件存在GitHub 是项目主家.github/workflows/mirror.yml 把main分支与v*标签推送到 GitLab 镜像。PR 门禁由 .github/workflows/test.yml 在Node 22上执行——与 web/Dockerfile / api/Dockerfile 使用的node:22-alpine镜像版本保持一致。门禁内容包括前端、api、MCP 三套测试、locale 检查以及构建并启动两个 api 镜像目标。GitLab CI.gitlab-ci.yml负责构建发布物签名 Android APK、多架构镜像与 SBOM。一条强约束值得记住绝不在 GitLab 上直接 push 或 merge镜像是 fast-forward only 的——所有变更必须走 GitHub 侧。五、前端架构一个 Zustand store 一批必须带单测的纯函数状态管理useStore.js与gym_state_v1CLAUDE.md 的前端部分指出 frontend/src/store/useStore.js 是唯一的 Zustand store持有全部客户端应用状态S其持久化链路在源码中可以逐环验证localStorage 持久化store 的持久化键为gym_state_v1useStore.js中const KEY gym_state_v1第 26 行写入时localStorage.setItem(KEY, JSON.stringify(S))。登录后防抖推送到服务器通过pushState而 frontend/src/lib/api.js 是唯一与后端通信的地方fetch 封装、会话 cookie 流程。Capacitor 移动端额外镜像到文件经 frontend/src/lib/mobile.js 的nativeSave因为 WebView 存储可能被系统清掉。UI 态与数据态分离frontend/src/store/useUI.js 单独持有瞬态 UI 状态模态框、当前打开的 sheet 等不进入持久化数据。lib/领域逻辑所在也是单测红线所在CLAUDE.md 强调lib/是纯的、无框架依赖的助手函数区每个文件旁配一个同目录*.test.js。它点名的核心模块与职责文件职责据 CLAUDE.md 与 CONTRIBUTING.mdfrontend/src/lib/progression.js渐进超负荷规则引擎线性、Greyskull LP、double progression、time-based。各规则实现统一的 policy 接口新增规则在此接入frontend/src/lib/onerm.js由已记录组次估算 1RMfrontend/src/lib/finish-workout.js把一次完成的训练 session 归约回状态重量推进、PR 记录等frontend/src/lib/recovery.js / frontend/src/lib/recovery-view.js疲劳/肌肉恢复模型哪些肌肉被练到、疲劳或退化了这一卖点的地基frontend/src/lib/workout-model.js、frontend/src/lib/supersetFlow.js训练中会话状态机含超级组supersetsfrontend/src/lib/exercises.js / frontend/src/lib/exercises-data.js动作库CLAUDE.md 写为 1,324 个内置动作 用户自定义frontend/src/lib/api.js唯一与后端通信的模块为什么必须带单测CLAUDE.md 引用了 CONTRIBUTING.md 的原文精神任何决定你下次练多重或回读一次已记录 session的逻辑都必须是lib/里的纯函数旁边必须有单测——这类规则很难靠肉眼点击验证而渐进超负荷引擎已经出过两次只有测试才能抓住的 bug。仓库中lib/下确实呈现一实现一测试的成对结构如progression.test.js、onerm.test.js、finish-workout.test.jsviews/与store/下亦有大量同名测试文件佐证这一约定是全局执行的。视图、组件与多语言views/一个文件一个屏幕路由由App.jsx经react-router-dom分发当前 frontend/package.json 中为 react-router-dom 7.x、React 19.2.x、Zustand 5.x。components/共享 UI图表、弹窗、计时器、BodyMap、Heatmap 等instr/存放各语言的动作说明文本locales/是 i18n 字符串目录由 frontend/src/lib/i18n.js / frontend/src/lib/i18n-core.js 消费。移动端门控capacitor/*把同一个 web 构建包进原生壳lib/mobile.js用一个MOBILE标志位门控原生专属行为文件持久化、本地通知、wake lock。六、API 架构单文件node:httproutes对象 原子写CLAUDE.md 对 api/server.js 的描述与源码完全对应以下是逐项展开路由一张以METHOD /path为键的普通表后端无框架请求经由一个routes对象分发键形如GET /api/health按req.method url.pathname匹配。新增端点就是加一个键。源码中const routes {出现在 api/server.js#L1732分发逻辑在 api/server.js#L2411-L2417let key req.method url.pathname; // 唯一带路径参数的路由 /api/media/{hash} 在此映射到模板键 const mm /^\/api\/media\/([0-9a-f]{64})$/.exec(url.pathname); if (mm) { key req.method /api/media/{hash}; req.mediaHash mm[1]; } const handler routes[key]; if (!handler) return json(res, 404, { error: not found });这个纯表查找 一个正则特例的设计让 CSRF 校验csrfOk与 404 兜底都能看到路由的统一名字所有路由的对外契约以 api/openapi.yaml 为准。状态两个扁平 JSON 文件 原子写状态就是DATA_DIRapi/server.js第 36 行process.env.DATA_DIR || /data下两个扁平 JSON 文件db.json用户、凭据passkey credential material、订阅、邀请码——因此saveDb()以0o600权限写入api/server.js#L104-L106 的注释解释了为何权限在文件而非目录上state-uid.json每个用户的训练数据。写入统一走atomicWrite——先写临时文件再 rename的原子模式api/server.js#L107-L111function atomicWrite(file, content, mode) { const tmp file .tmp; fs.writeFileSync(tmp, content, mode ? { mode } : undefined); fs.renameSync(tmp, file); }认证WebAuthn passkey HMAC 签名 cookie无 JWT认证是simplewebauthn/server的 passkey 流程加上一个签名会话 cookie——用首次启动时生成于DATA_DIR/secret的密钥做 HMAC 签名不依赖任何 JWT/session-store 库。POST /api/register/options中residentKey: requiredDiscoverable Credential等细节见 api/server.js#L1782-L1802。环境变量门控的可选项与审计日志CLAUDE.md 列出的一组由环境变量开关的能力从源码结构看均集中在 server.js 的顶部配置区ADMIN_UIDS管理面板、INVITE_ONLY注册需邀请码POST /api/register/options中的邀请码校验可见于 api/server.js#L1787-L1791、ALLOW_GUEST纯客户端游客模式完全不触达服务器另有滚动保留的data/audit.logJSONL记录登录/管理事件以及web-pushVAPID 密钥自动生成到data/vapid.json驱动的休息计时结束与每日提醒通知。关于依赖数量的一处勘误性说明CLAUDE.md 与 CONTRIBUTING 均将API 侧依赖极少作为硬性约束表述就当前版本而言api/package.json 列出simplewebauthn/server、undici、web-push三个核心依赖及一个可选依赖anthropic-ai/claude-agent-sdkAI 教练用。无论口径如何新增依赖需要充分理由a hard sell这条约定不变。七、MCP 服务器只读 stdio 桥与 API 共享同一份数据mcp/src 是基于modelcontextprotocol/sdk的只读 stdio MCP 桥LLM 客户端Claude Desktop、Cursor 等可以直接读取单个用户的 routines/workouts/体重/1RM/肌肉平衡数据直接来自 API 写入的同一个DATA_DIR——不走网络、不占额外容器且只在 LLM 客户端 spawn 它时运行。模块分工均可在仓库内核对mcp/src/state.js加载/派生数据mcp/src/tools.js定义暴露的 MCP 工具schema 用 zod 校验mcp/package.json 中依赖zod3.xmcp/src/labels.js把内部键映射为人类可读标签mcp/src/index.js装配入口bin为opengym-mcp。客户端配置Claude Desktop / Cursor见 mcp/README.md。测试为cd mcp npm test。八、Passkey 与自托管的硬约束RP_ID 与 ORIGIN 决定了很多代码形态CLAUDE.md 用一整节解释了一个对部署者极其关键的约束WebAuthn passkey 绑定精确的主机名RP_ID且要求 HTTPSlocalhost 除外。这直接塑造了 API 与 Settings 侧大量代码的形态——RP_ID/ORIGIN环境变量、两者都不可用时的游客模式回退等。文档同时提醒在改动认证、会话或通知相关代码前先读 docs/SELF_HOSTING.md它记录了真实部署依赖的完整环境变量契约RP_ID、ORIGIN、PORT、WEB_PORT、NGINX_PORT、BACKEND、SESSION_DAYS、ADMIN_UIDS、INVITE_ONLY、ALLOW_GUEST、AUDIT_*、VAPID_SUBJECT各变量的含义以 .env.example 的注释为准。九、Docker 部署三个服务与单源的必要性docker-compose.yml 定义三个服务media一次性的动作素材下载器产物 gitignoredapiNode 后端webfrontend/的多阶段构建 nginx。nginx 同时代理/api→api并托管共享 media 卷。单源single origin是 passkey 的硬性要求——这就是为什么媒体文件也经由 nginx 服务而不是让浏览器直连其他主机。web/nginx.conf.template 在容器启动时由环境变量渲染docker-compose.yml 中可见NGINX_PORT、BACKEND、PORT的注入WEB_PORT默认映射 8080因此对预构建镜像做宿主机端口重映射时无需重新构建。十、贡献前必须知道的三条工程红线CLAUDE.md 收尾部分与 CONTRIBUTING.md 一致给出三条在改动代码前必须遵守的约束依赖精简是硬性约束不是偏好前端只有 React Router Zustand加上 Capacitor 插件与构建工具链见 frontend/package.jsonAPI 侧依赖极少当前为 api/package.json 所列。两侧新增依赖都是a hard sell。不要提交media/与data/两者均为 gitignored前者由 media 服务运行时拉取后者是运行时数据。训练逻辑必须有单元测试渐进超负荷、1RM、session 回读等逻辑必须落在src/lib的纯函数中、测试与代码同目录而不是靠手工点击验证。结语如何继续深入CLAUDE.md 的价值在于它把一页纸能说清的架构事实与代码里能验证的实现细节对齐了routes表、atomicWrite、gym_state_v1、MCP 的 stdio 只读桥、Node 22 的 CI 门禁——每一句都能在本文给出的文件路径中找到对应源码。若你要动手改代码建议的阅读顺序是先 docs/README.md 选择场景文档docs/SELF_HOSTING.md、docs/API.md 对应 OpenAPI 规范再按本文第六节的源码路径核对实现最后以纯函数 同目录测试的模式落笔——这正是这个仓库对训练逻辑一以贯之的承诺。赞分享后端前端移动开发MCP 服务【免费下载链接】openGymSelf-hosted gym body-weight tracker — plan routines, log workouts (supersets, warm-ups, cardio), see which muscles are trained, fatigued or detrained, import from FitNotes/Strong/Hevy, passkey login. Your data, your server.项目地址https://gitcode.com/GitHub_Trending/op/openGym点击查看免费下载相关推荐ECC 仓库开发指南从 CLAUDE.md 解读 Claude Code 插件架构与工程约定ECC 仓库开发指南从 CLAUDE.md 解读 Claude Code 插件架构与工程约定 导读 本篇文章以 docs/ja JP/CLAUDE.md ht人工智能AI 技能AI 插件AI 评测Agent 评测MCP Clients开发工具ClawHub 仓库开发指南读懂 CLAUDE.md 中的项目结构、构建命令与 CI 门禁ClawHub 仓库开发指南读懂 CLAUDE.md 中的项目结构、构建命令与 CI 门禁 导读 本文基于 ClawHubSkill Plugin Re后端前端AI 技能AI 插件搜索引擎Mac Mouse Fix 鼠标加速修复完整指南Mac Mouse Fix 鼠标加速修复完整指南 想把指针挪一小格,手腕刚抬起来,它已经窜到屏幕对角——mac 鼠标加速,就是这种忽快忽慢、甩一下飞半屏的元凶。桌面应用系统编程上一篇基于 Bitnami Helm Chart 在 Kubernetes 上部署 GitLab Runner 的完整实战指南下一篇OpenVoice让任意文本拥有你的声音本地即时语音克隆三步跑通创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考