Manage the ATHLETE PROFILE — the Fitness add-on's TRAINING-FOCUS singleton that the AI coaching skills (training plan, weekly review, pre-workout brief) read to personalise their output. It SETS / UPDATES / READS the one profile per board via the `fitness` MCP's `get_athlete_profile` / `set_athlete_profile` tools: the training-focus goal + goal date, weekly availability (days/week, max session minutes), the sports trained, and the equipment on hand. It maps free-text ("5 days a week, 90 min m...
Scanned 9/2/2026
Install to Claude Code
npx -y skills add philipyaz/cos --skill fitness-athlete-profile --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Fitness Athlete Profile?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/philipyaz-fitness-athlete-profile)More formats (shields.io, HTML) on the badges page.
---
name: fitness-athlete-profile
description: >
Manage the ATHLETE PROFILE — the Fitness add-on's TRAINING-FOCUS singleton that the AI
coaching skills (training plan, weekly review, pre-workout brief) read to personalise their
output. It SETS / UPDATES / READS the one profile per board via the `fitness` MCP's
`get_athlete_profile` / `set_athlete_profile` tools: the training-focus goal + goal date,
weekly availability (days/week, max session minutes), the sports trained, and the equipment on
hand. It maps free-text ("5 days a week, 90 min max") onto the English `VALID_ATHLETE_*`
vocabularies and validates before writing. Training STATUS,
WEIGHT, and your BODY goal (fat loss / muscle / recomp) are NOT here — those live in the body
add-on (the `body-profile` skill / the `body` MCP). Use when the user says "set my athlete
profile", "I'm training for a triathlon", "I can train 4 days a week", "I have a kettlebell /
pool access", "what's my training profile", or otherwise asks to define what they're TRAINING
for and with. Not medical advice.
---
# Fitness — athlete profile (the coach's training-focus source of truth)
This skill owns the **athlete profile**: the one record (a **singleton** — one per board) that
says *what sport/event the user is training for, with how much time, on which sports, with what
gear*. The three generative coaching skills — **training plan**, **weekly review**, **pre-workout
brief** (all in `fitness-coach`) — read this profile to personalise everything. It writes **only**
through the **`fitness`** MCP — never `bash`/`curl` (Cowork's sandbox blocks outbound HTTP). The
`/fitness` overview page is the read twin.
The profile is **create-or-REPLACE** (`set_athlete_profile` overwrites the whole record;
`createdAt` is sticky). So the cardinal rule is: **read first, then write the merged whole** —
never send a partial that drops fields the user isn't changing.
> **This is the TRAINING half only — the BODY half lives elsewhere (v14).** Your training
> **STATUS** (novice / intermediate / advanced), your **weight + body composition**, and your
> **body goal** (lose fat / build muscle / recomp / maintain — the free-text objective) are owned
> by the **body** add-on, NOT this profile. Set them via the **`body-profile`** skill (or the
> `body` MCP: `set_body_profile` for training status, `log_weight` for weigh-ins, `set_body_objective`
> for the goal) or the **/body** page. This skill's `goal` is a **training FOCUS** — the sport or
> event — not the body objective. The coach reads training status + weight + the body goal
> cross-add-on; you don't set them here.
> **Gate — the add-on must be ENABLED.** `set_athlete_profile` 404s ("Not found — the fitness
> add-on may be disabled.") when the Fitness add-on is disabled; the read (`get_athlete_profile`)
> always works. If the save 404s, the add-on is off — tell the user to enable it from the board's
> **/addons** catalog, then retry. You don't enable it yourself.
> **NOT MEDICAL ADVICE.** Anything weight- or health-related is **informational**, not medical
> advice. Don't prescribe a weight or rate; defer medical conditions, pregnancy/breastfeeding, an
> eating-disorder history, or a user under 18 to a clinician or registered dietitian. The body goal
> + weight live in the body add-on (`body-profile`); the diet math (calorie/macro targets) lives in
> the Nutrition add-on (`nutrition-chef`).
---
## STEP 0 — Read the mode switch (always first)
Read `config/auto-sync.json` → `{ "autoSync": <bool> }` (default **ON / auto** if missing). State
the mode once.
- **`autoSync: true` (auto mode).** Read the profile, gather/infer the fields, write it, report.
- **`autoSync: false` (approval mode).** A **wholesale replace** of an existing profile (changing
the goal + several fields at once) is the one write to **confirm in chat** first. A first-time
set, or a single-field tweak you've echoed back, is low-stakes — just do it.
`get_athlete_profile` is a read — no confirmation in any mode.
---
## THE PROCEDURE — read → gather → validate → write → confirm
### 1. READ the current profile (always first)
Call **`get_athlete_profile {}`**. It returns the singleton (or none if unset).
- **None set yet** → tell the user, then gather it fresh (step 2).
- **Already set** → **show what's set** (goal, days/week, max session, sports, equipment, goal date)
so the user sees the starting point and you can **merge** their change onto it. For a pure
*"what's my training profile?"* read, this step is the whole job — render it and stop.
### 2. GATHER the fields (from the user, or infer from their message)
- **`goal`** *(required)* — the **training FOCUS**: the sport/event they're training toward.
- **`goalDate`** (`YYYY-MM-DD`, optional) — the race / target date; `""` when none.
- **`daysPerWeek`** (1–7, optional) and **`maxSessionMinutes`** (optional) — the weekly availability
the plan must respect.
- **`sports[]`** (optional) — what they train / like to do.
- **`equipment[]`** (optional) — what they have access to.
- **`notes`** (freeform, optional) — anything else the coach should know (injuries to work around,
schedule constraints, preferences).
Gather what's **missing** conversationally — *"to build a good plan I need your focus, how many days
a week you can train, and your max session length"*. If the user mentions their **training status**,
**weight**, or a **body goal** ("I'm an intermediate lifter", "I'm 80 kg", "I want to lose fat"),
**route those to the body add-on** (`body-profile` skill) — they don't belong on this profile.
### 3. VALIDATE against the allowed vocabularies (bind to these verbatim)
The board rejects anything outside these English enums and **silently drops** unknown
`sports` / `equipment` strings — so map free-text onto the allowed values yourself, and **ask if
ambiguous** rather than guessing.
- **`goal`** ∈ **`VALID_ATHLETE_GOAL`** =
`["sprint_triathlon", "olympic_triathlon", "cycling", "swimming", "running", "general_fitness"]`.
This is the training FOCUS (sport/event). The body goal — lose fat / build muscle / recomp — is the
free-text **body objective**: set that via `body-profile` (`set_body_objective`), and pick the relevant
sport or `general_fitness` here. (There is no `weight_loss` value anymore; it was retired in v14.)
- **`sports[]`** ⊆ **`VALID_ATHLETE_SPORT`** =
`["cycling_outdoor", "cycling_indoor", "running", "walking", "swimming_pool", "swimming_open_water", "rowing", "skiing_alpine", "skiing_cross_country", "snowboard", "hiking", "climbing", "surfing", "kayaking", "strength_training", "hiit", "yoga", "pilates", "dance", "martial_arts", "boxing", "crossfit", "stretching", "tennis", "padel", "soccer", "basketball", "cycling_indoor_zwift"]`.
- **`equipment[]`** ⊆ **`VALID_ATHLETE_EQUIPMENT`** =
`["road_bike", "home_trainer", "pull_up_bar", "dumbbells", "kettlebell", "resistance_bands", "treadmill", "rowing_machine", "elliptical", "jump_rope", "bodyweight", "pool_access", "gym_access"]`.
**Map free-text onto the vocabularies**, e.g.: *"I have a bike and a pool"* → equipment `road_bike` +
`pool_access`, sports `cycling_outdoor` + `swimming_pool`; *"I swim in the lake"* →
`swimming_open_water`; *"I have a Peloton / Zwift"* → `cycling_indoor` (`cycling_indoor_zwift`) +
`home_trainer`. When genuinely ambiguous, **ask**.
### 4. WRITE — `set_athlete_profile` (create-or-REPLACE)
Call **`set_athlete_profile { goal, goalDate?, daysPerWeek?, maxSessionMinutes?, sports[], equipment[], notes? }`**.
> **It REPLACES the whole record** — send the **merged** profile: the field(s) the user is changing
> **plus** every field you read back in step 1 that they're keeping. Dropping a field you didn't
> restate **erases** it. (`createdAt` is sticky and preserved; you never send it.)
`goal` is **required** (the board 400s without a valid value). The board coerces the optionals:
`daysPerWeek` rounds into 1–7, `maxSessionMinutes` must be positive (else `null`); `goalDate` must be
`YYYY-MM-DD` or `""`; `notes` is capped at 2000 chars; out-of-vocab `sports`/`equipment` are filtered.
(There is **no** `level` / `currentWeightKg` / `targetWeightKg` on this tool anymore — they moved to
the body add-on; passing them is simply ignored.)
### 5. CONFIRM — tell the user it's saved
Report the saved profile (goal, availability, sports, equipment, dates) and that it's **on the
`/fitness` overview**. Note the **coaching skills now use it** (the training plan, the pre-workout
brief, the weekly review — `fitness-coach`), and offer the natural next step (*"want a training plan
for the week?"*). If they haven't set their training status / weight / body goal, nudge them to the
**`body-profile`** skill so the coach has the full picture.
---
> **Example.** *"I'm training for an Olympic triathlon in September, 5 days a week, 90 min max, I've
> got a bike, a pool, and a gym."* (auto mode): `get_athlete_profile` → none set. Map: goal
> `olympic_triathlon`, goalDate the Sept date, daysPerWeek 5, maxSessionMinutes 90, sports `running`
> + `cycling_outdoor` + `swimming_pool`, equipment `road_bike` + `pool_access` + `gym_access`. →
> `set_athlete_profile { goal: "olympic_triathlon", goalDate: "2026-09-12", daysPerWeek: 5,
> maxSessionMinutes: 90, sports: ["running", "cycling_outdoor", "swimming_pool"], equipment:
> ["road_bike", "pool_access", "gym_access"] }`. Confirm + offer a training plan. (If they add *"and
> I want to lose a bit of fat"*, route that to `body-profile` — it's a body goal, not this profile.)
> **Example (update one field, MERGE).** *"actually I can only do 4 days a week now."*:
> `get_athlete_profile` → read the existing record, change `daysPerWeek` to 4, **re-send every other
> field unchanged**, `set_athlete_profile` the whole merged object.
---
## Conventions (guardrails recap)
- **`fitness` MCP only, via `get_athlete_profile` / `set_athlete_profile`.** Never `bash`/`curl`.
- **Singleton, create-or-REPLACE.** One profile per board — **always `get_athlete_profile` first and
merge**, never send a partial that drops kept fields.
- **TRAINING focus only.** `goal` is the sport/event. Training **status**, **weight**, and the **body
goal** are the **body** add-on's (`body-profile` skill / `body` MCP) — route those there.
- **The add-on must be ENABLED for the write** (a disabled add-on 404s `set_athlete_profile`).
- **English vocabularies, validated.** `goal` ∈ `VALID_ATHLETE_GOAL`, `sports` ⊆ `VALID_ATHLETE_SPORT`,
`equipment` ⊆ `VALID_ATHLETE_EQUIPMENT` (verbatim above). Map free-text; **ask when ambiguous**.
- **Mode (STEP 0):** auto → just do it; approval → confirm a **wholesale replace** in chat first.
There is **no pending/propose queue** — confirmation is conversational.
- **NOT MEDICAL ADVICE.** Defer medical conditions, pregnancy/breastfeeding, eating-disorder history,
or an under-18 user to a clinician/dietitian. Body goal + weight → `body-profile`; diet math →
`nutrition-chef`.
- **Report** the saved profile + that it's on `/fitness`, then note the coaching skills use it and
offer a training plan.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!