Sync WHOOP wearable data to health/whoop-YYYY-MM-DD.md files. Pure Python, zero dependencies.
Recovery (score/HRV/RHR/SpO2/skin temp), Sleep (performance/efficiency/stages/respiratory rate/sleep need/balance), Day Strain (strain/calories/HR), Workouts (sport/duration/strain/HR/zones/distance), Weekly summaries.
http://localhost:9527/callback → select all read:* + offline scopesEnv vars:
export WHOOP_CLIENT_ID="your-id"
export WHOOP_CLIENT_SECRET="your-secret"
Or 1Password: Create Login item named whoop (username=Client ID, password=Client Secret).
Local (browser on same machine):
python3 scripts/auth.py
Remote server (headless):
python3 scripts/auth.py --print-url
# User opens URL in browser, authorizes, copies callback URL back
python3 scripts/auth.py --callback-url "http://localhost:9527/callback?code=xxx&state=yyy"
Tokens auto-refresh via offline scope. Authorize once, runs forever.
python3 scripts/sync.py # Sync today
python3 scripts/sync.py --days 7 # Last 7 days
python3 scripts/sync.py --weekly # Weekly summary
python3 scripts/sync.py --date 2026-03-07 # Specific date
Output: ~/.openclaw/workspace/health/whoop-YYYY-MM-DD.md
openclaw cron add \
--name whoop-daily \
--schedule "0 10 * * *" \
--timezone Asia/Shanghai \
--task "Run: python3 ~/.openclaw/workspace/skills/whoop/scripts/sync.py --days 2. Then read the generated markdown files and send me the latest day's report."
| Problem | Fix |
|---|---|
| --------- | ----- |
No tokens found | Run auth.py first |
Token refresh failed (403) | Re-run auth.py to re-authorize |
error code: 1010 | Cloudflare block — uses curl to avoid. Check network |
No data for date | WHOOP finalizes sleep after waking; try later |
auth.py --print-url, send URL, wait for callback URLsync.py --days 1curl to bypass Cloudflare blocking Python urllib共 1 个版本