PickSkill
← Back

Oura Ring Analytics

Oura Ring data integration and analytics. Fetch sleep scores, readiness, activity, HRV, and trends from the Oura Cloud API. Generate automated reports, correlations with productivity, and trigger-based alerts for low recovery days. Requires OURA_API_TOKEN (get at cloud.ouraring.com).

README.md
Rendered from GitHub raw
View raw ↗

Oura Analytics - OpenClaw Skill

OpenClaw Community Skill ClawdHub Version License

Production-grade Oura Ring data integration for OpenClaw
Fetch sleep scores, readiness, activity, HRV, and trends from Oura Cloud API. Generate automated health reports and trigger-based alerts.

Features

Oura Cloud API Integration - Personal Access Token authentication
Sleep Analytics - Score, duration, efficiency, REM/deep stages
Readiness Tracking - Recovery score, HRV balance, temperature
Activity Metrics - Steps, calories, MET minutes
Trend Analysis - Moving averages, correlations, anomaly detection
Automated Alerts - Low readiness/sleep notifications via Telegram

Version

Current: v0.1.2

See CHANGELOG for version history.

Why This Exists

OpenClaw needs access to Oura Ring health data for:

  • Daily morning briefings ("How did I sleep?")
  • Correlating recovery with productivity/calendar
  • Automated alerts for low recovery days
  • Weekly/monthly health trend reports

This skill provides:

  • Simple Python API client for Oura Cloud API v2
  • Trend analysis and correlation tools
  • Threshold-based alerting system
  • Report generation templates

Installation

1. Get Oura Personal Access Token

  1. Go to https://cloud.ouraring.com/personal-access-tokens
  2. Create new token (select all scopes)
  3. Copy token to secrets file:
echo 'OURA_API_TOKEN="your_token_here"' >> ~/.config/systemd/user/secrets.conf

2. Install the skill

git clone https://github.com/kesslerio/oura-analytics-openclaw-skill.git ~/.openclaw/skills/oura-analytics
pip install -r requirements.txt

3. Add to OpenClaw's TOOLS.md

### oura-analytics
- Fetch Oura Ring metrics (sleep, readiness, activity, HRV)
- Generate health reports and correlations
- Set up automated alerts for low recovery
- Usage: `python ~/.openclaw/skills/oura-analytics/scripts/oura_api.py sleep --days 7`

Usage Examples

Note: For Python imports, set PYTHONPATH to the scripts/ folder:

export PYTHONPATH="$(pwd)/scripts"

Fetch Sleep Data

# Last 7 days
python scripts/oura_api.py sleep --days 7

Get Readiness Summary

python scripts/oura_api.py readiness --days 7

Generate Reports

# Weekly summary (last 7 days)
python scripts/weekly_report.py --days 7
 
# Monthly trends (last 30 days)
python scripts/weekly_report.py --days 30

Trigger Alerts

# Check for low readiness and send Telegram notification
python scripts/alerts.py --days 7 --readiness 60 --efficiency 80 --telegram

Generate Hybrid Morning Briefing

# Daily hybrid report (morning briefing + 7-day trends)
python scripts/oura_briefing.py --format hybrid

Example hybrid output:

🌅 *Morning Briefing — Jan 22*
────────────────────────
💤 *Sleep*: 6h 47m (↑75min vs avg) ⚠️
⚡ *Readiness*: 80 (stable) ✅
*Drivers*: recovery_index, body_temperature
*Recovery*: 🟡 YELLOW
*Rec*: Moderate day. Avoid heavy training.

*📊 7-Day Trends*
────────────────────────
*Sleep Score*: `89.5` ↓
*Readiness*: `77.1` ↑
• *7.3h* sleep • *89.7%* eff • *21ms* HRV

*Recent*: 01-20 → `87.4`/`73` • 01-21 → `90.4`/`80`

Baseline & Comparison Analysis

# Compare last 7 days vs 30-day baseline
python scripts/baseline.py --current-days 7 --baseline-days 30
 
