Exercise tracker for Claude Code. Setup, test, add exercises, tune detection. Launches pose-detection UI when Claude edits files.
Exercise tracker for Claude Code. Determine what the user needs based on context:
| User Intent | Action |
|---|---|
| First time / "setup" / "install" | β Setup Flow |
| "test" / "launch" / "run" | β Test Tracker |
| "add exercise" / "custom" / "new exercise" | β Add Exercise |
| "not counting" / "sensitivity" / "threshold" / "tune" | β Tune Detection |
| "pause" / "disable" / "stop" / "break" | β Pause/Resume |
| General question | β Overview |
Movement breaks while you code. When Claude edits files, vibereps launches a pose-detection exercise UI. Do a few squats or stretches while Claude works, then get notified when it's ready.
Supported exercises:
All pose detection happens locally via MediaPipe. No video data transmitted.
Use AskUserQuestion:
Question: "How would you like to set up vibereps?"
Header: "Install"
Options:
- "Run installer (Recommended)": "Downloads files, installs menubar app, configures hooks automatically"
- "Manual configuration": "I already have vibereps files, just configure my hooks"
If "Run installer":
curl -fsSL https://raw.githubusercontent.com/Flow-Club/vibereps/main/install.sh | bash
Then show summary and done.
If "Manual configuration": Continue below.
Question: "What type of exercises would you like?"
Header: "Mode"
Options:
- "Standing & Seated (Recommended)": "Full variety - squats, jumping jacks, plus desk-friendly neck stretches"
- "Standing only": "Active exercises - squats, jumping jacks, push-ups, calf raises"
- "Seated only": "Desk-friendly - shoulder shrugs, neck stretches"
Use AskUserQuestion with MultiSelect: true. Show exercises based on mode:
Standing: squats, jumping_jacks, calf_raises, standing_crunches, side_stretches, pushups, high_knees, torso_twists, arm_circles
Seated: shoulder_shrugs, neck_tilts, neck_rotations
if [[ -f "$HOME/.vibereps/vibereps.py" ]]; then
echo "$HOME/.vibereps"
else
echo "$(pwd)"
fi
Update ~/.claude/settings.json:
{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit|MultiEdit",
"hooks": [{
"type": "command",
"command": "VIBEREPS_EXERCISES={exercises} {vibereps_dir}/vibereps.py",
"async": true
}]
}],
"Notification": [{
"matcher": "idle_prompt|permission_prompt",
"hooks": [{
"type": "command",
"command": "{vibereps_dir}/vibereps.py",
"async": true
}]
}]
}
}
Replace {vibereps_dir} with full path (not ~) and {exercises} with comma-separated list.
Setup complete!
How it works:
1. Claude edits a file β Exercise tracker launches
2. Do a quick exercise while Claude works
3. Get notified when Claude is ready!
Launch in quick mode (exercises while Claude works):
pkill -f "vibereps.py" 2>/dev/null
~/.vibereps/vibereps.py user_prompt_submit '{}'
Launch in normal mode (after task complete):
pkill -f "vibereps.py" 2>/dev/null
~/.vibereps/vibereps.py task_complete '{}'
With specific exercises:
VIBEREPS_EXERCISES=squats,jumping_jacks ~/.vibereps/vibereps.py user_prompt_submit '{}'
Kill tracker:
pkill -f "vibereps.py"
Check if running:
lsof -i :8765
| Type | Use For | Example |
|---|---|---|
angle |
Joint angle changes | squats, pushups |
height_baseline |
Vertical movement from baseline | calf raises |
height_relative |
Position relative to reference | jumping jacks |
tilt |
Torso lean | side stretches |
distance |
Body parts approaching | standing crunches |
width_ratio |
Shoulder/hip width ratio | torso twists |
quadrant_tracking |
Circular motion | arm circles |
Create exercises/{exercise_name}.json:
{
"id": "squats",
"name": "Squats",
"description": "Strengthens legs",
"category": "strength",
"reps": { "normal": 10, "quick": 5 },
"detection": {
"type": "angle",
"landmarks": {
"joint": [23, 25, 27],
"joint_alt": [24, 26, 28]
},
"thresholds": { "down": 120, "up": 150 }
},
"instructions": {
"ready": "Squat down below {down}Β°",
"down": "Good! Now stand up"
}
}
~/.vibereps/vibereps.py user_prompt_submit '{}'
| Problem | Likely Cause | Fix |
|---|---|---|
| Not counting reps | Thresholds too strict | Lower down threshold or raise up threshold |
| Double counting | Thresholds too loose | Tighten thresholds, add hysteresis |
| Counts on wrong motion | Wrong landmarks | Check landmark IDs match exercise |
| Works for some people | Fixed thresholds | Use body-relative thresholds |
JSON configs (preferred): exercises/*.json β detection.thresholds
Legacy functions in exercise_ui.html:
detectLegacySquat, detectLegacyPushup, etc.~/.vibereps/vibereps.py user_prompt_submit '{}'For angle-based exercises, use joint_alt to average both sides:
"landmarks": {
"joint": [23, 25, 27],
"joint_alt": [24, 26, 28]
}
Temporarily disable vibereps until a specified time.
~/.vibereps/vibereps.py --pause
# ISO format timestamp
~/.vibereps/vibereps.py --pause "2026-01-30T18:00:00"
~/.vibereps/vibereps.py --resume
~/.vibereps/vibereps.py --status
If using the VibeReps menubar app, click the tray icon and select:
# Check pause status
curl http://localhost:8800/api/pause
# Pause until end of day
curl -X POST http://localhost:8800/api/pause
# Pause until specific time
curl -X POST http://localhost:8800/api/pause \
-H "Content-Type: application/json" \
-d '{"until": "2026-01-30T18:00:00"}'
# Resume
curl -X POST http://localhost:8800/api/resume