context-attachment-manager
Codex and Claude Code plugin (works in Claude Desktop): choose which past images go to the model with your next message. Unchecked images become placeholders, the conversation goes on, and requests st
Obsidian plugin to sync health data from smartwatches into Daily Notes
PluginsTypeScript · JavaScriptGitHub @davadevSelf-installOwner unconfirmed
Paste into Claude or ChatGPT for installation instructions suited to your environment.
Have you tried it? One tap is enough. No sign-in needed.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗English · Deutsch · 中文 · 日本語 · Español · Français
A companion for your daily notes. Garmin Health Sync brings the numbers that matter from your Garmin watch into your Obsidian daily notes, and, if you like, shows how you are doing against your own normal. It is not a copy of Garmin Connect: the aim is to help you make the right decisions for the day.
Two ways to use it
Works on desktop and mobile (Windows, macOS, Linux, iOS, Android). This plugin uses Garmin Connect's internal API — there is no official third-party API available. You sign in with your Garmin email and password (plus the verification code if you use two-step verification). If Garmin blocks that attempt, an alternative browser sign-in is available.
Journal/2024-07/), and creates date-based subfolders when the filename format contains / (e.g. YYYY/YYYY-MM-DD → Journal/2026/2026-08-04.md)trainings field for advanced Dataview queriesohs_ prefix to all frontmatter properties to avoid naming conflicts with other pluginslifestyle_<name> properties; the Habits card in the side panel shows each habit and, once there is enough data, how your HRV and resting heart rate look on the night after it---
steps: 15185
resting_hr: 69
sleep_score: 81
sleep_duration: 7h 43min
hrv: 39
stress: 30
vo2_max: 48
workout_location: Bad Honnef, Germany
---
Body battery: body_battery is Garmin's charged value, the sum of all body battery gains over the day (mostly the overnight recharge), not the current level. Enable body_battery_min and body_battery_max for the lowest and highest level of the day, which is what the Garmin app shows in its history.
Each workout is written as a frontmatter key with a summary string:
---
hiking: 8.2 km · 157min · Ø105 bpm · 696 kcal
e_bike: 22.1 km · 65min · Ø112 bpm · 420 kcal
---
Only days with actual workouts get activity keys. The plugin never touches your note content — it only adds or updates frontmatter properties.
Enable "Machine-readable trainings" in settings to add a structured trainings field for Dataview queries:
---
trainings:
- type: hiking
category: outdoor
distance_km: 8.2
duration_min: 157
avg_hr: 105
calories: 696
- type: e_bike
category: cycling
distance_km: 22.1
duration_min: 65
avg_hr: 112
calories: 420
---
main.js and manifest.json from the latest release.obsidian/plugins/garmin-health-sync/ in your vaultOpen the plugin settings and select Garmin Connect, then enter your Garmin email and password (and the verification code if you use two-step verification). The same sign-in works on desktop and mobile.
Garmin may limit repeated sign-in attempts from one device; the plugin then shows a countdown before you can try again. If sign-in is blocked, use Use browser login instead: you sign in on Garmin's page in your browser, copy the page text that contains ST-… and tap the clipboard button in the plugin (or paste it into the field). Once signed in, the plugin renews the connection by itself, so you rarely need to sign in again.
The daily notes path is the folder, the daily note format is the filename in moment.js syntax — the same convention as the core Daily Notes plugin. The format itself may contain / to nest notes into date-based subfolders, and square brackets keep text literal:
| Path | Format | Result |
|---|---|---|
Journal | YYYY-MM-DD | Journal/2026-08-04.md |
Journal | YYYY/YYYY-MM-DD | Journal/2026/2026-08-04.md |
Journal | YYYY/YYYY-MM/YYYY-MM-DD | Journal/2026/2026-08/2026-08-04.md |
Journal | YYYY-MM-DD [Workout] | Journal/2026-08-04 Workout.md |
Missing subfolders are created automatically.
On every Obsidian startup, the plugin checks the last 7 days and fills in any missing health data automatically. No action needed. By default it creates a daily note when one is missing.
If another tool owns your daily notes (Templater, the Calendar plugin, an external sync), set Days without a daily note in the settings to Skip the day. Auto-sync then waits until a real (non-empty) daily note exists and syncs the moment it appears — empty 0-byte placeholders are ignored. With Keep in history files the plugin creates no note for a day without one and stores the day in the history notes instead (see below). A manual sync always writes to the note you have open.
Open a Daily Note and run Garmin Health Sync: Sync current note from the Command Palette (Cmd/Ctrl+P).
Have years of Garmin data? Backfill health data fetches any range of days:
The days are fetched newest first, with the rate limiting Garmin needs. A notice at the top shows the day, how many days are done and the time left, with a Stop button, and on a desktop the status bar shows the percentage. If you click the notice away, the command Show the progress of the running backfill (listed only while one runs) or a click on the status bar item brings it back. Only one backfill runs at a time. A stopped or interrupted backfill goes on after a restart, from where it stopped. Garmin failures are retried, and a day that an earlier backfill fetched (with all your enabled metrics) is skipped, except the last 3 days, which may still change.
Open it from the ribbon icon or the command Open health panel; asking for it switches it on, there is nothing to turn on first (Side panel in the settings turns it off again). The cards compare today with your own usual range (the last 30 days) and never change your notes. Tap the date to pick a day, use the arrows to move by a day, and the pencil button to arrange the cards by dragging. Every card has a switch in the settings that also says which metrics to enable for it. Tap the light bulb on a card for What your data suggests (reasons and what helps, taken from your own data) and How to read this. The panel is not medical advice. Adding your birth year (only the year) in the settings gives heart rate zones and age-based goals. See what every card shows and how it is worked out.
With Days without a daily note set to Keep in history files, every fetched day is also stored in small monthly notes (Garmin history/Garmin history 2026-10.md, one line per day) in your daily notes folder. They are plain markdown, so they sync with your vault, and the panel reads them for days that have no note. The command Import history from daily notes copies the Garmin values of your existing notes into them. The backfill can fill them back to the start of your data in one go (Until my data starts). If you change your daily notes folder, the history notes move along with it.
The setting Properties of daily notes can fold the properties block of a daily note when it opens, hide the properties the plugin wrote (the panel shows them), or both. Nothing is deleted from a note. Folding and hiding follow the ideas of the community plugins Fold Properties By Default and Extended Properties; see Credits.
Garmin's typeKey values are normalized to cleaner canonical keys:
| Provider Key | Canonical Key | Category |
|---|---|---|
e_bike_fitness | e_bike | cycling |
e_bike_mountain | e_mtb | cycling |
resort_skiing_snowboarding | skiing | winter |
backcountry_skiing_snowboarding | backcountry_skiing | winter |
stand_up_paddleboarding | sup | water |
fitness_equipment | gym_equipment | gym |
All other Garmin keys pass through unchanged (e.g. hiking, running, cycling, swimming, strength_training, yoga, ...).
Each activity is assigned a category:
| Category | Examples |
|---|---|
cycling | cycling, e_bike, e_mtb, mountain_biking, indoor_cycling, road_biking, virtual_ride |
running | running, trail_running, treadmill_running, indoor_running, ultra_run |
walking | walking, indoor_walking |
outdoor | hiking, mountaineering, rock_climbing, bouldering |
swimming | swimming, lap_swimming, pool_swimming, open_water_swimming |
winter | skiing, backcountry_skiing, cross_country_skiing, snowboarding |
water | sup, rowing, kayaking, paddling, surfing, sailing |
gym | strength_training, gym_equipment, elliptical, yoga, pilates, hiit, indoor_cardio |
racket | tennis, badminton, squash, table_tennis, pickleball |
team | soccer, basketball, volleyball, rugby |
recovery | breathwork, meditation, stretching, mobility (left out of the load) |
other | golf, multi_sport, triathlon |
Newer sports carry a suffix from Garmin (kayaking_v2, skate_skiing_ws); it is dropped for the name and the category, so they count like the plain sport. Sessions are shown with the sport's name in your plugin language; a sport that is not listed here is shown as readable text and counts as other. The weekly load card tracks the distance of running, cycling, walking, outdoor sports and swimming.
This plugin makes network requests to two external services:
sso.garmin.com, or sso.garmin.cn for China) and are never stored or logged by the plugin. After sign-in the plugin keeps Garmin sign-in tokens in Obsidian's secret storage, which stays on the device, so they are not synced to other devices or included in vault backups and Git. Only if secret storage is unavailable or rejects the write does the plugin fall back to keeping them in data.json. Treat these tokens like a login: their lifetime is controlled by Garmin. Each device signs in separately. If Garmin blocks or rate-limits the sign-in, a browser sign-in is offered (you sign in on Garmin's own page in your browser and paste the one-time ticket back). The public OAuth client keys needed for sign-in are fetched from thegarth.s3.amazonaws.com (with bundled fallback keys if that host is unreachable). Using Logout clears the stored tokens on this device.nominatim.openstreetmap.org for reverse geocoding. You can disable this in settings under Workout location.No data is sent to any other server.
History notes: the optional history notes contain your health values and live in your vault like your daily notes. The plugin makes no extra network requests for them.
Vault access: the plugin lists the files of your vault (vault.getMarkdownFiles) to find your daily notes and its own history notes by their path and date-based name, and to tell the side panel which days have data. It reads the properties and contents only of the notes it recognises as daily notes or history notes, and writes only to those, to the plugin's backup of a broken note and to its history folder. File names and note contents never leave your device.
Clipboard: The plugin only uses the clipboard when you click a button, never in the background. Use browser login reads it once, when you click Sign in from clipboard, to pick up the one-time login ticket you copied from your browser. It writes to it when you click to copy the sign-in link, or Copy diagnostics (in the settings and in the sign-in window). Diagnostics contain no password, tokens, account data or health values, only technical details of the last sign-in or sync: data type names, HTTP status codes, response sizes, timings and the structure of Garmin's answers (field names and types, never values).
npm install
npm run dev # watch mode
npm run build # production build
Originally created by fcandi. Maintained and developed further by davadev.
The handling of properties in daily notes (folding the properties block, hiding the properties the side panel shows) was inspired by the community plugins Fold Properties By Default by Tommy Bergeron and Extended Properties by electroluminescent (both MIT licensed). No code was copied; see NOTICE.md.