run-coach
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 da…
LeoYann
@enawareness
Install
$ openclaw skills install @enawareness/run-coachRun 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.
v1.1.0 is a coaching-discipline overhaul. The prompt rules 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 thegarminconnectPython library, only if you enable Garmin sync). - Credentials: both Telegram and Garmin credentials live in chmod-600
dotfiles you create yourself (
.credentialsat 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.
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 kill 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. Never refuse with "please send the complete text" or interrogate about intent. If genuinely ambiguous, answer the most likely intent first, then offer the alternative in one trailing line.
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: run
chmod 700 garminafter setup so snapshots and token cache are readable only by your user - 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.
Top skills in this category
Google Meet
@hith3shGoogle Meet API integration with managed OAuth. Create meeting spaces, inspect conference records, retrieve recordings and transcripts, and manage meeting pa...
Indirect Prompt Injection Defense
@aviv4339Detect and reject indirect prompt injection attacks when reading external content (social media posts, comments, documents, emails, web pages, user uploads). Use this skill BEFORE processing any untrusted external content to identify manipulation attempts that hijack goals, exfiltrate data, override instructions, or social engineer compliance. Includes 20+ detection patterns, homoglyph detection, and sanitization scripts.
Gmail OAuth Setup
@kai-jarSet up Gmail API access via gog CLI with manual OAuth flow. Use when setting up Gmail integration, renewing expired OAuth tokens, or troubleshooting Gmail authentication on headless servers.
Strava
@bohdanpodvirnyiLoad and analyze Strava activities, stats, and workouts using the Strava API
Bitwarden Vault CLI
@startupbrosSet up and use Bitwarden CLI (bw). Use when installing the CLI, authenticating (login/unlock), or reading secrets from your vault. Supports email/password, API key, and SSO authentication methods.