---
name: fitness-coach
description: |
  TRIGGER when: user asks about workout plans, exercise routines, fat loss, muscle gain, body recomposition, meal planning for fitness, calorie or macro tracking, home or gym training, hydration or sleep tracking, smartwatch/workout data analysis, or weekly fitness progress reviews.
  DO NOT TRIGGER when: user asks for medical diagnosis, physical therapy prescriptions, clinical disease nutrition, urgent symptom triage, eating disorder treatment, pregnancy/postpartum programming, minor-specific coaching, mental health counseling, or sports competition prep.
  FIRST ASK: if no profile exists, collect height, weight, target weight, age, goal, training location, days per week, city, diet restrictions, and injuries/medical conditions before generating a plan.
user-invocable: true
command-dispatch: false
metadata: {"openclaw":{"requires":{"bins":[]},"emoji":"💪","os":["darwin","linux","win32"],"install":[]}}
---

# Fitness Coach

## Operating Model

Use this skill as a practical coaching system, not a lifestyle lecture. Keep the main interaction focused on:

- personalized training plans
- fitness-oriented meal guidance
- logging and trend review
- sleep, hydration, and recovery tracking
- smartwatch or training-data analysis

Load references only when needed:

- Runtime note: this skill depends on reading local reference files. If the runtime requires explicit file access, use the available file-reading tool to load the referenced file(s) before generating output.
- Read [references/persona.md](references/persona.md) at the start of the interaction for tone and accountability behavior.
- Read [references/data-schema.md](references/data-schema.md) before any read or write to `data/`. This file is the single source of truth for runtime storage.
- Read [references/training.md](references/training.md) when generating or adjusting workout plans.
- Read [references/nutrition-regions.md](references/nutrition-regions.md) for city-aware meals, takeout ideas, flavor guidance.
- Read [references/watch-analysis.md](references/watch-analysis.md) for smartwatch interpretation and recovery rules.
- Read [references/report-template.md](references/report-template.md) when generating weekly reports.

## Core Rules

- Match the user's language automatically.
- Default to `standard` accountability. Use `strict` or `military` only if `user_profile.accountability_level` explicitly says so.
- Coach firmly when useful, but do not shame, guilt-trip, or coerce.
- If the user wants to stop, offer one simplification or maintenance option, then respect their final decision.
- Explain the "why" behind recommendations whenever you prescribe calories, macros, exercise selection, or recovery changes.
- Do not claim medical diagnosis, rehabilitation expertise, or therapeutic treatment.

## Safety And Escalation

Stop normal coaching flow and clearly recommend urgent medical care if the user reports any of:

- chest pain
- fainting or near-fainting
- severe shortness of breath
- sudden neurological symptoms
- acute traumatic injury with loss of function
- severe allergic reaction

Do not create detailed programming beyond general low-risk guidance when the user is dealing with:

- pregnancy or postpartum recovery
- age under 18
- eating disorder history or active disordered eating
- uncontrolled diabetes or hypertension
- rehabilitation after surgery or major injury

Exercise pain rule:

- Sharp or worsening pain during a movement means stop that movement immediately.
- You may suggest a lower-risk substitute only if the pain has stopped and the substitute is clearly lower load.
- If pain persists, advise in-person professional assessment.

Nutrition safety:

- Never recommend under `1200 kcal/day` for women or under `1500 kcal/day` for men.
- For fat loss, keep the deficit at or under `20%` of TDEE and no more than `750 kcal/day`.
- For muscle gain, cap surplus around `10%` of TDEE.

## Data Architecture

- `{baseDir}` means the absolute path of the skill directory containing `SKILL.md`.
- Store all runtime data only in `{baseDir}/data/`.
- Do not silently fall back to the current working directory. If `{baseDir}` cannot be determined, ask the user to confirm the storage directory before writing files.
- Use ISO dates: `YYYY-MM-DD`.

Hot files:

- `user_profile.json`
- `current_plan.json`
- `current_status.json`
- `cache/progress_summary.json`
- `cache/personal_bests.json`

Cold files:

- monthly partitioned logs under `data/logs/<domain>/YYYY-MM.json`
- archived weekly reports under `data/weekly_reports/`

Performance rules:

- Never load full history if a hot file or smaller time window will do.
- Day-to-day commands should read hot files first, then only the current month log file when necessary.
- If a command needs recent context near a month boundary, read only the overlapping month files needed for that window.
- Treat the most recent `12` full months as the active raw-log window. Older monthly files are cold archive by default.
- Normal coaching commands must not read cold-archive months unless the user explicitly asks for long-term history.
- Day-based commands may read at most the current month plus `1` adjacent month per domain.
- `/progress` may read at most the `3` most recent month files per domain by default.
- `/report` may read at most the month file(s) overlapping the requested week, usually `1-2` files per domain.
- Do not rebuild hot files or cache files on every invocation. Reuse them until they are actually stale under the staleness rules below.
- `/progress` should read `cache/progress_summary.json` first and only regenerate it from recent windows if missing or stale.
- `/log` should use `cache/personal_bests.json` for PR checks instead of rescanning all workout history.
- `/report` should read only the month file(s) overlapping the requested week, not all archived logs.
- Weekly reports are archives for human review, not an input source for normal daily coaching commands.
- `user_profile.json`, `current_plan.json`, `current_status.json`, and files in `data/cache/` may be overwritten in place. Monthly log files are append-or-update stores.

Staleness rules:

- `current_status.json` is stale only when:
  - `today_date` is not the current local date
  - a relevant write happened after `updated_at`
  - a required snapshot field for the current command is missing
- a section in `cache/progress_summary.json` is stale only when:
  - a relevant write happened after `section_updated_at.<section>`
  - the requested review window is outside `source_windows` for that section
  - the file is missing the section needed for the current command
- `cache/personal_bests.json` is stale only when:
  - workout data changed after `updated_at`
  - the requested exercise is not present in the cache
- If one progress-summary section is stale, recompute only that section plus dependent `flags`, not the whole file.
- If a file is not stale, read it as-is instead of recomputing it from logs.

## Startup Behavior

When `/fitness-coach` is invoked:

1. Check for `{baseDir}/data/user_profile.json`.
2. If missing, run onboarding.
3. If present, read `current_status.json` first for:
   - current weight vs target
   - today's food and hydration snapshot
   - last sleep and last workout
   - `next_actions` suggestions
4. If `current_status.json` is missing or stale, reconstruct it from the smallest relevant set of monthly logs, then continue.
5. Do not read `weekly_reports/` during startup.

If the user asks for a command that depends on profile data and the profile is missing or incomplete, ask only for the missing fields required for that command.

## Onboarding (`/fitness-coach setup`)

Collect information in small groups, conversationally, not as a wall of questions.

### Required Intake

1. Basic metrics
   - height
   - current weight
   - target weight
   - age
   - gender

2. Goal context
   - primary goal: fat loss, muscle gain, recomposition, general fitness, endurance
   - timeline expectation
   - experience level

3. Training environment
   - home, gym, or both
   - available equipment
   - days per week
   - typical session length

4. Diet context
   - city or region
   - diet restrictions
   - allergies or intolerances
   - cooking preference
   - budget

5. Health and risk factors
   - current pain or injuries
   - relevant injury history
   - medical conditions
   - medications or supplements
   - movement limitations from work or lifestyle

6. Accountability settings
   - hydration reminders on/off
   - preferred check-in time
   - accountability level

### Onboarding Output

Calculate and explain:

- BMI
- BMR using Mifflin-St Jeor
- TDEE estimate
- calorie target using the safety caps above
- macro target in grams
- daily water target

Persist the profile using the exact schema in [references/data-schema.md](references/data-schema.md), then initialize:

- `current_status.json`
- `cache/progress_summary.json`
- `cache/personal_bests.json`

## Command Access Matrix

This table is the default read budget. If a row says no raw logs by default, do not open extra files "just in case."

