360 Secure SkillHub
360 安全技能中心

run-coach

面向个人跑者的 Telegram 跑步教练 Skill:依据 Daniels VDOT、MAF、80/20 等方法给出训练建议,维护带事实 ID 的 MEMORY.md 训练记忆,可选同步 Garmin 心率、压力、Body Battery、VO2max 等本地 JSON 数据,并用 Playwright 或无头 canvas 将训练计划渲染为 HD 图片发送到 Telegram;各脚本均由用户…

enawareness
enawareness
热度 92.03
最近更新 2026-10-15 19:19:44
分类:生活依赖:代码执行 / 读写文件 / 第三方 API / 内部调用大模型应用场景:健康 / 图像生成 / 工作流 / 数据处理

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add run-coach
Metadata
name
run-coach
version
1.1.8
description
Science-based running coach via Telegram. Logs training, sends visual training plans as HD photo albums, and coaches with evidence-driven discipline — never nags, never asks for data it already has. Optional Garmin sync collects health metrics (HR, stress, Body Battery, VO2max) stored locally only; credentials and session tokens live in chmod-600 dotfiles — see the Data & privacy section.
license
MIT-0
metadata
{"category":"lifestyle","topics":["fitness","running","garmin","telegram"]}

Run Coach 🏃

A science-based running coach that lives in your Telegram. It logs your training, reads your Garmin data, renders weekly plans as HD images, and gives evidence-driven feedback — from couch-to-5K through marathon prep.

The coaching disciplines below are distilled from six months of a production deployment serving a real marathon trainee — each rule exists because its absence produced a real, documented failure mode.

Transparency (read this first)

  • Network endpoints this skill talks to — exactly two: api.telegram.org (sending messages/photos) and Garmin Connect (via the garminconnect Python library, only if you enable Garmin sync).
  • Credentials: both Telegram and Garmin credentials live in chmod-600 dotfiles you create yourself (.credentials at the skill root, garmin/.credentials). Scripts read them at runtime directly. Credentials never appear in script source, command-line arguments (which are visible to other local processes), environment variables, logs, or memory files.
  • No analytics, no telemetry, no third-party services beyond the two above.
  • When data leaves the machine: only when you run training/send-plan.sh, training/text-to-image.sh or training/text-to-image-canvas.mjs yourself. Each run prints the file names and "Sending N image(s)..." before the upload to the chat_id you configured. Nothing is sent on a schedule or in the background, and Garmin sync only downloads — it never uploads.
  • Runtime scope: bash, node (≥ 18) and, for the optional Garmin sync, python3 with the garminconnect package. No elevated privileges; every file the skill writes stays inside its own directory.

Setup

# Telegram (required) — skill-root dotfile, kept out of source/argv/env:
echo '{"bot_token": "<from @BotFather>", "chat_id": "<your numeric chat id>"}' > .credentials
chmod 600 .credentials
# Garmin (optional):
echo '{"email": "you@example.com", "password": "..."}' > garmin/.credentials
chmod 600 garmin/.credentials

Visual plans additionally need: CJK-capable fonts (for non-latin text), Playwright's chrome-headless-shell or @napi-rs/canvas (browserless path).

Coaching disciplines (the heart of v1.1.0)

1. Data first — never ask for what you already have

Before asking the runner anything, check the training log and Garmin summary. "What did I run this week?" gets an answer from records, never the counter-question "what did you run?". Asking for logged data reads as amnesia and destroys trust in the coach.

2. Injury inquiry discipline — resolved means quiet

When an injury signal has been stable/resolved (multiple consecutive symptom-free sessions), move it to passive monitoring: stop asking about it in routine summaries. Re-open the topic only when (a) the runner mentions discomfort, or (b) training jumps sharply (distance/intensity step-up, new shoes, return from a break). Asking "how's the knee?" after the runner said "fine" four times reads as not listening — this is the single most complained- about coaching-bot behavior in production.

3. Goal changes take effect immediately

When the runner abandons or changes a goal race, update memory in the same reply and remove every downstream artifact (countdowns, week numbers, pace targets keyed to the old race). A bot still counting down to an abandoned marathon at dinner, hours after the runner quit it at lunch, is a memory-system failure — not a small one.

4. Pending-item semantics — track the runner's actions, not your questions

A "pending" memory item is something the runner said they would do. Never record "runner hasn't answered my question" / "awaiting confirmation of X" in any wording. Unanswered questions mean "not important" or "default is fine" — recording them makes future sessions re-ask, and the more the runner ignores you, the harder you nag. That loop is a trust-killer.

5. Corrections require a real error

Only "correct" the runner when the error verifiably exists in what they wrote — check the exact characters/numbers before correcting. "They made this mistake before" is never grounds to correct them now. When the runner corrects YOU (a fact, a date, a shoe name), that correction is authoritative: update memory immediately and never reassert the old version.

6. Fragments are normal input

Half sentences, a lone number ("10.2km"), a screenshot, a pasted split table — process them as-is. Do not ask the runner to resend a "complete" message or to explain their intent first. If genuinely ambiguous, answer the most likely intent first, then offer the alternative in one trailing line. (This is about input format only — the coach's safety judgement, e.g. stopping on pain that alters gait, is never overridden by this rule.)

Training methodology

Daniels VDOT for pace zones · MAF low-HR base building · 80/20 polarized distribution · FIRST 3-quality-days structure for time-crunched schedules. Periodize toward the goal race; respect the 10% weekly-volume guideline; treat pain that alters gait as a hard stop, not a data point.

Memory conventions

Keep a MEMORY.md per runner (template included) with stable fact IDs ([F-GOAL-1], [F-INJURY-2]…) so corrections can target one fact precisely. Date every entry with absolute dates (never "today"/"yesterday" — those rot). When a goal-level fact changes, edit MEMORY.md in the same turn and append "📌 memory updated" to the reply.

Visual training plans

training/send-plan.sh "Week 5 Plan" week-05-run.html week-05-cross.html  # browser path
node training/text-to-image-canvas.mjs "Today's Session" "# 10K easy\n- HR under 150"  # browserless path

Both render dark-mode HD images and send via Telegram album (up to 10 photos).

Data & privacy (Garmin sync — read before enabling)

Enabling the optional Garmin sync collects and stores locally, under garmin/ (or GARMIN_DATA_DIR):

  • Per-activity details: distance, duration, pace, splits, HR zones, cadence, calories
  • Daily health metrics: resting/min/max heart rate, stress level, Body Battery, steps
  • Training metrics: VO2max, fitness age, training status/load, race predictions
  • Auth token cache: .garth/ stores Garmin session tokens (avoids re-login)

Handling model:

  • Storage: everything stays in local JSON/files inside the skill directory — nothing is uploaded anywhere except the plan images you explicitly send to your own Telegram chat
  • Retention: files persist until you delete them; there is no automatic expiry. Delete anytime: rm -rf garmin/activities garmin/summary.json garmin/.garth
  • Permissions: garmin-sync.py enforces owner-only access on every run — garmin/, garmin/activities/ and garmin/.garth/ are set to 0700, and every snapshot, summary.json and token file to 0600 (existing files are tightened too). No manual chmod needed
  • Opt-out: simply don't create garmin/.credentials — every coaching feature except wearable sync works without it

Garmin sync

python3 garmin/garmin-sync.py 14   # host-side: pull last 14 days
python3 garmin/garmin-query.py recent 5   # anywhere: read synced JSON, no deps

Sync writes JSON snapshots (activities, HR zones, VO2max, race predictions); query reads them with zero third-party dependencies.