Fitness Coach Lite

v1.0.1

个人运动追踪教练skill — 低摩擦Telegram输入,训练记录+状态追踪+动态训练建议+日报周报月报。触发:用户发送任何运动/状态/查询相关消息时加载。

0· 86·0 current·0 all-time

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for youhan2021/fitness-coach-lite.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "Fitness Coach Lite" (youhan2021/fitness-coach-lite) from ClawHub.
Skill page: https://clawhub.ai/youhan2021/fitness-coach-lite
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install fitness-coach-lite

ClawHub CLI

Package manager switcher

npx clawhub@latest install fitness-coach-lite
Security Scan
VirusTotalVirusTotal
Pending
View report →
OpenClawOpenClaw
Benign
medium confidence
Purpose & Capability
Name/description match what is implemented: a local workout-tracking CLI (scripts/workout.py) plus SKILL.md instructions for recording workouts, status, plans and generating reports. The code and data files live under the skill's own data/ folder — appropriate for this purpose.
Instruction Scope
SKILL.md instructs the agent to invoke the included workout.py CLI to read/write JSON files under data/ (plan.json, history.json, body_status.json, .current_workout.json). That stays within the declared purpose. Two items to note: (1) the runtime script reads an environment variable HERMES_SESSION_START to determine session time (SKILL.md does not declare or document this), and (2) the plan import/plan set functionality accepts file paths or JSON strings — if the agent blindly accepts arbitrary file paths from untrusted input, it could read local files (e.g., plan import <path>) and incorporate their contents. Also the workout log behavior can overwrite the day's record (explicitly documented), which is a data-loss risk if misused.
Install Mechanism
No install spec, no remote downloads. This is an instruction-only skill with a bundled Python script and data files — minimal install risk; nothing is pulled from external URLs by the package itself.
Credentials
The skill does not request credentials or config paths. However, the shipped script reads HERMES_SESSION_START (a timestamp-like env var) to determine session date/time; that env var is not declared in the skill metadata. This is not a credential, but it's an undeclared runtime dependency that can change behavior if set. No other secrets or unrelated env vars are requested.
Persistence & Privilege
The skill writes and maintains files under its own data/ directory. always:false and default autonomous invocation are used. The skill does not request or appear to modify other skills' configurations or system-wide settings.
Assessment
This skill appears coherent with its stated purpose, but review a few things before installing: - Review the full scripts/workout.py (the provided file was truncated in the listing) for any network calls, hidden endpoints, or subprocess execution that might exfiltrate data. The visible portion only does local JSON read/write and date handling, but the file wasn't shown in full. - HERMES_SESSION_START is used at runtime to set the session timestamp but is not declared in the skill metadata or SKILL.md. If you rely on timestamps, decide whether you want to supply that env var or rely on the fallback behavior. - plan import accepts arbitrary file paths. Do not allow untrusted users to supply file paths to import, because that could cause the agent to read local files and store their contents in plan.json / history.json. Treat imports from paths as a privileged action or require explicit user confirmation. - The log operation intentionally overwrites the day's record; make backups if you care about accidental overwrites. - Data privacy: history.json and body_status.json store health-related information on disk. Ensure the skill runs in a secure environment with appropriate filesystem permissions and consider encrypting or backing up sensitive data if needed. If you want stronger assurance, ask the maintainer or provider for the full source (complete workout.py) and an explicit statement about whether the script contacts any external services; run the skill in a sandboxed environment first.

Like a lobster shell, security has layers — review code before you run it.

latestvk974x0chvcaagddwc3q3qga54585a9b9
86downloads
0stars
2versions
Updated 6d ago
v1.0.1
MIT-0

fitness-coach-lite

Telegram 低交互场景的个人运动追踪教练。把"像发消息一样记录运动"作为核心目标。


核心哲学

3秒记录原则:用户在任何对话轮次里,发来一条训练或状态消息,agent 应当能在最少回复轮次内完成记录。


数据文件(统一在 data/ 下)

data/
├── plan.json              # 当前训练计划(格式不变)
├── history.json           # 统一历史:训练记录+状态记录+快照引用(升级格式,见下)
├── body_status.json       # 身体基本信息+体重/体脂历史
└── .current_workout.json  # 训练中途进度(临时)

history.json 升级格式

{
  "records": [
    {
      "date": "2026-04-20",
      "type": "workout",
      "workout": {
        "summary": "练了背",
        "exercises": [
          {"name": "坐姿划船", "weight_kg": 25, "sets": [{"reps": 8}, {"reps": 8}, {"reps": 8}]},
          {"name": "高位下拉", "weight_kg": 25, "sets": [{"reps": 8}, {"reps": 8}]}
        ],
        "duration_min": 35,
        "note": "状态不错"
      }
    },
    {
      "date": "2026-04-20",
      "type": "status",
      "status": "累",
      "detail": "昨晚没睡好"
    },
    {
      "date": "2026-04-20",
      "type": "snapshot",
      "snapshot": {
        "week_of": "2026-04-14",
        "workout_count": 4,
        "status_summary": {"累": 2, "正常": 5},
        "plan_version": "v2"
      }
    }
  ]
}

触发判断(每条用户消息都要判断)

当用户发送消息时,按以下顺序判断意图:

1. 训练记录类(最高优先级)

关键词/模式:跑了练了深蹲卧推走了多少步拉伸骑车上半身今天训练了做了.*组Xkg.*X次开始练练完了第.*组

处理流程:

  1. 提取动作名称、重量、组数、次数、时长
  2. 若重量缺失 → 尝试从 plan.json 推断今日计划中的默认重量
  3. 若完全无法提取 → 将用户描述作为 summary 自由文字保存
  4. 调用 workout.py log 写入 history.json

格式灵活接受:

  • 今天跑了40分钟{summary:"跑步40分钟"}
  • 深蹲60kg 5x5,卧推30kg 5x5 → 两个动作分别记录
  • 晚上练了腿{summary:"练腿"}
  • 走了8000步{summary:"步行8000步"}
  • 今天拉伸了15分钟{summary:"拉伸15分钟"}
  • 上半身训练{summary:"上半身训练"}

实时记录工作流(低摩擦版):

  1. 用户说「开始练」→ 调用 workout.py start-session(记录开始时间到 data/.session.json
  2. 用户报每组成绩如「第1组 10个」「第二组 8个」→ 调用 workout.py log "<date>" '<json>' 实时更新记录(duration_min 先写 null
  3. 用户说「练完了」→ 调用 workout.py finish-workout(从 .session.json 读取开始时间,计算实际时长,更新历史记录中对应记录的 duration_min
  4. 注意log 每次调用会覆盖当天训练记录,所以每组完成后要重新传入完整的 exercises 列表

2. 状态记录类

关键词/模式:没睡好不想练.*这周只能.*次出差经期恢复不舒服膝盖.*状态

处理流程:

  1. 提取状态类型和详情
  2. 调用 workout.py status-log 写入 history.json
  3. 若状态影响训练建议(如"出差"、"经期"、"恢复模式"),触发训练建议调整

状态类型映射:

用户词存储值
累、很累、疲惫tired
没睡好、睡眠差poor_sleep
出差travel
经期、生理期period
不想练X、讨厌练Xavoiding:{部位}
这周只能练X次frequency_limit:{N}
恢复、休息一下recovery
膝盖不舒服、肩膀疼injury:{部位}
状态不错good
正常normal

3. 查询报告类

关键词/模式:今天练了什么这周练了几次报告周报月报这周为什么执行.*最近计划改了.*练什么

处理流程:

  1. 先判断今天周几:调用 workout.py plan view,内部已根据 date.today() 自动确定真实日期对应的星期
  2. 再查今日计划workout.py plan view 输出中已包含今日训练内容(标注了当天)
  3. 其他查询
    • 今天练了什么 → 查 history.json 中今日 type=workout 记录
    • 这周练了几次 → 统计本周 type=workout 数量
    • 这周状态 → 查本周 type=status 记录
    • 日报 → 调用 workout.py report today
    • 周报 → 调用 workout.py report week
    • 月报 → 调用 workout.py report month
    • 阶段总结 → 调用 workout.py report summary

4. 计划管理类

关键词/模式:新计划改训练计划更新计划训练计划.*调整

处理流程:

  1. 理解新的训练安排
  2. 调用 workout.py plan set 保存 plan.json
  3. 调用 workout.py plan version 追加版本记录到 history

5. 身体数据类

关键词/模式:体重.*kg体脂.*%身高.*cm

处理流程: 调用 workout.py body updateworkout.py body log


训练建议动态调整

触发条件

以下状态变化后,agent 应主动或被动更新训练建议:

  • 用户说出差经期恢复模式这周只能练X次 → 降频建议
  • 用户说不想练腿讨厌练背 → 调整部位偏好
  • 用户连续3天状态为tired → 建议降强度
  • 用户连续poor_sleep → 建议推迟主训练日

调整输出格式

当触发调整时,输出格式:

📋 训练建议已调整(v{N})
原因:{触发原因}
建议:{具体建议}

方案版本记录

每次调整训练建议,调用 workout.py plan version <reason> 记录到 history.json 的 plan_versions 数组。


Quick Actions(适合 Telegram Inline Keyboard )

提供以下快捷操作选项:

[🏋️ 练什么] [📝 记录训练] [📊 查看报告]
[😫 状态记录] [⚖️ 体重记录] [📋 训练计划]

命令一览(供 agent 内部调用脚本)

脚本命令功能
workout.py start-session开始训练计时(记录开始时间到 .session.json)
workout.py log "<date>" '<json>'记录/更新一条训练(实时逐组更新)
workout.py finish-workout结束训练(从 session 自动算时长并更新记录)
workout.py status-log "<date>" <status> <detail>记录一条状态
workout.py plan version <reason>记录方案版本变更
workout.py plan view查看当前计划(自动标注今天)
workout.py report today日报
workout.py report week [date]周报(默认本周)
workout.py report month [date]月报(默认本月)
workout.py report summary阶段总结
workout.py body update key=value...更新身体数据
workout.py body log key=value...记录当天体重体脂
workout.py body view查看身体数据
workout.py body history [days]体重体脂历史
workout.py history [days]训练历史(仅训练记录)
workout.py reset-today重置今日
workout.py reset-date <date>重置指定日

Telegram 低摩擦输入设计原则

  1. 不需要确认轮次:记录完成后直接显示"✅ 已记录:..."
  2. 模糊重量可接受:若用户说"练了腿"无细节,仍可记录为 {summary:"练腿"}
  3. 同一条消息可混合记录:如"今天跑了30分钟,状态很累" → 一次性写入训练+状态
  4. 查询即时响应:不要求二次确认,直接查直接回
  5. 周报/月报一次性输出:不分段确认

报告模板

日报

📅 2026-04-20 日报
━━━━━━━━━━━━━━━
🏋️ 训练:坐姿划船 25kg×3组 / 高位下拉 25kg×3组
⏱️ 约 35 分钟
😫 状态:累(昨晚没睡好)
📝 备注:—
━━━━━━━━━━━━━━━

周报

📅 周报(4/14 - 4/20)
━━━━━━━━━━━━━━━
🏋️ 训练次数:4次
😫 状态:累×2 / 正常×3 / 出差×1
📉 执行率:4/5 计划日(80%)
⚠️ 问题:周二因出差未训练
📋 方案变更:v2(出差降频)
━━━━━━━━━━━━━━━

月报

📅 月报(4月)
━━━━━━━━━━━━━━━
🏋️ 训练次数:18次
⏱️ 总时长:约 9 小时
😫 状态趋势:上半月累×6 / 下半月正常×8
📉 执行率:18/22(82%)
💪 进步:卧推+5kg,深蹲+10kg
📋 方案变更:3次
━━━━━━━━━━━━━━━

现有数据兼容说明

  • plan.json 格式完全不变,继续使用
  • history.json 追加兼容:原有训练记录结构在 records[].workout 中,原有格式可直接读取
  • body_status.json 继续使用,不变
  • scripts/workout.py 扩展新命令,不删除原有功能

MVP 第一版实际能力

✅ 以下是本 skill 第一版实际交付的能力集:

输入处理:

  • 自然语言训练记录解析
  • 状态记录(7种类型)
  • 混合输入(一次消息含训练+状态)

数据层:

  • history.json 升级格式(含 type=workout/status/snapshot)
  • plan.json 继续使用
  • body_status.json 继续使用
  • 训练方案版本记录

报告输出:

  • 日报
  • 周报
  • 月报
  • 阶段总结

训练建议:

  • 基于状态触发动态调整
  • 方案版本记录

Quick Actions:

  • 6个快捷操作选项

⚠️ 技术注意事项

日期必须从 HERMES_SESSION_START 环境变量读取

workout.py 脚本中的日期/时间计算禁止使用 Python 内置的 date.today()datetime.now(),因为系统时钟可能与实际用户时区不一致。

正确做法: 脚本从 HERMES_SESSION_START 环境变量解析 session 开始的 UTC 时间戳,再转换为 UTC+8(用户所在时区)。

from datetime import datetime, timezone, timedelta

def _get_session_dt():
    raw = os.environ.get("HERMES_SESSION_START", "")
    if raw:
        try:
            return datetime.fromisoformat(raw.replace("Z", "+00:00"))
        except Exception:
            pass
    return datetime.now(timezone.utc)  # fallback

def _get_session_dt_local():
    dt = _get_session_dt()
    utc8 = timezone(timedelta(hours=8))
    return dt.astimezone(utc8)

def _get_session_date():
    return _get_session_dt_local().date()

然后将所有 date.today() 替换为 _get_session_date(),所有 datetime.now() 替换为 _get_session_dt_local()

.gitignore 清单

__pycache__/
*.py[cod]
backend/.pybase/
backend/.vendor/
backend/.venv/
.pytest_cache/
.env
.data/
*.log
*.lock
dist/

❌ 以下为第一版不做项(留待后续迭代):

  • 饮食记录
  • 热量计算
  • 网页端/复杂 UI
  • 自动化训练计划生成

Comments

Loading comments...