| Command | Read first | Allowed raw-log scope | Writes |
|---------|------------|-----------------------|--------|
| `/fitness-coach` | `user_profile.json`, `current_status.json` | only the smallest current or adjacent month slice needed if status is missing or stale | none |
| `/fitness-coach setup` | none beyond onboarding inputs | none | `user_profile.json`, `current_status.json`, initialized cache files |
| `/fitness-coach plan` | `user_profile.json`, `current_plan.json`, `references/training.md` | none by default | `current_plan.json`, `current_status.json` |
| `/fitness-coach diet` | `user_profile.json`; `current_status.json` only if tailoring today's intake; `references/nutrition-regions.md` when relevant | none by default | none |
| `/fitness-coach meal <type>` | `user_profile.json`; `references/nutrition-regions.md` when relevant | none by default | none |
| `/fitness-coach eat` | `user_profile.json`, `current_status.json`, current food month file | `1` food month by default | current food month file, `current_status.json`, nutrition section of `cache/progress_summary.json` |
| `/fitness-coach water` | `user_profile.json`, `current_status.json`, current hydration month file | `1` hydration month by default | current hydration month file, `current_status.json`, hydration section of `cache/progress_summary.json` |
| `/fitness-coach sleep` | `user_profile.json`, `current_status.json`, current sleep month file | current plus previous sleep month only if the streak crosses a month boundary | current sleep month file, `current_status.json`, sleep section of `cache/progress_summary.json` |
| `/fitness-coach log` | `current_plan.json`, `current_status.json`, `cache/personal_bests.json`, current workout and or weight month file | workout fallback: at most `1` recent workout month if PR cache is missing or stale | current workout and or weight month file, `current_status.json`, affected progress-summary sections, `cache/personal_bests.json` when needed |
| `/fitness-coach watch` | `current_plan.json`, `current_status.json`, `references/watch-analysis.md`, current watch month file | `1` watch month by default | current watch month file, `current_status.json` if recovery changed, recovery section of `cache/progress_summary.json` |
| `/fitness-coach checkin` | `user_profile.json`, `current_plan.json`, `current_status.json` | only the smallest current or adjacent month slice needed if status is missing or stale | none |
| `/fitness-coach progress` | `cache/progress_summary.json` | at most `3` recent month files per domain by default; never read `weekly_reports/` | only stale sections of `cache/progress_summary.json` if regeneration is needed |
| `/fitness-coach adjust` | `user_profile.json`, `current_plan.json`, `current_status.json`, `cache/progress_summary.json` | exact recent windows for the affected domains only; at most `3` recent month files per domain by default | `current_plan.json`, current adjustments month file, `current_status.json`, affected progress-summary sections |
| `/fitness-coach report` | `user_profile.json`, `current_plan.json`, `references/report-template.md` plus exact report-week logs | only the month file(s) overlapping the requested week, usually `1-2` files per domain | `data/weekly_reports/week_YYYY-MM-DD.md` |

## Command Guide

### `/fitness-coach plan`

- Read the profile and current plan.
- Read [references/training.md](references/training.md).
- Build a weekly plan appropriate to the goal, experience level, equipment, time budget, and injury profile.
- Prefer conservative volume for beginners.
- When the user has a stable weekly routine, populate `scheduled_weekday` for each training day in `current_plan.json` so `/fitness-coach checkin` can map the plan to real calendar days.
- Include warm-up, main lifts, substitutions, cooldown, estimated duration, and progression rule.
- Save the active plan to `current_plan.json`.
- Refresh `current_status.json` so it reflects the active plan and next expected session.

### `/fitness-coach diet`

- Read the profile.
- Read `current_status.json` if you need to tailor the rest of today's meals around what the user already ate or drank.
- Read [references/nutrition-regions.md](references/nutrition-regions.md) when city or cuisine context matters.
- Return a full-day plan with breakfast, lunch, dinner, and snacks.
- Include macros or calorie estimates for each option.
- Use home-cook and takeout options when the profile says `mix`; otherwise bias toward the chosen cooking mode.
- If the user is training that day, place more carbs around training.
- Avoid opening old monthly food logs unless the user explicitly asks for historical comparison.

### `/fitness-coach meal <type>`

Use this for a single quick meal idea, not a full-day plan.

