openGym

DuarteSantos8AGPL-3.0活跃维护

开源健身与自重训练记录应用,支持 iPhone、Apple Watch 和 Android,可规划训练、记录动作并查看肌肉训练分布,还能导入 Strong/Hevy/FitNotes 数据,支持自托管或单机使用。

Open-source gym & body-weight tracker, now in the App Store (iPhone + Apple Watch) and as an Android APK. Plan routines, log workouts, see which muscles are trained, import from Strong/Hevy/FitNotes. Self-host it or use it on the phone alone.

v1.4.4发布于 2026-11-03 10:51 UTC20,779star +609 / 7 天2,792fork同步于 2026-11-10 17:24 UTC

怎么上手

由 README 提炼,执行前请确认
git clone https://github.com/DuarteSantos8/openGym
cd openGym
cp .env.example .env
docker compose pull
docker compose up -d
硬件要求按 README 说明

README 未说明;服务端只需能运行 Docker 与 Compose 的机器,镜像提供 amd64 和 arm64 版本

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

自托管的开源健身与体重追踪应用,数据存在自己手里,手机端也能离线单独用

开源健身与自重训练记录应用,支持 iPhone、Apple Watch 和 Android,可规划训练、记录动作并查看肌肉训练分布,还能导入 Strong/Hevy/FitNotes 数据,支持自托管或单机使用。

核心能力

  • 内置 5600+ 个带动作动画的练习,可按肌群和器械筛选
  • 支持线性、Greyskull、双重/三重渐进等进阶规则并解释目标数值
  • 用肌群热力图展示训练量、恢复状态和未训练部位
  • 支持从 Strong/Hevy/FitNotes 导入历史训练数据
  • 同一套代码用 Capacitor 打包 iPhone、Apple Watch 和 Android 应用

容易踩的坑

