| name | google-health-cli |
| description | CLI for Google Health API v4 — read steps, heart rate, exercise, sleep, weight, and 35+ health data types with agent-first JSON output |
| triggers | ["get my step count from google health","fetch heart rate data from google fit","read my sleep data using google health api","export exercise data from google health","set up google health cli authentication","query my weight history from google health","retrieve daily health metrics from google fit","import health data using ghealth command"] |
google-health-cli
Skill by ara.so — Devtools Skills collection.
CLI for the Google Health API v4 built for AI agents and developers. Supports 40+ verified health data types including steps, heart rate, exercise, sleep, weight, SpO2, HRV, ECG, blood glucose, and nutrition. Outputs deterministic JSON with agent-friendly exit codes.
Installation
git clone https://github.com/Google-Health-API/google-health-cli.git
cd google-health-cli
go build -o ghealth .
Move the binary to your PATH:
sudo mv ghealth /usr/local/bin/
Authentication Setup
Interactive Setup
ghealth setup
Walks through:
- GCP project ID
- OAuth credentials (download from Console as Desktop application)
- Health API enablement
- Scope selection
- Browser-based OAuth login
Credentials stored in ~/.config/ghealth/ (override with GHEALTH_CONFIG_DIR):
client_secret.json — OAuth client (mode 0600)
credentials.json — access + refresh tokens (mode 0600)
config.toml — active profile
Non-Interactive Setup (CI/Agents)
ghealth setup \
--project-id $GCP_PROJECT_ID \
--client-secret ~/Downloads/client_secret.json \
--scopes-preset readonly \
--skip-enable-api \
--no-prompt
Headless OAuth Flow
ghealth auth login --non-interactive --scopes-preset readonly
ghealth auth login --complete 'http://localhost/?code=4/0AX4XfWh...&state=cQq...'
ghealth auth login --complete 4/0AX4XfWh...
Environment Variables
export GHEALTH_ACCESS_TOKEN=ya29...
export GHEALTH_CREDENTIALS_FILE=/path/to/creds.json
export GHEALTH_CONFIG_DIR=/custom/config/path
Precedence: GHEALTH_ACCESS_TOKEN > GHEALTH_CREDENTIALS_FILE > stored credentials > Application Default Credentials.
Moving Tokens Between Machines
ghealth auth export > /tmp/ghealth-creds.json
ghealth auth import --file /tmp/ghealth-creds.json
Key Data Types
| Type | Key Values | Operations |
|---|
steps | countSum (daily rollup) | list, rollup, daily-rollup, reconcile |
heart-rate | beatsPerMinute | list, rollup, daily-rollup, reconcile |
exercise | type, duration, calories, avgHeartRate | list, get, create, update, delete, export-tcx |
sleep | minutesAsleep, minutesAwake, stageMinutes | list, get, create, update, delete, reconcile |
weight | weightGrams | list, get, create, update, delete, rollup, daily-rollup |
distance | millimetersSum (daily rollup) | list, rollup, daily-rollup, reconcile |
oxygen-saturation | percentage (SpO2) | list, reconcile |
heart-rate-variability | RMSSD | list, reconcile |
blood-glucose | mg/dL, mealType, timing | list, get, rollup, daily-rollup, reconcile |
nutrition-log | nutrients, energy, mealType | list, get, rollup, daily-rollup, reconcile |
Run ghealth schema types for all 40+ types.
Reading Data
Sample Data (Individual Readings)
ghealth data heart-rate list --from today --limit 10
ghealth data heart-rate list --from 2026-03-22 --to 2026-03-29 --limit 100
ghealth data oxygen-saturation list --from 2026-06-01 --limit 20
ghealth data weight list --limit 10
Rollup Data (Aggregated)
Critical: For steps, distance, and other interval types, use daily-rollup to get actual values. list returns time intervals without totals.
ghealth data steps daily-rollup --from 2026-03-22 --to 2026-03-29
ghealth data distance daily-rollup --from 2026-03-01 --to 2026-03-31
ghealth data heart-rate rollup --from 2026-03-01 --to 2026-03-31 --duration 7d
ghealth data steps rollup --from today --duration 1h
Exercise Data
ghealth data exercise list --from 2026-03-01 --limit 20
ghealth data exercise get --id <exercise-id>
ghealth data exercise export-tcx --id <id> --output ride.tcx
ghealth data exercise export-tcx --id <id> --output ride.csv --as csv
ghealth data exercise export-tcx --id <id> --output - --as csv | head
Sleep Data
ghealth data sleep list --limit 5
ghealth data sleep list --limit 5 --detail
ghealth data sleep get --id <sleep-id>
Pagination
All list commands support pagination:
ghealth data heart-rate list --from 2026-06-15 --limit 500
ghealth data heart-rate list --from 2026-06-15 --limit 500 --page-token ABC
Writing Data
Create Exercise
ghealth data exercise create \
--start-time 2026-03-28T14:00:00Z \
--end-time 2026-03-28T15:30:00Z \
--type running \
--calories 450 \
--distance-meters 8000 \
--avg-heart-rate 152 \
--notes "Morning run in the park"
Update Exercise
ghealth data exercise update \
--id <exercise-id> \
--notes "Evening run - felt great" \
--calories 475
Create Sleep Session
ghealth data sleep create \
--start-time 2026-03-27T23:00:00Z \
--end-time 2026-03-28T07:00:00Z \
--minutes-asleep 450 \
--minutes-awake 30
Log Weight
ghealth data weight create \
--timestamp 2026-03-28T08:00:00Z \
--weight-grams 75000
Delete Data
ghealth data exercise delete --id <exercise-id>
ghealth data sleep delete --id <sleep-id>
ghealth data weight delete --id <weight-id>
Agent-Friendly Patterns
Deterministic JSON Output
Every read command returns:
{
"dataPoints": [
{"date": "2026-03-28", "countSum": "9037"},
{"date": "2026-03-27", "countSum": "8245"}
],
"_hints": {
"type": "steps",
"rollupDuration": "1d"
},
"nextPageToken": "optional-token-if-more-data"
}
Parse with jq:
ghealth data steps daily-rollup --from 2026-03-22 --to 2026-03-29 | jq -r '.dataPoints[].countSum'
ghealth data steps daily-rollup --from 2026-03-22 --to 2026-03-29 | jq '[.dataPoints[].countSum | tonumber] | add'
ghealth data heart-rate list --from today --limit 100 | jq '[.dataPoints[].beatsPerMinute | tonumber] | add / length'
Dry Run Mode
ghealth data steps daily-rollup --from today --dry-run
Raw API Response
ghealth data heart-rate list --from today --limit 10 --raw
Exit Codes
0 — Success
1 — General error
2 — Authentication/validation error
3 — API error
4 — Data not found
5 — Configuration error
Critical Data Handling Rules
Missing Days vs. Zero Values
For presence-aware types (altitude, distance, floors, steps, total-calories):
- Missing date → device not worn/synced — render as "no data", NOT zero
countSum: "0" → true zero (device worn, no activity)
Never average over absent days as if they were zeros — this silently deflates statistics.
Time Formats
- Use ISO 8601:
2026-03-28T14:00:00Z
- Shortcut:
today, yesterday
- Date-only:
2026-03-28 (interprets as start of day in user's timezone)
ghealth data steps daily-rollup --from 2026-03-22 --to today
ghealth data heart-rate list --from yesterday --limit 50
Common Workflows
Weekly Step Summary
#!/bin/bash
WEEK_AGO=$(date -d '7 days ago' +%Y-%m-%d)
TODAY=$(date +%Y-%m-%d)
ghealth data steps daily-rollup --from $WEEK_AGO --to $TODAY | \
jq -r '.dataPoints[] | "\(.date): \(.countSum) steps"'
Export All Exercise Data
#!/bin/bash
ghealth data exercise list --from 2026-03-01 --to 2026-03-31 | \
jq -r '.dataPoints[].id' | \
while read id; do
ghealth data exercise export-tcx --id "$id" --output "exercise_${id}.csv" --as csv
done
Daily Health Dashboard
#!/bin/bash
echo "=== Health Metrics for $(date +%Y-%m-%d) ==="
echo -n "Steps: "
ghealth data steps daily-rollup --from today --to today | jq -r '.dataPoints[0].countSum // "no data"'
echo -n "Average Heart Rate: "
ghealth data heart-rate list --from today --limit 500 | \
jq '[.dataPoints[].beatsPerMinute | tonumber] | add / length | round'
echo -n "Weight: "
ghealth data weight list --limit 1 | jq -r '.dataPoints[0].weightGrams // "no data"'
Data Reconciliation
Check for data conflicts and resolve:
ghealth data heart-rate reconcile --from 2026-03-01 --to 2026-03-31
ghealth data exercise reconcile --from 2026-03-01 --strategy newest
Troubleshooting
No OAuth Credentials
If you see exit code 5 with JSON error:
{
"error": {
"type": "config",
"code": 5,
"message": "No OAuth client_secret.json configured",
"next_steps": [
"Open https://console.cloud.google.com/apis/credentials",
"Create or select a Google Cloud project",
"Enable the Google Health API",
"Create OAuth client ID with Application type: Desktop app",
"Download the client_secret JSON",
"Run: ghealth setup --client-secret /path/to/client_secret.json"
]
}
}
Get instructions without error:
ghealth setup --instructions
Token Refresh Issues
ghealth auth status
ghealth auth refresh
ghealth auth login
Empty Data Results
Check:
- Date range is correct (use
--from and --to)
- Using correct command (
daily-rollup vs list)
- OAuth scopes include necessary permissions
- Device has synced data
ghealth auth status | jq -r '.scopes'
ghealth schema types
Rate Limiting
The API has rate limits. Space out requests:
for id in $(ghealth data exercise list | jq -r '.dataPoints[].id'); do
ghealth data exercise get --id "$id"
sleep 1
done
Schema Exploration
ghealth schema types
ghealth schema type --name steps
ghealth schema type --name exercise | jq -r '.operations[]'
Best Practices for Agents
- Always use
daily-rollup for totals — list returns intervals, not sums
- Handle pagination — check for
nextPageToken in responses
- Respect missing data — don't coalesce absent days to zero
- Use exit codes — check
$? for error handling
- Parse with jq — all output is structured JSON under
.dataPoints
- Set explicit date ranges —
--from and --to prevent unbounded queries
- Use
--dry-run for validation before destructive operations
- Store credentials securely — use environment variables for tokens