Skip to main content
Glama
bank3005-jpg

Garmin Nutrition Coach

by bank3005-jpg
README.md
<p align="center">
  <img src="assets/leanloop-cover.jpg" alt="LeanLoop for Garmin β€” private AI nutrition & fitness coach (Garmin + Claude + Notion + Google Cloud)" width="100%">
</p>

**Turn Claude into your personal, data-driven health coach β€” self-hosted, private, ~$0/month.**

[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![MCP](https://img.shields.io/badge/Protocol-MCP-blue)](https://modelcontextprotocol.io)
[![Cloud Run](https://img.shields.io/badge/Runs%20on-Google%20Cloud%20Run-4285F4?logo=googlecloud&logoColor=white)](https://cloud.google.com/run)
[![Python](https://img.shields.io/badge/Python-3.12-3776AB?logo=python&logoColor=white)](requirements.txt)

### Why LeanLoop?

Losing weight is a calorie deficit β€” but a deficit run **blind** burns muscle, not just fat. Lose muscle and your daily burn (TDEE) drops, so you have to eat *even less* to keep losing. That's the slow-starvation spiral that makes most diets miserable and short-lived.

LeanLoop keeps you on the healthy side of that line by giving Claude three things at once:

- 🍽️ **What you eat** β€” snap a photo or just type it; calories **and macros** land in Notion, and every meal is kept with its time so you can see your real eating habits, not just a daily number.
- πŸ”₯ **What you *actually* burn** β€” your Garmin measures it live, every day (workouts, steps, all-day movement), so your deficit is based on your real body β€” not a one-size-fits-all formula that's wrong for you.
- πŸŒ™ **How you're recovering** β€” sleep, HRV, stress and body battery feed the coaching, so "train hard or rest today?" fits the day you're actually having.

Because all of it already flows to Claude, there's **no more screenshotting dashboards into chat**. Just ask.

> *"Coach me today" Β· "How did I sleep?" Β· "Why did my run feel bad?" Β· "What are my eating patterns this week?" Β·* πŸ“Έ *[photo of lunch]*

## ✨ Features

| | Feature | What it does |
|---|---|---|
| πŸ“Έ | **Photo (or text) food logging** | Snap a meal or type it β†’ calories & macros estimated and auto-saved to Notion, with the full per-meal history (time + item) kept on the day's page for habit analysis |
| πŸŒ™ | **Automatic day close** | Every night your server pulls the finished day's true TDEE from Garmin and writes TDEE + workouts into your log (your deficit column recalculates itself instantly β€” it's a Notion formula) β€” self-heals 3 days back, colored sync tags show status at a glance |
| πŸ”₯ | **Progress you can see** | Cumulative deficit (β‰ˆ kg of fat) updated nightly right on your Notion food log |
| πŸƒ | **Coaching on real data** | One-call readiness verdicts, post-workout analysis (splits, HR zones, sleep context), weekly reviews, injury pattern tracking |
| πŸ‹οΈ | **Strength tracking + progression** | Log lifts in plain speech (with optional **RIR**/effort) β†’ a clean per-exercise table with volume + estimated 1RM; the coach reads your last session, sees the trend, and prescribes the next load like a trainer |
| πŸ“Š | **Fast strength history** | Every lift is mirrored into a flat Notion DB, so "what did I press last time?" is ONE query instead of opening a month of day-pages β€” the load table stays on the page too, so nothing depends on it |
| πŸ“± | **Phone/watch widget** | Optional read-only endpoint serving today's kcal + macros vs target β€” point an iOS Scriptable widget at it and see your remaining calories from the home screen, no app to open |
| πŸ“ˆ | **Second-by-second analysis** | FIT-file parsing: HR/pace/cadence streams + **aerobic decoupling** β€” the endurance metric real coaches use |
| βš–οΈ | **Calibration loop** | Every 2 weeks: logged deficit vs. actual weight change reveals your personal estimation bias, which corrects all future estimates |
| πŸ”„ | **Live-updating brain** | Coaching rules live in [`playbook.md`](playbook.md), fetched by your server at runtime β€” improvements reach every user instantly, no reinstall |

## πŸš€ Install (no coding needed)

1. In Claude, create a **Project** and name it **LeanLoop** (this is where your coach will live).
2. In that Project, enable the **Notion** connector (Claude needs it to build your databases).
3. Open a chat inside the Project β€” set the model to **Sonnet at Medium** effort for setup (lots of IDs to track; switch to Low for everyday use afterward) β€” and paste:

```
Read https://github.com/bank3005-jpg/LeanLoop-for-Garmin/blob/stable/SETUP.md and set this up for me
```

Claude interviews you (goals, body stats), creates your Notion databases, walks you through the cloud steps, then adds your server as a second connector and loads the coaching rules into the Project. **45–60 minutes, one time.** After setup, everyday food logging runs fine on **Sonnet Low**.

> ⚠️ **Requires Claude Pro (or Max/Team/Enterprise).** LeanLoop runs on **two custom connectors at once** β€” Notion (your food/training/body logs) and your Garmin server (live wearable data). The **Free plan allows only one** custom connector, which isn't enough for the full loop. Pro also gives the usage headroom for daily photo food-logging. You do *not* need any paid Notion or Garmin plan β€” their free tiers are fine.

**Prerequisites:** a Garmin watch Β· Notion account (free) Β· Google account with billing enabled (stays within free tier) Β· **Claude Pro** (or Max/Team β€” needs two custom connectors at once; Free allows only one) Β· Windows or macOS computer for one step.

> πŸ“š **Docs:** [USAGE.md](USAGE.md) β€” how to use it (what to say to your coach) Β· [SETUP.md](SETUP.md) β€” install Β· [CONFIG-REFERENCE.md](CONFIG-REFERENCE.md) β€” the Config "brain" Β· [SECURITY.md](SECURITY.md) β€” keep your data safe Β· [CONTRIBUTING.md](CONTRIBUTING.md) β€” fork / maintainer notes

## πŸ—οΈ Architecture

```
Claude (any device, incl. phone)
   └── your Cloud Run server  ← this repo, deployed to YOUR Google account
         β”œβ”€β”€ Garmin Connect   ← your token, created on your own computer
         β”œβ”€β”€ your Notion      ← food / training / body logs
         └── playbook.md      ← coaching rules, served live from GitHub
   Cloud Scheduler β†’ nightly close-day job + keep-warm pings
   GET /<WIDGET_KEY>/today β†’ phone home-screen widget (optional, read-only)
```

**Privacy by design:** everything runs in *your* accounts. No third party β€” including this repo's author β€” ever sees your data. The server is protected by a long random secret; Garmin credentials never pass through chat.

## 🧰 What's inside (23 lean MCP tools)

**Health** `get_wellness(metric)` β€” sleep, HRV, stress, body battery, heart rate, SpO2, respiration, intensity minutes, hydration, blood pressure, body composition, training readiness/status Β· `get_daily_summary`
**Training** `get_activities` (recent or date range) · `get_activity(id, view)` — summary, splits, HR zones, FIT streams, aerobic decoupling · `get_fitness(metric)` — VO2max, race predictions, endurance/hill scores, lactate threshold, PRs, fitness age · `get_coach_snapshot` (one-call verdict data) · `analyze_activity` (one-call post-workout bundle) · `weekly_report` / `calibrate_report` (pre-computed reviews) · `traininglog_read` (Notion actuals: runs + weight lift tables) · `lift_history(exercise, weeks)` (one fast query for a single lift's full history — loads, RIR, volume, e1RM, oldest→newest) · `lift_backfill` (one-time import of past sessions into the flat Lifts DB)
**Body** `get_weight_history` Β· `add_body_composition` (**write** InBody/DEXA scans into Garmin)
**System** `foodlog_read` / `foodlog_upsert` (direct Notion food log, meal-by-meal history) Β· `get_config` / `foodlib_find` / `foodlib_upsert` / `exercise_find` (fast server-side Notion reads, dedup foods into your library) Β· `weightlog_upsert` (log a lift session) Β· `get_today` (server date/time β€” anchor dated actions) Β· `get_playbook` (live coaching rules)

Few tools by design: a lean tool list keeps every chat's context small β€” grouped tools with a `metric`/`view` parameter carry the same 35 capabilities at ~half the token overhead.

## πŸ”„ Updating

- **Coaching rules** β€” update automatically (served live from this repo)
- **Server code** β€” `git pull` + one deploy command, or enable a Cloud Build trigger on `stable` for fully automatic deploys
- Want to customize the code? **Fork** the repo and point your deployment at your fork

## πŸ€– Using it with ChatGPT or OpenAI Codex (instead of Claude)

LeanLoop's brain is a **standard remote MCP server** β€” it is *not* tied to Claude. Any MCP-capable client can connect to the exact same Cloud Run server and get the same 23 tools. Two confirmed paths (verified Aug 2026):

**ChatGPT β€” Developer Mode** (Plus / Pro / Business / Enterprise / Edu, web app):
`Settings β†’ Apps β†’ Advanced β†’ Developer Mode` β†’ **add a remote MCP server** β†’ paste your server URL (`https://<your-cloud-run-url>/<MCP_SECRET>/mcp`). ChatGPT supports Streamable HTTP + SSE with *OAuth-or-none*, so the secret-in-URL that LeanLoop already uses works as-is. Put the bootstrap (below) into a **Custom GPT**'s instructions.

**OpenAI Codex** (CLI or desktop):
`codex mcp add leanloop -- <streamable-http url>`, or add it to `~/.codex/config.toml` (a project-scoped `.codex/config.toml` also works). Codex supports remote **Streamable HTTP** MCP with bearer/none auth. Put the bootstrap into `AGENTS.md` / project config.

**Bootstrap** (the equivalent of the Claude-Project setup β€” paste into the Custom GPT instructions / AGENTS.md):
> *At the start of any food / training / coaching conversation, call `get_playbook` (no args) and follow every rule it returns, and read `get_config` for the user's current targets. All coaching logic lives in those two tools β€” never guess.*

**What ports 1:1 (zero changes):** the whole server, all 23 tools, your Garmin token, your Notion databases, the Cloud Run deployment, and the nightly cron. These are **model-agnostic** β€” build them once, any AI uses them.

**What's different / to watch:**
- **You likely need only the ONE LeanLoop connector**, not a separate Notion one β€” the server reads *and writes* your food / config / training logs in Notion **itself** (server-side, via its own token). A separate Notion MCP is only needed for occasional hand-editing of page structure.
- **The playbook is tuned to Claude's behaviour.** GPT models follow instructions a little differently β€” expect to tweak some wording (e.g. the "always render the full food table" rules) until it behaves.
- **Photo food-logging** needs a client with vision β€” ChatGPT has it.
- **Codex-only shortcut that skips Google Cloud:** because Codex runs code locally, you *can* run `main.py` as a **local stdio MCP server** (no Cloud Run at all) β€” this removes the single hardest setup step. Trade-offs: no nightly auto-close cron (that needs an always-on host) and no phone access β€” it only works while your computer + Codex are running. Great for trying it; Cloud Run is still better for daily hands-off use.

**Bottom line β€” fully feasible.** The three genuinely fiddly one-time steps people worry about β€” **Notion setup, Garmin token, cloud deploy** β€” are *identical* on any platform, because they connect **your data**, not Claude specifically. Once they're done, pointing ChatGPT or Codex at the server is a ~2-minute config. The one-time steps are in [`SETUP.md`](SETUP.md). *(Community/experimental β€” the maintainer builds on Claude; GPT/Codex paths may need small prompt tweaks.)*

## ❓ FAQ

**Is it really free?** Yes β€” Cloud Run free tier covers personal use many times over. The setup guide includes guardrails so you stay in it.
**Does my data go anywhere?** No. Your server, your Garmin token, your Notion. Self-hosted means self-owned.
**What if Garmin changes their API?** The community library this builds on ([python-garminconnect](https://github.com/cyberjunky/python-garminconnect)) gets patched quickly; update with one `git pull` + deploy.
**Garmin China accounts?** Not supported (separate system).
**No watch some days?** The nightly job falls back to your formula baseline and tags the day `estimated`.

## πŸ’¬ Why this exists

I'm not a programmer. I built LeanLoop together with Claude because I wanted to lose weight, get my confidence back, and just *feel better* β€” and I couldn't find a tracker that coached me on my **real** data instead of generic formulas. It worked for me, so I'm sharing it.

I use LeanLoop every single day and keep refining it as I go. If you hit a problem or want a feature, **[open a thread in Discussions](https://github.com/bank3005-jpg/LeanLoop-for-Garmin/discussions)** β€” I read everything.

## πŸ™ Credits

Built on [python-garminconnect](https://github.com/cyberjunky/python-garminconnect) by cyberjunky Β· [fitdecode](https://github.com/polyvertex/fitdecode) Β· [MCP](https://modelcontextprotocol.io) by Anthropic.

## ⚠️ Disclaimer

This is a personal tracking and coaching tool, **not medical advice or a medical device**. Calorie and macro estimates are approximations. Consult a healthcare professional for medical decisions, and stop training and seek care for any concerning symptoms.

## πŸ“„ License

[MIT](LICENSE) β€” use it, fork it, share it.