Query 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:
bash
# 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:
bash
uv run oura-data.py <subcommand> [--date YYYY-MM-DD | --start ... --end ...]
SubcommandReturnstoday / dailySleep + Activity + Readiness combined for today (or --date)sleepScore, total/deep/REM/light durations, efficiency, bedtime, avg/lowest HR, HRVactivityScore, steps, active/total calories, walking distancereadinessScore, temperature deviation, score contributorsheartrateMin/max/avg BPM, sample countworkoutAuto-detected and manual workouts (raw JSON)spo2Blood oxygen during sleep (raw JSON)stressStress levels (raw JSON)ringRing configuration & battery levelpersonalAge, weight, height, biological sex
ring and personal)#text
--date YYYY-MM-DD # single day (default: today)
--start YYYY-MM-DD --end YYYY-MM-DD # date range (any length)
bash
# 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".
BandMeaningSuggested response85+OptimalGreen light for hard training / demanding work70–84GoodNormal day; no special caveats60–69FairSuggest moderate intensity; recommend earlier bedtime< 60PoorActively 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.
SymptomLikely causeFixNo tokens foundOAuth not yet completedRun oauth-authorize.py (see Prerequisites)config.json not foundRefresh credentials missingRe-run oauth-authorize.py``API error 401 (after auto-refresh)Refresh token revoked or expiredRe-run oauth-authorize.py``API error 429Rate-limited (Oura cap: 5000/day)Wait and retryAPI error 426Subscription required for this endpointTell user the endpoint needs Oura membershipNo data for a recent dateRing hasn't synced yetAsk user to open the Oura app on their phoneEmpty data arrayNo measurement on that dateLikely 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