
这是什么
一个本地优先的饮食、体重与训练记录应用,iOS 用 Swift、Android 用 Kotlin。记一餐可以一次拍最多十张照片、扫条码、说一句、打字,或者用 Siri;分析交给你配置好的那家 AI provider——支持十三家,包括任意 OpenAI 兼容端点——密钥存在系统钥匙串里。核心记录功能不需要账号、也没有分析上报;产品里唯一的一处第一方同步是一个可选的每周挑战,分享的是聚合分数而不是日志。运动示意图是一套 875 个动作的手绘动画库,而只有一份清单随应用一起发布。
谁做的一个人:2,361 次提交里 2,142 次是他写的,并在 2026 年 9 月 9 日把这个项目在印度注册为微型企业,Udyam 编号 UDYAM-DL-06-0225072。其余提交来自一个有自己 GitHub 身份的 agent 账号、一个依赖机器人和大约十几位其他人。应用已上架 App Store 与 Google Play,第一次订阅提交与 7.1.2 版一起发出去。
它是怎么搭起来的
组成 · 6两个原生客户端架在一套刻意超大的共享素材语料之上,而所有外部智能都藏在一条由用户配置的链后面。塑造整个仓库的那个决定,是插画库放在哪:7,000 帧太大、装不进安装包,于是语料留在仓库里作为正典副本,一份小清单随应用发布,应用再从静态 CDN 拉取并缓存单独的帧——这让两个安装包都待在自己的体积上限内,也把一条美术流水线变成了一个有契约的投递问题。AI 那边是链形而不是适配器形:一次请求先走用户选的 provider,再走用户选的备用项,某些情况下最后走到设备本地的模型,于是一家厂商挂掉时退化的是答案,而不是功能。两件事之外,这个项目把不可撤销的动作当成默认关闭的闸门,把可撤销的本地数据当成常态——没有账号、没有分析上报,唯一一处可选同步传的是聚合分数而不是日志。
- ios/calorietracker
- 464 个文件:一层
@Observable的档案与 store(食物、体重、饮水、训练、对话),一个 services 层,其中GeminiService与ChatService各自路由十三个 provider,语音服务把远端转写路由到五家厂商,体重分析服务装着预测算法;密钥走 Keychain;视图从十五步 onboarding 一路到图表和教练页。旁边还有 Watch 应用、两个 widget 扩展、一个分享扩展,以及 47 个测试文件。 - android/
- 一个 Kotlin + Compose 应用,725 个文件,共用同一套语料和同一套路由思路,用 Health Connect 而不是 HealthKit,另有自己的应用内语言选择器。
android/release里放着 42 个打包产物,共 513 MB。 - shared/workout-vectors
- 7,011 个文件、1.21 GB:性别感知动画语料的正典副本、运行时清单,以及那份 README——里面写着命名契约、每帧的动画语义(起始、第一个动作、过渡或最大幅度、镜像或受控回位)、所有序列共用的一套视觉语言,以及一个如实写下的空缺:
Other档案目前用男性素材,直到画出专门的包容性一套。 - artifacts/workout-visual-qa
- 7,835 个文件、1.26 GB 的修复凭据:整段序列的对齐报告(其中一份 8.8 MB)、复核过的前后帧、每帧按哈希命名的记录、已验收修复的清单,以及那份跟踪「哪些已验收、哪些停在版本控制之外、哪些发现仍在阻止验收」的 README。
- scripts/ 与 workers/
- 48 个脚本,管素材流水线、商店操作与发布检查,其中包括后台修复运行器以及它的提升、描边和对齐测试套件;
workers/里是一批编号的生成运行,每个动作输出四帧男性与四帧女性,外加一份结果文件。 - store/、services/ 与 web/
store/是那份自带 README 的发布机制:产品与订阅目录、各平台元数据占位,以及那些闸门变量。services/里是托管 AI 代理的文档,和一个 Discord 机器人——它的四个注册脚本负责创建/ask、bug 与 feature 三个命令。web/是官网,带自己的工作流和测试;local-models/装着目录、一个校验器和本地语音与语言模型的第三方声明。
取舍,以及它替代了什么
自带密钥,跑在设备上 替代 经开发者服务器转发的第一方代理
README 把 AI 访问写成免费、由用户自带密钥:密钥存在系统钥匙串里,请求直接发往所选 provider——并且它记下了早先那个第一方托管代理已被停止提供,也就是另一种选择的早期版本。
插画语料不进商店安装包 替代 把 7,000 帧打进应用
理由是带着算术写出来的:Google Play 把基础模块卡在 200 MB,而 iOS 包会涨大约 1.3 GB。于是只有清单随应用发布,这个目录保持为唯一正典副本,帧在首次使用时从静态 CDN 取回并缓存——CDN 打不开就显示动作图标。
把本地分析放在链的最后一步 替代 在 provider 失败处结束
在支持的 iPhone 上,文字、语音转写和 Siri 记录的食物描述分析,可以在所配 provider 与备用项都试过之后,落到设备上的 Apple Intelligence;iOS 27 上用户选定的照片同理。这是一项写明前提的能力,而不是一个默认行为。
所有商店动作在运维打开之前都是关的 替代 打一个标签就发布
发布 README 写明:
android-v*标签只构建并创建 GitHub Release,不发布;正式发布默认关闭;iOS 仍然由 Xcode Cloud 上传。文案、截图与提审都已接好但都在闸门之后,所以默认路径下不会误发出任何东西。没实现的门就让构建失败 替代 让它静静地未实现
把 RevenueCat 同步那个变量打开会让工作流失败,因为写入那条路还不存在。README 说这是刻意的:另一种做法是留一个看起来能用、实际什么也不做的开关。
除非用户主动选择,记录功能的任何东西都不同步 替代 一个需要账号、历史在云端的应用
核心应用不需要账号、不做分析上报、日志留在本地;唯一一处第一方同步是每周挑战,分享的是一个化名和有限的聚合分数,需要参与者凭证,退出即远程删除档案,不活跃档案九十天后自动删除。原始日志与照片从不同步。
依据README.md(32,980 字符,含其中带注释的 iOS 目录树与隐私一节)、shared/workout-vectors/README.md、artifacts/workout-visual-qa/README.md、store/README.md、.github/workflows/quality.yml,以及完整的 16,512 个文件树及其体积。
制作过程
6 个阶段- 01
一个人,两个商店上架
仓库建于 2026-02-04,到 2026-09-28 有 2,361 次提交,其中光是九月就占 883 次。它带的不是一条发布线而是两条——
ios-v*与android-v*——最新的分别是 iOS 7.1.2 和 Android 7.1.1,两者相隔几小时发布。应用已在 App Store 和 Google Play 上架,包名com.apoorvdarshan.calorietracker,两个平台各支持十八种语言,445 个星、91 个 fork,27 个未关闭 issue 里多数是用户按模板写得很规整的功能请求。2026 年 9 月 9 日,作者把它在印度注册为个体经营的微型企业,而 7.1.2 版是和第一次订阅提交一起发出去的。一个个人项目配一个营业执照号,这个组合本档案还没记过。 - 02
仓库里装着两吉字节,以及它为什么不进安装包
GitHub 报的是 16,512 个文件、2.43 GB,而其中几乎没有源码。最大的两个目录都是生成物:
artifacts/workout-visual-qa1.26 GB,shared/workout-vectors1.21 GB。后者是这个项目自己的插画语料——875 个动作,每个四帧男性加四帧女性,7,000 张 PNG,每张约 175 KB——它的 README 把这套语料称作性别感知运动动画的唯一正典来源,规定了<exercise-id>_<gender>_<version>_<frame>.<format>的命名契约,以及一份作为格式、帧名、帧数与代表帧唯一真相来源的运行时清单。让这个体积成为设计决定而不是意外的,是紧接着的那句话:这套语料从不打包进商店安装包,因为 Google Play 把基础模块卡在 200 MB,而 iOS 包会涨大约 1.3 GB。真正随应用发布的只有 0.75 MB 的清单,帧则由应用首次打开某个动作时从静态 CDN 拉取并缓存——一次不带账号、不带设备标识的普通图片请求——CDN 打不开时就显示该动作的图标。语料旁边还躺着 513 MB 的发布产物和大约 150 MB 的市场素材,后者的目录名里带空格。 - 03
一个根 agent 和三个 worker,在修 7,000 张画
这次修复单独有一份 README,读起来像一份作业记录。图库被审计过,计划是清理背景并对齐画面——在本地做,分割跑在作者的 Mac 上,没有上传任何运动图片,也没有使用付费图像 API。账目记得很细:875 个动作里 5 个已验收并集成,四十张复核过的 PNG 同时进入两个平台的资源目录,五个复核清单被
accepted-repairs.json钉住,复制后做了 SHA 校验,并跑完了整套 875/7,000 的同步检查;清理、描边、对齐与提升四套测试里共有 48 个通过的安全测试——同时注明视觉复核仍然不可省。剩下的 6,960 帧被停放在一个刻意 gitignore 的目录里,原则是未完成的候选不许进入应用资源、也不许进入发布;进度记在 run-state 文件里,每帧另有按哈希命名的记录,而 README 提醒要先确认记录里的进程还活着——因为一次停下的运行会留下一条仍写着running的状态。工作本身是分开做的:根 agent 之外还有三个 worker agent,一个改进队列调度并复核一个肌群,一个做完深蹲,一个完成恢复后的跪姿批次;根负责对齐弯举,并且只提升被完整验收的整组。可疑帧优先处理但一帧都不丢,未被标记的帧明确不等于已验收,而 README 直说跑完推理并不等于图库修好了:原图裁切、透视、前景保护和帧序复核都还是分开的事,并且不给总时长承诺。 - 04
那个 agent 是一个有自己账号的贡献者
2,361 次提交里 153 次由
cursoragent用cursoragent@cursor.com提交——一个拥有自己 GitHub 账号的 agent,而不是挂在作者名下,它和十几个人一起出现在贡献者列表上。Cursor 还作为共同作者出现在 182 次提交里,而仓库里出现次数最多的尾注名字是作者自己的,231 次。Claude 系列出现在十次提交里,Copilot 三次。审查同样是混合的:README 上挂着一枚写着由 Qodo、GitHub Copilot 与 Greptile 完成代码审查的徽章,项目还持有 OpenSSF Best Practices 通过徽章和一份 Scorecard。至少十二个人落地过改动,其中几位超过五次。整体画面是:一个个人产品,而它的提交历史是作者、一个商业编程 agent,和一条长尾贡献者之间的协作。 - 05
十三个 provider、一条降级链,以及本地兜底
AI 这一层是当链条做的,不是当集成做的。在设备上你挑 provider、模型、备用项和语音语言;支持十三家,从 Gemini、OpenAI、Claude、Grok 到 Groq、Hugging Face、Fireworks、DeepInfra、Mistral,以及任意 OpenAI 兼容端点,密钥存在 iOS 钥匙串或 Android 加密偏好里,请求直接发往你所选的那家。遇到 503、529 或 429 时,食物分析和教练对话都会按 1 秒、2 秒、4 秒退避重试,于是短暂的服务抖动不会变成用户可见的失败。而在支持的 iPhone 上,这条链的尽头不是某家厂商:在你自己的密钥与备用项都失败之后,最终的兜底是设备上的 Apple Intelligence;在 iOS 27 上它还能在本地读食物照片,本地语音转写则是六个转写选项之一。README 也记下了被拿掉的东西——早先的第一方托管 AI 代理已停止提供,应用回到免费自带密钥、另有一个可选付费档的模式。
- 06
护栏:不会误触发的商店发布,以及只检出 200 MB 的 CI
上架是移动项目里最不可撤销的一步,也是这个仓库把闸门设得最紧的一步。打
android-v*标签不会发布到 Play——它只构建并创建一个 GitHub Release——再往后的每一步都藏在一个默认关闭的变量后面,store/README.md用一张表列清了商店文案、截图、提审、正式发布与目录同步里哪些已经接好、哪些仍然手动。其中一个变量被明确写成「打开就会让工作流失败」:STORE_SYNC_REVENUECAT=true是错误,因为写入那条路还没实现——README 明说了这件事,而不是留一个看起来像功能的缺口。iOS 的二进制由 Xcode Cloud 上传,周边一切都由每次打标签时的本地流程准备。持续集成也是同一种性格:workflow 里的 action 全部钉死在提交 SHA 上而不是标签上,凭证不被持久化,每个 job 只检出它需要的那几个目录——这就是为什么一次网页 lint 不会把两吉字节的插画帧一起拉下来——而 Android job 会跑 Gradle 自己的 wrapper 校验,把 wrapper 二进制与官方发布的校验和比对,于是被篡改的 wrapper 会让构建失败。质量检查在每次分支推送、每个 pull request 上跑,并且每天 23:03 再跑一次。
相关档案
全部档案 →第 057 号
VibeRave
一个 Strudel 分支:按住一个键、把想要的风格说出来,音乐就在下一小节变掉,而节拍从不中断。
第 039 号
Vibe Projects
一个人的 monorepo:六个由 AI 生成的项目——一个 Android agent 运行框架、一个按 hunk 审阅改动的 VS Code 扩展,以及四个小型 Android 应用——被刻意当作「模型现在能造出什么」的持续标尺。
第 038 号
Codewhale
一个用 Rust 写的终端编码 agent:读你的项目、改文件、跑命令——背后是一个同时被网页客户端和桌面应用共用的运行时,一层把各家模型当成可替换路由的模型层,以及一份把大半篇幅花在「多个 agent 如何共用一个检出」上的贡献指南。