garmin-cli
Agent-first CLI for Garmin Connect. Wraps the garminconnect Python library so it can be driven from a shell or by an AI agent. Every command emits JSON, exits with a typed code, and carries an actionable hint on failure.
Scope: sleep, steps, and auto-detected activities. Designed to grow.
Not affiliated with, endorsed by, or sponsored by Garmin Ltd. This tool talks to Garmin Connect through the unofficial, reverse-engineered
garminconnectlibrary, not an official Garmin API; it can break if Garmin changes their endpoints.
Install
Requires Python 3.12+.
pipx install garmin-cli
# or:
uv tool install garmin-cli
# or:
pip install garmin-cli
garmin is now on your PATH.
Auth (one-time)
Interactive login. Caches OAuth tokens to ~/.garminconnect (override with $GARMINTOKENS).
garmin auth login
Prompts for email, password, and MFA. Re-run only if subsequent calls fail with auth errors (≈ yearly).
For headless hosts (no TTY): run auth login on a machine with a terminal, then copy ~/.garminconnect/ to the headless host.
Quickstart
# Sleep that ended on 2026-05-11 (Garmin's "wake date" convention)
garmin sleep get --date 2026-05-11
# Steps for a day in 30-min buckets (default is 15m — Garmin's native granularity)
garmin steps get --date 2026-05-11 --bucket 30m
# Walks that Garmin auto-detected on a given day
garmin activities list --date 2026-05-11 --type walking
# All activity types over a date range
garmin activities list --start 2026-05-01 --end 2026-05-11
# Just the timestamps from sleep
garmin sleep get --date 2026-05-11 \
--fields sleepStartTimestampGMT,sleepEndTimestampGMT,sleepWindowConfirmed
# What operations exist?
garmin schema --list
# What does any operation accept and return?
garmin schema sleep.get
garmin schema steps.get
garmin schema activities.list
Agent skills
Bundled, offline agent docs ship inside the package. An agent can read them at runtime or install them locally — no credentials needed.
garmin skills list # one line per skill (name + description)
garmin skills get garmin-shared # print a skill's body
garmin skills install # interactive: ./.claude/skills or ~/.claude/skills
garmin skills install --output-dir ./.claude/skills # non-interactive
Start with garmin-shared (the front door), then the per-resource skills
(garmin-sleep, garmin-steps, garmin-activities) and the
recipe-reconstruct-day workflow.
Common recipes
"Was my 09:00–09:30 commute active?" Pull steps in 30-min buckets, find the slot that overlaps:
garmin steps get --date 2026-05-11 --bucket 30m \
| jq '.[] | select(.startGMT | startswith("2026-05-11T07:00"))'
# (note: startGMT is UTC; convert your local time first)
"Was that empty calendar slot a walk?" Check Garmin's auto-detected activities for that day:
garmin activities list --date 2026-05-11 --type walking \
--fields startTimeLocal,duration,distance,activityName
If nothing comes back, fall back to step buckets and look for sustained primaryActivityLevel == "active" runs.
Output contract
- stdout: JSON (default), NDJSON (
--format ndjson, one object per line), or one-line text (--format text). - stderr: errors as JSON
{"error": ..., "hint": ...}. --fields a.b,c.d: dotted-path filter, comma-separated. Arrays descend implicitly.- Envelope:
garmin sleep getpeels Garmin's outerdailySleepDTOwrapper; you consume the inner object directly. So--fields sleepStartTimestampGMT(notdailySleepDTO.sleepStartTimestampGMT).steps getandactivities listreturn arrays as-is. - Bucket aggregation (steps): Garmin's API returns 15-min buckets.
--bucketrolls them up client-side; sumsstepsand takes the most-activeprimaryActivityLevelacross constituents (none < sleeping < sedentary < active < highlyActive). Bucket must be a multiple of 15 minutes.
Exit codes
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | API error (no confirmed sleep for date, etc.) |
| 2 | auth error (no cached tokens / expired) |
| 3 | validation error (bad --date, etc.) |
| 4 | schema error (unknown op in schema <op>) |
| 5 | internal error |
Tests
uv run pytest -v
License
MIT.
Metadata
Release files for garmin-cli 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| garmin_cli-0.1.0.tar.gz | 44.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| garmin_cli-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 68.4 kB
Release files / garmin_cli-0.1.0.tar.gz
| Download URL | garmin_cli-0.1.0.tar.gz |
|---|---|
| Size | 44.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7214ed43e99c28f3296714b14b73564c72df1d9e6ce80a7b0fe6916f62a75b5f
|
|
BLAKE2b-256 checksum How to use checksums |
b9fa13dc60533252197daf4b634da7418916452d12b76a586ce1e83e5fe8ee89
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency logRelease files / garmin_cli-0.1.0-py3-none-any.whl
| Download URL | garmin_cli-0.1.0-py3-none-any.whl |
|---|---|
| Size | 24.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9270b0ce3eb8d7158b7cd6437133708b022f6944772bdc8f061d6f8b3a3a311a
|
|
BLAKE2b-256 checksum How to use checksums |
aa4f98afa62028adc1342f0e510b6ade24e67bb03f6daae47c41ccd5bf8f2898
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency log