WHOOP Skill
Fetch, interpret, chart, and track your WHOOP data via the WHOOP Developer API (v2).
Data Directory
All user-specific data is stored in ~/.config/whoop-skill/ — separate from the skill install directory, which is read-only.
CODEBLOCK0
The directory and credentials.json are created automatically when you run scripts/auth.py. You never need to create them manually.
Setup
Before you begin: This skill requires a WHOOP Developer App to authenticate with the WHOOP API. It's free and takes about 2 minutes to set up.
Step 0 — Install Python dependencies
CODEBLOCK1
Step 1 — Choose your callback method
Before creating your WHOOP app, decide how you want to handle the OAuth callback:
Option A — Local server (local installs)
- - Redirect URI: INLINECODE3
- A temporary server runs on your machine to catch the redirect automatically
- Requires a browser on the same machine as OpenClaw
Option B — Manual code paste (remote/cloud installs)
- - Redirect URI: INLINECODE4
- The script prints an authorization URL — open it in any browser, authorize, then copy the
?code= value from the redirect URL and paste it back into the script - Nothing passes through any external server — fully self-contained
Step 2 — Create a WHOOP Developer App
- 1. Go to https://developer-dashboard.whoop.com
- Sign in with your WHOOP account
- Create a Team if prompted (any name works)
- Click Create App and fill in:
-
App name: anything (e.g. "My WHOOP Skill")
-
Redirect URI: the URI from Step 1 (Option A or B)
-
Scopes: select all
read:* scopes +
offline
- 5. Copy your Client ID and Client Secret — you'll need them in the next step
Step 3 — Run the setup script
CODEBLOCK2
This will:
- 1. Prompt you for your Client ID and Client Secret
- Ask which callback method you chose in Step 1 (local server or manual)
- Walk you through the authorization flow
- Save credentials to INLINECODE8
Customize paths (optional):
Copy config.example.json from the skill root to ~/.config/whoop-skill/config.json and edit to override defaults:
CODEBLOCK3
Workflow
- 1. Load credentials from INLINECODE11
- If
expires_at is in the past (or within 60s), call scripts/refresh_token.py to get a new access token and update the file - Call the appropriate endpoint (see
references/api.md) - Parse and present the data in plain language
Common Requests
- - "How's my recovery today?" → GET latest recovery score, HRV, RHR
- "How did I sleep?" → GET latest sleep (performance %, stages, duration)
- "What's my strain today?" → GET latest cycle strain + avg HR
- "Show my recent workouts" → GET workout collection (last 5–7) via INLINECODE15
- "Give me a health summary" → Combine recovery + sleep + today's cycle
Token Refresh
Run scripts/refresh_token.py when the access token is expired. It reads/writes ~/.config/whoop-skill/credentials.json automatically.
To re-auth from scratch, run scripts/auth.py again.
API Base URL
INLINECODE19
All requests: INLINECODE20
See references/api.md for endpoint details, scopes, and response shapes. For the full official API documentation (including error codes and rate limits), see https://developer.whoop.com/api.
Fetching Data (scripts/fetch.py)
General-purpose API fetcher. Used internally by other scripts.
CODEBLOCK4
Output is JSON to stdout.
Charting (scripts/chart.py)
Generates self-contained HTML charts using Chart.js (CDN). Dark theme with stat cards showing avg/min/max + trend arrow. Opens in browser automatically.
Chart Types
| Chart | Description |
|---|
| INLINECODE24 | Bar chart color-coded green/yellow/red by recovery score |
| INLINECODE25 |
Stacked bar: REM / Deep / Light / Awake per night |
|
hrv | Line chart with 7-day rolling average overlay |
|
strain | Bar chart with calories as secondary line axis |
|
dashboard | 2×2 grid of all four charts |
Usage
CODEBLOCK5
Flags
| Flag | Default | Description |
|---|
| INLINECODE29 | (required) | Chart type: recovery, sleep, hrv, strain, dashboard |
| INLINECODE30 |
30 | Days of history to fetch |
|
--output |
/tmp/whoop-<chart>.html | Output file path |
|
--no-open | false | Don't auto-open in browser |
Chart Delivery (always do both)
After running chart.py, the script prints the output file path to stdout. Always:
- 1. Attach the HTML file to the Telegram message — so remote users get it instantly
- Auto-open in browser (default, unless
--no-open) — so local users get it immediately
This means both local and remote users are covered without any configuration. The file is self-contained, static, and safe to share — no credentials or API calls embedded.
Experiment Tracking (scripts/experiment.py)
Define, monitor, and evaluate personal health experiments. Data stored in ~/.config/whoop-skill/experiments.json.
Supported Metrics
INLINECODE38 , recovery, sleep_performance, rhr, INLINECODE42
Commands
Plan a new experiment
CODEBLOCK6
Baseline is auto-captured from the 14 days before --start. Override manually:
CODEBLOCK7
Plan with post-workout segmentation
Use --segment-workouts when your hypothesis is specifically about recovery after training sessions rather than overall daily averages. The tracker will fetch your workout history, identify qualifying sessions, and measure recovery metrics only in the 24–48h window after each workout.
CODEBLOCK8
Flags:
- -
--segment-workouts — enables post-workout segmentation mode - INLINECODE46 — minimum workout strain to qualify (default: 5.0). Filters out light activity like walking or yoga.
- INLINECODE47 — recovery window to measure, e.g.
1-2 (days 1 and 2 after workout) or 1 (next day only). Default: INLINECODE50
When segmentation is on, status and report show two views: overall rolling averages (all days) and post-workout recovery (only the days after qualifying workouts). The verdict is evaluated against the post-workout view.
The post-workout baseline is also segmented — auto-captured from qualifying workouts in the 14 days before --start — so the comparison is apples-to-apples.
Add segmentation to an existing experiment
CODEBLOCK9
Patches a previously created experiment to add post-workout segmentation and recomputes the post-workout baseline from the original baseline window.
List experiments
CODEBLOCK10
Check status (mid-experiment)
python3 scripts/experiment.py status --id <id>
Shows current averages vs baseline with % change and trend arrows. If segmentation is enabled, shows both overall and post-workout views with a per-workout breakdown.
Final report
python3 scripts/experiment.py report --id <id>
Full before/after comparison, verdict (met / partially met / not met / inconclusive), plain-language summary. Verdict is evaluated on post-workout data when segmentation is on.
Obsidian Logging (scripts/log_to_obsidian.py) (optional)
This feature is entirely optional. If you don't use Obsidian, skip this section — the rest of the skill works without it. To enable it, set vault_path in ~/.config/whoop-skill/config.json to your Obsidian vault directory. The script will not run if no vault is configured.
Note: git is declared as a dependency because the script calls git commands, but it is only ever invoked if your Obsidian vault is a git repository. If the vault directory has no .git folder, the script detects this, writes the daily note, and skips all git commands — no errors, no git required in practice.
Appends today's WHOOP stats to the Obsidian daily note at:
<vault_path>/Daily Notes/YYYY-MM-DD.md (configured via vault_path in ~/.config/whoop-skill/config.json)
After writing, commits and pushes the vault (git add -A && git commit && git push).
Usage
CODEBLOCK13
Output format in daily note
CODEBLOCK14
- - Creates the daily note if it doesn't exist
- Skips silently if the WHOOP section already exists
- Idempotent — safe to run multiple times
Morning Brief Integration
Add the following snippet to HEARTBEAT.md to include WHOOP recovery + HRV in morning briefs.
CODEBLOCK15
Copy-paste ready HEARTBEAT.md snippet:
CODEBLOCK16
Health Interpretation
See references/health_analysis.md for a science-backed guide covering:
- - HRV (RMSSD) ranges by age, what trends mean, red flags
- Resting heart rate interpretation by fitness level
- Sleep stage breakdown (deep/REM/light targets, deficit consequences)
- Recovery score zones (green/yellow/red) and recommended actions
- Strain scale and how to match strain to recovery
- SpO2 and skin temperature context
- Overtraining pattern recognition
- When to see a doctor
References
- -
references/api.md — Full WHOOP API endpoint reference - INLINECODE66 — Health metric interpretation guide
- WHOOP Developer Dashboard: https://developer-dashboard.whoop.com
- WHOOP API docs: https://developer.whoop.com/api
WHOOP 技能
通过 WHOOP 开发者 API(v2)获取、解读、图表化并追踪您的 WHOOP 数据。
数据目录
所有用户特定数据存储在 ~/.config/whoop-skill/ 中——与只读的技能安装目录分开。
~/.config/whoop-skill/
credentials.json — OAuth 令牌(首次设置时由 auth.py 创建)
experiments.json — 实验追踪数据(首次执行 plan 命令时创建)
config.json — 可选的路径/时区覆盖(从 config.example.json 复制)
该目录和 credentials.json 会在您运行 scripts/auth.py 时自动创建。您无需手动创建它们。
设置
开始之前: 此技能需要一个 WHOOP 开发者应用来与 WHOOP API 进行身份验证。它是免费的,大约需要 2 分钟设置。
第 0 步 — 安装 Python 依赖
bash
pip install -r requirements.txt
第 1 步 — 选择您的回调方法
在创建 WHOOP 应用之前,决定如何处理 OAuth 回调:
选项 A — 本地服务器 (本地安装)
- - 重定向 URI: http://localhost:8888/callback
- 您的机器上会运行一个临时服务器来自动捕获重定向
- 需要与 OpenClaw 在同一台机器上的浏览器
选项 B — 手动粘贴代码 (远程/云端安装)
- - 重定向 URI: http://localhost:8888/callback
- 脚本会打印一个授权 URL — 在任何浏览器中打开它,授权,然后从重定向 URL 中复制 ?code= 值并粘贴回脚本
- 没有任何内容通过外部服务器 — 完全自包含
第 2 步 — 创建一个 WHOOP 开发者应用
- 1. 访问 https://developer-dashboard.whoop.com
- 使用您的 WHOOP 账户登录
- 如果提示,创建一个团队(任何名称都可以)
- 点击 创建应用 并填写:
-
应用名称: 任意名称(例如 My WHOOP Skill)
-
重定向 URI: 第 1 步中的 URI(选项 A 或 B)
-
作用域: 选择所有 read:* 作用域 + offline
- 5. 复制您的 客户端 ID 和 客户端密钥 — 您将在下一步中需要它们
第 3 步 — 运行设置脚本
bash
python3 scripts/auth.py
这将:
- 1. 提示您输入客户端 ID 和客户端密钥
- 询问您在第 1 步中选择的回调方法(本地服务器或手动)
- 引导您完成授权流程
- 将凭据保存到 ~/.config/whoop-skill/credentials.json
自定义路径(可选):
将技能根目录中的 config.example.json 复制到 ~/.config/whoop-skill/config.json 并编辑以覆盖默认值:
json
{
creds_path: ~/.config/whoop-skill/credentials.json,
vault_path: ~/my-obsidian-vault,
dailynotessubdir: Daily Notes,
timezone: America/New_York,
logged_by: Assistant
}
工作流程
- 1. 从 ~/.config/whoop-skill/credentials.json 加载凭据
- 如果 expiresat 已过期(或在 60 秒内),调用 scripts/refreshtoken.py 获取新的访问令牌并更新文件
- 调用相应的端点(参见 references/api.md)
- 用通俗语言解析和呈现数据
常见请求
- - 我今天恢复得怎么样? → 获取最新的恢复分数、HRV、RHR
- 我睡得怎么样? → 获取最新的睡眠(表现百分比、阶段、时长)
- 我今天的状态如何? → 获取最新的周期状态 + 平均心率
- 显示我最近的锻炼 → 通过 /activity/workout 获取锻炼集合(最近 5–7 次)
- 给我一个健康摘要 → 结合恢复 + 睡眠 + 今天的周期
令牌刷新
当访问令牌过期时运行 scripts/refresh_token.py。它会自动读取/写入 ~/.config/whoop-skill/credentials.json。
要重新从头开始认证,再次运行 scripts/auth.py。
API 基础 URL
https://api.prod.whoop.com/developer/v2
所有请求:Authorization: Bearer
有关端点详情、作用域和响应结构,请参见 references/api.md。有关完整的官方 API 文档(包括错误代码和速率限制),请参见 https://developer.whoop.com/api。
获取数据 (scripts/fetch.py)
通用 API 获取器。由其他脚本内部使用。
bash
最新的恢复数据
python3 scripts/fetch.py /recovery --limit 1
最近 30 天的睡眠数据
python3 scripts/fetch.py /activity/sleep --limit 30
最近 7 天的锻炼数据
python3 scripts/fetch.py /activity/workout --limit 7
按日期范围获取
python3 scripts/fetch.py /recovery --start 2026-02-01 --end 2026-02-28
用户资料
python3 scripts/fetch.py /user/profile/basic
输出为 JSON 到标准输出。
图表化 (scripts/chart.py)
使用 Chart.js(CDN)生成自包含的 HTML 图表。深色主题,带有显示平均值/最小值/最大值和趋势箭头的统计卡片。自动在浏览器中打开。
图表类型
| 图表 | 描述 |
|---|
| recovery | 按恢复分数颜色编码为绿色/黄色/红色的条形图 |
| sleep |
堆叠条形图:每夜的 REM / 深睡 / 浅睡 / 清醒 |
| hrv | 带有 7 天滚动平均叠加的折线图 |
| strain | 带有卡路里作为次要折线轴的条形图 |
| dashboard | 所有四个图表的 2×2 网格 |
用法
bash
恢复图表(30 天)
python3 scripts/chart.py --chart recovery --days 30
完整仪表板
python3 scripts/chart.py --chart dashboard --days 30 --output ~/whoop-dashboard.html
HRV 趋势(90 天),不自动打开
python3 scripts/chart.py --chart hrv --days 90 --no-open
睡眠分解
python3 scripts/chart.py --chart sleep --days 14
状态 + 卡路里
python3 scripts/chart.py --chart strain --days 21
标志
| 标志 | 默认值 | 描述 |
|---|
| --chart | (必需) | 图表类型:recovery, sleep, hrv, strain, dashboard |
| --days |
30 | 要获取的历史天数 |
| --output | /tmp/whoop-
.html | 输出文件路径 |
| --no-open | false | 不在浏览器中自动打开 |
图表交付(始终执行两者)
运行 chart.py 后,脚本将输出文件路径打印到标准输出。始终:
- 1. 将 HTML 文件附加到 Telegram 消息 — 以便远程用户立即获取
- 在浏览器中自动打开(默认,除非使用 --no-open) — 以便本地用户立即获取
这意味着本地和远程用户都无需任何配置即可覆盖。该文件是自包含的、静态的,并且可以安全共享 — 没有嵌入凭据或 API 调用。
实验追踪 (scripts/experiment.py)
定义、监控和评估个人健康实验。数据存储在 ~/.config/whoop-skill/experiments.json 中。
支持的指标
hrv, recovery, sleep_performance, rhr, strain
命令
计划一个新实验
bash
python3 scripts/experiment.py plan \
--name 30 天不喝酒 \
--hypothesis HRV 将比基线增加 10% 以上 \
--start 2026-03-01 \
--end 2026-03-31 \
--metrics hrv,recovery,sleep_performance
基线自动从 --start 之前的 14 天捕获。手动覆盖:
bash
python3 scripts/experiment.py plan \
--name 冷水浸泡实验 \
--hypothesis RHR 将下降 3+ bpm \
--start 2026-03-10 --end 2026-04