intervals-icu — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited intervals-icu (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
┌─────────────────┐ fetch data ┌───────────────────┐
│ intervals-icu │ ──────────────────► │ cycling-training │
│ (DATA API) │ │ (ANALYSIS) │
│ │ ◄────────────────── │ │
│ • wellness │ interpret results │ • zone calc │
│ • activities │ │ • periodization │
│ • power curves │ │ • workout design │
│ • fitness │ │ • load management │
└─────────────────┘ └───────────────────┘Usage pattern:
intervals-icu to fetch data from APIcycling-training to analyze and interpretintervals-icu to update wellness/eventsAPI wrapper for intervals.icu cycling training platform. Designed to work alongside the cycling-training skill.
# Set credentials (one-time)
export INTERVALS_API_KEY="your_api_key"
export INTERVALS_ATHLETE_ID="iXXXXX"
# Set skill directory for local installs
SKILLS_DIR="<path-to-your-skills-dir>"
# Use the API helper
"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness today
"$SKILLS_DIR/intervals-icu/scripts/api.sh" activities 2024-01-01 2024-01-31Get your API key from https://intervals.icu/settings → Developer Settings → API Key.
Find athlete ID in the URL when logged in: intervals.icu/athlete/iXXXXX/...
Intervals.icu API has rate limits. The script handles this with:
INTERVALS_MAX_RETRIES environment variable# Increase retries for bulk operations
export INTERVALS_MAX_RETRIES=5If you hit rate limits frequently:
sleep 1brew install jq (macOS) / apt install jq (Linux)brew install bats-coreUse scripts/api.sh to handle authentication and common operations:
| Command | Description |
|---|---|
api.sh wellness [date] | Get wellness for date (default: today) |
api.sh wellness-range <start> <end> | Get wellness for date range |
api.sh wellness-update <date> <json> | Update wellness fields |
api.sh activities <start> <end> [format] [--all] | List activities (--all for pagination) |
api.sh activity <id> | Get single activity details |
api.sh activity-streams <id> [types] | Get activity data streams |
api.sh activity-upload <file> | Upload activity (.fit, .gpx, .tcx) |
api.sh athlete | Get athlete profile |
api.sh fitness | Get current CTL/ATL/TSB |
api.sh zones | Get power/HR zone settings |
api.sh events <start> <end> | Get planned events/workouts |
api.sh event-create <date> <json> | Create planned workout/event |
api.sh power-curves <start> <end> [format] | Power curves (json/summary/seconds) |
# Get today's wellness
"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness
# Get wellness for specific date
"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness 2024-01-15
# Update wellness (weight and sleep)
"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness-update 2024-01-15 '{"weight": 72.5, "sleepSecs": 28800}'
# Get last month's activities
"$SKILLS_DIR/intervals-icu/scripts/api.sh" activities 2024-01-01 2024-01-31
# Export activities as CSV
"$SKILLS_DIR/intervals-icu/scripts/api.sh" activities 2024-01-01 2024-01-31 csv > activities.csvFor custom operations not covered by the helper:
# Base URL
BASE="https://intervals.icu/api/v1"
# Auth header
AUTH="Authorization: Basic $(echo -n "API_KEY:$INTERVALS_API_KEY" | base64)"
# Get power curve
curl -s -H "$AUTH" "$BASE/athlete/$INTERVALS_ATHLETE_ID/power-curves?oldest=2024-01-01&newest=2024-12-31"
# Get streams for activity
curl -s -H "$AUTH" "$BASE/activity/iXXXX/streams?types=watts,heartrate,cadence"
# Upload activity
curl -s -H "$AUTH" -F "[email protected]" "$BASE/athlete/$INTERVALS_ATHLETE_ID/activities"| Endpoint | Method | Purpose |
|---|---|---|
/athlete/{id} | GET | Athlete profile |
/athlete/{id}/wellness/{date} | GET/PUT | Wellness data |
/athlete/{id}/wellness | GET | Wellness range (add ?oldest=&newest=) |
/athlete/{id}/activities | GET | Activities list |
/activity/{id} | GET | Activity details |
/activity/{id}/streams | GET | Activity data streams |
/athlete/{id}/events | GET | Planned workouts/events |
/athlete/{id}/power-curves | GET | Power duration curves |
| Field | Type | Range | Description |
|---|---|---|---|
weight | float | 30-200 kg | Body weight |
restingHR | int | 30-100 bpm | Resting heart rate |
hrv | float | 10-150 ms | HRV RMSSD (typical: 20-80) |
hrvSDNN | float | 10-200 ms | HRV SDNN |
sleepSecs | int | 0-43200 | Sleep duration (0-12h in seconds) |
sleepScore | float | 0-100 | Sleep quality percentage |
sleepQuality | int | 1-5 | 1=poor, 5=excellent |
fatigue | int | 1-5 | 1=fresh, 5=exhausted |
mood | int | 1-5 | 1=bad, 5=great |
motivation | int | 1-5 | Training motivation |
readiness | int | 1-5 | Training readiness |
stress | int | 1-5 | Stress level |
soreness | int | 1-5 | Muscle soreness |
ctl | float | 0-200 | Chronic Training Load (fitness) |
atl | float | 0-300 | Acute Training Load (fatigue) |
rampRate | float | -10 to +10 | CTL weekly change rate |
Use both skills together:
"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness-range 2024-01-01 2024-01-31 > wellness.json
"$SKILLS_DIR/intervals-icu/scripts/api.sh" activities 2024-01-01 2024-01-31 > activities.json "$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness-update today '{"weight": 72.5, "sleepSecs": 28800, "readiness": 4}'Complete example: Morning HRV-based workout adjustment using both skills.
You wake up, check HRV, and want to adjust today's planned workout based on recovery status.
# Get today's wellness (HRV from device sync)
WELLNESS=$("$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness today)
echo "$WELLNESS" | jq '{hrv, restingHR, sleepSecs, ctl, atl}'Output:
{
"hrv": 42.5,
"restingHR": 54,
"sleepSecs": 25200,
"ctl": 65.3,
"atl": 72.1
}Based on the data:
cycling-training recommendation: Reduce intensity. Convert threshold workout to endurance/recovery.
# Find today's planned workout
TODAY=$(date +%Y-%m-%d)
EVENTS=$("$SKILLS_DIR/intervals-icu/scripts/api.sh" events $TODAY $TODAY)
EVENT_ID=$(echo "$EVENTS" | jq -r '.[0].id')
# Update to easier workout
"$SKILLS_DIR/intervals-icu/scripts/api.sh" event-update "$EVENT_ID" '{
"name": "Recovery Ride (HRV adjusted)",
"description": "Original: Threshold intervals. Adjusted due to low HRV (-15% from baseline).",
"icu_training_load": 40
}'"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness-update today '{
"readiness": 3,
"fatigue": 3,
"mood": 4,
"soreness": 2
}'| HRV vs Baseline | TSB | Recommendation |
|---|---|---|
| >+10% | >0 | Execute as planned or add intensity |
| ±10% | >0 | Execute as planned |
| ±10% | <0 | Execute but monitor |
| <-10% | Any | Reduce intensity or rest |
| <-20% | Any | Rest day |
Run the test suite:
# Requires: bats-core
# Install: brew install bats-core (macOS) or apt install bats (Linux)
"$SKILLS_DIR/intervals-icu/tests/run_tests.sh"Tests verify:
| Error | Cause | Solution | |
|---|---|---|---|
| HTTP 401 | Invalid API key | Regenerate key in settings | |
| HTTP 403 | No permission | Check athlete ID ownership | |
| HTTP 404 | Resource not found | Verify date format (YYYY-MM-DD) | |
| HTTP 429 | Rate limited | Wait 60s, reduce request frequency | |
| "jq: command not found" | jq not installed | brew install jq (macOS) / apt install jq (Linux) | |
| Empty response | No data for date range | Check date range contains activities | |
| "Invalid JSON" | Malformed JSON payload | Validate JSON: `echo '{"key": "value"}' | jq .` |
Enable verbose output for debugging:
# Show curl commands
export INTERVALS_DEBUG=1
"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness todayIssue: Activities not syncing from Garmin/Wahoo
api.sh activity-upload ride.fitIssue: HRV not appearing in wellness
Issue: Power curves show 0 for some durations
api.sh activity-streams <id> wattsIssue: CSV export has wrong encoding
For endpoints not covered by api.sh, inspect the current Intervals.icu API documentation before adding a helper command. Prefer extending scripts/api.sh with a tested command over embedding one-off curl snippets in the skill body.
# Get HRV device data (if synced)
"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness today
# Update subjective metrics
"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness-update today '{"readiness": 4, "mood": 4, "soreness": 2}'# Get last 7 days
END=$(date +%Y-%m-%d)
START=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d "7 days ago" +%Y-%m-%d)
"$SKILLS_DIR/intervals-icu/scripts/api.sh" activities $START $END
"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness-range $START $END
"$SKILLS_DIR/intervals-icu/scripts/api.sh" fitness # Current CTL/ATL/TSB# CSV export for spreadsheet analysis
"$SKILLS_DIR/intervals-icu/scripts/api.sh" activities 2024-01-01 2024-12-31 csv > yearly_activities.csv
"$SKILLS_DIR/intervals-icu/scripts/api.sh" wellness-range 2024-01-01 2024-12-31 csv > yearly_wellness.csv~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.