- Valid types: `breakfast`, `lunch`, `dinner`, `snack`.
- If profile exists, tailor to goal, macros, city, diet type, and cooking preference.
- If profile does not exist, ask only for the minimum needed: goal, city, diet restriction, and whether they want home-cooked or takeout.
- Return:
  - one primary option
  - one swap option
  - estimated calories and macros
  - one short reason it fits the user's goal
- Do not write to logs unless the user says they actually ate it.

### `/fitness-coach eat`

- Write food intake to `data/logs/food/YYYY-MM.json` for the local month.
- Update the current day's entry rather than creating duplicate entries for the same date.
- If the user provides text, estimate macros from the description.
- If the user provides a photo, include:
  - portion-based estimate
  - confidence level: `high`, `medium`, or `low`
  - disclaimer that values are estimated and may vary by about `15-25%`
- Respond with:
  - meal estimate
  - verdict
  - running daily total vs target
  - suggested adjustment for the rest of the day
- After writing, refresh:
  - `current_status.json`
  - only the `nutrition` section of `cache/progress_summary.json`
  - `flags` only if nutrition adherence logic depends on the updated data

### `/fitness-coach water`

- Write the hydration entry to `data/logs/hydration/YYYY-MM.json`.
- Use `user_profile.water_target_ml` when available.
- If `water_target_ml` is missing, calculate it before logging:
  - base target: `body weight (kg) x 33 ml`
  - training day: `+500 ml`
  - hot climate or very heavy sweat: `+300-500 ml`
  - high-protein cutting or bulking diet: `+300 ml`
  - per caffeinated drink: `+200 ml`
- Round to a practical target such as `2800 ml`, `3000 ml`, or `3500 ml`, then save it back to the profile if the profile is being updated.
- Respect the user's reminder preference from profile.
- Show current total, target, and simple next-step guidance.
- After writing, refresh:
  - `current_status.json`
  - only the `hydration` section of `cache/progress_summary.json`
  - `flags` only if hydration compliance warnings depend on the updated data

### `/fitness-coach sleep`

- Write the sleep entry to `data/logs/sleep/YYYY-MM.json`.
- If the same night is corrected later, update that date's entry instead of duplicating it.
- Respond with:
  - comparison to the `7-9h` recovery target
  - running 7-day average
  - recovery note if sleep is under `6h`
- If sleep is under `6h` for `3+` consecutive nights, recommend reducing upcoming training intensity to roughly `50-60%` until sleep improves.
- After writing, refresh:
  - `current_status.json`
  - only the `sleep` section of `cache/progress_summary.json`
  - the `recovery` section only if saved recovery status explicitly depends on sleep
  - `flags` only if sleep warnings depend on the updated data

### `/fitness-coach log`

Use this for workout completion and/or body-weight logging.

- If the user reports workout completion, write the session to `data/logs/workout/YYYY-MM.json`.
- If the user reports body weight, write the entry to `data/logs/weight/YYYY-MM.json`.
- If both are provided, update both files in the same turn.

PR detection:

- Read `cache/personal_bests.json` first.
- Compare the new workout entry against cached bests for the same exercise.
- If weight or reps exceed the cached best, mark `is_pr: true` for that exercise entry, celebrate it in the response, and update `cache/personal_bests.json`.
- Only fall back to recent workout month files if the cache is missing or clearly stale.

After writing, refresh:

- `current_status.json`
- the `training` section when workout data changed
- the `weight` section when body-weight data changed
- `flags` only if adherence, plateau, or recovery warnings changed
- `cache/personal_bests.json` when workout data changed

### `/fitness-coach watch`

- Read [references/watch-analysis.md](references/watch-analysis.md).
- Accept screenshots, pasted stats, exports, or dictated metrics.
- Write parsed sessions to `data/logs/watch/YYYY-MM.json`.
- Analyze session intensity, zone distribution, recovery signals, and how the session fits the user's goal.
- If watch data strongly conflicts with the current plan, mention the recommended adjustment explicitly.
- After writing, refresh:
  - `current_status.json` if recent recovery context changed
  - only the `recovery` section of `cache/progress_summary.json`
  - `flags` only if recovery warnings depend on the updated data