# View 90-day baseline statistics
python scripts/baseline.py --baseline-only --baseline-days 90
 
# JSON output for programmatic use
python scripts/baseline.py --json

Example output:

📈 Current vs Baseline (Last 7d vs 30d baseline)

   ↗️ Sleep Score: 89.5 (+10.6, z=0.53)
      Above baseline

   ➡️ Readiness: 77.1 (+1.0, z=0.15)
      Within baseline

   ↗️ Sleep Duration: 7.3 (+1.4, z=0.52)
      Above baseline

   ↗️ Efficiency: 89.7 (+6.8, z=0.52)
      Above baseline

✅ All metrics within or above baseline range

Interpretation:

  • z-score: Standard deviations from baseline mean
    • z > 1.5: 🔥 Well above baseline
    • 0.5 < z < 1.5: ↗️ Above baseline
    • -0.5 < z < 0.5: ➡️ Within baseline
    • -1.5 < z < -0.5: ↘️ Below baseline
    • z < -1.5: ⚠️ Well below baseline (needs attention)
  • Baseline range: P25-P75 (middle 50% of your historical data)
  • Sample size: Number of days used to calculate baseline

Core Workflows

1. Morning Health Check

from oura_api import OuraClient, OuraAnalyzer
 
client = OuraClient(token=os.getenv("OURA_API_TOKEN"))
sleep_data = client.get_sleep(start_date="2026-01-18", end_date="2026-01-18")
today = sleep_data[0] if sleep_data else {}
 
if today:
    print(f"Sleep Score: {today.get('score', 'N/A')}/100")
    print(f"Total Sleep: {today.get('total_sleep_duration', 0)/3600:.1f}h")
    print(f"REM: {today.get('rem_sleep_duration', 0)/3600:.1f}h")
    print(f"Deep: {today.get('deep_sleep_duration', 0)/3600:.1f}h")

2. Recovery Tracking

readiness = client.get_readiness(start_date="2026-01-11", end_date="2026-01-18")
avg_readiness = sum(d.get('score', 0) for d in readiness) / len(readiness) if readiness else 0
print(f"7-day avg readiness: {avg_readiness:.0f}")

3. Trend Analysis

from oura_api import OuraAnalyzer
 
analyzer = OuraAnalyzer(sleep_data, readiness_data)
avg_sleep = analyzer.average_metric(sleep_data, "score")
avg_readiness = analyzer.average_metric(readiness_data, "score")
print(f"Avg Sleep Score: {avg_sleep}")
print(f"Avg Readiness Score: {avg_readiness}")

API Client Reference

OuraClient

client = OuraClient(token="your_token")
 
# Sleep data (date range required)
sleep = client.get_sleep(start_date="2026-01-01", end_date="2026-01-16")
 
# Readiness data
readiness = client.get_readiness(start_date="2026-01-01", end_date="2026-01-16")
 
# Activity data
activity = client.get_activity(start_date="2026-01-01", end_date="2026-01-16")
 
# HRV trends
hrv = client.get_hrv(start_date="2026-01-01", end_date="2026-01-16")

OuraAnalyzer

from oura_api import OuraClient, OuraAnalyzer
 
client = OuraClient(token="your_token")
sleep = client.get_sleep(start_date="2026-01-01", end_date="2026-01-16")
readiness = client.get_readiness(start_date="2026-01-01", end_date="2026-01-16")
 
analyzer = OuraAnalyzer(sleep_data=sleep, readiness_data=readiness)
 
# Average metrics
avg_sleep = analyzer.average_metric(sleep, "score")
avg_readiness = analyzer.average_metric(readiness, "score")
 
# Trend analysis
trend = analyzer.trend(sleep, "score", days=7)
 
# Summary
summary = analyzer.summary()

OuraReporter

from oura_api import OuraClient, OuraReporter
 
client = OuraClient(token="your_token")
reporter = OuraReporter(client)
 
