Install
openclaw skills install oura-dataFetch the user's personal Oura Ring health data via the official Oura API v2, using the zero-dependency `oura-cli` Python tool. Use this skill when the user asks about their sleep (score, total/deep/REM/light duration, efficiency, bedtime, HRV, resting heart rate), daily readiness, activity (steps, calories, walking distance), heart rate, workouts, blood oxygen (SpO2), stress levels, body temperature deviation, or any other biometric tracked by their Oura Ring. Also use when the user asks "how did I sleep", "am I recovered", "should I push hard today", "should I rest", or wants historical data for specific dates or date ranges. Assumes `oura-cli` is cloned locally and OAuth-authorized; if not, the skill provides setup instructions.
openclaw skills install oura-dataQuery your Oura Ring sleep, readiness, activity, HRV, and biometric data via the official Oura API v2. Wraps the zero-dependency oura-cli Python tool — no Node, no Docker, no SaaS middleman, no telemetry. Your tokens stay on your machine.
Once installed, your assistant can answer questions like:
The skill does not invent numbers — every answer is grounded in a live API call.
This skill assumes oura-cli is cloned and OAuth-authorized locally. If commands fail with No tokens found or config.json not found, walk the user through setup — do not attempt to resolve automatically:
# 1. Clone the repo (one-time)
git clone https://github.com/zqchris/oura-cli ~/oura-cli
cd ~/oura-cli
# 2. Register an Oura API app at:
# https://cloud.ouraring.com → My Applications → New Application
# - Redirect URI: http://localhost:8080/callback
# - Scopes: enable all
# 3. Authorize (opens browser; one-time per machine)
uv run oauth-authorize.py --client-id <ID> --client-secret <SECRET>
# 4. Verify
uv run oura-data.py today
After first auth, tokens auto-refresh on HTTP 401. No manual renewal needed.
All commands run from inside the oura-cli directory:
uv run oura-data.py <subcommand> [--date YYYY-MM-DD | --start ... --end ...]
| Subcommand | Returns |
|---|---|
today / daily | Sleep + Activity + Readiness combined for today (or --date) |
sleep | Score, total/deep/REM/light durations, efficiency, bedtime, avg/lowest HR, HRV |
activity | Score, steps, active/total calories, walking distance |
readiness | Score, temperature deviation, score contributors |
heartrate | Min/max/avg BPM, sample count |
workout | Auto-detected and manual workouts (raw JSON) |
spo2 | Blood oxygen during sleep (raw JSON) |
stress | Stress levels (raw JSON) |
ring | Ring configuration & battery level |
personal | Age, weight, height, biological sex |
ring and personal)--date YYYY-MM-DD # single day (default: today)
--start YYYY-MM-DD --end YYYY-MM-DD # date range (any length)
# Today's full summary (sleep + activity + readiness)
uv run oura-data.py today
# Yesterday's sleep detail
uv run oura-data.py sleep --date $(date -v -1d +%Y-%m-%d)
# Last 7 days of readiness
uv run oura-data.py readiness \
--start $(date -v -7d +%Y-%m-%d) \
--end $(date +%Y-%m-%d)
# Sleep on a specific date
uv run oura-data.py sleep --date 2026-03-15
# Activity for a full month
uv run oura-data.py activity --start 2026-04-01 --end 2026-04-30
# Workouts this week
uv run oura-data.py workout \
--start $(date -v -7d +%Y-%m-%d) \
--end $(date +%Y-%m-%d)
For a Linux date equivalent, replace -v -7d with -d "7 days ago".
| Band | Meaning | Suggested response |
|---|---|---|
| 85+ | Optimal | Green light for hard training / demanding work |
| 70–84 | Good | Normal day; no special caveats |
| 60–69 | Fair | Suggest moderate intensity; recommend earlier bedtime |
| < 60 | Poor | Actively suggest rest if user asks "should I push?" |
Higher = better autonomic recovery. Always compare to the user's own trend, never to absolute population numbers — individual baselines vary 20–200ms.
| Symptom | Likely cause | Fix |
|---|---|---|
No tokens found | OAuth not yet completed | Run oauth-authorize.py (see Prerequisites) |
config.json not found | Refresh credentials missing | Re-run oauth-authorize.py |
API error 401 (after auto-refresh) | Refresh token revoked or expired | Re-run oauth-authorize.py |
API error 429 | Rate-limited (Oura cap: 5000/day) | Wait and retry |
API error 426 | Subscription required for this endpoint | Tell user the endpoint needs Oura membership |
| No data for a recent date | Ring hasn't synced yet | Ask user to open the Oura app on their phone |
Empty data array | No measurement on that date | Likely ring wasn't worn |
tokens.json or config.json — they contain OAuth secrets and client credentials.oura-cli directory — token files are resolved relative to the script.today first and ground recommendations in the actual readiness score and HRV.references/api-reference.md — full Oura API v2 endpoint dictionary, scopes, rate limitsreferences/example-outputs.md — real sample outputs for each subcommand