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 |
/api/export/pdf |
GET |
PDF download |
/api/settings |
GET |
Settings |
/api/settings |
PATCH |
Update settings |
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