# Generate weekly report
report = reporter.generate_report(report_type="weekly", days=7)
print(json.dumps(report, indent=2))

Metrics Reference

Metric Description Range
Sleep Score Overall sleep quality 0-100
Readiness Score Recovery readiness 0-100
HRV Balance Heart rate variability -3 to +3
Sleep Efficiency Time asleep / time in bed 0-100%
REM Sleep REM stage duration hours
Deep Sleep Deep stage duration hours
Temperature Deviation Body temp vs baseline °C

See references/metrics.md for full definitions.

Architecture

  • scripts/oura_api.py - Oura Cloud API v2 client with OuraAnalyzer and OuraReporter classes
  • scripts/alerts.py - Threshold-based alerting CLI
  • scripts/weekly_report.py - Weekly report generator
  • scripts/data_manager.py - Data storage and privacy controls
  • scripts/oura_data.py - Data management CLI
  • scripts/schema.py - Canonical data structures with unit normalization
  • references/ - API docs, metric definitions

Data Management & Privacy

What Data is Stored

All data is stored locally in ~/.oura-analytics/:

~/.oura-analytics/
├── cache/                  # Cached API responses (cleanup is manual)
│   ├── sleep/             # Sleep records by date (YYYY-MM-DD.json)
│   ├── daily_readiness/   # Readiness records
│   └── daily_activity/    # Activity records
├── events.jsonl           # User-logged events (optional)
├── config.yaml            # User preferences (optional)
└── alert_state.json       # Alert tracking (optional)

No data is sent to third parties. All Oura data stays on your local machine.

View Storage Info

python scripts/oura_data.py info

Output:

Data directory: /home/user/.oura-analytics
Total size: 187.1 KB

Cache:
  Size: 187.1 KB
  Files: 21
  sleep: 7 files, 46.4 KB, 2026-01-14 to 2026-01-20
  daily_readiness: 7 files, 3.6 KB, 2026-01-14 to 2026-01-20
  daily_activity: 7 files, 137.2 KB, 2026-01-14 to 2026-01-20

Export Data (Backup)

Export all local data to a single JSON file:

# Full backup
python scripts/oura_data.py export --output backup.json
 
# Compressed tarball
python scripts/oura_data.py export --output backup.tar.gz --format tar.gz
 
# Export events only
python scripts/oura_data.py export-events --output events.csv --format csv

Clear Data (Privacy)

# Clear cache only (keeps events/config)
python scripts/oura_data.py clear-cache --confirm
 
# Clear specific endpoint
python scripts/oura_data.py clear-cache --endpoint sleep --confirm
 
# Clear events
python scripts/oura_data.py clear-events --confirm
 
# Clear ALL local data
python scripts/oura_data.py clear-all --confirm

Important: All clear commands require --confirm flag to prevent accidental deletion.

Automatic Cleanup

Delete cached data older than 90 days:

# Default: 90 days
python scripts/oura_data.py cleanup
 
# Custom retention period
python scripts/oura_data.py cleanup --days 180

GDPR Compliance

  • Data ownership: You own your data (local storage only)
  • Data retention: You control retention (manual cleanup)
  • No data sharing: No third-party services
  • Right to deletion: Clear data anytime with clear-all

Note: This skill is NOT HIPAA-compliant. Do not use for medical decision-making. Consult healthcare professionals for health concerns.

Troubleshooting

Authentication Failed

# Check token is set
echo $OURA_API_TOKEN
 
# Or use explicit token
python scripts/oura_api.py sleep --days 7 --token "your_token"

No Data Returned

# Check date range (Oura data has ~24h delay)
python scripts/oura_api.py sleep --days 10
 
# Or fetch and inspect manually
python scripts/oura_api.py sleep --days 7 | python -m json.tool | head -50

Credits

Created for production OpenClaw health tracking
Developed by @kesslerio • Part of the ClawdHub ecosystem

Powered by:

License

Apache 2.0