garmin
Your Garmin data, answered in the terminal
Body Battery, HRV, resting heart rate, sleep stages and score, VO2 max, training load and readiness - asked live, or written out as a markdown day and a weekly rollup you keep. Your password is never stored, and the skill talks to Garmin and nothing else.
Install garmin
Add the DBHQ marketplace, once
/plugin marketplace add dbhq-uk/marketplaceInstall the skill
/plugin install garmin@dbhq
Both commands work in Claude Code and in Codex. The marketplace is a public repository you can read first: dbhq-uk/marketplace (external site)
What it is good at
No MCP server, and nothing in the middle
A Garmin Connect MCP server is the other common way to do this. This is a set of scripts instead: your agent runs one when you ask, it reads from Garmin Connect directly and it exits, so there is no server to run and no service in between. It does have one thing to keep up to date. The library underneath tracks an API Garmin does not document, and when that library changed its login, every saved session needed one fresh login.
Answering, and archiving
Most integrations do one or the other. A live query returns today's vitals into the conversation; a snapshot writes a whole day as a markdown file and a rollup aggregates a week into a summary, both into a directory you name. Those files are yours, in plain text, and they outlive both this skill and your Garmin account.
The whole spread, not a headline number
Resting heart rate, HRV, Body Battery, stress, steps and calories; sleep score with deep, light, REM and awake; activities with heart rate, calories and training effect; VO2 max, training load, training status and training readiness.
Telling "no data" apart from "the call failed"
A day Garmin has nothing for renders as no data and the file still writes. A fetch that failed stops the run and writes nothing, so a day already archived stays as it was. That distinction sounds pedantic until the alternative bites you: an archive quietly full of empty days, indistinguishable from days you did not wear the watch. And once Garmin rate-limits a call, no script calls it again until the block has had time to clear, because knocking again only extends it.
Being tested against the real client, not only a mock
Garmin Connect has no public API and no versioning, and the library that wraps it renames things when Garmin moves underneath it. A mock invents whatever attribute it is asked for, which is how an authentication rename went unnoticed for months. So one test imports the real library and inspects its actual surface - and still makes no network call.
What it does not do
It will not write anything back to Garmin
Every call is a read. There is no code path that creates, edits or deletes anything in your Garmin account, and there never will be. A health record you did not enter yourself is worse than no record.
It will not send your data anywhere but Garmin and you
No analytics, no aggregation service, no anonymised upload, and no DBHQ service in the middle. Your password is never stored: the login hands it to Garmin and forgets it, and the tokens Garmin issues are kept in your home directory at mode 600. What it reads does go into your agent's conversation, and so to whoever runs the model behind it. Run it with the network off and it fails to reach Garmin and does nothing else.
It will not give you medical advice
It reports what the watch measured, and Garmin's own figures are estimates from a wrist optical sensor. Body Battery, stress and sleep staging in particular are proprietary models rather than measurements. Treat them as trend lines, not diagnoses.
It will not run below Python 3.12
That floor comes from the library underneath, not from the skill. It also needs a Garmin Connect account - the same one you use in the app - and it will not log in for you: you run the login yourself, in your own terminal, and it asks for a multi-factor code if Garmin sends one. Every other script only resumes that session.
Read it before you install it
Every line is public and MIT licensed. The README is the long version of this page, including the parts that are still rough.