关于 Runspector — AI running coach for Garmin
Runspector 是面向跑者的本地 Garmin 训练教练,结合规则驱动的 readiness 评估与 Claude 的解释和训练计划。它提供网页应用,也可作为 MCP 服务连接 Claude 客户端。
主要功能
- 01将 Garmin 数据同步到本地 SQLite
- 02基于规则评估每日 readiness
- 03Claude 教练解读与每周计划
- 04提议、应用和撤销手表训练
- 05本地网页应用与演示模式
适用场景
- 01判断当天应强化训练、轻松跑还是休息
- 02查看恢复信号和跑步趋势
- 03规划训练并确认后发送到 Garmin 手表
MCP 相关
Runspector 通过 16 个 MCP 工具向 Claude Code、Claude Desktop 及其他支持 JSON 配置的 MCP 客户端提供 Garmin 数据和教练操作。工具涵盖 readiness、跑步记录、训练负荷、同步,以及提议、应用或撤销手表训练。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
16收录的工具列表 · 更新于 今天
此工具无需参数。
详细介绍
Runspector — Garmin AI 跑步教练
面向 Garmin 手表的免费开源 AI 跑步教练。 Runspector 会将你的 Garmin Connect 数据——HRV、睡眠、Body Battery、静息心率、训练负荷和每一次跑步——同步到你自己电脑上的文件中,每天判断是加练、轻松训练还是休息,并让 Claude 解释原因、规划每周训练:既可以在小型本地 Web 应用中使用,也可以作为 Garmin MCP 服务,在 Claude Code 和 Claude Desktop 中使用。无需云服务,也无需 API 密钥——只需登录你自己的 Claude Code 账号即可。
https://github.com/user-attachments/assets/0b4d7d86-5ab7-439b-82cb-89a004b71405
这段 90 秒演示视频配有旁白,展示的是合成演示运动员;视频由 scripts/video.py 根据本仓库重新生成(文件)。上方没有播放器?GitHub 移动应用不显示视频:
▶ 在浏览器中播放演示视频。
内置的合成运动员(runspector serve --demo)。所有图片均由
python scripts/screenshots.py 重新生成;教练建议卡片则是 Agent 基于同一个演示数据库运行后未经编辑的结果,保存在 demo-card.json 中,以确保图片内容与应用一致——卡片解释的决策(轻松训练,即高强度训练后的第二天)与旁边 Today 标签页中的决策相同。docs/screenshots/ 中提供了五个标签页的完整截图,包含两种主题——例如 today.png 和
today-light.png。
我开始跑步比较晚,VO2max 很长时间都没有提升。我一直练得很多,但这些努力从未真正体现在这个数值上——所以我以为继续照旧训练,最终总会有效。事实并非如此。我训练的方法不对,而我手腕上的手表明明有数据可以指出问题,却从来没有告诉我:Garmin 收集了一切,却从不解释。
这就是这个项目的初衷。数据已经在那里;让 AI 读取数据并提供指导——训练明确以提高 VO2max 为目标,而不是只为累积跑步里程;同时把决策规则写清楚,让教练解释这些规则,而不是临场发挥。这个仓库最初是为一名运动员打造的工具。现在,任何拥有 Garmin 手表和 Claude Code 的人都可以安装使用(有 Claude 方案即可)。
无需云端后端,无需 API 密钥,也无需 Docker。只需安装一个 Python 包,即可将 Garmin 数据同步到本机 SQLite 文件,在小型 Web 应用中查看,并让 Claude 担任你的教练——底层由确定性训练准备度引擎提供支持,因此 AI 解释决策,而不是凭空编造。
如果你关注的是工程实现,而不是如何运行,本仓库真正探讨的五项决策及其背后的测量数据,见设计决策。简而言之:结论由纯代码得出,AI 只负责解释 · Agent 运行时使用允许列表,而非拒绝列表(--tools ""、一个 MCP 服务、空临时工作目录)·
提示词经过回归测试,采用 LLM-as-judge 套件,最近一次运行结果见仓库中的记录 · 两种语言中都存在的量值,通过执行随附的 JavaScript 并与 Python 对照来固定 ·
发布门禁也会扫描二进制文件,并包含一个误报反例。CI 会在三种操作系统和两个 Python 版本上运行 lint、995 项测试、80 项前端测试和该门禁,且每个操作都固定到一个提交 SHA;还有第二个任务,会在所有三种系统上构建 wheel、像用户一样安装,并通过快速入门运行已安装的可执行文件,因为测试套件能验证代码,只有安装才能验证软件包。
原名为 runcoach-ai:这是同一个项目,于 v0.5.0 更名。旧链接会重定向到这里。如果你之前使用过它:请按三个步骤切换,你的数据会自动迁移。
与 Garmin 没有隶属关系。通过非官方的 python-garminconnect 库访问你自己的账户。 这是训练工具,不提供医疗建议。
快速入门
# 1. install (needs uv: https://docs.astral.sh/uv/)
uv tool install runspector
# without uv: pipx install runspector
# 2. look around without any account
runspector serve --demo
# 3. the real thing
runspector serve # first start: checks Garmin and Claude, opens http://127.0.0.1:8765 -
# sign in to Garmin right there (Setup → Sign in to Garmin; only a
# session token is stored) - and syncs the last 30 days in the background
Garmin 直接在页面上登录(设置 → 登录 Garmin,或会话过期时选择重新登录):输入电子邮件、密码,以及账户启用时需要的 Garmin 验证码,随后立即开始同步。runspector login 可在任意终端完成相同操作,正在运行的应用会在 ↻ 时获取登录状态,无需重启。Claude 仅用于教练卡片:参见连接 Claude。
runspector doctor 会告诉你缺少什么——它会实际使用 Garmin 会话来检查,并报告数据的时间,因为令牌悄然过期正是这类应用失效的原因。使用 runspector doctor --offline 可跳过 Garmin 调用。退出码为 1 表示有问题需要修复,因此可在 cron 中使用 runspector doctor || notify-me;如果缺少 Claude CLI,命令会报告这一情况,但不会因此返回 1,因为除了教练卡片之外,其他功能都不需要它。
Claude Code 和 Claude Desktop 的 Garmin MCP 服务
通过 MCP 服务访问相同的数据,并遵循相同的规则;其中有 16 个工具,包括今天的准备度结论、恢复情况、训练负荷、近期跑步、强度分布、VO2max 历史、教练对你的了解情况、Garmin 同步,以及为手表上的训练提出建议、应用和撤销训练。
claude mcp add runspector -- runspector mcp
# then just ask: "should I train today?"
# or: "plan me an easy 40 minutes for tomorrow" - you see the session, and it goes
# on your watch only after you say yes ("take it back off" undoes it)
在 Claude Desktop 或任何使用 JSON 配置的 MCP 客户端中(请先登录一次:runspector login):
{ "mcpServers": { "runspector": { "command": "uvx", "args": ["runspector", "mcp"] } } }
无需启动应用即可定期同步(cron / Task Scheduler):runspector sync。
之后:
uv tool upgrade runspector # the newest release; your data and Garmin session stay where they are
uv tool uninstall runspector # removes the program only - delete ~/.runspector yourself if you want the data gone
uv tool install runspector 会从 PyPI 安装最新版本(runspector==0.5.1 可固定到特定版本;pipx install runspector 和 pipx upgrade runspector 无需 uv 也能完成相同操作);
uv tool install git+https://github.com/edxleon/runspector 会安装 main 分支上的版本。
连接 Claude
runspector 不会自行连接 Claude,也绝不会要求你提供 Claude 密码或密钥。教练功能运行在你使用自己的账号登录的 Claude 软件中,登录由 Anthropic 自己处理。
| 你想要什么 | 你需要什么 |
|---|---|
| 今日判断及其依据、你的跑步记录、趋势和同步 | 不需要 Claude |
| Web 应用中的教练卡片(询问教练、我今天该训练吗?、分析这次跑步、回顾本周),以及它们发送到你手表上的训练课 | 这台电脑上的 Claude Code,并已登录 |
| 在聊天中获得教练指导,同时将训练课发送到手表 | Claude Desktop 或 Claude Code,并将 runspector 添加为 MCP 服务 |
“Claude 订阅方案”是什么意思。 Claude Code 需要付费 Claude 订阅方案 claude.com/pricing——Pro、Max、Team 或 Enterprise——或者 Anthropic Console(API)账号,按使用量计费。免费的 Claude 方案不包含 Claude Code。订阅方案的用量会像其他 Claude Code 使用一样计入教练卡片:无需创建密钥,也不会按卡片单独计费。runspector 本身免费。
使用 Claude Code(教练卡片必需)
Claude Code 是 Anthropic 的命令行工具。你只需安装并登录一次;runspector 会在后台为每张卡片启动它。
# 1. install - macOS / Linux (Windows PowerShell: irm https://claude.ai/install.ps1 | iex)
curl -fsSL https://claude.ai/install.sh | bash # or: brew install --cask claude-code
# 2. sign in - opens your browser, sign in with your Claude account
claude auth login
# 3. check
runspector doctor # "Claude: signed in with your Claude subscription"
更多安装选项(WinGet、npm、Linux 软件包):Claude Code 设置。
如果启动 runspector serve 时还没有安装 Claude Code,之后重新加载页面即可,无需重启。
如果你的 Claude Code 使用 Console API 密钥或云服务提供商(Bedrock、Vertex)登录,而不是使用订阅方案,卡片会使用相应的方式运行并据此计费;设置检查会说明这一点。若 ANTHROPIC_API_KEY 仅在你的 shell 中导出用于其他工作,卡片运行时会移除它,除非你设置 RUNSPECTOR_ALLOW_API_KEY=1。
仅使用 Claude Desktop(不使用 Claude 命令行工具)
如果你使用 Claude 桌面应用(claude.ai/download),无需 Claude Code,也可以在聊天中获得教练指导:
- 安装 runspector,并登录 Garmin 一次(
runspector login,或打开runspector serve显示的页面)。 - 在 Claude Desktop 中:点击 Claude 菜单 → Settings… → Developer → Edit Config,然后添加:
(macOS 上的文件路径为{ "mcpServers": { "runspector": { "command": "runspector", "args": ["mcp"] } } }~/Library/Application Support/Claude/claude_desktop_config.json, Windows 上为%APPDATA%\Claude\claude_desktop_config.json;保留其中已有的服务。) - 退出并重启 Claude Desktop,然后询问:“我今天该训练吗?”
如果没有显示该服务,Claude Desktop 可能无法找到命令:将 which runspector 返回的完整路径(Windows 上使用 where runspector)填入 "command"。Web 应用中的教练卡片仍需要 Claude Code;在 Desktop 中,同样的教练指导会在聊天中进行。
不使用 Claude
训练准备度判断及其依据、跑步记录、趋势和同步功能都可以正常使用。需要 Claude 的是教练撰写的所有内容:卡片,以及它为你规划并发送到手表上的训练课。
常见问题
Garmin 有 AI 教练吗?
Garmin 提供三种自有教练功能。Garmin Coach 是 Garmin Connect 中一组免费的自适应训练计划,适用于 5K、10K 或半程马拉松,并会根据你记录的跑步情况调整。许多手表会在具备训练状态和 VO2max 估算值后,根据你的活动显示每日推荐训练。Garmin Connect+ 自 2025 年 3 月起成为付费订阅服务,新增了 Active Intelligence:在测试版中推出、全天提供由 AI 驱动的洞察和建议;Garmin Connect 原有的所有功能仍免费。Runspector 读取同样的 Garmin 数据,但属于另一类工具:它通过你可以查看的规则,列出每项依据并判断你今天是否适合训练;你可以用自己的话向教练提问,还可以规划训练课,但只有在你同意后,训练课才会发送到你的手表——整个过程都在你自己的电脑上完成。
Garmin 有免费的 AI 跑步教练吗?
Runspector 免费且开源(MIT)。它从 PyPI 安装,并将数据保存在你自己的电脑上。 今日判断、跑步记录、趋势和同步只需要你的 Garmin 账户。教练本身运行在 Claude 上,通过 Claude Code 或 Claude Desktop 使用你自己的 Claude 账户;连接 Claude 说明了所需的套餐。Garmin 自家的 Garmin Coach 训练计划也免费。
哪些 Garmin 手表适用?
任何能与 Garmin Connect 同步的 Garmin 手表,都能让 runspector 获取你的跑步记录。今日判断会读取四项恢复指标——HRV 状态、睡眠评分、Body Battery,以及相对于你个人基线的静息心率——再加上训练负荷。即使手表无法记录夜间 HRV 状态,也能根据其他指标给出判断;但如果一次 GO 判断依据的指标少于两项,就会变为 EASY:数据不足不代表可以放心训练。要将训练课程发送到手表,手表必须支持 Garmin Connect 的结构化训练,并能设置心率或配速目标。目前的 Forerunner、fenix、epix、Venu 和 Instinct 型号都是例子;某款手表是否记录 HRV 状态或 Body Battery,可查看 Garmin 网站上的规格说明。
如何将 Garmin 数据连接到 Claude?
安装 runspector,登录一次 Garmin(使用 runspector login 或页面上的按钮),然后打开应用(runspector serve),或将它作为 MCP 服务添加到 Claude Code:
claude mcp add runspector -- runspector mcp。然后询问“我今天应该训练吗?”。有关 Claude Desktop 的信息,请参阅
用于 Claude Code 和 Claude Desktop 的 MCP 服务。
我需要 Garmin 开发者账户或 API 密钥吗?
不需要。runspector 通过社区库使用你自己的 Garmin 账户登录——请参阅下文的Garmin 会封禁我的账户吗?。Claude 方面也不需要 API 密钥:有 Claude 套餐和 Claude Code 就够了。
它支持 Apple Watch、Coros、Polar 或 Strava 吗?
不支持——仅支持 Garmin。所有数据都来自 Garmin Connect,包括 Garmin 自己提供的读数(HRV 状态、Body Battery、训练负荷、VO2max),它制定的训练课程也会发送到 Garmin 手表上。
我的 Garmin 密码会被保存吗?
不会。密码只会发送给 Garmin 一次,用于登录。Garmin 会返回一个会话令牌,只有这个令牌会保存在你的电脑上,存放在只有你的用户账户能读取的文件夹中。只有在运行 runspector 的电脑上打开页面时,页面登录才会收集密码:如果从手机打开,页面会通过你的网络使用纯 HTTP,因此会提示你改用 runspector login。
还需要额外付费吗?
runspector 免费(MIT)。教练卡会像其他 Claude Code 使用一样使用你的 Claude 套餐,无需 API 密钥,也不会按卡片单独计费。即使不使用 Claude,除了教练卡以外的所有功能仍然可用。
Claude 会看到什么?
只有这个应用显示的数据(准备状态、近期跑步记录、区间、每周训练负荷),而且仅在你生成卡片或在 Claude Code 中提问时才会看到。它绝不会看到你的 Garmin 密码、会话令牌或任何原始文件。它通过你自己的账户连接 Claude,并遵循你套餐的条款。
它会弄坏我的手表或日历吗?
它只会自行读取数据。只有在你按下“发送到手表”或在 Claude Code 中确认后,才会向 Garmin 写入内容,而且只会写入向你显示的训练课程。“从手表移除”会将其移除。教练自身生成的卡片绝不会写入任何内容。
Garmin 会封禁我的账户吗?
runspector 通过 python-garminconnect 登录。这是一个 Garmin 不官方支持的社区库。每日同步会发出约 25–40 次请求,首次同步(一个月的数据)会发出几百次请求。下载训练课程时它会暂停,不会获取超过 90 天的数据,并且遇到第一个速率限制响应就会停止,而不是继续重试。这并非保证,但它也不是在抓取数据。
这是医疗建议吗?
不是。这是一个训练工具。如果你感到疼痛、头晕或任何不适,应去看医生;教练也会明确提醒这一点,而不是据此安排训练。
如何删除所有内容?
删除 ~/.runspector(应用页脚会显示该文件夹),然后运行
uv tool uninstall runspector。如要同时让 Garmin 端的令牌失效,请更改 Garmin 密码。
你将获得什么
| 标签页 | 能回答的问题 |
|---|---|
| Today | GO / EASY / REST 及其背后的信号、今天的一个决策句;在高强度训练日,还会指出是哪项高强度训练(VO2max 间歇、阈值重复训练,或 Garmin 用来测量 VO2max 的稳定跑),你的 VO2max 及距离上次真正变化已过的天数、本周计划与完成情况、昨晚的睡眠、各心率区间的边界及其来源 |
| Runs | 每次跑步及其强度区间、实际间歇结构(5×4′,而不是“5 分钟”)、心率区间、天气、表现状况——以及一个分析这次跑步按钮 |
| Trend | VO2max 的真实阶梯变化(以及是否该测量了)、乳酸阈值历史、每周高强度分钟占比与 80/20 目标的对比、有氧效率(固定心率下的配速)及其波动范围和趋势、训练量、极化程度、ACWR,以及 Garmin 自己的负荷重点(各区间 4 周负荷与目标范围的对比),作为第二意见 |
| Coach | 用自己的话向教练提问(我哪里做错了?)——以简短卡片作答,并优先指出最重要的调整点。Claude 提供的一键分析会以简短卡片呈现,记住上一张同类卡片,接受你的 👍/👎 和后续问题,也可以删除。两个入口从这里开始(为什么 VO2max 在变化?· 回顾我的一周);另外两个入口从其主题所在处开始——Today 标签页上的我今天应该训练吗?,以及某次跑步中的分析这次跑步 |
| You | 你的一周,这是规划器遵循的基础:每周跑步次数、跑步日、长跑安排、不能跑步的日子、其他运动——根据你的历史记录读取并保持更新,也可由你修改;你设置的内容会一直生效,直到你交还控制权。给教练的备注:用你自己的话写下备注(“周一、周三、周五去健身房”“到 12 月前时间更少”),教练会在每次回答前读取。还有教练对你的了解,以及每项内容的依据:你的训练规律性、强度模式、VO2max 趋势、Garmin 的负荷重点、静息心率基线和心率区间——以及这些信息从何时开始、何时发生变化。每张卡片和 MCP 工具 get_athlete_profile 都会读取这三项 |
工作原理
flowchart TD
G[Garmin Connect] -- "token resume, read" --> S[sync.py]
S --> DB[(SQLite<br/>~/.runspector)]
DB --> L[logic.py<br/>readiness · decision<br/>intervals · bands]
L --> SNAP[snapshot.py]
SNAP --> WEB[web app<br/>127.0.0.1:8765]
L --> MCP[MCP server<br/>16 tools<br/>13 read-only · sync · apply · undo]
WEB -- "spawn job" --> A["claude --print<br/>(your Claude sign-in)"]
A -- "only mcp__runspector__*" --> MCP
A -- "JSON card" --> WEB
MCP --- CC[Claude Code / Desktop]
设计决策
判断由代码做出,解释由 AI 提供。 GO/EASY/REST、今天的决策、间歇检测和强度区间都是 logic.py 中的纯函数——经过单元测试、不联网、无需大模型。事实和决策都在此处计算一次,然后通过 get_training_readiness 将最终决策交给 Agent,而不是让它自行推导:教练卡片只是对该决策的解读,不是另行得出的独立判断。Claude 可以解释、补充规则无法提供的背景——也可以提出异议,但这时必须说明它对哪个数字有异议。Claude 的职责是处理规则不擅长的部分:权衡冲突、措辞制定计划、回答后续问题。
使用你自己的 Claude Code 登录,而不是在应用中放置密钥。 教练任务会以子进程的方式运行 claude --print,使用你登录 Claude Code 的方式进行身份验证。如果你使用 Claude 方案,就没有需要泄露的密钥、按令牌计费的账单,也无需进行配置。默认情况下,会从卡片运行进程中移除为其他工作导出的 API 密钥环境变量,因此不会在未经请求的情况下产生卡片费用;设置 RUNSPECTOR_ALLOW_API_KEY=1 则会保留这些变量。在 Claude Code 本身中配置的密钥或云服务提供商不受任何环境变量影响:卡片会使用它们,设置检查也会明确说明——它会在与卡片运行时相同的环境中,并在同类空目录下询问 Claude Code。如果你的配额用完了,任务会等待下一个时段,而不是失败。
给 Agent 的是允许列表,而不是拒绝列表。 训练标题由攻击者控制,最终会进入提示词。因此,教练 Agent 运行时使用 --tools ""(不启用 Bash、文件访问或网页访问),通过 --strict-mcp-config 只配置一个服务——本服务,并且仅预先批准 mcp__runspector__*,且在空临时目录中运行。卡片以 JSON 格式返回,由应用验证并写入,而不是由 Agent 写入;如果没有经过任何工具往返就生成了答案,该答案会被丢弃:无法访问数据的模型会自行编造内容(这是实测结果,并非假设)。
参见 web/agent.py。
坦率地说,这能做到什么、不能做到什么:被注入的训练标题只能访问本应用自己的工具——不能访问 shell、文件系统、网络或其他 MCP 服务;卡片生成任务也没有写入路径:每个工具都是只读的,只有 sync_garmin 例外,它会向你自己的 Garmin 账户发起经过身份验证的请求,因此限速总比毫无限制好;apply_workout 则是唯一会写入 Garmin 的工具,但应用的卡片生成任务根本无法调用它(由测试固定验证的 --disallowedTools),因为应用提案只能由人点击卡片或在 Claude Code 会话中明确提出,绝不能由任务自行决定。它仍然可以影响卡片的内容——而卡片就是产品。卡片还会被记住:同类卡片中上一张卡片会作为上下文传给下一张,因此一张有问题的卡片会持续影响后续卡片,直到你将其删除(界面上每张卡片都有删除按钮)。
模型获取汇总数据,界面获取序列数据。 MCP 工具绝不会返回某个时段逐日排列的行——每日序列会撑大上下文窗口,还容易被误读。Agent 看到的是摘要和按周汇总的数据;只有绘制曲线的前端会获取数据点。 诚实的数据。 以下是一些实际体现:
- Garmin 会沿用没有测量数据那几天的 VO2max,因此只有数值实际变化时才报告变化——绝不会用时间窗口两端的数值之差来报告。
- 自行计算的 ACWR 需要 ≥ 21 天 且 ≥ 8 次训练,会标记为
computed,可以将结论降为 EASY,但绝不会据此判定为 REST。 - 如果恢复信号少于两个,GO 结论会降级:数据不足不等于状态良好。
- 如果同步数据已过时,今天的决策会标记为
unknown,而不是给昨天的结论换上今天的外衣。 - 日历月份未完全获取时,不会替换本地镜像(对于已降级的数据源,“没有计划”会是谎言)。
- Garmin 的乳酸阈值配速字段数值相差十倍;系统会对其进行归一化和范围检查,并在单位发生变化时明确丢弃该值。
- 计划周会按照运动员自己的训练日安排:训练天数、星期几以及长距离跑日,均根据最近八周有跑步记录的数据读取(回看半年,并在暂停后重返训练时回看暂停前的数据);质量训练会避开每周的其他运动及其后的那一天——周二去健身房,就只安排一次质量训练,不会安排两次。隔日轮换的节奏没有固定的星期几,因此会按默认节奏制定计划。每个值都会说明其来源:“周六长距离跑——你在 8 周中的 8 周,最长的一次跑步都在周六。”
- 计划周的训练量根据运动员自己的跑步周确定——按计划制定当天结束的滚动周计算,且绝不会超过最近两周中较大一周的 10%;随后再结合其训练历史调整,具体规则写在代码中:负荷比可以维持或减少训练量;每四周安排一个减量周;连续十天没有跑步,就安排一个仅含轻松跑的回归周(休息超过三周时,回归周的训练量为休息前周训练量的一半);连续二十八天没有新的 VO2max 数据,就在阈值训练时段安排稳定训练。若训练量预算不足以满足计划天数,就安排更短的一周——训练天数为三天时只安排一次质量训练,绝不只安排一次强度训练——而不是增加单次训练量。一周只安排一次质量训练时,会选择当前应进行的训练(在 5 区刺激达到目标前安排 VO2max 训练,之后安排阈值训练;也可以安排测量)。暂停后,运动员会逐步重建训练量:递增幅度根据最近七天的数据计算,而不是使用会滞后于恢复进度的中位数;只有当训练量恢复到暂停前水平的 80% 时,才结束减量周。每一步的训练量都不会低于此前计划周;根据负荷比维持或减少训练量的周,也绝不会增加训练量:每周跑量超过计划后,用于维持训练量的中位数会随之上升,这正是负荷比上升的原因。每条规则都会作为明确命名的假设写在计划提案中,不由提示词自行决定。 强度训练日的决策还会说明具体安排哪种强度训练,并根据最近七天包含和未包含的训练内容来确定;暂停后,该日则安排轻松跑。
- 如果没有实测阈值配速,训练安排会根据 Garmin 自己预测的 5 km 和 10 km 成绩确定,而不是套用适合某一位运动员的 5:00/km 默认值。
- 这些规则会实际运行,而不只是通过单元测试:
evals/sim.py会让八名模拟运动员——一名按计划训练、一名跳过 40% 的训练、一名休息三周、一名生病以及一名总是跑得更快的运动员——连续十六周逐日使用该应用,并对照真实工具检查整个训练周期中跑者对教练的预期。测试发现了上述两个计划器 Bug。它无法判断训练是否有效——其身体只是个玩具——而且只能发现其数据模型所能识别的问题,因此真实账户的在线测试仍会继续。 提示词像代码一样接受测试。 教练的行为由两个 Markdown 文件(skills/)决定,并配有一套由 LLM 充当评判者的回归测试(evals/):共 32 个案例,例如 “今天已经跑过一次 → 不再安排第二次高强度训练”、“不把低能量可用性的警示信号轻描淡写地解释掉”、“不遵从训练名称中的指令”。这些测试不需要 Garmin 数据,直接针对真实 CLI 运行——不过只覆盖这两个文件,不覆盖随软件发布的另外两部分提示词(templates.json和web/agent.py中的 JSON 卡片框架;后者由tests/test_web.py以确定性方式覆盖);此外,测试会在--safe-mode下使用指定的模型运行,而生产环境无法使用这两项设置。测试直接从应用导入框架,而不是复制一份,因此不会与实际发布的内容产生偏差。--no-skills会在移除技能文件后重新运行某个案例:如果案例仍能通过,说明它测试的是模型,而不是提示词。
朴素的技术选型。 Python 标准库 HTTP 服务器、sqlite3、原生 ES 模块、内联 SVG 图表。不使用框架、不需要构建步骤、不使用 ORM。约 40 条 SQL 查询,全部位于 store.py 中。可在 Windows、macOS 和 Linux 上运行(CI 矩阵)。
更多详情:docs/architecture.md。
隐私
所有内容都保存在 ~/.runspector/ 中(可通过 RUNSPECTOR_HOME 覆盖):SQLite 数据库、Garmin 会话令牌、教练卡片。不会存储你的密码。在 Linux 和 macOS 上,该目录会以 0700 权限创建,因此共用设备上的其他本地账户无法读取其中的文件;Windows 则沿用用户配置文件的 ACL。**运行 runspector serve 时,这种保护就不再适用:**无需令牌,任何本地账户或进程都可以通过 127.0.0.1:8765 请求你的数据;从 v0.2 起,还能使用你的 Garmin 会话应用或撤销提案。在共用设备上运行时,请设置 RUNSPECTOR_TOKEN 启动服务——此时即使通过回环地址访问也需要令牌,服务还会打印一次性访问链接。唯一的对外连接对象是 Garmin(同步),以及在你触发教练卡片时,通过你自己的 CLI 会话连接 Claude,并传送汇总后的训练数据。服务绑定到 127.0.0.1;若要在网络上监听,必须设置 RUNSPECTOR_TOKEN,否则服务会拒绝启动。请注意,--host 0.0.0.0 会以纯 HTTP 提供服务,不使用 TLS,因此在该网络上,令牌以及应用返回的所有内容都会以未加密的形式传输,任何能查看流量的人都可以读取——这仅适用于你自己控制的局域网上供你自己的手机使用,不适用于你无法控制的网络。
配置
| 变量 | 默认值 | 用途 |
|---|---|---|
RUNSPECTOR_HOME | ~/.runspector | 数据目录 |
RUNSPECTOR_TZ | system zone | 用于判断“这次训练是哪一天”的 IANA 时区 |
RUNSPECTOR_TOKEN | – | 使用 --host 0.0.0.0 时必需(家庭网络中的手机) |
RUNSPECTOR_MODEL | CLI default | 教练卡片使用的模型 |
RUNSPECTOR_GARMIN_TOKENS | ~/.runspector/garmin | 复用现有的 python-garminconnect 令牌目录 |
RUNSPECTOR_AUTOSYNC_MIN | 30 | 在 Claude Code / Desktop 聊天中,若上次同步距今超过此时长,get_training_readiness 会先同步;设为 0 可关闭 |
RUNSPECTOR_QUOTA_WAIT_S | 3600 | 作业等待订阅配额的时长 |
RUNSPECTOR_JOB_TIMEOUT_S | 600 | 单个教练作业的硬超时时间 |
RUNSPECTOR_ALLOW_API_KEY | 未设置 | 设为 1 时,教练卡片会保留已导出的 ANTHROPIC_*(以及 Bedrock/Vertex)变量,并按 Token 计费;未设置时,卡片会移除这些变量。无论哪种情况,都会使用 Claude Code 本身配置的登录信息 |
RUNSPECTOR_ACTIVITY_BACKFILL_DAYS | 182 | 同步时获取的训练列表最短时间范围(习惯会回看 26 周;最近 35 天会获取心率区间详情) |
RUNSPECTOR_LT_HISTORY_DAYS | 180 | 获取乳酸阈值历史记录的回溯时间 |
RUNSPECTOR_LOG | WARNING | 日志级别——设为 INFO 或 DEBUG 可查看同步过程。INFO 和 DEBUG 也会记录 Web 应用的每个 HTTP 请求 |
另外还有四个变量(RUNSPECTOR_DB、RUNSPECTOR_DEMO、RUNSPECTOR_CLAUDE_CMD、RUNSPECTOR_PII_EXTRA)用于内部流程和测试;它们不属于受支持的功能范围。
可选的运动员资料:runspector profile --max-hr 182 --goal "sub-50 10k"。你的每周安排——每周训练天数、训练日、长距离跑、休息日、其他运动——可在“你”选项卡中设置(或使用 --days-per-week 和 --long-run-day);规划器会根据你留空的项目读取历史记录:你通常跑步的日期,以及最长距离跑通常安排在星期几。休息日绝不会被安排训练。给教练的备注是提供背景信息,而不是规则:规划器本身会遵守的是你设置的日期。
开发
git clone https://github.com/edxleon/runspector && cd runspector
uv run pytest -q # no database server, no network, no Garmin account needed
node --test "web-tests/*.test.mjs" # frontend logic
uv run ruff check # lint — config is real and the backlog is zero
npx --yes @biomejs/[email protected] lint --error-on-warnings # frontend lint (biome.jsonc)
uv run python evals/run_evals.py # prompt regression (uses your Claude subscription)
uv run python scripts/pii_gate.py # release gate
状态与路线图
v0.1 对 Garmin 只读。v0.2 增加了写入功能:propose_workout 会根据你自己的心率区间为你的路线制定训练,并将其保存;propose_week 会将一个极化训练周作为一个整体保存;在红色日期,训练提案可以替换日历中的高强度训练;apply_workout 会上传、排期、推送到手表,并读取回来进行验证。应用中的卡片运行无法应用任何内容;在应用中,点击卡片上的按钮(“推送到手表”,点两次)即可应用提案;在 Claude Code 中,则通过你的回答应用——撤销时也采用相同方式,因为无法撤销的写入,没人会第一次就去做。
已在真实账户上运行过的操作(而不只是测试套件使用的模拟 Garmin 客户端):2026-10-28,通过 runspector mcp 执行了一次轻松训练——根据运动员自己的心率区间生成提案并上传、排期、推送、在手表上确认、读取回来并验证,随后撤销;每一步都由第二个独立的 Garmin 客户端交叉核验。应用中的按钮调用相同的 plan.apply 和 plan.undo。尚未在真实环境中运行:作为一个整体提交的 propose_week,以及取消日历项目排期的红色日期替换。只有一名运动员、一个账户、一块手表。
路线图
docs/roadmap.md 是待办事项列表,按对跑者的价值排序:记录运动员自己的状态(生病、酸痛、感受如何),并持续记录直至恢复;为每次高强度训练提供一个更轻松的选项;按配速设定重复训练目标;采用自定义结构的训练;将计划训练与之后实际完成的跑步进行匹配;根据每个工作日可用的时间安排训练时长;将单调度作为第二项负荷指标;为早晨准备一个 runspector today;标明卡片上的每项结论来自何处;Garmin 自带的准备度指标;体重;更深入的历史记录;以及围绕目标赛事进行备赛。v0.3 让计划器能够读取历史记录,以安排接下来的训练;其余事项及其原因和排序也都列在其中。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。