google-health-api/google-health-cli/ghealth
Claude Code and agent skill by google-health-api/google-health-cli
- community
Checking that the SKILL.md file is still in the repository.
Query Google Health API v4 — steps, heart rate, exercise, sleep, weight, SpO2, HRV, ECG, blood glucose, nutrition, and 40 total data types
Install
npx vskill@latest install google-health-api/google-health-cli/ghealthSKILL.md
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. Requires `ecg.readonly`.irregular-rhythm-notification— alert windows. Requires `irn.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 <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:
This reports the account timezone for information only — to have the CLI resolve dates in that zone, set it explicitly with ghealth config set timezone <IANA zone>.
Sleep/exercise page size is capped at 25 per request (auto-paginated by CLI):
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:
Correlate heart rate with exercise sessions:
Exporting data for analysis
Use `-o <file>` 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.
What stdout shows (this is all the agent sees):
What the file contains (full CSV, not printed to stdout):
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:
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:
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:
Write operations use create, update --id <id> [--update-mask fields], delete --ids <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<comparators. Civil time fields (noZ): interval types use{type}.interval.civil_start_time, sleep usessleep.interval.civil_end_time(only end-time is filterable), daily types use{type}.date. Physical time fields (withZ): sample types use{type}.sample_time.physical_time- Write operations are asynchronous — the API returns an Operation object, not the created/updated data. Use
listto verify persistence - Body fat
deletereturns HTTP 500 — this is an API bug - Height
updatereturns HTTP 400 ("updateMask not recognized") — API bug; usecreate+deleteas a workaround daily-rollupaggregates by civil/local day (1-day windows; override with--window-days N).rollupaggregates by physical time (--window-size, default86400s); bare--from/--todates anchor at midnight in the configured timezone (ghealth config set timezone <IANA zone>), 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
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/ghealth/SKILL.md
Popularity
- Repository stars
- 258
- Repository forks
- 27
- 7-day trend score
- 28
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/google-health-api/google-health-cli/ghealth)