Fetch health and fitness data from Garmin Connect -- 40+ metrics including sleep, HRV, stress, body battery, SpO2, VO2 Max, training status, and activities. Stores data locally as JSON and SQLite.
浏览器
Google Health
试用Read your Google Health data from any agent. Lists data points for every Google Health data type (heart rate, resting heart rate, sleep, steps, distance, weight, blood oxygen, VO2 max, exercise, and more), returns server-side daily roll-ups (one reconciled total per day), gives a parsed view of exercise sessions, and can GET any read-only v4 API path. A self-contained, read-only client for the Google Health v4 API: authenticates via OAuth2 (token cached locally and auto-refreshed) and emits JSON. It does NO filtering, merging, or writing — the caller decides what to do with the data. Single static binary, no Python or other runtime. NOTE: needs your own Google Cloud OAuth client and a one-time interactive browser login; runs headless afterward.
它能做什么
Read your Google Health data from any agent. Lists data points for every Google Health data type (heart rate, resting heart rate, sleep, steps, distance, weight, blood oxygen, VO2 max, exercise, and more), returns server-side daily roll-ups (one reconciled total per day), gives a parsed view of exercise sessions, and can GET any read-only v4 API path. A self-contained, read-only client for the Google Health v4 API: authenticates via OAuth2 (token cached locally and auto-refreshed) and emits JSON. It does NO filtering, merging, or writing — the caller decides what to do with the data. Single static binary, no Python or other runtime. NOTE: needs your own Google Cloud OAuth client and a one-time interactive browser login; runs headless afterward.
技能文档
Google Health — read-only data extractor
Read your Google Health data from any agent. This is a generic, read-only client for the Google Health v4 API: it authenticates, pulls data points for any data type, and prints JSON. It does no filtering, merging, or interpretation — you get the data and parse whatever you care about. Single static binary — no Python or other runtime.
⚠️ Read-only. It requests only read-only Google Health scopes and never writes your health data.
🔒 Privacy — sensitive health data leaves on stdout. Every
data list,rollup daily,sessions, andapi getprints your personal health information (heart rate, sleep, weight, exercise, blood oxygen, profile, …) to stdout as JSON. In an agent or pipeline, stdout may be logged, summarized, persisted, or transmitted to other tools, model providers, or third parties. Treat this output as sensitive PII: only run it in contexts you trust to handle health data, and do not persist or forward it unless you intend to. The tool never sends your data anywhere itself (it only talks to Google's API over HTTPS) — what happens to stdout is the caller's responsibility. Every data-emitting command also prints a one-line privacy notice to stderr at run time as an execution-time reminder (it stays on stderr, never on the JSON stdout).
🧭 Data minimization & consent. Request only the data types and the narrowest time window you actually need (
--days/--date/--from/--to, not--all); prefer the typeddata/rollup/sessionscommands overapi get; and don't persist or forward the output beyond the task at hand. Run this only against an account whose owner has knowingly consented to having their health data read by this agent — the one-timeauth loginis the owner consenting to read-only access for the tool, not consent for a downstream agent to collect, retain, or transmit that data more broadly.
🩺
doctorprints local environment metadata. ThedoctorJSON includes your token-cache and config file paths, the configured account (user), and the API base URL — local filesystem layout and account identifiers rather than health data, but still local environment metadata that an agent or pipeline may log, forward, or persist. It exists to diagnose your own setup; treat its output like any other local path/account detail and don't paste it into untrusted contexts.
Setup (one time)
Unlike a simple email/password tool, Google Health uses OAuth, so first-time setup needs a human in a browser once. After that it runs headless (the token auto-refreshes).
- Install the binary:
# A) Download a release for your OS/arch and put it on PATH: # https://github.com/stozo04/google-health-cli/releases # B) Or with Go (1.25+): go install github.com/stozo04/google-health-cli/cmd/google-health-cli@latest - Create a Google Cloud OAuth client (Desktop app, read-only Health scopes, ~10 min, no fees). Full walkthrough: the repo's OAUTH_SETUP.md.
- Provide the client via
GOOGLE_HEALTH_CLIENT_ID/GOOGLE_HEALTH_CLIENT_SECRET(or aconfig.jsonwith those keys in the working directory). - Authorize once (opens a browser, asks a human to consent to read-only access):
The token is cachedgoogle-health-cli auth login google-health-cli doctor # expect "tokenValid": true0600and auto-refreshed; every later run is headless.
Credentials
| Variable | Required | Notes |
|---|---|---|
GOOGLE_HEALTH_CLIENT_ID | ✓ | OAuth client ID (Desktop app) |
GOOGLE_HEALTH_CLIENT_SECRET | ✓ | OAuth client secret |
GOOGLE_HEALTH_CONFIG | — | Path to a config.json holding the above instead |
GOOGLE_HEALTH_TOKEN_CACHE | — | Override the cached-token path |
GOOGLE_HEALTH_BASE_URL | — | Override the API base URL |
config.json (gitignored) is an alternative to the env vars:
{
"client_id": "PASTE_CLIENT_ID",
"client_secret": "PASTE_CLIENT_SECRET"
}
🔑 Protect your credentials. The OAuth
client_id/client_secretand the cached token are sensitive secrets stored on disk in plaintext (config.json/token.json, written0600). They're gitignored — keep it that way: never commit them, copy them into a shared folder, back them up to an untrusted location, or paste them into logs or chat. Rotate the OAuth client (and runauth logout) if one may have leaked.
Commands
Discover the data types
google-health-cli types list # all types ( * = supports list )
google-health-cli types describe heart-rate # one type's record shape, scope, time field
Read data points (the core)
google-health-cli data list heart-rate --days 1 # last 1 day
google-health-cli data list sleep --days 14 # last 14 days
google-health-cli data list daily-resting-heart-rate --days 30
google-health-cli data list steps --date 2026-06-16 # one civil day
google-health-cli data list weight --from 2026-01-01T00:00:00Z --to 2026-07-01T00:00:00Z
google-health-cli data list distance --all # everything, no time filter
stdout is always a JSON array of the raw data points (verbatim from the API); a one-line
count goes to stderr. Window flags (precedence: --all > --from/--to > --date/--days):
--date today|yesterday|YYYY-MM-DD, --days N (default 7), --from/--to (RFC3339, together),
--all (no filter).
Example (data list daily-resting-heart-rate):
[
{
"dataSource": { "platform": "FITBIT", "device": { "displayName": "Google Pixel Watch 4 (45mm)" } },
"dailyRestingHeartRate": { "date": { "year": 2026, "month": 6, "day": 17 }, "beatsPerMinute": "78" }
}
]
A few types are roll-up/reconcile-only and can't be listed (types list marks listable ones
with *); read those with rollup daily instead (below). One type —
daily-heart-rate-zones — supports neither list nor rollup daily; it is reachable only via
the api get escape hatch.
Daily roll-ups (server-side totals)
google-health-cli rollup daily steps --days 7 # one reconciled total per civil day
google-health-cli rollup daily active-minutes --days 7 # a roll-up-only type (no `data list`)
rollup daily returns the API's daily roll-up rows — one value per civil (local)
calendar day — instead of the raw per-minute/per-sample points data list returns. It's the cheap
way to get daily totals (e.g. a steps total per day rather than a per-minute dump) and the only
way to read the roll-up-only types that have no list op (active-minutes, total-calories,
floors, calories-in-heart-rate-zone, time-in-heart-rate-zone). stdout is a JSON array of the
raw roll-up rows; an N daily rollup(s) count goes to stderr. Each value is reconciled
across data sources (and excludes off-wrist intervals), so it is not a naive sum of data list
points. Window flags mirror data list minus --all (the range is required).
[
{
"civilStartTime": { "date": { "year": 2026, "month": 6, "day": 16 }, "time": {} },
"civilEndTime": { "date": { "year": 2026, "month": 6, "day": 17 }, "time": {} },
"steps": { "countSum": "8000" }
}
]
Parsed exercise sessions (convenience)
google-health-cli sessions --days 14 --json # flattened exercise rows
google-health-cli sessions --raw # raw exercise data points
[
{ "date": "2026-06-16", "exercise_type": "ELLIPTICAL", "duration_min": 35,
"avg_hr": 130, "calories": 236, "platform": "FITBIT" }
]
sessions returns all exercise types (no filtering); the caller keeps what it wants.
Raw read-only API access
google-health-cli api get /v4/users/me/profile # GET any read-only v4 path
google-health-cli api get /v4/users/me/settings
⚠️ Sensitive endpoints — broader than the typed metrics.
api getcan read any read-only v4 path, includingusers/me/profileandusers/me/settings— account, identity, and settings data that the typed commands don't surface. Its responses are personal data printed to stdout, so the same Privacy caution above applies, and the broad reach makes over-collection easy. It stays GET-only (no path can write or delete) and is constrained to the read-only v4 surface (/v4/...): a non-v4/path, an absolute URL, or a..traversal — literal or percent-encoded (%2e%2e,..%2f) — is rejected (exit 64) before any request is made. Still, prefer the typeddata/rollup/sessionscommands and reach forapi getonly when you need an endpoint they don't model.
Full command reference
| Command | What it does | --json |
|---|---|---|
auth login | logout | status | OAuth login (one-time browser), token mgmt | status |
doctor | Config + token validity; reports configFound/clientIdLoaded and exits non-zero (78) when no config / no client_id is found, else 2 if not authed | always |
types list | describe | Inspect the data-type catalog (no network) | ✓ |
data list | List data points for a type (always JSON) | n/a (always) |
rollup daily | Server-side daily totals, reconciled per civil day | n/a (always) |
sessions [--days N] [--raw] | Parsed exercise sessions (convenience) | ✓ |
api get | Raw read-only GET of any v4 path | n/a |
config show | path | Inspect resolved config (client_secret masked) | show |
version | Build metadata (also --version) | ✓ |
completion | Shell completion (bash/zsh/fish/powershell) | — |
Conventions
- stdout is parseable; human hints, counts, and logs go to stderr, never interleaved.
- Exit codes:
0success,2auth/API failure (incl.doctorwhen unauthenticated),64usage error (incl. an expired token with no OAuth client credentials to refresh it),78config error. An expired token plus an undiscoverable/credential-less config fails fast with an actionable message — not the crypticoauth2 "Could not determine client ID"error. - Read-only: six read-only
googlehealth.*.readonlyscopes; no write operations exist. - Secrets:
config.jsonand the token cache are gitignored — never commit them. - Time-filter formats are handled for you per data type (civil wall-clock, RFC3339
instant, or date-only); a
--date/--dayswindow always covers your local calendar days. If a type rejects server-side filtering, re-run with--all.
See the repo's AGENTS.md for the exact --json shapes and exit-code contract.
相关技能
Ingest Apple Health Auto Export JSON (HealthMetrics + Workouts) into a local DuckDB database and render offline HTML dashboards plus a Markdown daily summary...
Use the Health Data AI Analyzer Mac app read-only localhost API on macOS to generate a concise Apple Health daily brief and 3 practical suggestions. Only run...
More granular and few more features than the original one that is based on and seems to be abandoned. I will be fine to merge with original one but I have got not reply for MRs.
Access the user's biohub — WHOOP, Oura, Fitbit, Apple Health, and Garmin biometrics (recovery, sleep, strain, HRV, SpO₂); FreeStyle Libre continuous glucose...
Answers questions about your website traffic from Google Analytics 4: top pages, traffic sources, what changed last month, who is on the site now. Read-only; calls Google's Analytics API with your credential and returns the rows here. Ask "how many visitors last week" or "top pages".