Clawhub Run Coach

Science-based running coach via Telegram. Logs training, syncs Garmin data, sends visual training plans as HD photo albums, and coaches with evidence-driven discipline — never nags…

LeoYann

@enawareness

Install

$ openclaw skills install @enawareness/run-coach

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.

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 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.

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).

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