内容
# garmin-cli
用于从Garmin Connect提取健康、活动、锻炼和性能数据的命令行工具。设计用于人类使用(表格输出)和LLM代理使用(JSON输出)。
## 安装
从PyPI(发行版为`garmin-py`;安装命令为`garmin-cli`):
```bash
pip install garmin-py
```
或从本地checkout:
```bash
pip install .
```
验证安装:
```bash
garmin-cli --version
```
## 身份验证
`garmin-cli`通过维护的[`python-garminconnect`](https://github.com/cyberjunky/python-garminconnect)后端进行身份验证。主要会话首页现在是`GARMIN_HOME` / `--garmin-home`;`GARTH_HOME` / `--garth-home`仍然作为已弃用的兼容性别名。
### 交互式登录(推荐)
```bash
garmin-cli login
# 邮箱: your@email.com
# 密码: (隐藏)
# 登录成功。令牌存储在: ~/.garminconnect/garmin_tokens.json
```
使用 `--email` / `--password` 跳过提示(适用于脚本):
```bash
garmin-cli login --email your@email.com --password yourpassword
```
在任何时候检查登录状态:
```bash
garmin-cli login status
# 已登录。令牌存储在: ~/.garminconnect/garmin_tokens.json
garmin-cli --json login status
# {"ok": true, "command": "login status", "count": 1, "data": [{"authenticated": true, "garmin_home": "..."}]}
```
### 环境变量(替代方案)
```bash
export GARMIN_EMAIL="your@email.com"
export GARMIN_PASSWORD="yourpassword"
garmin-cli health sleep --days 1
```
| 变量 | 默认值 | 描述 |
| --- | --- | --- |
| `GARMIN_EMAIL` | - | 凭证登录的账户邮箱 |
| `GARMIN_PASSWORD` | - | 凭证登录的账户密码 |
| `GARMIN_CLI_HTTP_TIMEOUT` | `30` | 秒为单位的HTTP请求超时时间(浮点数);无效或非正值回退到 `30` |
| `GARMIN_CLI_RETRY_DELAYS` | `2,4,8` | 以逗号分隔的重试延迟序列(秒为单位)(例如 `1,2,4`);无效值回退到 `2,4,8` |
| `GARMIN_CLI_AUTH_PROBE_TTL` | `600` | 秒为单位的缓存成功身份验证探测时间(浮点数);`0` 禁用缓存并在每次调用时探测 |
| `GARMIN_CLI_DAILY_CALL_DELAY` | `0.5` | 秒为单位的请求提交延迟(浮点数)间隔为每天的端点(例如 `daily-summary`);无效或负值回退到 `0.5` |
| `GARMIN_CLI_FETCH_CONCURRENCY` | `4` | 并发扇出抓取的 worker 限制(每天范围,报告快照部分,多运动子项);无效或非正值回退到 `4` |
### 自定义会话目录
```bash
garmin-cli --garmin-home /path/to/session login
garmin-cli --garmin-home /path/to/session health sleep --days 1
```
默认会话目录为 `~/.garminconnect`。它以 `0o700` 权限创建。拒绝符号链接。不要共享此目录。
新会话存储为 `garmin_tokens.json`,位于 `GARMIN_HOME` 内。如果您仍然拥有现有的 `~/.garth/garmin_tokens.json`,则 CLI 将在首次使用时将其复制到新的默认首页。`GARTH_HOME` / `--garth-home` 仍然作为已弃用的别名工作,当您需要显式保留旧路径时。
## 输出格式
所有命令默认输出表格。使用 `--json` 或 `--format csv` 更改:
```bash
garmin-cli health sleep --days 7 # 表格(默认)
garmin-cli --json health sleep --days 7 # JSON 信封
garmin-cli --format csv health sleep --days 7 # CSV
```
**JSON 信封结构:**
```json
{
"ok": true,
"command": "health sleep",
"date_range": {"from": "2026-03-05", "to": "2026-03-11"},
"count": 7,
"data": [
{"date": "2026-03-05", "bedtime": "2026-03-04T23:10:00", "wake_time": "2026-03-05T06:25:00", "duration_hours": 7.2, "score": 78, ...}
]
}
```
**错误信封:**
```json
{
"ok": false,
"command": "health sleep",
"error": "Rate limited by Garmin. Try again later.",
"error_code": "RATE_LIMITED"
}
```
退出代码始终为 `0` 表示成功,`1` 表示错误。
## 命令
### 健康
```bash
garmin-cli health sleep [--date DATE | --from DATE --to DATE | --days N]
garmin-cli health hrv [--date DATE | --from DATE --to DATE | --days N]
garmin-cli health weight [--date DATE | --from DATE --to DATE | --days N]
garmin-cli health body-battery [--date DATE | --from DATE --to DATE | --days N]
garmin-cli health stress [--date DATE | --from DATE --to DATE | --days N]
garmin-cli health spo2 [--date DATE | --from DATE --to DATE | --days N]
garmin-cli health resting-hr [--date DATE | --from DATE --to DATE | --days N]
garmin-cli health readiness [--date DATE | --from DATE --to DATE | --days N]
garmin-cli health status [--date DATE]
garmin-cli health steps [--date DATE | --from DATE --to DATE | --days N]
garmin-cli health daily-summary [--date DATE | --from DATE --to DATE | --days N]
garmin-cli health intensity-minutes [--date DATE | --from DATE --to DATE | --days N]
```
`health daily-summary` 对每天进行一次 API 调用 - 大范围的日期可能较慢。
`health status` 返回 Garmin 的完整训练负荷图景,涵盖当天的训练状态、急/慢性负荷、急:慢性工作负荷比(ACWR)、慢性负荷“隧道”、月负荷聚焦桶及其目标,以及负荷平衡状态。
### 活动
```bash
garmin-cli activity list [--limit N] [--type TYPE] [--search TEXT] [--date DATE | --from DATE --to DATE | --days N]
garmin-cli activity get ACTIVITY_ID [--detail] [--laps] # --detail/-d 显示运动感知指标;--laps 附加圈数据
garmin-cli activity laps ACTIVITY_ID # 每圈行(跑/骑行:心率,功率,踏频,start_time_gmt/local)或每泳池长度行(lap_swimming)
garmin-cli activity zones ACTIVITY_ID # 心率分区时间分布
garmin-cli activity weather ACTIVITY_ID # 温度,表观温度,露点,湿度,风,条件
garmin-cli activity metrics-describe ACTIVITY_ID # 指标描述:键,单位,metricsIndex
garmin-cli activity detail-metrics ACTIVITY_ID [--metric KEY]... # 原始每样本时间序列(一个活动约 2000 行;列为手表的指标键,如 directTimestamp,directHeartRate,directPower)
garmin-cli activity download ACTIVITY_ID [--fmt original|tcx|gpx|kml|csv] [--output PATH] [--force]
garmin-cli activity upload FILE # .fit / .gpx / .tcx
garmin-cli activity delete ACTIVITY_ID [--confirm]
garmin-cli activity rename ACTIVITY_ID NEW_NAME
garmin-cli activity set-type ACTIVITY_ID TYPE_KEY # 例如:running,cycling
```
`--limit` 默认值为 20,最大值为 100。 `--type` 按活动类型键过滤(例如 `running`,`cycling`)。
`activity detail-metrics` 返回原始记录的样本流(~2000 行典型活动;列为手表的指标键,如 `directTimestamp`,`directHeartRate`,`directPower`)。使用可重复的 `--metric` 标志选择列 - `activity metrics-describe` 列出给定活动记录了哪些指标。这是用于活动内分析的指标数据,例如前半部分与后半部分的有氧解耦。
`activity download` 将活动文件写入磁盘(它从不将二进制文件打印到 stdout)。 `--fmt` 默认值为 `original`(ZIP 存档内的 FIT 文件);默认输出名称为 `activity_<id><ext>`,位于当前目录,如果给出 `--force`,则不会覆盖现有文件。 `activity delete` 在给出 `--confirm` 时提示确认。 `activity set-type` 接受 Garmin 的实时运动类型表中的任何 `typeKey`(未知键在写入前被拒绝)。
#### 详细的运动特定指标
`activity get --detail` 针对活动的运动类型投影指标:
| 运动 | 详细模式指标(除了基本汇总,心率,卡路里,升降,速度,持续时间) |
| --- | --- |
| 自行车 | 平均/最大/标准化功率,踏频(rpm),TSS,强度因子,训练效果,VO2最大值,恢复时间 |
| 跑步 | 踏频(spm),接地时间,垂直振荡/比率,步长,训练效果,VO2最大值,恢复时间 |
| 泳池游泳 | SWOLF,总划桨次数,平均划桨率,每次划桨距离,训练效果 |
| 开水游泳 | 通用额外 + 训练效果(无每长度划桨指标) |
每个运动还包含通用训练反应字段:`training_effect_label`(Garmin 的主要受益标签,如 `TEMPO`),`training_load`(基于活动的 EPOC 负载)和 `workout_id`(执行的结构化锻炼,链接计划到执行)。 `training_load` 也出现在 `activity list` 行中。
`duration_min` 是移动时间;`elapsed_time_min` 是总时钟时间,因此 `elapsed - moving` 是停止的时间。
JSON 和 CSV 输出使用稳定的联合模式 - 每个键都存在(对于不适用的运动指标为 `null`),因此下游解析器会看到稳定的形状。表格输出是运动感知的:只有运动适用的列才会出现,保持表格紧密。
当 `--detail` 设置时,JSON 还包含一个 `unavailable` 数组,描述哪些注册已知的指标未为此活动生成。每个条目都有 `field`、`reason`(`not_applicable_to_sport` 或 `absent_in_response`)和 `leg_index`(在多运动子贡献中设置)。表格输出打印单个仅计数页脚;CSV 输出保持扁平表格格式,不携带清单。
```bash
# 自行车详情
garmin-cli activity get 12345678 --detail
# 运行详情带心率分区
garmin-cli activity get 12345678 --detail
garmin-cli activity zones 12345678
# 泳池游泳每长度行(自动路由到 typed_splits)
garmin-cli activity laps 12345678
# 自行车详情 + 圈功率套件在一个信封中
garmin-cli --json activity get 12345678 --detail --laps
```
### 锻炼
```bash
# 读取
garmin-cli workout list [--limit N]
garmin-cli workout get WORKOUT_ID
garmin-cli workout calendar [--from DATE --to DATE | --days N | --ahead N]
# 写入
garmin-cli workout create FILE # JSON 或 YAML 文件
garmin-cli workout create --stdin # 从 stdin 读取 JSON
garmin-cli workout update WORKOUT_ID FILE # 部分更新(仅提供字段更改)
garmin-cli workout delete WORKOUT_ID [--confirm] # --confirm 跳过交互式提示
garmin-cli workout schedule WORKOUT_ID DATE # DATE = YYYY-MM-DD
garmin-cli workout unschedule SCHEDULE_ID [--confirm] # 删除日历条目;SCHEDULE_ID 是 workoutScheduleId 返回的 schedule
```
`--ahead N` 显示接下来的 N 天计划的锻炼(未来)。 `--days N` 显示过去 N 天。
YAML 输入开箱即支持。参见 [SKILL.md](SKILL.md) 完整的锻炼 JSON 架构参考和步骤/目标类型。
### 性能
```bash
garmin-cli performance thresholds
garmin-cli performance zones
garmin-cli performance vo2max
garmin-cli performance race-predictions
garmin-cli performance endurance-score [--date DATE | --from DATE --to DATE | --days N]
garmin-cli performance hill-score [--date DATE | --from DATE --to DATE | --days N]
garmin-cli performance personal-records
```
`performance endurance-score` 和 `performance hill-score` 对每天进行一次 API 调用 - 大范围的日期可能较慢。
`performance personal-records` 返回所有时间最优记录(最快 1 公里至马拉松,最长跑/骑行,最大爬升,最佳 20 分钟功率,步数记录)带有人类可读的 `label`;Garmin 未公开的类型 ID 携带 `label: null` 与原始值。
### 设备
```bash
garmin-cli device list # 注册设备:device_id, display_name, device_type, last_sync_time
```
## 标准化 JSON 架构
最近的修复标准化了几个 JSON 有效载体以支持代理安全输出:
- `performance vo2max` 返回 `date`、`vo2max`、`sport`
- `performance zones` 返回 `sport`、`lt_hr_bpm`、`lt_pace`
- `workout calendar` 包括 `id`
- `workout get` 包括 `steps` 和 `steps_summary`
- `health hrv` 读取 `lastNightAvg` 仍然回退到旧的 `lastNight`
## 日期范围选项
| 选项 | 含义 | 示例 |
| --- | --- | --- |
| `--date DATE` | 单日 | `--date 2026-03-11` |
| `--days N` | 过去 N 天(包括) | `--days 7` |
| `--from DATE --to DATE` | 显式范围(两者均包括) | `--from 2026-03-01 --to 2026-03-11` |
| `--ahead N` | 下一个 N 天的日历日历(仅限日历) | `--ahead 7` |
最大范围:90 天。冲突的选项(例如 `--date` 和 `--days`)会产生一个清晰的错误。
## 示例
```bash
# 最近一周的睡眠数据
garmin-cli health sleep --days 7
# 特定日期范围的 HRV
garmin-cli health hrv --from 2026-03-01 --to 2026-03-10
# 以 CSV 格式列出最近的跑步活动
garmin-cli --format csv activity list --limit 10 --type running
# 特定日期范围内的活动
garmin-cli activity list --from 2026-03-01 --to 2026-03-31
# 过去 7 天的活动
garmin-cli activity list --days 7
# 即将计划的锻炼
garmin-cli workout calendar --ahead 7
# 从 JSON 文件创建锻炼
garmin-cli --json workout create my_workout.json
# 通过 stdin 创建并计划锻炼
echo '{"name":"Easy Run","sport":"running","steps":[{"type":"interval","duration":{"type":"time","value":1800},"target":{"type":"heart.rate.zone","zone":2}}]}' \
| garmin-cli --json workout create --stdin
# 安排现有锻炼
garmin-cli --json workout schedule 12345678901 2026-04-01
# 所有性能阈值
garmin-cli performance thresholds
# 代理使用:用于脚本的 JSON 输出
garmin-cli --json health hrv --date 2026-03-11
garmin-cli --json activity list --limit 5
```
## 错误代码
| 代码 | 含义 |
| --- | --- |
| `AUTH_MISSING` | 未找到凭证(无会话且无环境变量) |
| `AUTH_FAILED` | 凭证被 Garmin 拒绝 |
| `NOT_FOUND` | API 端点不可用(404) |
| `RATE_LIMITED` | 3 次重试后返回 429 |
| `SERVER_ERROR` | 3 次重试后返回 5xx |
| `NETWORK_ERROR` | 连接或超时失败 |
| `INVALID_INPUT` | 错误的参数或冲突的选项 |
| `INTERNAL_ERROR` | 意外的错误 |
## MCP 服务器(可选)
将 garmin-cli 暴露为 MCP 工具服务器,用于本地或远程 MCP 客户端。包括健康、活动、锻炼、性能和设备的读取工具,以及锻炼的写入工具(`workout_create`、`workout_schedule`、`workout_update`、`workout_delete`、`workout_unschedule`),以及活动(`activity_download`、`activity_upload`、`activity_delete`、`activity_rename`、`activity_set_type`)。`report_snapshot` 工具组装了一个完整的日报/晚报/周报,在一次调用中展开底层读取 - 设计用于定期智能代理每日摘要。参见 [SKILL.md](SKILL.md#report_snapshot-section-composition) 获取其章节组成。
### 安装
该软件包在 PyPI 上以 `garmin-py` 发布(CLI 命令仍为 `garmin-cli`)。推荐的安装方法是 `uv tool install`,它将二进制文件放在 `~/.local/bin` 中 - 一个稳定、与 venv 无关的位置,桌面应用程序可以访问而无需 macOS 沙盒问题:
```bash
uv tool install "garmin-py[mcp]"
```
或从源代码 checkout:
```bash
uv tool install --editable "/path/to/garmin-py[mcp]"
```
要卸载:
```bash
uv tool uninstall garmin-py
```
**避免将 MCP 客户端指向项目虚拟环境中的二进制文件**(例如 `.venv/bin/garmin-cli`)。在 macOS 上,桌面应用程序在沙盒中运行,无法读取 `pyvenv.cfg`,位于它们未获得访问权限的目录中,这会导致 Python 启动时出现致命错误:
```
PermissionError: [Errno 1] Operation not permitted: '/path/to/.venv/pyvenv.cfg'
```
`uv tool install` 方法完全避免了这一点。或者,授予 Claude Desktop 在系统设置中完全访问磁盘权限 -> 隐私和安全 -> 完全访问磁盘。
### 克劳德桌面
将以下内容添加到您的克劳德桌面配置文件:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"garmin": {
"command": "/Users/YOU/.local/bin/garmin-cli",
"args": ["mcp-server"]
}
}
}
```
使用自定义会话目录:
```json
{
"mcpServers": {
"garmin": {
"command": "/Users/YOU/.local/bin/garmin-cli",
"args": ["--garmin-home", "/path/to/.garminconnect", "mcp-server"]
}
}
}
```
### 克劳德代码
```bash
claude mcp add --transport stdio garmin -- garmin-cli mcp-server
```
### ChatGPT(通过 MCP 桥接)
ChatGPT 不原生支持 MCP。要连接,请使用 HTTP 传输运行服务器,并使用 MCP 到 OpenAI 桥接器,例如 [mcp-openai-bridge](https://github.com/nicobailey/mcp-openai-bridge) 或类似的代理:
```bash
# 启动带有流式 HTTP 的 MCP 服务器
garmin-cli mcp-server --transport streamable-http --host 127.0.0.1 --port 8000
```
然后将桥接器指向 `http://127.0.0.1:8000/mcp`,并将其配置为 ChatGPT 插件或自定义 GPT 操作。有关设置详细信息,请参阅桥接器项目的文档。
### HTTP 传输
SSE 和流式 HTTP 使用 MCP SDK 的内置 HTTP 服务器。 `--host` 默认值为 `127.0.0.1`(仅限环回)。
流式 HTTP(推荐用于远程客户端):
```bash
garmin-cli mcp-server --transport streamable-http --port 8000
```
SSE(适用于需要它的客户端):
```bash
garmin-cli mcp-server --transport sse --port 8000
```
可选的 HTTP 标志: `--sse-path`、`--message-path`(仅限 SSE)、 `--streamable-http-path`、`--stateless-http`、`--json-response`(仅限流式 HTTP)。
#### 非环回绑定上的 Bearer-token 关卡
绑定到任何非环回地址( `--host 0.0.0.0` 或外部接口)需要一个 bearer token。否则,服务器拒绝启动。
```bash
export GARMIN_MCP_BEARER_TOKEN="<a-long-random-token>"
garmin-cli mcp-server --transport streamable-http --host 0.0.0.0 --port 8000
```
当设置了令牌并且绑定为非环回时,MCP SDK 在传输层通过 `Authorization: Bearer <token>` 保护每个工具调用(读 **和** 写)。环回绑定(`127.0.0.1`、`::1`、`localhost`)和 `stdio` 传输不受保护 -- 它们被信任到与运行进程的 shell 用户相同的程度。
TLS 预计由服务器前面的反向代理终止;内置 HTTP 监听器是纯 HTTP。
对于远程客户端,请使用 `--garmin-home` 指定一个专用会话目录,而不是将凭证导出到另一个进程中。
参见 [SKILL.md](SKILL.md#mcp-server-alternative) 获取完整的工具列表和参数参考。
## 开发
```bash
pip install -e ".[dev]"
pytest tests/ # 单元测试(超过 1100 个测试)
pytest tests/ --e2e # 单元测试 + 集成测试(需要 GARMIN_HOME/garmin_tokens.json)
```
要运行 MCP 服务器测试,还需要安装 mcp 额外依赖:
```bash
pip install -e ".[dev,mcp]"
```
E2E 测试会调用真实的 Garmin Connect API 调用。它们需要一个有效的 `garmin_tokens.json` 会话,位于 `~/.garminconnect`(或 `GARMIN_HOME`;`GARTH_HOME` 仍然作为别名)。设置 `E2E_RATE_LIMIT_SECONDS`(默认:5)以调整请求间隔。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器