| name | exercise-log |
| description | Log workouts with exercises, sets, reps, and weights. Automatically tracks personal records, monitors workout streaks, manages training goals, and exports data as CSV or PDF. Use when a user needs to log a workout, check personal records, review weekly volume, or track goal progress. |
exercise-log
Local-first workout tracker with automatic PR detection and progress analysis.
When to use
- User wants to log a workout session
- User needs to check or review personal records
- User wants to track progress on a specific exercise
- User is setting or reviewing training goals
- User wants to see weekly training volume or streak
- User needs to export workout history
Privacy model
All data stored locally in SQLite at ./data/exercise.db. No external transmission. Workout values never appear in log output.
Prerequisites
- exercise-log running:
pnpm dev or docker compose up -d
- Server at
http://localhost:3851
Key API operations
Create a workout
curl -X POST http://localhost:3851/api/workouts \
-H "Content-Type: application/json" \
-d '{"title": "Upper Body", "workout_date": "2026-03-20", "duration_mins": 52}'
Add a set
curl -X POST http://localhost:3851/api/workouts/1/sets \
-H "Content-Type: application/json" \
-d '{"exercise_id": 1, "set_number": 1, "reps": 8, "weight_kg": 80.0}'
Response includes is_pr: true if a personal record was broken.
Get all personal records
curl http://localhost:3851/api/records
Get current streak
curl http://localhost:3851/api/stats/streak
Get weekly stats
curl "http://localhost:3851/api/stats/weekly?weeks=8"
Get per-exercise progress
curl http://localhost:3851/api/stats/exercise/1
Download CSV
curl -o workouts.csv http://localhost:3851/api/export/csv
API Reference
| Endpoint | Method | Description |
|---|
/api/exercise-types | GET | List exercise types |
/api/exercise-types | POST | Create exercise type |
/api/exercise-types/:id | PUT | Update |
/api/exercise-types/:id | DELETE | Delete |
/api/workouts | GET | List workouts |
/api/workouts | POST | Create workout |
/api/workouts/:id | GET | Detail with sets |
/api/workouts/:id | PUT | Update |
/api/workouts/:id | DELETE | Delete with cascade |
/api/workouts/:id/sets | POST | Add set (returns is_pr) |
/api/sets/:id | PUT | Update set |
/api/sets/:id | DELETE | Delete set |
/api/records | GET | All personal records |
/api/records/:exerciseId | GET | Per-exercise records |
/api/goals | GET | List goals |
/api/goals | POST | Create goal |
/api/goals/:id | PATCH | Update goal |
/api/stats/weekly | GET | Weekly volume (param: weeks) |
/api/stats/streak | GET | Current and best streak |
/api/stats/exercise/:id | GET | Per-exercise progress |
/api/export/csv | GET | CSV download |
|
Exercise metric types
| metric | Fields logged |
|---|
weight_reps | reps + weight_kg |
distance_time | distance_km + duration_secs |
time_only | duration_secs |
reps_only | reps |
Personal record types
| record_type | Applies to |
|---|
max_weight | weight_reps exercises |
max_reps | weight_reps and reps_only |
max_distance | distance_time exercises |
fastest_time | cardio (time for a given distance) |
longest_time | time_only exercises |
Environment Variables
| Variable | Default | Description |
|---|
PORT | 3851 | Server port |
DATA_DIR | ./data | SQLite location |
EXPORT_DIR | ./exports | CSV/PDF output |
LOG_LEVEL | info | debug / info / warn / error |
NODE_ENV | development | development / production |
Troubleshooting
PR not detected after logging a set
- Verify the exercise_id is correct and the exercise exists
- Check that the metric type matches the fields submitted (e.g. weight_reps requires reps and weight_kg both non-null)
- A PR is only recorded if the new value strictly exceeds the existing record (equal value does not count)
Streak showing 0 despite recent workouts
- Verify workout_date is stored as YYYY-MM-DD format
- Streak is calculated based on calendar days with at least one workout - check there are no gaps