默认监听 8080 端口,手机端使用 passkey 登录需要配置域名和 HTTPS;Android APK 按动画分辨率分 Standard/Plus/HD 三种体积,最大约 760 MB;AI 教练需用 API_TARGET=coach 构建额外镜像,默认镜像不含

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v1.4.4
  1. v1.4.4v1.4.4: a fresh look, Modules and Google Play最新正式版2026-11-03 · 2026-11-03 10:51 UTC

    The biggest openGym yet: a fresh look, Modules to switch off what you don't use, every set against last time, and openGym is coming to Google Play (closed test, join below).

    Google Play testers wanted: join https://groups.google.com/g/opengym-testers/about, then opt in at https://play.google.com/apps/testing/ch.duartesantos.opengym. Google lets us go public after 12 testers for 14 days.

    Which APK? openGym-1.4.4.apk (Standard, 180 px animations), openGym-Plus-1.4.4.apk (240 px), openGym-HD-1.4.4.apk (360 px). Same app and key: each installs over another and keeps your data. Checksums in SHA256SUMS.

    Modules: as much app as you want. Settings → Modules switches whole parts of openGym on and off: Effort, Plates and warm-ups, Strength levels, Form videos, Watch, Gym check-in, Body, Health, Motivation, the AI Coach, Integrations and Seasonal themes. Pick Just training, Training and body or Everything, or flip them one by one. A module that's off is gone from Home, Stats, Settings and the search, and stops its notifications; health sync, the watch, webhooks and Coach reviews pause until it's back. Nothing is ever deleted, and everything stays on after the update. New profiles get the choice on their first screen. The idea came from seals187 and Shadowbyte on Discord.

    Integrations, all in one place. Settings → Integrations is a short list of what openGym can talk to, each with whether it's on and the one thing to do next: Apple Health or Health Connect (their switches moved here from Data & backup, which still has a way in), the Hevy and file imports, the CSV export, the Coach and the MCP server. Nothing new talks to anything until you switch it on, and a card only shows where it can do something. Garmin, COROS, Polar, Fitbit, Samsung Health, Oura, Withings and Renpho get an honest "works with": they reach openGym through Apple Health or Health Connect, no fake Connect button.

    Webhooks (self-hosted, INTEGRATIONS=webhook). Tell Home Assistant, n8n, ntfy or Node-RED when you finish a workout, set a record or weigh in, from whichever device you logged it on. Each message is signed, retried for about an hour if the other side is down, never sent twice, and a test event is one tap away. Home Assistant on your home network needs INTEGRATIONS_ALLOW_LAN=1 from your admin. Payloads and a signature checker are in docs/INTEGRATIONS.md.

    On its way to F-Droid. A new Android build without anything from Google, made to be built by F-Droid from the source: the gym card scanner uses the camera in the app instead of Google's, updates come from F-Droid, and Wear OS watches (they need Google Play services) are left out, which the app says in Settings → About. Everything else is the same app.

    openGym on Amazfit watches (Zepp OS 3 and later: Balance, GTR 4, GTS 4, Active, T-Rex, Cheetah, Bip 5 and friends). Same deal as Wear OS: start a routine on the wrist, turn the crown (or tap + and -) for weight and reps, Done, a rest ring that buzzes, heart rate on every set, a summary, and a shortcut card with your streak. It talks to openGym through your own server, so pair it in Settings → Zepp OS watch and type the code into the Zepp app. Works with the web app too.

    A fresh coat of paint. The whole app got a proper look-and-feel pass, the kind where nobody can point at what changed but everything sits better. Home's cards all introduce themselves the same way now (a small line, a title, one button), so the screen stops sounding like five apps talking at once. Stats is in four parts, Overview, Body, Lifts and Effort, with an index that sticks to the top and jumps you there; #/stats?section=lifts links straight to one. The Library keeps its filters in one row: Filters opens a sheet with the type and the equipment, and tapping the chosen body part again shows them all. The end of a workout is one tidy list (Add exercise, the session note) with Finish under it, the routine editor's Copy, Share and Print sit togethe

  2. v1.4.3v1.4.3: the Halloween update 🎃2026-10-26 · 2026-10-26 14:11 UTC
    查看更新说明

    The community release. Most of what's below was asked for on GitHub and Discord or sent in as a pull request, the Apple Watch learned a whole bag of tricks, and openGym starts again on iPhones that 1.4.2 left staring at the logo. Sorry about that one.

    openGym starts again on iOS 15.5 to 16.3 (P1). 1.4.2 and the web demo sat on the splash forever there, because one tiny link check used regex syntax Safari only learned in 16.4. Rewritten, the build now targets Safari 15 like the app does, and a test reads every built file for syntax older iPhones can't handle. Should a browser still choke, openGym says so on screen with the error and a Reload button instead of lifting the logo forever. Thanks h097327 for the excellent report. Once it starts, iOS 15.5 to 16.1 also gets its missing tints back (the Coach's header and error bubbles, the admin pills, the focus card's badges, the tinted buttons, the body map's shades): plain stand-ins close enough that you'd need a colour picker to tell, and a test makes sure every new tint brings one.

    Gym reminder (#614, phone app). Walk into your gym and openGym nudges you to hit Start. Add your gyms in Settings → Reminders → Gym reminder: "I'm at the gym right now" or a pin on an OpenStreetMap map, each with its own radius and text. Once a day at most, never after you trained, never mid-workout, optionally only between certain hours. Off by default, and your gyms stay on the phone (not on your server, not in backups). Android uses the system's own proximity alerts, so no Google services are needed. Android can be slow to notice you arrived (up to half an hour), so near a gym the phone can take a short GPS look and nudge you at the door; that needs openGym's battery use on Unrestricted (Settings shows it as "Quick arrival check"). And if you logged a workout on your laptop that your phone hasn't synced yet, the phone asks your server first (3 seconds at most) instead of nagging you anyway.

    See what a session hits before you start it. Every routine on the Plan page (the week, the rotation and the routine list) and today's session on Home carry a tiny body, front and back, with the muscles it works lit up. No more opening Leg Day to remember it is, in fact, legs. It keeps going once you start: the exercise chips at the top of a workout end in the same tiny body, faint where the session is headed and lit where you've already ticked sets, in every layout and without moving a single set row (#670). Tap it for the big map and done/planned sets per muscle. Settings → Workout → Fine-tuning turns it off.

    Export as a spreadsheet (#647). Settings → Data & backup → Export as spreadsheet (CSV): your workouts with one row per set (date, workout, exercise, set, weight, reps, RPE or RIR, warm-ups, drops, supersets, cardio distance and time) and, as a second file, body weight and measurements. Pick everything or a stretch of days. Opens in Excel or Sheets, makes your coach happy, and openGym reads it straight back in without losing a set. The importer also learned GymMane's CSV.

    Keep what you added (#592). Threw an extra exercise into a routine's workout? The finish summary lists it under "New in this workout" with one button to add it to the routine, sets, reps and weight as you did them. Ignore it and the routine stays exactly as it was.

    Halloween. Until the end of October a small spider drops in whenever you open openGym (tap it and it runs), bats cross the header now and then, cobwebs gather in a few corners and a shy pumpkin hides somewhere on Home. Find it for a little surprise, once a day. Stats gets a skeleton hanging off the activity card, spiders on threads, a moon with a tiny witch and two pumpkins peeking out. Rarely, a bigger witch. Workouts get a quiet version that never sits on a set, a button or a timer: a cobweb and a spider in the header's corner, two bats along the rest bar and pumpkins on the finish screen (Also during workouts turns that off). Gone on 1 November by

  3. v1.4.22026-10-23 · 2026-10-23 09:01 UTC
    查看更新说明

    openGym comes to the App Store, with an Apple Watch app in tow. Plus everything you asked for since v1.4.1, five reported security holes closed and a fresh look at the animations.

    openGym on the iPhone. The App Store app is the same openGym: use it on the phone alone, or connect it to your own server. Your data stays where it is (no account with us, nothing collected). Get it on the App Store: https://apps.apple.com/app/id6822275400

    • Apple Watch. Start a workout on the wrist, or on the phone and the watch app opens with it, then tick off sets with a big Done button and the Digital Crown for reps and weight. Rest is a full-screen countdown with +15 s and Skip, holds count down, sides say Left or Right, supersets go in turns. Heart rate per set, a summary at the end, a Smart Stack widget and complications for your watch face. It speaks the app's language, asks for a weigh-in at the start if you like, makes weights quick to change, and you pick what the set screen shows. No phone in reach? Your ticks wait on the watch and catch up later.
    • Widgets and a Live Activity. Today's workout on the Home Screen and the Lock Screen, your streak too. A running workout sits on the Lock Screen and in the Dynamic Island, with a Done button that logs the set and starts the rest without opening the app.
    • Apple Health. Finished workouts and weigh-ins go to Apple Health, the same switch Android has for Health Connect, offered once at the start. Delete a workout in openGym (on any of your devices) and it leaves Apple Health too.
    • Sharper animations, your choice. Settings → Workout → Animation quality: Still only, built in (180 px), or 240, 360, 480, 720 and 1080 px, downloaded from the App Store when you pick them. Auto takes 360 on a phone and 720 on an iPad, over Wi-Fi. Female and male figures download separately, so you only get the one you use.
    • No more boxes. The animations in the app showed faint rectangles around the moving parts. They are re-made from the original files, frame by frame, and look like the originals now. The APKs get the same fix (180, 240 or 360 px built in, see Android below).
    • Swipe from the left edge to go back, with the page you came from sliding in underneath.
    • Notifications are asked for at the start, not in the middle of your first rest.
    • The Vibrate switch works on the iPhone, and a server or Coach on your home network works over plain http, like on Android (#428).
    • A logo instead of a black screen while the app starts, loading its plates.

    Android. The app now targets Android 16 and needs Android 7.0 or newer (6.0 is out). The APK you know stays and updates itself, now in three sizes: Standard (openGym-1.4.2.apk, animations built in at 180 px, the small one), Plus (openGym-Plus-1.4.2.apk, 240 px) and HD (openGym-HD-1.4.2.apk, 360 px, sharp and hungry). Each one updates to its own kind, so nobody gets a surprise download twice the size. Phones on v1.4.1 update to Standard; want Plus or HD? Install it on top, your data stays (same goes for going back). A Google Play version is ready for the store too: it updates through Play and gets the sharper animations as Play downloads, like the iPhone, and an APK phone can move to it later without losing anything.

    Your account, your call.

    • Delete your account from Settings → Account. It offers your backup first, asks you to type your name, and then a passkey or password (on the phone: Face ID, Touch ID or the passcode). The server's last admin hears straight away why they can't, instead of after all that.
    • The Coach asks before anything leaves. The first time the Coach would send your training to an AI service, it says which one and what goes there. You can take it back in the Coach menu. A model on your home network doesn't ask; it's yours.
    • Sign in on a computer from the phone app (#551): Settings → Account → Add another device makes the same one-t
  4. v1.4.12026-10-10 · 2026-10-10 16:23 UTC
    查看更新说明

    Bug fixes for v1.4.0, mostly the things you told us about on Discord and GitHub.

    • Smooth animations in the app. They lagged and stuttered on real phones (the phone's video player stalled at every loop). The app now shows them as animated images, the way the old GIFs worked, with the original timing. The web and self-hosted servers keep their clips.
    • The update check finds new versions again. It asked the GitLab mirror, which never got v1.4.0. It asks GitHub now, and the 300 MB download goes straight to storage instead of into memory, checked against its checksum before the installer opens.
    • The rest bell rings over music. With the app open, the end tone now plays like the screen-off alarm does: your music turns down for a moment instead of drowning it.
    • The Coach has its own button on the Plan page, no more hunting in the share menu.
    • Search: the exercises you have done come right after your favourites, and "leg press" finds the plain 45° leg press first.
    • Add exercise gets the Type row the library has (#521).
    • Exercise progress gets 1M / 3M / 1Y / All, like the body weight chart (#511).
    • Imports: two workouts on the same day stay two (#505).
    • Coach: an OpenAI-compatible server without /v1 in its address works, e.g. Open WebUI (#508).

    Android: openGym-1.4.1.apk, check it with sha256sum -c openGym-1.4.1.apk.sha256.

  5. v1.4.02026-10-09 · 2026-10-09 13:54 UTC
    查看更新说明

    The biggest update openGym has had: a new exercise database with 5,632 exercises and new animations, everything that was planned for v1.3.11 and v1.3.12, and the features you asked for most. Forty-seven community pull requests from twenty contributors. Web bundle, APK and API image.

    Nothing you logged changes. Every exercise that ever shipped keeps its id, name and muscles, so workouts, routines, records and backups stay exactly as they are. A phone still on v1.3.x keeps working with a v1.4.0 server, and shows the new exercises it doesn't know yet without losing them.

    The new exercise database

    • 5,632 exercises instead of 1,324: bands and kettlebells, suspension trainers and landmines, machines of every kind, plus stretching, mobility, yoga and pilates. Each one with a short description, steps, body part, equipment and muscles, and its name in every app language (German names for the new exercises are machine-made and waiting for a review).
    • New animations, licensed from Gym visual: sharp 360 px loops inside the app, 180 px on the web and on your own server, and a still for every exercise.
    • Male or female drawings: about 940 exercises are drawn on both figures. Settings, Look, "Exercise drawings" picks which one you see. Only the picture changes, never your data.
    • A type filter in the library: strength, calisthenics, olympic, stretching, mobility, yoga and more.
    • Search rebuilt (#192): best matches first, typos forgiven ("sqat", "dumbel curl"), gym shorthand understood ("db", "rdl", "ohp"), plurals too ("pull ups"), and "Similar exercises" under the results, so a search almost never ends on nothing.
    • Swap suggests the same muscle first (#473), same equipment at the top.
    • The catalogue lives in the repository, one file per exercise, open to fixes and translations by pull request (catalogue/README.md). "Suggest a fix for this exercise" in the app opens an issue for that one exercise.

    Training

    • Sets to failure: mark any set as taken to failure from its set menu and it gets a little purple "F". It counts as RIR 0 in your effort stats and the fatigue map (unless you rated it yourself) and stays a normal work set for volume and records. "Last set to failure" in an exercise's settings plans the final set as an all-out one.
    • Triple progression (#179): reps climb to the top of the range, then a set is added, up to the most sets you allow; when every set sits at the top, the weight goes up and you start over.
    • Back-off sets (dennismstfc, #475): every set one step lighter than the one before.
    • Per dumbbell or both together (#474): say what a dumbbell weight means, and volume and records count it right. Your old entries stay as you typed them.
    • Your dumbbell rack (#376): list the dumbbells you own, and progression, deloads, warm-ups and the + and − buttons only land on those.
    • Treadmill incline: an incline in % next to speed on walking, running and stair machines.
    • A fairer fatigue map (sg41, #436): counted in hard sets with its own recovery time per muscle, so a split no longer looks fatigued forever.
    • Pyramid sets with a weight per set (akram1089, #446, #445), 1RM from seven formulas with your pick of one (giulioleuci, #195, #155), per-set progress lines (iamtechnoana, #450, #145).

    During a workout

    • Exercise chips (#323): a numbered dot per exercise at the top, filled as you go. Tap one to jump there.
    • Collapse completed exercises (helgehelge123, #241; Discord): in the list view a finished exercise folds into one line the moment you tick its last set, and a tap opens it again. Turn it on for good in Settings, Workout.
    • Focus view (giulioleuci, #222): one exercise at a time, nothing else on screen.
    • Pick your rest-end sound (#306): chime, classic, bell, beep-beep, whistle or soft, with a preview, on Android with the screen off too.
    • **Superset names and their own rest

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Website · Live demo · Roadmap · Changelog

    Why openGym

    Most workout apps keep your data on their servers, push you towards a subscription, or vanish when the company does. openGym runs on your own box, keeps your data in a folder you control, and is yours to fork. It still behaves like a modern app: installable on the home screen, passkey sign-in, works offline, syncs between your phone and your laptop.

    No account on someone else's server, no subscription, no ads, no telemetry. One docker compose up and it's running.

    The in-browser demo is the real app with example data, if you want to try it before installing anything.

    Features

    Planning

    • A routine per weekday over a library of over 5,600 exercises with animated demos, searchable and browsable by muscle on a body map. Filter by the equipment you own.
    • Four starter plans (Push/Pull/Legs, Upper/Lower, Full Body, 5×5) that load as ordinary, editable routines.
    • Every session on the Plan page and today's on Home carries a tiny body map with the muscles it works lit up, so you know Leg Day is legs before you open it.
    • Move a session to another day without touching the weekly plan. The week starts on Monday or Sunday, your choice.
    • Or skip the weekdays altogether: a rotation (A, B, C, A, ...) where the next session is simply the next one you haven't done, however the week went.
    • Supersets, warm-up sets, drop sets and rest-pause, timed exercises (planks, hangs, carries), cardio by time and speed, rest time per exercise, planned deloads.
    • Your own exercises, with your own photo, GIF or short video. Location data is stripped on the device before upload.

    Training

    • Guided sessions: today's workout starts itself, weights are pre-filled from last time, a rest timer runs between sets, PRs are detected as you go. On a rest day it tells you when the next session is.
    • A quiet workout screen: one menu per exercise, the set number as the set's own menu, card or list view. Switches in Settings bring the old button rows back if you liked them.
    • Optional effort column as RIR or RPE, colour-coded, with a plain-language line per level.
    • Plate math for barbell, EZ bar, trap bar and Smith machine, worked out from the plates you own. Train in more than one place? Each gym keeps its own plates, dumbbells, bars and machine stacks, and the phone can switch to the gym you just walked into.
    • Bodyweight exercises know they carry no load: log reps, add a dip belt if you use one.
    • Per-side reps for lunges and single-arm work, the screen stays awake while you train, and a rest-timer alert can flash the screen for loud gyms.
    • Swipe a set left to delete it (with Undo) or right to copy it. Pyramid sets with their own reps and rest per set, and a scroll wheel for any rest time up to 15 minutes, or no timer at all.
    • Machine taken? A planned backup exercise swaps in with one tap and keeps the slot's sets and reps. Machines can carry their real weight stack, odd steps included, and progression sticks to it.
    • The session's volume runs live at the end of the progress bar.

    Progress

    • Progression rules per routine or per exercise: linear, Greyskull LP, double progression through a visible rep range, triple progression (reps, then sets, then load), or adding time. Each target explains why it is that number; missed reps never add load, stalls trigger a deload.
    • Estimated 1RM per exercise with its own curve, Structural Balance ratios (Poliquin, Thibaudeau, ATG), a year-long activity heatmap.
    • A muscle map in three modes: where your volume went, what is still recovering, and what has gone untrained.
    • Body-weight chart against a goal line, with your weekly rate and an optional lose, gain or hold range, and progress photos on a timeline with a before/after slider.
    • Lifts as a percentage of body weight, and a running total of everything you've ever lifted.
    • Edit any saved workout after the fact, log one you did on paper, or move it to the right date. Records are re-read from the corrected history.

    Accounts and data

    • Passkeys (Face ID, Touch ID, fingerprint) with per-profile data synced across devices. Password sign-in can be switched on per instance; new devices pair with a one-time code or QR.
    • Two devices editing at once merge field by field instead of overwriting each other (see sync).
    • Import from FitNotes, Strong, Hevy (CSV or API key) and Apple Health weight exports. Export everything as one JSON file, or your workouts and body data as a spreadsheet (CSV).
    • Share a plan as a small file or print it as a PDF.
    • Optional admin dashboard with invite-only signup and an activity log.
    • 20 languages, including right-to-left Arabic and Traditional Chinese. Exercise names and instructions are translated for most of them.

    On the phone and the wrist

    • Apps for iPhone, iPad and Android that work on their own (no server, no account) or connected to yours. Rest timer in the notification shade, reminders, and Health Connect or Apple Health in both directions: workouts go out, weigh-ins and heart rate per set come back in.
    • A gym reminder, off by default: walk into one of your gyms and the phone nudges you to hit Start. Once a day at most, never after you trained, and your gyms stay on the phone.
    • An Apple Watch app: tick off sets with the Digital Crown, RPE or RIR right on the wrist, a full-screen rest countdown, heart rate per set, a Lock button against stray crown presses, and complications. No watch? AirPods Pro 3 do the heart rate on iOS 26.
    • Widgets and a Live Activity on the iPhone: log a set, skip the rest or jump to the next exercise from the Lock Screen without opening the app.

    Only what you use

    • Modules: switch whole parts of the app on and off in Settings → Modules, from "Just training" to "Everything". Body, Health, Motivation, the Coach, seasonal themes and more each disappear completely while they're off, and nothing is deleted.

    Optional extras, off by default

    • An AI coach that drafts a week of routines and later suggests changes based on what you logged, and answers questions about your training. You approve every change. It runs on your server, or on the phone alone, with your own provider key (Anthropic, OpenAI, Gemini or any OpenAI-compatible endpoint, Ollama included).
    • An MCP server so an assistant like Claude Desktop can answer questions about your training history, and log a workout you describe to it. Local; not part of the Docker build.
    • Integrations in one place: Apple Health, Health Connect (Garmin, Fitbit, Withings and friends come in through them), imports, and signed webhooks to Home Assistant, n8n or ntfy when you finish a workout, set a record or weigh in.

    The full list of what changed release by release is in the changelog.

    Quick start

    You need Docker with Compose.

    git clone https://github.com/DuarteSantos8/openGym
    cd openGym
    cp .env.example .env
    docker compose pull      # prebuilt images, amd64 + arm64 (skip this to build from source)
    docker compose up -d
    

    Open http://localhost:8080, tap Create profile, and you're in. The exercise animations are part of the image, so there's nothing else to download.

    To reach it from your phone with passkeys you need HTTPS on a domain; that's a two-line change in .env. The self-hosting guide walks through Cloudflare Tunnel, Caddy, Traefik and nginx, and there are separate guides for HTTPS on a LAN, a Mac with Tailscale and Kubernetes.

    [!NOTE] Images are published from the same tag to ghcr.io/duartesantos8/opengym-{api,web} (what docker-compose.yml pulls) and registry.gitlab.com/duartesantos8/opengym/{api,web}. Swap the image: lines if you prefer GitLab's registry, or run docker compose up -d --build to build locally. Either way you don't need Node on the host.

    VariableWhat it doesDefault
    RP_IDHostname passkeys are bound tolocalhost
    ORIGINFull URL the app is served fromhttp://localhost:8080
    WEB_PORTHost port for the web UI8080
    NGINX_PORTPort the web container listens on inside the container80
    BACKENDName of the API service that /api is proxied toapi
    PORTPort the API listens on; the web container proxies to the same value3000
    RP_NAMEName shown in the passkey promptopenGym
    SESSION_DAYSHow long a sign-in lasts, in days90
    ADMIN_UIDSUser ids that get the admin dashboard, comma-separated(none)
    FIRST_USER_ADMIN1: the first profile created on an empty instance becomes its admin(off)
    INVITE_ONLYRequire an invite code to create a profile(off)
    ALLOW_GUESTOffer "Continue without account"; 0 requires a profile(on)
    PASSWORD_LOGINOffer name-and-password sign-in next to passkeys(off)
    TRUST_PROXYLet the sign-in throttle read the client address from proxy headers1 in docker-compose.yml
    AUDIT_LOGRecord sign-ins and admin actions; 0 records nothing(on)
    AUDIT_MAXEvents kept in the activity log; 0 for no limit5000
    AUDIT_DAYSDays kept in the activity log; 0 keeps until AUDIT_MAX90
    AUDIT_IPRecord the caller's address: off, net (network only) or fulloff
    ALLOWED_PRIVATE_IPSPrivate addresses push endpoints may resolve to (FakeDNS, split-horizon DNS): comma-separated IPs, a-b ranges or CIDR blocks(none)
    INTEGRATIONSServer integrations to offer, comma-separated: webhook (integrations)(none)
    INTEGRATIONS_ALLOW_LAN1: webhooks may reach your home network (Home Assistant), http included; never loopback(off)
    VAPID_SUBJECTContact URL sent with push notificationsyour ORIGIN
    API_TARGETAPI image to build: default, or coach with the Claude Agent SDK and Codex CLIdefault
    COACH_DISABLED1 forces the AI coach off instance-wide(unset)

    Push-notification keys are generated on first run into ./data/vapid.json. DATA_DIR is pinned to /data inside the container and mapped to ./data on the host; change the volume, not the variable. The self-hosting guide covers every option in detail.

    Phone app

    The same codebase builds the phone apps with Capacitor. Use them on their own (everything stays on the phone, no account) or connect them to your server and sync.

    Get it
    iPhone and iPad, with the Apple Watch appThe App Store, in every App Store country
    AndroidThe signed APK from the latest release or opengym.ch, in three sizes: Standard (openGym-X.Y.Z.apk, animations at 180 px, about 315 MB), Plus (openGym-Plus-X.Y.Z.apk, 240 px, about 424 MB) and HD (openGym-HD-X.Y.Z.apk, 360 px, about 760 MB). It updates itself and stays the kind you picked
    Google PlayIn closed testing: Google wants 12 testers for 14 days before it lets everyone in. Join the tester group, then opt in. It installs right over the APK and keeps your data
    Wear OS watch (beta)Rides along with the Google Play test: once Google's watch review is done, "openGym Beta" shows up in the Play Store on your Galaxy Watch, Pixel Watch and friends. Details: docs/WEAR_OS.md

    Every APK sits next to its .sha256. The APK and the Play app share one signing key, so you can switch between them (or between Standard, Plus and HD) without losing data. Details, building it yourself and connecting to your server: docs/MOBILE.md.

    How it works

    • frontend/ is React 19 and Vite (React Router, Zustand), built to static files inside Docker.
    • api/ is plain node:http with three dependencies: @simplewebauthn/server for passkeys, web-push for notifications and undici for the AI coach's provider calls. Everything is stored as JSON under ./data.
    • web/ builds the frontend and serves it with nginx, proxying /api so the whole app sits on one origin, which passkeys require.

    The architecture overview has the longer version, with diagrams of the frontend, sync, the exercise media and the watch.

    The training logic (progression rules, 1RM, how a logged session is read back) lives in pure functions under frontend/src/lib/ with tests beside them. The HTTP API is documented as an OpenAPI spec in api/openapi.yaml, browsable at opengym.ch/api.html.

    How sync works

    Each profile's data is one document with a server revision. A device sends the revision it last saw along with its changes; if another device wrote in between, the server refuses and returns the current document so the device can merge and retry. Every change carries its own stamp, down to a single setting or routine field, so the merge keeps the newest edit of each one and a deletion stays deleted.

    Nothing that hasn't reached the server is discarded on disconnect or sign-out, and the app shows a banner whenever it's working offline.

    Your data

    Everything lives in ./data on your host:

    FileContents
    db.jsonProfiles and public passkey data
    db.json.bakA copy of the last good db.json, used if the main file can't be read
    state-<user>.jsonEach user's plan, workouts, body weight and settings
    audit.logAdmin activity log (no IP addresses unless you turn that on)
    secretSession-cookie signing key

    Back up ./data and you've backed up everything. Passkey private keys never reach the server; they stay in your phone's secure hardware or your password manager.

    Documentation

    The documentation index sorts every guide by who it's for. The most used ones:

    I want toRead
    Get a quick answerFAQ
    Set up my own instanceSelf-hosting
    Use the Android or iPhone appPhone app
    Bring my history from another appImporting data
    Turn on the AI coachAI coach
    Contribute codeContributing
    Report a security problemSecurity

    Roadmap

    A release roughly every one to two weeks, each one whatever has passed testing by then. The full plan is in ROADMAP.md, and the issues sit in the GitHub milestones.

    ReleaseWhenTheme
    v1.4.0released Oct 2026A new exercise database with 5,632 exercises, plus two rounds of community work
    v1.4.1released Oct 2026Bug fixes for v1.4.0
    v1.4.2released Oct 2026The App Store, the Apple Watch, widgets, three APK sizes
    v1.4.3released Oct 2026The Halloween and community release: gym reminder, health data read back, watch upgrades, CSV export
    v1.4.4released Nov 2026Programmes, a fresh look, Modules, a tour with tutorials, AirPods heart rate, kg or lb per exercise, the Google Play closed test and a Wear OS beta
    v1.4.5Nov 2026Google Play for everyone, F-Droid, Settings → Integrations (Strava, webhooks, calendar, Nextcloud), timed holds that start themselves
    v1.4.6Dec 2026Wear OS out of beta, deeper Health Connect, body composition
    v1.4.7Dec 2026The progression engine by @giulioleuci, circuits, AMRAP and EMOM
    laterdates are guessesSearch and catalogue, accounts, a trainer role, skins, Garmin, database storage

    Community

    • Discord for release announcements, self-hosting help and quick back-and-forth. Usually the fastest way to get an answer.
    • Discussions for questions and ideas you want the next person to find by searching.
    • Issues for reproducible bugs and agreed-on work. Login trouble is almost always an RP_ID/ORIGIN mismatch; the self-hosting guide covers it.
    • Pull requests are welcome; start with CONTRIBUTING.md.

    Where the code lives

    GitHub is the home of the project. gitlab.com/DuarteSantos8/opengym is a mirror, updated by a GitHub Actions workflow on every push to main and every release tag. It exists because its CI builds the multi-arch images and the SBOMs for its registry (the APKs are built and signed on the release machine and attached to the GitHub release). Nothing is merged there by hand. In the changelog, !NN refers to a GitLab merge request from the weeks in August and September 2026 when the project lived there.

    How openGym is built

    People have asked about this, so plainly: openGym is developed with Claude Code, Anthropic's coding agent. A large share of the code, tests and documentation is drafted in Claude Code sessions, and the repository carries a CLAUDE.md with the project context those sessions start from.

    What that does and doesn't mean:

    • A person decides and ships. What goes in, what gets reviewed and merged, and every release are the maintainer's call. Changes are tested on a staging instance and on real phones before they are tagged.
    • Tests hold the logic in place. The training logic is covered by unit tests, and pull requests run the frontend, API and MCP suites in CI. That is the guard against plausible-looking code that is wrong, whoever or whatever wrote it.
    • The app itself doesn't need an LLM. Nothing in a default install calls an AI service. The AI coach and the MCP server are opt-in, and the coach only talks to the provider you configure, with your own key.

    Community pull requests are written by their authors, with whatever tools they like, and reviewed the same way.

    Support

    openGym is free and stays free: AGPL, no paid tier, nothing held back for sponsors. If it replaced a paid tracker for you and you'd like to chip in, there's Buy Me a Coffee, Ko-fi and GitHub Sponsors (the app has the same three under Settings → About & updates, and on the iPhone a shortcut to leaving an App Store review). A star, a bug report or a pull request helps just as much.

    GitHub Sponsors

    Star History Chart

    License

    openGym's own code is licensed under the GNU AGPL v3.0. You can self-host, use, modify and share it; if you run a modified version as a network service, you have to offer that version's source under the same license.

    [!IMPORTANT] The exercise media is not covered by that license. The stills and animations are © Aliaksandr Makatserchyk, Gym visual, licensed for use in openGym only: 180 px in this repository and on self-hosted servers, larger only inside the app packages. A non-commercial fork may keep them unmodified with the notice; anything else needs your own licence from gymvisual.com. The exercise text in catalogue/ is openGym's and open to contributions.

    Contributing: pull requests are signed off once with the Contributor License Agreement: you keep the copyright in your work, openGym may use and relicense it (so the app can stay in the App Store and Google Play long term), and every version released under the AGPL stays AGPL.

    Full third-party notices, including the body-diagram geometry, are in NOTICE.md.