Gym
<!-- GENERATED by ops/tools/skill-sync — do not edit by hand. Run pnpm skills:sync. -->
<!-- GENERATED by ops/tools/skill-sync — do not edit by hand. Run pnpm skills:sync. -->
Gym — what you can do
/admin/d/gym · pillar apps
Run a self-hosted gym — 1,324 exercises, weekly plans, guided sessions, 4 progression systems, AI coach.
Fetch this, never remember it
These change per install and per release. Call for them - a list written here would be a future lie.
| What | Call | Why |
|---|---|---|
| this gym's exercise library, including its own custom exercises | GET /api/gym/exercises | the 1,324 shipped rows are the same everywhere, but a gym's custom exercises are not — and the facets tell you which filter combinations would return anything at all |
| whether a session is already running | GET /api/gym/overview | running is what makes Today resume rather than restart; starting a second session without force silently returns the first |
| what to lift next for one exercise, and why | GET /api/gym/next/:exerciseId | the prescription is DERIVED from the log every time it is asked for — never stored — so it is always current and there is no counter to go stale |
| whether this install can show exercise animations at all | GET /api/gym/settings | mediaConfigured is false by default and that is not a fault: the media belongs to Gym visual and Leumas ships none of it |
How to actually do things here
Written by hand, because the order and the traps are the part no file can derive.
Give somebody a program to start on
GET /api/gym/startersfor the three shipped programs and what each would cost this catalog.POST /api/gym/routineswithstarterIdto build it, orPOST /api/gym/ai/programto have one written.- Check
unfilled(starter) orwarnings(AI) before telling anyone it is ready.
Trap: A non-empty unfilled means the catalog could not supply those slots — the routine EXISTS and is missing exercises. Say so. The AI lane refuses the whole document rather than dropping an exercise it invented, so a 422 there means nothing was saved, not that something partial was.
Run a workout
POST /api/gym/sessionswith{ routineId, day }— it returns the sets already prescribed and stamped.PATCH /api/gym/sessions/:id/sets/:setIdwith{ reps, weight, completed: true }per set as it happens.POST /api/gym/sessions/:id/finishto close it and get the records it set.
Trap: An unticked set is a MISS, not an absence — that is what stops a session that fell apart from advancing the load next time. Finishing DELETES the unticked rows, so tick as you go rather than at the end. Sending completed: false un-ticks and changes the judgement.
Work out why a weight went down
GET /api/gym/next/:exerciseIdand readprescription.reason.text— it names the rule and the count.GET /api/gym/stats/exercise/:exerciseIdfor the curve and the records behind it.
Trap: A deload is the policy working, not a bug. Greyskull resets after ONE failure by design where linear gives three attempts. A field the policy has no opinion on comes back undefined, not 0 — reading it as 0 prescribes an empty bar.
Bring history over from another tracker
POST /api/gym/importwith the file text and NOcommit— this previews and returnsunresolved.- Map each unresolved name to an exerciseId and re-post with
mappingandcommit: true.
Trap: A commit with unresolved names is REFUSED (409) unless you pass ignoreUnresolved, which DROPS those rows. Inventing an exercise is the one irreversible mistake an importer can make, so it will not guess. Weights convert per row, not per file.
Show exercise animations
- Obtain a licence from Gym visual, or host a copy you are entitled to.
PATCH /api/gym/settingswithmediaBaseset to that absolute https origin.
Trap: Leumas ships NO exercise media — it belongs to Gym visual and is excluded from the dataset's MIT grant. There is deliberately no default base, a relative path is refused, and the attribution must render wherever the media does. An empty mediaBase is the correct state, not a broken install.
Tabs
Every one is a real URL. A tab with its own section below carries a real job.
| Tab | Path | Group | What it is for |
|---|---|---|---|
desk | /admin/gym | - | - |
today | /admin/gym/today | - | - |
plan | /admin/gym/plan | - | - |
classes | /admin/gym/classes | - | - |
library | /admin/gym/library | - | - |
history | /admin/gym/history | - | - |
stats | /admin/gym/stats | - | - |
members | /admin/gym/members | - | - |
settings | /admin/gym/settings | - | - |
API
Mounted prefixes that serve this domain: /api/gym
The full route table is leumas-capabilities/reference/api-routes.md.