plugins/claude-code-fitness-hermit/skills/capture-activity-rpe/SKILL.md
Captures RPE (1-10) and subjective notes when the operator replies to a daily fitness-brief notification on any configured channel. Triggers on inbound channel messages matching RPE grammar while state/strava-pending-rpe.json has a sync from the last 24h. Channel-agnostic.
npx skillsauth add gtapps/claude-code-hermit capture-activity-rpeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Records the operator's perceived effort and subjective notes for the most recent synced activity.
Self-triggers on RPE-shaped replies while state/strava-pending-rpe.json is fresh. The skill's description is intentionally narrower than claude-code-hermit:channel-responder's so the harness picks it for these specific messages; any non-matching message exits silently and the normal channel-responder flow proceeds. Re-checks allowed_users itself.
Read .claude-code-hermit/state/strava-pending-rpe.json. If the file is absent: exit silently. If synced_at is more than 24 hours ago: run rm .claude-code-hermit/state/strava-pending-rpe.json and exit silently (reply window closed).
Authorization. Read .claude-code-hermit/config.json → channels.<channel>.allowed_users for the inbound channel (extract the channel name from the inbound message metadata):
allowed_users exists and the sender's platform user ID is not in it: exit silently. No response, no log, no state write.allowed_users is absent: accept (backwards-compatible).allowed_users is []: reject all — exit silently.Parse the inbound message body (case-insensitive, leading/trailing whitespace stripped):
^(?:RPE\s*:?\s*)?(\d{1,2})(?:\s*/\s*10)?(?:[\s,:]+(.+))?$
This matches: 7, 7/10, RPE 7, RPE: 7, RPE:7, 7 heavy legs, RPE 7, heavy legs, RPE: 7 heavy legs.
rpe (group 1) and notes (group 2). If group 2 is absent or an empty string after trim, treat notes as null.rpe is an integer from 1 to 10 inclusive.yes/no/y/n cannot match \d{1,2} so they are naturally excluded; the micro-approval branch in channel-responder handles them.)Persist the entry via the script (atomic upsert into state/activity-notes.json, keyed by <pending.activity_id>, overwriting silently):
bun ${CLAUDE_PLUGIN_ROOT}/scripts/fitness-lab.ts rpe <pending.activity_id> <rpe> [notes...]
Pass the parsed rpe; append the notes words only when group 2 matched (omit entirely when notes are null). The script writes {rpe, notes, recorded_at} — notes is always present, null when none were captured — and stamps recorded_at itself. No Strava call is made (the activity ID is supplied, not latest), so this never touches the network.
Run rm .claude-code-hermit/state/strava-pending-rpe.json so the same sync cannot bind twice.
Reply via the channel's reply tool with {chat_id, text}. allowed-tools only lists Discord (mcp__plugin_discord_discord__reply); on non-Discord channels this step will fail with a permission error, but the RPE is already persisted in step 4. Extend allowed-tools when adding Telegram or iMessage.
Got it — RPE <rpe>/10 saved for <pending.name>.
Refresh the deep-dive. If pending.sport is Run, re-invoke /claude-code-fitness-hermit:activity-deep-dive <pending.activity_id>. The fitness-brief evening run generated this activity's deep-dive before any RPE existed, so re-running now folds the RPE in — the skill reads state/activity-notes.json at its step 3b and overwrites compiled/activity-<id>-*.md. For non-Run sports the brief writes no deep-dive, so skip.
tools
Composes and delivers the daily fitness brief — a forward-looking morning read (readiness + today's plan) or a backward-looking evening read (today's training, or an earned-rest note, + tomorrow's setup) — in the operator's configured voice. Invoke with /claude-code-fitness-hermit:fitness-brief --morning|--evening|--slot <name>. Becomes the plugin's two daily beats — the morning Strava connectivity check and the evening activity sync, RPE binding, and Run deep-dive.
development
Renew the hermit's long-lived Claude login token over the channel, before it expires. Relays a one-time sign-in link to the operator, takes the code back, installs the new token, and restarts. Activates on messages like 'relogin', 'renew my login', 'reauth', 'the login is expiring', or when doctor's credential-expiry check flags setup-token.
development
Synthesizes the past 7 days of archived briefs into a weekly digest — top stories, emerging vs faded themes, category activity, and per-source performance built from archive frontmatter. Delivers to the operator's configured channel and archives a weekly note. Designed as a weekly routine. Invoke with /feed-hermit:weekly-digest.
development
Manage developing story arcs tracked across briefs — add, resolve, and list active arcs in compiled/story-arcs-*.md. Arc Watch keywords drive the feed-brief arc-tagging enrichment. Invoke with /feed-hermit:story-arcs add|resolve|list.