Skip to content

LuigiCerone/obsidian-garmin-connect-scripts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

obsidian-garmin-connect-scripts

Python script to fetch Garmin Connect stats and update Obsidian note frontmatter.

Key Features:

  • Automatically detects dates from YYYY-MM-DD.md filename pattern
  • Updates Obsidian note frontmatter with Garmin daily stats
  • Configurable field mappings for custom frontmatter properties
  • Activity-based tracking by sport type (cycling, running, swimming, etc.)
  • Works seamlessly with Obsidian's Daily Notes plugin

Setup

  1. Install dependencies with uv:
uv sync
  1. Set up your Garmin Connect credentials by creating a .env file:
cp .env.example .env

Then edit .env with your credentials:

GARMIN_EMAIL=your-email@example.com
GARMIN_PASSWORD=your-password

Important:

  • Credentials MUST be set in .env file (required for automated script execution)
  • MFA (Multi-Factor Authentication) is currently NOT supported
  • If you have MFA enabled on your Garmin account, you'll need to disable it to use this script
  1. First run authentication:

On first run, the script will authenticate with Garmin Connect and save tokens to ~/.garmin_tokens. Future runs will use these cached tokens automatically.

Running from Obsidian

Using Shell Commands Plugin

  1. Install the Shell Commands plugin in Obsidian

  2. Open Settings → Shell commands → New shell command

  3. Add this command (choose one option):

    Option A - Use full path to uv (Recommended):

    cd /path/to/obsidian-garmin-connect-scripts && ~/.local/bin/uv run main.py "{{file_path:absolute}}"

    Option B - Source your shell profile:

    source ~/.zshrc && cd /path/to/obsidian-garmin-connect-scripts && uv run main.py "{{file_path:absolute}}"

    Note: Replace /path/to/obsidian-garmin-connect-scripts with your actual project directory.

  4. Configure the command:

    • Alias: Give it a name like "Sync Garmin Stats"
    • Hotkey (optional): Assign a keyboard shortcut in Settings → Hotkeys
    • Icon (optional): Add to ribbon or command palette
  5. Now you can:

    • Use the command palette (Cmd/Ctrl+P) and search "Sync Garmin Stats"
    • Use your custom hotkey
    • Click the ribbon icon if configured

Using Custom Mappings in Obsidian

If you want different mappings per vault or note type, modify the command:

cd /path/to/obsidian-garmin-connect-scripts && ~/.local/bin/uv run main.py "{{file_path:absolute}}" --map steps:totalSteps --map distance:totalDistanceMeters

