Personal Hevy workout client with analytics, goal tracking, Google Fit integration, and an AI coach that remembers your conversations.
| Feature | Details |
|---|---|
| Sync | Fetches your full Hevy workout history locally. Every sync shows a report with new workouts, PRs set, training streak, and volume vs last week. |
| Analytics | Volume per muscle group, exercise progression (e1RM), personal records, plateau detection. |
| Goals | Set lift targets, frequency goals, body weight / fat / volume targets. Multiple goals of any type coexist. Tracks progress automatically after every sync. |
| AI Report | One-shot coaching report: Training / Health / Combined scores (0–100), volume distribution by muscle group and by individual muscle, strengths, weaknesses, recommendations, and a complete routine tailored to your goals. |
| AI Chat | Interactive coach that knows your full history, can push routines to Hevy, and can update your goals — all with your approval. Chat is the first option in the main menu. |
| Snapshot | At-a-glance panel shown before every menu: last report scores, volume split by muscle group, and all goal progress bars. |
| Memory | After every chat the AI extracts key insights (injuries, preferences, feedback) and saves them. Future sessions start with that context already loaded. |
| Google Fit | Syncs sleep, steps, calories, and resting HR. Recovery score shown in the header and used in AI suggestions. |
| Settings | Weight units (kg / lbs), goal check-in frequency, auto-sync on startup, default stats window, display name — all configurable through the menu. |
| Multi-model | Works with Gemini (default), Claude, OpenRouter, Groq, GitHub Models, or Amazon Bedrock — swap with one env variable. |
- Python 3.11+
- Hevy Pro subscription (API access is Pro-only)
- One of: Gemini API key, Anthropic API key, OpenRouter API key, Groq API key, GitHub token, or AWS credentials
- (Optional) Google account with Fitness data
cd lifter
pip install -r requirements.txtcp .env.example .envOpen .env and fill in your keys (see sections below).
- Log in at hevy.com
- Go to Profile → Settings → Developer
- Copy your API key
- Add to
.env:
HEVY_API_KEY=your-key-here
Option A — Gemini (recommended to start, has a free tier):
- Go to aistudio.google.com and create an API key
- Add to
.env:
AI_PROVIDER=gemini
GEMINI_API_KEY=your-key-here
# AI_MODEL=gemini-2.5-flash ← optional, defaults to gemini-2.5-pro
Option B — Claude (Anthropic):
- Create an account at console.anthropic.com
- Generate an API key
- Add to
.env:
AI_PROVIDER=claude
ANTHROPIC_API_KEY=sk-ant-your-key-here
# AI_MODEL=claude-sonnet-4-6 ← optional, defaults to claude-opus-4-8
Note: Claude Code Pro and claude.ai subscriptions do not include API access. You need a separate API account at console.anthropic.com.
Option C — OpenRouter (access to many models through one API key):
- Create an account at openrouter.ai and generate an API key
- Add to
.env:
AI_PROVIDER=openrouter
OPENROUTER_API_KEY=your-key-here
# AI_MODEL=anthropic/claude-3-5-sonnet ← optional, defaults to anthropic/claude-3-5-sonnet
Option D — Groq (fast inference, free tier available):
- Create an account at console.groq.com and generate an API key
- Add to
.env:
AI_PROVIDER=groq
GROQ_API_KEY=your-key-here
# AI_MODEL=llama-3.3-70b-versatile ← optional, defaults to llama-3.3-70b-versatile
Option E — GitHub Models (free if you have a GitHub account):
- Go to github.com/marketplace/models and generate a personal access token
- Add to
.env:
AI_PROVIDER=github
GITHUB_TOKEN=your-token-here
# AI_MODEL=gpt-4o ← optional, defaults to gpt-4o
Option F — Amazon Bedrock:
Requires an AWS account with Bedrock model access enabled. Credentials are read from the environment using the standard AWS credential chain (IAM role, ~/.aws/credentials, or explicit keys).
- Install the Bedrock extras:
pip install "anthropic[bedrock]"(only needed for Claude models on Bedrock) - Add to
.env:
AI_PROVIDER=bedrock
AWS_REGION=us-east-1
# For Claude models:
# AI_MODEL=anthropic.claude-3-5-sonnet-20241022-v2:0 ← default
# For non-Claude models (Llama, Mistral, etc.) use their Bedrock model ID.
# Explicit credentials (optional — omit if using IAM role or aws configure):
# AWS_ACCESS_KEY_ID=
# AWS_SECRET_ACCESS_KEY=
# AWS_SESSION_TOKEN= ← only needed for temporary credentials
python3 cli.pyThe interactive menu opens. Select Sync new workouts → Full to download your entire Hevy history.
After completing the setup above you can make lifter available as a global command so you can run it from any directory without typing python3 cli.py.
This uses pipx, which installs Python applications into isolated environments and exposes their commands on your PATH. The source code stays in this directory — the global command just points here.
make installlifter is now available everywhere. The first time you run it from a new directory it will still read your .env and use the database in this folder.
After pulling new changes:
pipx reinstall lifterOr equivalently:
make uninstall && make installmake uninstallNote:
pipxinstalls commands to~/.local/bin. Make sure that directory is on yourPATH(most modern shells include it by default). Iflifteris not found after install, addexport PATH="$HOME/.local/bin:$PATH"to your shell profile and reload it.
Adds sleep, steps, calories, and heart rate data to your analytics and AI context.
- Go to console.cloud.google.com
- Create a new project (or select an existing one)
- APIs & Services → Library → search for Fitness API → Enable it
- APIs & Services → OAuth consent screen
- User type: External
- Fill in app name (anything, e.g. "lifter")
- Add your Gmail as a Test user → Save
- APIs & Services → Credentials → Create Credentials → OAuth client ID
- Application type: Desktop app
- Name: anything
- Click Create
- Download JSON → Google will download a file named something like
client_secret_123456789-abcdefg.apps.googleusercontent.com.json
Rename it tofit_credentials.jsonand place it in thelifter/project folder
In the menu: Google Fit → Connect / re-authenticate
A browser window opens. Sign in with the Gmail you added as a test user and approve the fitness permissions. The token is saved as fit_token.json and reused automatically.
Google Fit → Sync health data → 30 days
After syncing, the recovery score appears in the header and the AI coach uses your sleep and HR data in all suggestions.
Samsung Health syncs to Google Fit by default on Android. Enable it in the Samsung Health app under Settings → Connected services → Google Fit.
Run python3 cli.py to open the interactive menu.
Sync new workouts
Chat with coach
─────────────────────
My goals
Dashboard & stats
Exercise progression
Personal records
─────────────────────
AI coaching report
Google Fit (sleep, steps, HR)
─────────────────────
Settings
Exit
Quick view panel — shown above the menu on every launch: last AI report scores (Training / Health / Overall), volume split by muscle group, and compact goal progress bars.
Downloads workout data from Hevy. After every sync:
- Workout cards show each new session with exercises, weights, and ★ PR badges
- Training streak with fire emojis
- Volume bar chart vs last week with % change per muscle group
- Goal progress panel with bars for all active goals
Choose Incremental (default, only fetches changes) or Full (re-downloads everything).
Interactive conversation with the AI. The coach has full access to:
- Your training history and analytics
- Your active goals (with IDs for modifications)
- Google Fit recovery data
- Memories from all previous conversations
What the coach can do during chat:
| Action | How to trigger |
|---|---|
| Answer questions about your training | Just ask |
| Create and push a routine to Hevy | "Create a push day for me" |
| Update an existing Hevy routine | "Update my push day routine" |
| Add a new goal | "Add a goal to deadlift 180kg" |
| Update a goal | "Change my bench goal to 130kg" |
| Remove a goal | "Remove my weight loss goal" |
All goal changes and routine pushes require your explicit confirmation before anything is saved. Pushed routines include a ✦ Powered by Lifter note in the routine description.
After the conversation ends, the AI analyses the full transcript and extracts memorable facts (injuries mentioned, exercise preferences, feedback on suggestions, lifestyle context). These are saved and automatically included in all future sessions.
Set and track training goals:
| Goal type | Example |
|---|---|
| Lift PR | Bench Press — 120 kg |
| Frequency | Train 4× per week |
| Weight loss / gain | Reach 75 kg body weight |
| Body fat | Reach 12% body fat |
| Volume | Chest — 15 sets/week |
| Custom | Free-text goal (AI tracks qualitatively) |
Multiple goals coexist — you can have a lift PR goal, a frequency goal, a custom goal, and body composition goals all active at the same time.
First run: the wizard runs automatically to set your goals.
Check-in: configurable frequency (7 / 14 / 30 days) — the app asks if your goals are still the same.
Progress bars: shown in the Quick view panel and after every sync (green ≥80%, yellow ≥50%, red <50%, ★ when achieved).
Weight input in the goals wizard follows your units preference (kg or lbs) and is stored as kg internally.
Full analytics for a selectable time period (4 / 8 / 12 / 24 weeks). The default period is saved as a preference so the prompt is skipped on repeated use.
- Workout frequency, average duration, rest days, longest streak
- Volume by muscle group with inline bar chart, sets/week, sessions/week
- Body measurement trends (weight, body fat %)
- Personal records set in the last 30 days
- Plateau warnings for stalled exercises
- Top gainers: exercises with the highest e1RM improvement over the period
- Specific exercise: fuzzy-search any exercise and see a session-by-session progression table with per-session e1RM delta (green/red)
Uses the Epley formula (weight × (1 + reps/30)) for estimated 1RM so sets with different rep ranges are comparable.
All-time best set per exercise ranked by estimated 1RM.
Analyses your training data against your goals and generates:
Performance Scores panel:
- Training score (0–100): consistency, progressive overload, balance, plateau avoidance
- Health score (0–100): sleep, recovery, resting HR trend — only shown when Google Fit data is present
- Combined score (0–100): weighted 70% training + 30% health
- Color-coded: green ≥80 · cyan ≥60 · yellow ≥40 · red <40
- Scores are cached and shown in the Quick view panel on every launch
Volume Distribution panel:
- By muscle group (Chest, Back, Legs, Shoulders, Arms, Core, Cardio): % of total weekly sets with bar chart
- By individual muscle: granular breakdown of every trained muscle
Analysis:
- Strengths: what's working
- Weaknesses: imbalances, underworked muscles, plateaus
- Recommendations: 3–5 actionable tips for the next weeks
- Next focus: the single most important thing to address
- Suggested routine: a complete workout with exercises, sets, reps, and weights matched to your current strength level — ready to push to Hevy
Select the number of weeks to analyse (4 / 8 / 12 / 16). After the report, the app asks if you want to push the routine directly to your Hevy app.
- Sync health data: pulls sleep sessions, daily steps, calories, and heart rate
- Recovery dashboard: sleep averages, nightly consistency, resting HR, active minutes
- Recovery score (0–100): composite of recent sleep quality and resting HR trend
- 80–100: Excellent | 65–79: Good | 45–64: Fair | <45: Poor
- Connect / re-authenticate: runs the OAuth browser flow
- Disconnect: removes the token (local data stays in the DB)
When connected, the Google Fit menu item shows a ✓ status chip.
Menu → Settings gives you full control over app behaviour and your local data.
| Setting | Description |
|---|---|
| Display name | Your name shown in the header and used by the AI coach |
| Setting | Options | Default |
|---|---|---|
| Weight units | kg / lbs | kg |
| Goal check-in frequency | Every 7 / 14 / 30 days | 7 days |
| Auto-sync on startup | on / off | off |
| Default stats window | 4 / 8 / 12 / 24 weeks | 8 weeks |
When auto-sync is on, stale Hevy and Google Fit data syncs silently on launch without prompting. When off, you get a confirmation prompt.
Weight units apply everywhere: goal wizard input, dashboard stats, exercise progression, personal records, and the AI routine preview.
| Setting | Description |
|---|---|
| Context mode | Full (all analytics) or Slim (fewer tokens, faster) |
| Token counter | Cumulative input / output / cache-read tokens with cache hit % |
| Reset token counter | Zero out the cumulative counters |
Nothing on Hevy or Google Fit is ever touched — only the local cache on your machine.
| Option | What it clears |
|---|---|
| Clear coach memories | Deletes everything extracted from past chat sessions — the coach starts fresh with no prior context |
| Clear all goals | Removes all active goals; the wizard runs again on next launch |
| Clear sync state | Resets the sync timestamp so the next incremental sync re-downloads all workouts (existing local data is kept) |
| Wipe everything | Double-confirmed — deletes hevy.db and disconnects Google Fit (fit_token.json). Run Sync → Full afterwards to restore |
You can also reset individual pieces manually:
# Delete the local database entirely
rm hevy.db
# Disconnect Google Fit (keeps DB data)
rm fit_token.json
# Force the next sync to re-download everything
sqlite3 hevy.db "UPDATE sync_state SET value='1970-01-01T00:00:00Z' WHERE key='last_sync';"
# Clear only coach memories
sqlite3 hevy.db "DELETE FROM chat_memories;"The panel at the top of every screen shows:
┌─ LIFTER · Your Name ─────────────────────────────────────────────────┐
│ Last workout: 2d ago · 🔥🔥 5d streak · 3 routines │
│ 145 workouts · 3 this week · 4.2/wk avg · 2 goals │
│ AI: claude · claude-opus-4-8 · Sync ✓ 5m ago · Recovery 82/100 │
└──────────────────────────────────────────────────────────────────────┘
- Sync status: green ✓ if synced within 24h, yellow ⚠ if stale
- Routine count: number of routines saved in Hevy
- Recovery: shown when Google Fit is connected and has recent data
lifter/
├── hevy/
│ ├── client.py API wrapper (all Hevy endpoints + payload sanitization)
│ └── sync.py Full + incremental sync via /v1/workouts/events
├── db/
│ ├── store.py SQLite schema + upsert helpers
│ ├── goals.py Goal CRUD, progress computation, user preferences
│ └── memories.py Chat memory: save/load/context
├── fit/
│ ├── auth.py Google OAuth (InstalledAppFlow, token persistence)
│ ├── client.py Google Fit REST API (aggregate + sessions)
│ ├── sync.py Sync sleep and daily stats
│ └── analytics.py Recovery score, sleep summary, activity summary
├── analytics/
│ ├── volume.py Weekly tonnage per muscle group
│ ├── progression.py e1RM progression and plateau detection
│ ├── frequency.py Workout cadence and session duration
│ └── records.py Personal records and body measurement trends
├── ai/
│ ├── provider.py Unified ChatSession abstraction (Gemini, Claude, OpenRouter, Groq, GitHub Models, Bedrock)
│ ├── coach.py Coaching report (with scores + distribution), chat loop, goal tools, memory extraction
│ └── sanitize.py Input sanitization and prompt-injection defence
├── cli.py Interactive menu (questionary + Rich)
├── config.py .env loader
├── hevy.db Local SQLite database (created on first sync)
├── fit_credentials.json Google OAuth credentials (you create this)
└── fit_token.json Google OAuth token (created automatically)
| Table | Contents |
|---|---|
workouts |
Workout metadata |
workout_exercises |
Exercises per workout |
workout_sets |
Sets per exercise (weight, reps, type) |
exercise_templates |
Exercise library with muscle group tags |
body_measurements |
Weight, fat %, body measurements by date |
fit_sleep |
Sleep session duration by date |
fit_daily |
Steps, calories, avg/min HR, active minutes by date |
routines |
Workout routines (created by AI or synced from Hevy) |
routine_exercises |
Exercises within routines |
routine_sets |
Sets within routine exercises |
user_goals |
Active and achieved training goals |
user_preferences |
Display name, units, auto-sync, default windows, cached scores, and other settings |
chat_memories |
Insights extracted from past conversations |
sync_state |
Last sync timestamps and other state keys |
All settings live in .env:
# Hevy
HEVY_API_KEY= # from hevy.com/settings?developer
# AI provider — pick one value for AI_PROVIDER, set the matching key
AI_PROVIDER=gemini # gemini | claude | openrouter | groq | github | bedrock
GEMINI_API_KEY=
ANTHROPIC_API_KEY=
OPENROUTER_API_KEY=
GROQ_API_KEY=
GITHUB_TOKEN=
AI_MODEL= # optional — overrides the provider default (see setup section)
# Amazon Bedrock (only when AI_PROVIDER=bedrock)
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID= # optional if using IAM role or aws configure
AWS_SECRET_ACCESS_KEY=
AWS_SESSION_TOKEN= # optional, for temporary credentials
# Google Fit
GOOGLE_CREDENTIALS_FILE=fit_credentials.json # path to downloaded OAuth JSON
# Database
DB_PATH=hevy.db # path to local SQLite fileAll in-app preferences (units, auto-sync, check-in frequency, etc.) are stored in the user_preferences table in the database, not in .env.
python -m pytest tests/The test suite uses an in-memory SQLite database per test — no real hevy.db is touched. All AI provider calls and external HTTP requests are mocked.
See CONTRIBUTING.md for setup instructions, branch naming, commit format, CI checks, and the PR template.