Install
$ agentstack add skill-google-health-api-google-health-cli-ghealth ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
ghealth
CLI for the Google Health API v4. 40 verified data types.
Prerequisites: See ../ghealth-shared/SKILL.md for auth, setup, global flags.
Choosing the right operation
| Goal | Operation | Example | |------|-----------|---------| | Daily totals (steps, distance, calories) | daily-rollup | ghealth data steps daily-rollup --from 2026-03-22 --to 2026-03-29 | | Individual readings (HR, weight, SpO2) | list | ghealth data heart-rate list --from today --limit 20 | | Sessions (exercise, sleep) | list | ghealth data exercise list --from 2026-03-01 | | Daily summaries (resting HR, HRV, resp rate) | list | ghealth data daily-resting-heart-rate list --from 2026-03-01 | | Merged multi-source data | reconcile | ghealth data weight reconcile --from 2026-01-01 |
Why this matters: steps list returns minute-level intervals without counts. Use daily-rollup to get actual step totals (countSum). Same for distance (millimetersSum) and floors.
Types at a glance
Run ghealth schema types for the live version. Quick reference:
Use daily-rollup for totals:
steps→countSumper daydistance→millimetersSumper daytotal-calories→kcalSumper day (rollup-only)floors→countSum(rollup-only)active-minutes→ (rollup-only)swim-lengths-data→strokeCountSumper daycalories-in-heart-rate-zone→caloriesInHeartRateZonesper day (rollup-only)
Use list for readings: heart-rate, weight (writable), body-fat (writable), height (writable), oxygen-saturation, heart-rate-variability, altitude, vo2-max, active-zone-minutes, activity-level, basal-energy-burned, active-energy-burned, blood-glucose, core-body-temperature, respiratory-rate-sleep-summary, run-vo2-max, sedentary-period, swim-lengths-data, hydration-log
Use list for sessions:
exercise(writable) — includes type, duration, calories, HR summary, notessleep(writable) — includes summary by default. Add--detailfor per-stage breakdown.
Cardiac (dedicated scopes, list-only):
electrocardiogram— waveform samples + rhythm classification. Requiresecg.readonly.irregular-rhythm-notification— alert windows. Requiresirn.readonly.
Nutrition:
nutrition-log— logged food entries with nutrient/energy breakdown (list, get, rollup, daily-rollup, reconcile)food,food-measurement-unit— reference catalogs (list, get only). No time filter —--from/--toare ignored.
Daily summaries (one value per day, filter by date): daily-resting-heart-rate, daily-heart-rate-variability, daily-oxygen-saturation, daily-respiratory-rate, daily-vo2-max, daily-sleep-temperature-derivations
Get a single point by ID: get --id is supported on exercise, sleep, weight, body-fat, height, hydration-log, nutrition-log, blood-glucose, core-body-temperature, food, food-measurement-unit.
Patterns the CLI can't tell you
These require judgment that --help and schema don't provide.
Get the user's timezone before querying date-sensitive data:
ghealth user settings get # → timeZone: "Europe/London", utcOffset: "3600s"
# Then use --from/--to with the correct local dates
Sleep/exercise page size is capped at 25 per request (auto-paginated by CLI):
ghealth data sleep list --limit 5 # CLI handles pagination internally
Paging through large list results. list returns up to --limit rows (default 500). When more exist, the response carries a nextPageToken and a hint. Pass it back with --page-token to fetch the next page — it resumes exactly where the last page ended, no rows skipped or repeated:
ghealth data heart-rate list --from 2026-06-15 --limit 500
# → {"dataPoints":[…500…], "nextPageToken":"ABC", "_hints":[…]}
ghealth data heart-rate list --from 2026-06-15 --limit 500 --page-token ABC
# → next 500 rows
Correlate heart rate with exercise sessions:
# 1. Get exercise time window
ghealth data exercise list --from today --limit 1
# → start: "2026-03-29T14:18:32+01:00", end: "2026-03-29T14:39:14+01:00"
# 2. Query HR for that window using --filter (raw API syntax, UTC required)
ghealth data heart-rate list --filter 'heart_rate.sample_time.physical_time >= "2026-03-29T13:18:32Z" AND heart_rate.sample_time.physical_time ` to write data to a file.** When `-o` is set, stdout shows only a summary with the column schema — not the data itself. This means you can fetch data and immediately write analysis code using the column names from stdout, without reading the file.
```bash
ghealth data steps daily-rollup --from 2026-03-24 --to 2026-03-30 --format csv -o steps.csv
What stdout shows (this is all the agent sees):
Wrote 6 rows to steps.csv
Columns: countSum, date
Preview:
countSum,date
4062,2026-03-29
9122,2026-03-28
2469,2026-03-27
What the file contains (full CSV, not printed to stdout):
countSum,date
4062,2026-03-29
9122,2026-03-28
2469,2026-03-27
6541,2026-03-26
4025,2026-03-25
3995,2026-03-24
The agent now knows the columns are countSum and date, and can write pd.read_csv("steps.csv") without ever reading the file.
Do not pipe to file — use -o instead. Piping (> file.csv) sends the full data to the file but prints nothing to stdout, so the agent has no column schema and must read the file to learn the structure.
More examples:
# Sleep — nested stageMinutes auto-flattened to stageMinutes.AWAKE, stageMinutes.DEEP, etc.
ghealth data sleep list --from 2026-03-01 --format csv -o sleep.csv
# Exercise — metricsSummary.caloriesKcal, metricsSummary.averageHeartRateBeatsPerMinute, etc.
ghealth data exercise list --from 2026-03-01 --format csv -o exercise.csv
# Heart rate — 500 readings straight to file
ghealth data heart-rate list --from today --limit 500 --format csv -o hr.csv
Exercise time series (GPS/heart-rate track) → CSV. export-tcx --as csv flattens the TCX track to one row per trackpoint — pd.read_csv it directly instead of parsing TCX XML:
# Find the exercise id first, then export its track
ghealth data exercise list --from 2026-06-01 --limit 10
ghealth data exercise export-tcx --id --output ride.csv --as csv # or --output - for stdout
Columns (fixed, stable for dataframes): time, activity, lap, sport, latitude_deg, longitude_deg, altitude_m, distance_m, heart_rate_bpm, cadence_rpm, speed_mps, watts. Absent sensors are empty cells (NaN in pandas), never zeros. distance_m is cumulative. 0 rows = indoor/no-sensor activity (Google emits no track for those) — the session summary and workout notes come from data exercise list, not the track export.
Writing data
Writable types: exercise, sleep, weight, body-fat, height. Writes are async (API returns Operation object).
Discover the correct payload format by inspecting a real response with --raw:
ghealth data weight list --raw --limit 1
# Use the response structure as a template for your create payload
Write operations use create, update --id [--update-mask fields], delete --ids .
Gotchas
- Missing days are NOT zeros (
altitude,distance,floors,steps,total-calories): a date absent from rollup output means the device wasn't worn / didn't sync — NOT zero.countSum: "0"is a true zero (worn, no activity). Never coalesce missing buckets to 0 or average over absent days as zeros — that silently deflates weekly/monthly stats - String vs number values follow protobuf JSON encoding:
int64fields (beatsPerMinute,countSum,minutesAsleep) are strings;int32/doublefields (weightGrams,caloriesKcal,percentage) are numbers --filterraw syntax: only>=and `), falling back to machine-local time when unset. For local-day totals usedaily-rollup`. Both send their window size explicitly — the API rejects requests that omit it
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Google-Health-API
- Source: Google-Health-API/google-health-cli
- License: Apache-2.0
- Homepage: https://developers.google.com/health
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.