Tips

  • The script will update the currently open note when triggered from Obsidian
  • If your daily notes use YYYY-MM-DD.md naming (Obsidian's default), the date will be automatically detected from the filename
  • Make sure your .env file is configured with Garmin credentials
  • The first run will authenticate and cache tokens for future use
  • You'll see a success message in the shell output pane
  • Works perfectly with Obsidian's Daily Notes plugin (uses YYYY-MM-DD.md format by default)

Troubleshooting

"uv: command not found"

  • Use the full path: ~/.local/bin/uv instead of just uv
  • Or find your uv location: run which uv in terminal and use that path

"Permission denied"

  • Make sure the script has execute permissions: chmod +x main.py

"Missing GARMIN_EMAIL or GARMIN_PASSWORD"

  • Ensure your .env file is in the project root directory with both variables set
  • Check that the shell command is running from the correct directory (the cd part)

"403 Forbidden" or authentication errors

  • Your Garmin session tokens may be expired or invalid
  • Delete the token cache: rm -rf ~/.garmin_tokens
  • Run the script again to re-authenticate
  • Check your Garmin credentials in .env are correct
  • If you have MFA enabled, disable it - MFA is not supported for automated scripts

"Too many requests" or rate limiting

  • Garmin has rate limits on API calls
  • Wait a few minutes before trying again

Usage

Basic Usage

Run the script from command line with the path to your Obsidian note:

uv run main.py /path/to/your/note.md

The script will:

  • Authenticate with Garmin Connect (tokens cached in ~/.garmin_tokens)
  • Automatically detect the date from the filename (if it matches YYYY-MM-DD.md pattern)
  • Fetch activity stats for the detected date (or today's date as fallback)
  • Update the note's frontmatter with default fields

Automatic Date Detection

The script automatically extracts dates from filenames that follow the YYYY-MM-DD.md pattern:

# Automatically uses 2026-01-13 from filename
uv run main.py 2026-01-13.md

# Falls back to today's date (filename doesn't match pattern)
uv run main.py my-daily-note.md

Date priority:

  1. --date argument (if provided) - highest priority
  2. Date extracted from filename (YYYY-MM-DD.md pattern)
  3. Today's date (fallback)

This makes it easy to update historical daily notes without manually specifying dates.

Default Fields

By default, the following fields are updated:

  • steps: Total steps
  • distance_km: Total distance in kilometers
  • calories: Total kilocalories burned
  • active_minutes: Moderate + vigorous intensity minutes

Custom Field Mapping

Map custom frontmatter properties to Garmin stats:

uv run main.py note.md --map steps:totalSteps --map calories:totalKilocalories --map floors:floorsAscended

Add more fields like heart rate, floors, calories, etc.:

uv run main.py note.md --map steps:totalSteps --map distance_km:totalDistanceMeters --map active_minutes:moderateIntensityMinutes --map floors:floorsAscended --map calories:totalKilocalories --map resting_hr:restingHeartRate

Activity-Specific Fields

Track time spent on different sports by using the activity: prefix:

uv run main.py note.md --map cycling_minutes:activity:cycling --map running_minutes:activity:running --map swimming_minutes:activity:swimming --map other_minutes:activity:other

Supported activity categories:

  • activity:cycling - Cycling, mountain biking, road biking, gravel, indoor cycling
  • activity:running - Running, treadmill, trail running, track running
  • activity:swimming - Swimming, lap swimming, open water
  • activity:walking - Walking, hiking
  • activity:other - Any activity not in the above categories

The script automatically:

  1. Fetches your activities for the day
  2. Categorizes them by sport type
  3. Sums up the duration (in minutes) for each category
  4. Updates your note with the totals

Show Available Stats

See all available Garmin Connect stats:

uv run main.py note.md --show-available

This will display all stats from Garmin Connect with their values, helping you decide which fields to map.

Override Date with --date Argument

You can explicitly specify a date to override the automatic detection:

# Override automatic date detection
uv run main.py 2026-01-13.md --date 2026-01-04

# Specify date when filename doesn't have a date pattern
uv run main.py my-note.md --date 2026-01-04

This is useful when:

  • You want to fetch stats for a different date than the filename suggests
  • The filename doesn't follow the YYYY-MM-DD.md pattern but you don't want today's date

Command-Line Options

  • --map KEY:VALUE or -m KEY:VALUE: Map frontmatter property to Garmin stat (can be used multiple times)
  • --show-available or -s: Display all available Garmin stats and their values
  • --date DATE or -d DATE: Override date detection and fetch stats for specific date (ISO format: YYYY-MM-DD)
  • --help or -h: Show help message

Examples

Default Field Mapping

Given a note named 2026-01-05.md with frontmatter:

---
title: Daily Log
date: 2026-01-05
---

# My Daily Log

Run:

# Date automatically extracted from filename (2026-01-05)
uv run main.py 2026-01-05.md

Result:

---
title: Daily Log
date: 2026-01-05
steps: 8542
distance_km: 6.32
calories: 2341
active_minutes: 45
---

# My Daily Log

Custom Field Mapping

If you want different property names or additional fields:

# Date automatically extracted from filename
uv run main.py 2026-01-05.md --map daily_steps:totalSteps --map km_walked:totalDistanceMeters --map floors:floorsAscended --map calories:totalKilocalories

This will create:

---
title: Daily Log
date: 2026-01-05
daily_steps: 8542
km_walked: 6.32
floors: 12
calories: 2341
---

Activity-Based Example

Track your daily activities by sport:

# Date automatically extracted from filename
uv run main.py 2026-01-05.md --map steps:totalSteps --map cycling_minutes:activity:cycling --map running_minutes:activity:running --map walking_minutes:activity:walking --map other_minutes:activity:other

If you did a 45-minute bike ride and a 30-minute run on 2026-01-05:

---
title: Daily Log
date: 2026-01-05
steps: 8542
cycling_minutes: 45
running_minutes: 30
walking_minutes: 0
other_minutes: 0
---

Discovering Available Stats

Run with --show-available to see what Garmin data you can use:

# Works with any filename
uv run main.py 2026-01-05.md --show-available

Output:

Available Garmin Connect stats:
------------------------------------------------------------
  floorsAscended: 12
  moderateIntensityMinutes: 30
  totalDistanceMeters: 6324
  totalKilocalories: 2341
  totalSteps: 8542
  vigorousIntensityMinutes: 15
  ...
------------------------------------------------------------

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages