openpacemaker

OpenPacemaker user guide.

A complete reference for the chat-based coach that lives in Telegram. Read top-to-bottom for the first run, or jump to a section when something specific comes up.

Quick start

OpenPacemaker is a coach you talk to. Everything happens in a 1-on-1 Telegram chat: morning briefings, post-activity analysis, plan adjustments, voice notes. There’s a small companion web dashboard for the visual stuff (sign-in, plan view, billing) but the coaching itself lives in chat.

Connect Strava

Open @runwhisperer_bot in Telegram and hit Start. The bot sends you a Strava authorisation link. Click it, approve read-only access, and you’re connected — your full activity history syncs in the background.

Read-only Strava access. The bot can read your activities, profile, and per-second heart-rate streams. It cannot post, edit, or delete anything on Strava — that’s a hard constraint of the OAuth scope we request. You can revoke access any time from your Strava app settings.

Athlete assessment (~5 minutes)

The first time you chat with the bot it walks you through a structured onboarding flow:

01
Primary sport. Running, cycling, triathlon, swimming, hiking, or walking. Picks the methodology block the coach uses (Jack Daniels for running, FTP-based power for cycling, balanced periodisation for triathlon, etc.).
02
Goal & target race. What you’re training for. Specific event + date if you have one, or an open-ended fitness goal otherwise.
03
Fitness baseline. Current weekly volume, recent personal bests, and any benchmark data (HR zones, FTP for cyclists, swim CSS pace for triathletes). The coach reads your full Strava history alongside this to calibrate.
04
Health & demographics. Age, weight, current injuries or niggles, work schedule. All used to shape session prescription and load tolerance.
05
Coaching style. Three role buttons — Coach (direct, performance-focused), Partner (collaborative, analytical), Companion (low-pressure, life-aware). You can change later via /style, which exposes five underlying tones plus a Jon easter egg.
06
Plan generation. The coach drafts a plan based on everything above. Review the preview, accept or ask for changes, and you’re running.

The first 14 days are a calibration window. The coach is more cautious during this period — caveats strong claims, asks at most one calibration question per logged workout, treats the auto-generated plan as a starting hypothesis rather than a contract. It drops out automatically after day 14.

Write descriptive Strava titles

The coach reads your Strava activity title and description to understand the intent behind each session. "Easy 10k, kept it conversational" tells a very different story than "10.0 km".

Good examples:

Easy recovery jog — legs still heavy from Sunday
Tempo 3×2km @ HM pace, felt strong
Long run 26km — bonked at 22, nutrition off
Commute home, easy spin (auto-detected as a commute and skipped for coaching)

The title is also how you communicate workout structure to your watch — when you write 4×1km @ 3:45, the coach reads that as your stated intent for the day and judges execution against it, not just against the plan’s prescription.

Your first week

Once onboarding is done, your week looks roughly like this:

  • Each morning — a personalised briefing arrives at your chosen check-in hour (default 08:00 athlete-local). Shows today’s session, recent load context, and any niggles you’ve logged.
  • After every Strava upload — the bot DMs an analysis card with HR zone distribution, target match, and an effort-rating prompt. Replying with a 1–5 RPE feeds the coaching memory.
  • Sunday evening — a weekly debrief lands with the week’s actual vs planned km, adherence, and a forward-looking note.
  • Anytime — chat naturally. "Should I run tomorrow?" or "Move Tuesday’s tempo to Thursday" both work without typing a command.

Daily rhythm

The bot is proactive — it reaches out at the right moments. You don’t need to remember to ask.

Morning check-in

A personalised briefing every morning at your chosen hour. Surfaces today’s prescribed session, recent fatigue trend, plan progress, and any open wellness issues. Tap the sleep emoji at the end of the message (😴 / 😐 / 😊) for a one-tap sleep quality log — feeds into next-day load advice.

Tuesday, week 6 of 12 — sharpening phase
Today: 5×1km @ 3:50 / 90s recovery (target HR Z4)
ATL is +12 vs last week — quality session is right on the edge. If your legs feel heavy on the warm-up, drop to 4 reps.

😴 poor · 😐 ok · 😊 good

Change your check-in time via /settings or the dashboard. Pause check-ins entirely via /pause.

Post-activity coaching

When you finish an activity, Strava webhooks the bot. ~10 minutes later (giving Strava time to process splits and HR streams) you get a structured analysis card:

5×1km @ 3:50 — tempo
📏 8.2 km · 🏃 4:18/km avg · ❤ HR 168 · ⛰ +42m

Work block 3:48 / 3:49 / 3:51 / 3:49 / 3:52 — that’s textbook execution. HR climbed slightly across reps (164 → 174) which is the normal cardiac drift signature on a 25-min tempo.

How did that feel? [1] [2] [3] [4] [5] [Skip] [🎤 Voice]

Reply with a 1–5 RPE (or skip). The RPE feeds into the coaching memory and shapes next week’s prescription.

Voice debriefs

The 🎤 button on the RPE keyboard accepts a voice note instead of a number tap. Useful when you’ve got more to say than a digit — *"felt good, hills were harder than expected, calves cramped at km 6"*. The bot transcribes via Whisper, parses an RPE out of the transcript (any 1–5 in the text), and saves the rest as the debrief notes. If no RPE is detectable, it re-prompts with the standard keyboard.

Voice notes outside the RPE flow also work — chat the bot a voice note anytime and it transcribes and responds in chat. Premium feature.

Smart tips

Once a week (Wednesday afternoon, athlete-local) the bot may send a single personalised tip if a detector fires on your data — examples:

  • Split workout candidate — when your tempo split into multiple short pieces is consistently faster than the prescribed continuous one.
  • HR zones unset — when activities are syncing but you haven’t configured zones, blocking the load calculation.
  • Chronic reschedule — when a specific weekday consistently gets moved or skipped, suggesting the plan’s shape doesn’t match your life.

Each tip has an 8-week cooldown so you’re not nagged. Toggle with /tips on or /tips off.

Weekly review

Every Sunday evening the bot sends a weekly summary — actual vs planned km, adherence breakdown (✅ done / 🔶 partial / ❌ missed / 😴 rest), and a forward-looking note about next week. You can also pull it any time with /review.

Under the hood, the bot also runs a longer-form review once a week (Sunday 04:00 UTC) that writes 1–3 durable "weekly insight" memories — observations that compound across weeks and surface in future chats. You don’t see this directly; you see its effect when the bot brings up *"you mentioned shin pain four weeks ago — still bothering you?"* in a hill-week conversation.

Plan

Your plan is generated during onboarding and adapts continuously. It’s structured data — not just text — so the bot can reason about specific sessions and edit them surgically.

Editing the plan

Three ways:

  • Plain English in chat. "Move Tuesday’s tempo to Thursday" or "I’m travelling next week — make it a rest week". The coach handles the restructuring with the right tool calls.
  • /editweek <N> <instruction> — explicit week-level edit, useful for big changes.
  • /reschedule <session> — move a single session within the current week.

Plan edits never happen silently. The coach always tells you what changed and why, and adjustments that touch multiple weeks surface a Yes/No confirmation button before they commit.

Pause & easy weeks

/pause stops scheduled jobs (morning check-in, plan adjustments) and rolls plan dates forward when you resume. Useful for illness, injury layoffs, business trips, or just needing a break.

/easyweek (or /recover) dials back the current week — volume and intensity drop without rebuilding the plan. Quick recovery move without committing to a full pause.

Writing a great /setplan prompt

If onboarding finished without a plan you’re happy with, or you want to regenerate from a one-line goal, use /setplan. The plan generator is Claude under the hood — it responds well to natural language and uses everything you tell it. A richer prompt produces a much better plan.

The essentials

  • Race + date + target time. Be specific: event name, full date, goal finish time. "Berlin Marathon on 27 September 2026, target 2:58" beats "marathon in autumn".
  • Current shape. A recent race time, recent long-run pace, or rough equivalent. "Currently in 3:05 shape" or "ran a half in 1:24 last month".
  • Weekly volume. What you’re doing now and what you want to cap at. "Currently 60km/week, happy to peak at 80".
  • Days & sessions per week. Days you can train, days you can’t. "Max 5 days, sessions Tue/Fri/Sun".

Things that improve the plan significantly

  • Personal bests. Anchors VDOT calculations and pace zones. "PBs: 5k 17:30, 10k 37:40, half 1:21".
  • Terrain & facilities. Hills, flat loops, track. The coach assigns hill reps and track work when appropriate.
  • Cross-training. Cycling, swimming, gym, yoga — and roughly how often. Factors into total load.
  • VO2max estimate. Garmin or Apple Watch usually has one. "Garmin VO2max 56". Helps calibrate intensity.
  • Race-week constraints. Taper preferences, race-morning routine, A-race vs B-race designations.
  • Start date. "Start from this Monday" if you want a clean week-boundary, or "start from yesterday and include today’s 4×2km tempo" if you’ve already started.

What you don’t need to specify

Your full Strava history is already loaded — the coach can see your recent training, longest runs, HR zones, and load trend. You don’t need to summarise your training history; just describe what you want.

Example prompt

/setplan
race Valencia Marathon 7 December 2026 · target sub-3:00
schedule 5 sessions a week · Tue/Thu/Sat plus long run Sunday · easy Wed if I want it
fitness currently 3:05 shape · half PB 1:21 · 10k PB 37:40 · VO2max 56 per Garmin
volume currently 60km/week · happy to peak at 80–85km · no need to build slowly
terrain hills (Hampstead Heath) · 400m track · flat park loops
cross-training easy bike commute 4x/week · gym 1-2x for general strength
b-race Hackney Half 17 May (tune-up, not a target)
start from next Monday · clean week boundary

Editing after generation

You don’t need to get everything right first time. Once the plan is generated, you can:

  • Edit a week with /editweek <N> <instruction> — e.g. "remove the track session in week 3, I’m travelling"
  • Move a session with /reschedule
  • Dial back a week with /easyweek if you’re tired or ill
  • Pause the whole plan with /pause
  • Or just ask in chat — "can you swap Thursday and Saturday this week?" works

Analysis

The bot computes everything from your raw Strava data on demand. Nothing is pre-aggregated or out of date.

Load & injury-risk signals — /load

The classic Performance Management Chart inputs:

  • CTL (Chronic Training Load) — 42-day rolling load, what we usually call "fitness".
  • ATL (Acute Training Load) — 7-day rolling load, "fatigue".
  • TSB (Training Stress Balance) — CTL − ATL. Positive = fresh, negative = under fatigue.

Plus two injury-risk signals from sports-science literature:

  • ACWR (Acute:Chronic Workload Ratio, Gabbett) — week-of-load ÷ 4-week-baseline-load. Safe band 0.8–1.3; above 1.5 is the injury-risk band. Refuses to compute when chronic baseline is too thin (athletes returning from injury or building up).
  • Foster weekly monotony — mean(daily load) ÷ stdev(daily load) over 7 days. Above 2.0 means every day looks the same — the classic signature for overtraining independent of total volume. Inject a real easy or rest day.

Plus a 12-week km/vert table so you can see the build visually. Honours your /sport filter for the display but uses whole-body load for the injury-risk signals.

Consistency heatmap

GitHub-style 7-row × 12-week grid, shown on your web dashboard's insights page:

⬛ rest · 🟩 easy (<40 TSS) · 🟨 mod (40–90) · 🟧 hard (90–150) · 🟥 race (150+)

Plus a footer with the week’s session count, current consecutive-day streak, longest streak in window, and the easy/quality/rest percentage mix. Coaching read fires when the distribution is notably skewed (heavy quality, mostly rest, all easy and no quality).

Zone breakdown — /breakdown

Time-in-zone across the last 4 weeks, computed from second-by-second Strava heart-rate streams — not lap averages. Surfaces grey-zone heavy training (too much Z3) and easy-day-not-easy patterns (Z2 prescribed but ran in Z3 because the route was hilly).

Race readiness — /readiness

Composite assessment based on CTL, TSB, plan adherence, recent training quality, and time-to-race if a goal event is set. Outputs a Garmin-style status label (peaking / productive / overreaching / detraining / recovery / maintaining) plus a coaching note. Use it 2–4 weeks out from a goal race to sanity-check whether the plan is landing where it should.

Other analysis tools

  • /adherence — sessions completed, partial, missed, and rest days honoured over the last N weeks.
  • /focus — strengths and limiters audit for running and cycling. What to work on next.
  • /score / /myscore — weekly training compliance traffic light (🟢 ≥80% · 🟡 60–79% · 🔴 <60%) with a 4-week trend.
  • /last — full detail on your most recent activity.
  • /analyse — manually re-run the post-activity analysis with a Claude coaching narrative.

Multi-sport

OpenPacemaker supports running, cycling, triathlon, swimming, hiking, and walking. The bot picks methodology and language based on your primary sport, but the chat handles any sport you log to Strava.

Sport filter — /sport

Display filter for /load, /last, /analyse, and the recent-sessions block in the chat context.

/sport run · ride · tri · swim · hike · walk · all

Doesn’t affect CTL/ATL — fatigue is whole-body regardless of which sport you’re looking at. If you commute by bike five days a week, your CTL still reflects that even when the display is filtered to running.

Ignoring a sport for coaching — /sport ignore

If a sport is genuinely non-training for you (daily cycling commute that isn’t a workout, dog walks, etc.) you can tell the coach to ignore it entirely:

/sport ignore ride — coach stops counting cycling toward load, recent-sessions context, and post-activity opinions
/sport unignore ride — put it back
/sport ignored — see what’s currently hidden

Or just ask in chat: "stop counting my cycling as training" or "my bike rides are commutes, ignore them".

Activities of ignored sports still exist in your Strava history; the bot just treats them as invisible. Auto-detected commutes (Strava’s commute flag, or "commute"/"to work" in the title) are also hidden by default — the explicit ignore list is for the cases the auto-detector misses.

Coaching personality

You set a coaching tone during onboarding via three role buttons:

  • 🎯 Coach — direct and opinionated. Pushes back on bad decisions, leads with the call. Best when you want structured training and performance focus.
  • 🤝 Partner — collaborative. Offers options instead of prescriptions, frames recommendations as suggestions, lets you steer. Still honest about the data.
  • 🤗 Companion — low-pressure. Leads with how you’re doing, normalises imperfect weeks, no urgency language. Best when training has to fit around life.

These map internally to the five-tone vocabulary the chat agent uses. Power users can switch directly via /style:

  • direct — no-nonsense, honest feedback. Default for Coach.
  • analytical — references metrics, explains trade-offs. Default for Partner.
  • encouraging — warm, leads with progress. Default for Companion.
  • banter — light-hearted with jokes.
  • strict — high standards, no excuses, results-focused.
  • jon — Royal Marine Commando PTI. Roasts you regardless of effort. Easter egg.

Change anytime: /style direct or /style jon. Style changes take effect on your next message.

Integrations

Strava (read-only)

The primary data source. The bot requests read + activity:read_all scopes only — minimum required to see your activities and your full private activity history. Specifically:

  • Reads activity data (date, sport, duration, distance, splits, per-second HR streams, per-second power streams for cycling, elevation, weather).
  • Reads activity title and description (the coach uses these as your stated intent).
  • Reads your public profile name.
  • Cannot read your followers, kudos, routes, or other athletes’ data.
  • Cannot write — no uploads, edits, or deletions on Strava.

New activities arrive in the bot within ~1 minute via Strava webhook. If the webhook drops (Strava’s side, not ours), a daily backstop sync at 04:30 UTC catches anything missed.

Garmin Connect (push)

Optional integration for pushing structured workouts from your plan onto your Garmin watch. Athletes who use Wahoo, COROS, Polar, or just don’t want this can ignore the Garmin commands entirely.

Linking — /garminconnect

The bot sends you a one-use link to a private HTTPS form on openpacemaker.com. You enter your Garmin email and password (plus 2FA if Garmin requires it) on the form. The webapp authenticates against Garmin, swaps your credentials for an OAuth token, and stores only the token. Your password is never sent through Telegram, never stored, and never logged.

The OAuth token is good for ~1 year. Re-link via /garminconnect if it expires.

Why a web form and not chat? Telegram chat messages live in your chat history until you delete them, and pass through Telegram’s servers. A private HTTPS form on our domain keeps the password on the encrypted wire between your browser and our server only — the standard pattern for "log in with username/password" flows.

Pushing workouts — /garminpush [week]

Uploads the current week’s sessions to Garmin Connect as structured workouts with VDOT-based pace targets, AND schedules each one on the right day in your Garmin calendar so it shows up when you sync your watch.

Pass a week number to push a different week: /garminpush 6. Each upload is tagged [OPM] in its name so the cleanup command can identify them later.

Re-pushing the same week is safe. If you change your plan and push again, the bot finds the prior [OPM]-tagged workouts for that week’s dates and deletes them BEFORE uploading the fresh batch. No more "3 versions of Tuesday’s tempo on my watch." The reply tells you what got replaced: Replaced 3 stale workouts → uploaded 5 fresh.

Trade-off: a workout you manually edited inside Garmin Connect after it was uploaded gets nuked on the next replace. The bot’s view of the week is authoritative — manual edits don’t survive a re-push.

Bulk cleanup — /garmincleanup

Lists every workout in your Garmin Workouts library that’s tagged [OPM] (plus legacy date-prefix-named workouts the bot uploaded before the tag existed), shows a count and preview, and offers a single-button bulk delete. Only touches workouts the bot uploaded; manually-created Garmin workouts are untouched.

Use this when you want to start fresh — e.g. before a long break, or if you’ve switched to another coaching app. Day-to-day plan edits don’t need cleanup; the re-push behaviour above handles them automatically.

Optional: overnight HRV + sleep

When you link Garmin, the bot asks (one tap) whether to also pull overnight HRV (rMSSD) and sleep duration each morning. The pull fires at your local morning check-in hour, so it lands just after your watch has had time to sync with the Garmin app — fresh reading every day. Default is OFF — these signals are sensitive enough that we never read them by default. Tap "Yes" once and the daily pull starts; both signals feed the coaching context (recovery framing, week pacing). Tap "No" and only workout sync is enabled. Toggle on/off later via /settings → Training & notifications.

We deliberately don’t pull sleep score, resting HR, stress, or body battery — sleep score is proprietary, the others are all HRV-derived. Two signals is enough.

Free vs Premium. Linking Garmin is free for everyone. Pushing workouts is a Premium feature — free-tier users see a Premium upgrade prompt when they try /garminpush <week>, but /garminconnect and /garmincleanup are always available so an ex-Premium athlete can still tidy up.

Web dashboard

A companion to the chat coach at openpacemaker.com/dashboard. Visual surface for the things that work better as a page than a chat message: full plan view, recent activities list, billing.

Signing in

The dashboard has no separate password. To sign in:

  1. Visit openpacemaker.com/dashboard
  2. Tap the “Open bot to sign in” button — this opens @runwhisperer_bot in Telegram with /login pre-filled.
  3. Send /login. The bot DMs a one-use sign-in link.
  4. Tap the link — you’re signed in.

Sessions last 30 days. To sign out, send /dashboard/logout in your browser’s address bar.

What’s on it

  • Plan overview — current week + the rest of the plan.
  • Recent activities — last ~10 with distance, pace, HR, elevation.
  • Load summary — CTL/ATL/TSB headline numbers.
  • Billing — manage your subscription, see trial status, cancel.

How the coach remembers you

Three independent memory layers run in parallel:

  • Sectioned profile. The durable "what the coach knows" document — goals, background, injuries, preferences, patterns, free-form notes. Pinned to every chat as ground truth, updated incrementally by the bot when it learns something new.
  • Vector store. Searchable per-fact memory of session feedback, race debriefs, preferences, injuries, weekly insights. Uses both vector similarity (pgvector + Voyage AI embeddings) and Postgres full-text search so the right memory surfaces even when you don’t use the same words.
  • Entity index. A secondary index on body parts (with left/right), proper noun phrases, distance/pace/power/HR numerics. Pulls cross-category recall — "shin pain" from four months ago surfaces when you load up a hill week, even though it’s in the general-notes category that the text-similarity search wouldn’t reach.

Dream consolidation

Once a week (Sunday 03:00 UTC) a separate process walks recent memories and consolidates them — merging duplicates, rewriting stale facts, deleting noise. Every event (ADD / UPDATE / DELETE / KEEP) is logged so the lineage can be reconstructed; consolidations that would delete more than 70% of inputs auto-abort as a safety floor.

You don’t interact with this directly. You see its effect: the bot stays sharp and on-topic over months rather than drowning in stale notes.

Data & privacy

What we store

Per user: Strava activities (with full HR/power streams), training plan, post-run RPE debriefs, wellness log, three-layer coaching memory, conversation history, account settings, billing state (Stripe customer/subscription IDs only — no card data). All in our Postgres database in europe-west2.

What we don’t store

Anything in your Telegram outside this 1-on-1 chat (your contacts, other conversations, photos — Telegram’s Bot API only exposes messages sent directly to the bot). Anything from Strava outside read-only activity scopes. Your Garmin password (we hold only an OAuth token after linking).

Exporting your data — /mydata

/mydata opens a hub with an Export JSON button that downloads everything we hold on you, plus a Delete button.

Deleting your data — /delete confirm

Send /delete confirm in the bot chat. Permanent and immediate — no soft-delete, no grace period. You can also revoke Strava access from your Strava settings at any time.

Privacy policy

Full text at openpacemaker.com/privacy. The summary: we read your Strava data to coach you, store it in our database to coach you over time, never sell or share it, and let you delete it whenever you want.

Full command reference

Every command available in the Telegram bot, grouped by function. Most commands have a short alias — both forms work identically. Most things also work in plain English chat without commands; the reference below is for power users.

Getting started
/start

Show your status overview, sync state, and a link to connect Strava if not yet linked. Always safe to run.

/sync

Fetch your latest activities from Strava. Useful if Strava’s webhook seems to have dropped a recent activity.

/setup

Run (or re-run) the guided athlete assessment. Generates or regenerates your training plan. Takes about 5 minutes.

/cancel

Bail out of an in-progress /setup flow without saving partial state.

/login

Reconnect your Strava account if authorisation has expired.

/help [category]

Show the in-chat command index. With a category argument (training, analysis, health, settings, setup, data) jumps to that section.

/help analysis
Daily coaching
/today

Today’s prescribed training session — type, target pace, distance, and notes. Shows ✅ if already completed.

/week [N]

This week’s actual vs planned km with a day-by-day breakdown. Pass a week number to see a specific week.

/week 3
/review

On-demand weekly coach review. Week summary plus a Claude-generated coaching narrative with a forward-looking suggestion for next week.

/countdown

Days remaining to your goal race, current training phase, and a one-line readiness note.

/last

Full detail on your most recent activity: distance, pace, HR zones, GAP, and how it compared to the plan.

/plan

Week-by-week training plan overview showing each week’s sessions and total planned km, with buttons for editing, rescheduling, and regenerating.

Analysis
/analyse

Claude analyses your last activity against the training plan — effort flags, HR zone distribution, coaching verdict, and debrief prompt.

/load

CTL · ATL · TSB plus the two injury-risk signals (ACWR, Foster monotony) and a 12-week km/vert bar chart. Honours your /sport filter for display; whole-body load for injury-risk signals.

/score · /myscore

This week’s training compliance score. Each session rated 0–100 on intensity and distance vs plan. Traffic light — 🟢 ≥80% · 🟡 60–79% · 🔴 <60% — with a 4-week trend.

/race · /readiness

Race readiness assessment based on CTL, TSB, plan adherence, and recent training quality.

/breakdown [weeks]

Time-in-zone breakdown across the last N weeks, from second-by-second Strava heart-rate streams.

/breakdown 6
/adherence [weeks]

Plan adherence: sessions completed, partial, missed, and rest days honoured over the last N weeks.

/adherence 8
/focus

Strengths and limiters audit — what to work on next, derived from your training distribution. Run + ride.

Training plan
/setplan <goal>

Generate a new personalised training plan from a one-line goal. The richer the prompt the better the plan — see the prompt guide above.

/setplan Valencia marathon 7 Dec, target sub-3:00, currently 3:05 shape, 60km/week, max 5 sessions, hills + track available
/editweek <N> <instruction>

Ask Claude to adapt a specific week — swap sessions, reduce load, add a race-week shape, work around travel.

/editweek 4 work trip Wed-Fri, drop everything in those days
/reschedule <session>

Move a single session to a different day within the same week.

/reschedule tempo Tuesday to Thursday
/easyweek · /recover

Dial back the current week — reduces volume and intensity for recovery, without rebuilding the plan.

/pause

Pause your plan and scheduled jobs. Resume with another /pause. Plan dates roll forward to match the time off.

Goals & objectives

You don’t need exact syntax here — type what you mean and the coach works out which objective you’re referring to. Your objectives and constraints feed straight into how plans are generated.

/objectives [add | done | remove] <text>

Your goals — races, performance targets (FTP, goal pace), consistency habits, or health aims. List them with no argument; refer to one by description, not a number.

/objectives done the spring marathon
/races [add | remove] <text>

Your race calendar — a focused view of your race objectives, with A/B/C priority. Add in natural formats ("London Marathon, 26 April, target 3:15") or remove by name.

/races remove London
/constraints <text>

Life and training constraints the plan must respect — rest days, weekly caps, recurring commitments, equipment. Set several at once in plain language.

/constraints no riding on Mondays, easy week every 4th week
Zones & PBs
/zones

Show your current HR and pace training zones.

/setzones <resting> <max>

Recalculate HR zones using the Karvonen formula from your resting and max heart rate.

/setzones 48 188
/setftp <watts>

Set your FTP for cycling power zones.

/setftp 285
/setweight <kg>

Set your weight — used for W/kg calculations and load context.

/pbs · /setpbs <results>

Save personal bests in plain English. Include when each was achieved if you remember — otherwise the coach has no anchor and treats them as undated. Feeds VDOT calculations and pace zone recommendations.

/setpbs 5K in 17:30 from March 2024, 10K in 37:40, half in 1:21
/findpbs

Scan your Strava history for fastest times at 5K / 10K / half / marathon distance. Surfaces candidates with their activity date and offers one-tap save. Useful when you haven't tagged your races with Strava's race flag.

/results

Race results log with VDOT equivalents and predictions across distances.

Health & wellness
/wellness · /health

Show your active injury and wellness log.

/wellness <body_part> <1–10> [notes]

Log a new issue. Severity 1 = minor niggle, 10 = can’t run. The coach tracks these and factors them into load recommendations.

/wellness left knee 4 tight after long run
/wellness resolve <id>

Mark an issue as resolved. The bot stops factoring it into recommendations going forward.

/memory

Show coaching memory stats — notes the bot has stored about your training history and preferences.

Garmin integration
/garminconnect

Link your Garmin Connect account via the private web form. See the Garmin integration section above for details on the auth flow.

/garminpush [week]

Upload the current (or specified) week’s sessions to Garmin Connect as structured workouts, scheduled on the right day in your Garmin calendar.

/garminpush 6
/garmincleanup

Bulk-delete OpenPacemaker-uploaded workouts from your Garmin Workouts library. Two-step confirm UX — see the preview before anything is deleted.

Settings & account
/settings

One place for HR · FTP · PBs · style · engagement · sport · check-in · timezone. Tap-based UI; everything else here is a shortcut into a specific setting. The Training & notifications screen adjusts training volume, session difficulty, weekly-review time, and the Garmin toggles.

/style [direct|analytical|encouraging|banter|strict|jon]

Set the coaching tone. Without arguments shows the current value and the list of options. See the personality section for what each tone does.

/style analytical
/sport · /filter [type]

Display filter for analysis: run / ride / tri / swim / hike / walk / all. Doesn’t affect CTL/ATL.

/sport ignore <sport>

Hide a whole sport from coaching context. Useful when (say) your cycling is daily commutes that aren’t training. /sport unignore <sport> to undo, /sport ignored to see what’s hidden.

/sport ignore ride
/tips on|off

Toggle weekly smart tips (Wed afternoon, athlete-local).

/mydata

Your data hub — a summary of everything stored for your account, with buttons to export it all as JSON or delete it.

/feedback <message>

Send feedback directly to the developer — bugs, ideas, anything.

/feedback the RPE buttons are great but I'd love a Monday morning weekly summary
/clear

Clear the current conversation history. Useful if the context gets cluttered or you want a clean slate.

/delete confirm

Permanently and immediately delete all your data from OpenPacemaker. Cannot be undone.

Coach features
/coachlink · /coach <coach_code>

Link yourself to a coach. Ask your coach for their code (their Telegram user ID) and run /coachlink <code>. With no argument it shows usage.

/roster · /myroster

Coaches: view linked athletes with recent-activity summaries. Also surfaces your coach code so athletes can link to you.

Troubleshooting

The bot isn’t responding

Check the chat header — if you see "last seen recently" the bot service is up. If messages just sit unread, ping /help as a heartbeat. If still silent, the bot service may be restarting (Cloud Run revisions roll over in seconds; outages are rare).

Strava activities aren’t syncing

Run /sync manually first — pulls the last 7 days. If activities still don’t appear, your Strava authorisation may have expired. Re-link with /login. A daily backstop sync runs at 04:30 UTC for every active user as a safety net; webhook drops self-heal within 24h.

The plan looks wrong

Two common causes:

  1. Onboarding inputs were thin. Re-run /setup with more detail, or use /setplan directly with a rich prompt (see the prompt guide).
  2. Plan drifted from reality. If the bot keeps prescribing rides you already did, the plan JSON may have duplicate entries. Ask the bot directly in chat: "is my plan reading correctly for this week?"

Garmin link failed

The web form returns a specific error message — usually one of: wrong password, 2FA code expired, Garmin server temporarily unavailable. Tap "🔗 Link Garmin account" in Telegram for a fresh one-use link and retry. If the failure persists, Garmin may have rotated their auth flow — open a feedback message with /feedback and we’ll patch.

Workouts on Garmin watch don’t have pace targets

You may have an older upload from before the pace-target shape was fixed (May 2026). /garmincleanup the affected weeks and re-push with /garminpush <week>.

Voice notes aren’t being transcribed

Voice transcription is a Premium feature — free-tier athletes see a Premium upgrade prompt instead of a transcript. Voice notes over 4 minutes also aren’t supported (Whisper request limits).

The morning check-in fires at the wrong time

The bot uses your athlete-local timezone. Re-check it via /settings → check-in. If the timezone looks right but the time is still off, the bot may be running in UTC fallback because no timezone was set — re-run the relevant onboarding step.

How do I get more help?

Send /feedback <message> in the bot chat — it routes directly to the developer.