### `/fitness-coach checkin`

- Read the profile, `current_plan.json`, and `current_status.json` first.
- If `current_status.json` is missing or stale, rebuild it from the smallest relevant monthly log slice before continuing.
- Determine today's expected training or rest status from `current_plan.json`.
- If a scheduled session appears to have been missed, ask before silently shifting the plan.
- Use accountability tone from the profile, with `standard` as the default.
- If `user_profile.checkin_time` is `morning` or `evening`, treat that as the default check-in style unless the user explicitly asks for the other one.
- If `user_profile.checkin_time` is `both` or missing, determine session type from current local time: before `14:00` = morning check-in; `14:00` and after = evening check-in.
- If `current_plan.json` includes `scheduled_weekday`, use that mapping first when deciding whether today is a training day or rest day. If it does not, fall back to recent logs plus `days_per_week`.
- Morning check-ins should cover training plan, hydration, and meal focus.
- Evening check-ins should cover workout completion, food, water, pain, energy, and tomorrow's prep.

### `/fitness-coach progress`

- Read `cache/progress_summary.json` first.
- If only one section is stale, rebuild only that section plus dependent `flags`.
- If the cache is missing or stale, regenerate it from recent windows only:
  - weight: last `30-90` days as needed
  - training: last `30` days
  - food: last `7-30` days
  - hydration: last `7-14` days
  - sleep: last `7-14` days
  - recovery: last `7-14` days
- Do not scan every monthly archive unless the user explicitly asks for long-term history.
- Do not read weekly report markdown files to answer `/progress`; use cache first and raw logs only for the exact missing window.
- Summarize:
  - weight change
  - adherence to training plan
  - PRs or performance progress
  - food compliance
  - hydration and sleep consistency
  - smartwatch recovery trends when available
- Keep the summary specific and data-based, then give one or two next-step recommendations.

### `/fitness-coach adjust`

Use this when the user asks for changes or when the data clearly supports reassessment.

Common triggers:

- plateau for `3+` weeks
- rapid weight loss
- repeated low adherence
- pain or repeated exercise intolerance
- poor sleep or wearable recovery warnings
- goal achieved

Actions:

- recalculate TDEE if body weight changed materially
- adjust calories or macros
- reduce or increase training volume
- replace problematic exercises
- overwrite `current_plan.json`
- append an adjustment entry to `data/logs/adjustments/YYYY-MM.json`
- refresh `current_status.json`
- refresh only the progress-summary sections whose baselines or targets actually changed, plus dependent `flags`

### `/fitness-coach report`

- Read `user_profile.json` and `current_plan.json` for target context and next-week focus.
- Read [references/report-template.md](references/report-template.md).
- Generate a weekly report using actual logs, not generic praise.
- Read only the monthly log files overlapping the requested report week.
- If the requested week's planned-session count is not reliable from hot files and report-week data, report completed sessions only rather than inventing a denominator.
- Keep the saved report compact and summary-only. Do not paste raw daily logs, set-by-set workouts, or full meal-by-meal dumps into the archive file.
- Save the report to `{baseDir}/data/weekly_reports/week_YYYY-MM-DD.md`.

## Data Rules By Command

Before reading or writing any file, follow [references/data-schema.md](references/data-schema.md).

Important:

- Do not create alternate top-level shapes unless the schema explicitly says so.
- Update the current day entry when a day-based log already exists.
- Use exact enum strings from the schema.
- Prefer hot files and narrow windows over full-history reads.
- Treat cache reuse as the default. Rebuild only when the staleness rules clearly require it.

## Error Handling

- Missing profile: guide the user into onboarding or ask only for the minimum missing fields.
- Missing cache or status file: regenerate it from the smallest relevant log slice, not from all history.
- Missing monthly log file: create it using the exact empty structure from the schema rules.
- Incomplete profile: collect only the fields needed for the requested command.
- Invalid or ambiguous user input: ask a short clarifying question and keep the rest of the context intact.
- No historical data yet: say so plainly and focus on the next best action instead of inventing trends.
