Search...Search plugins and themes...
⌘K
Sign in
  • Get started
  • Download
  • Pricing
  • Enterprise
  • Account
  • Obsidian
  • Overview
  • Sync
  • Publish
  • Canvas
  • Mobile
  • Web Clipper
  • CLI
  • Learn
  • Help
  • Developers
  • Changelog
  • About
  • Roadmap
  • Blog
  • Resources
  • System status
  • License overview
  • Terms of service
  • Privacy policy
  • Security
  • Community
  • Plugins
  • Themes
  • Discord
  • Forum / 中文论坛
  • Merch store
  • Brand guidelines
Follow us
DiscordTwitterBlueskyThreadsMastodonYouTubeGitHub
© 2026 Obsidian

Workout Planner

spatariuraresspatariurares3k downloads

Track workouts in your notes: log sets, follow a guided session, and see progress with tables, charts, timers and a dashboard with PRs, trends and a muscle heat map. Data stays in one CSV file.

Add to Obsidian
  • Overview
  • Scorecard
  • Updates15
Workout Planner logo

Workout Planner

English · العربية · Čeština · Dansk · Deutsch · Español · Français · हिन्दी · Bahasa Indonesia · Italiano · 日本語 · 한국어 · Nederlands · Norsk bokmål · Polski · Português (Brasil) · Português (Portugal) · Română · Русский · Shqip · Türkçe · Українська · 简体中文 · 繁體中文

The all-in-one workout tracker for Obsidian. Lifting, running, cycling, yoga or exercises with your own fields: log from your phone, follow a guided session, and see your progress in charts, a dashboard and a muscle heat map. One CSV, 24 languages.

Built for your phone: log each set, run or pose as you train, then watch your progress in tables, charts and a dashboard inside the same notes where you plan your training. Your sets go into one CSV file in your vault. No account, no cloud.

Charts show your trend, the muscle heat map shows what you trained, and each set keeps its own kg/lb unit. You can query your sets from Dataview.

Workout Planner on a phone: a workout-sets card with two sets ticked and the rest timer running, the log form with +/− buttons and kg/lb picker, and the dashboard summary with the training calendar

Features

  • Log sets with reps and weight, pre-filled from your last set, with +/− buttons and one-tap recent exercises
  • Log each set in kg or lb, whatever the plates in front of you say
  • Tag sets with a protocol: drop set, myo-reps, rest-pause, superset, 21s, or your own
  • Tables of your sets, grouped by day with daily totals, editable with one tap
  • Today's sets as rows to fill in on your phone: tick a set to log it, and the rest timer starts
  • Charts for weight, volume, reps, duration, distance, pace and heart rate, and a trend that tells you plainly if you're improving
  • A dashboard with weekly streak (with a weekly goal), a training calendar, personal records, total volume, recent workouts and protocol stats
  • A muscle heat map, front and back, by volume, sets or reps
  • Rest timers (countdown, interval, stopwatch) with presets, that restart when you log a set and beep on iOS and Android
  • A guided session that walks through the workout note one exercise at a time
  • An estimate of how long a planned workout takes
  • Strength, bodyweight, timed, distance and cardio exercises, or your own fields
  • Every set in one plain CSV file, readable from Dataview and Templater
  • Built for phones: no sideways scrolling, buttons always in reach
  • Available in 24 languages

Getting started

The first time you install the plugin, it adds example notes (sample exercises, two workouts with six weeks of logs, a dashboard and a feature showcase), points the plugin at them and opens the Getting started guide: one short page per feature, with working examples you can try. You don't need to open settings. Poke around before setting up your own.

Want the examples or the guide again? Select Open getting started guide under Settings → Workout Planner → Getting started (it adds the example notes that are missing first), or run Create example notes or Open getting started guide from the command palette (Ctrl/Cmd + P). Creating the examples never overwrites anything: running it again only adds the example files that are missing, and files you changed stay as they are. The guide offers to create the examples if they don't exist yet. An empty table, chart or dashboard also has an Or explore with example data link. If you already have a workout log, the examples get their own log file and yours stays untouched.

To add a table to any note, for example Push Day:

```workout-log
exercise: Bench Press
```

Tap + under the table, enter reps and weight, and save. The table updates on its own. You don't have to write blocks by hand either: the Insert workout chart / table / sets / timer / dashboard / duration and Insert guided session commands open a form (or write the block) for you.

Logging sets

Open the log form with the + under a table (the exercise is filled in for you), the dumbbell icon in the ribbon, or the Create workout log command. The form starts from your last set, so most of the time you tap +/− once and save. Done before your rest is over.

The form asks for the fields that fit the exercise: reps and weight for a squat, seconds for a plank, distance and time for a run (see Exercise types). Each set can also carry a note and a protocol, shown as a badge in the table.

The weight field has a kg/lb picker, so you can log 225 lb even if your setting is kg. The table shows that set as "225 lb"; charts, stats and volume convert every set to your setting.

When you log a set from a note, the note's name is saved as the set's workout, so a table or chart with workout: Push Day finds it later.

Tables

A workout-log block shows the sets of an exercise or workout, newest first. Sets from the same day are grouped under a row with that day's totals, and each row has an edit button; delete a set from the edit form. On a phone each set becomes a compact row with no sideways scrolling.

A workout-log table on a phone, sets grouped by day with their time and a drop-set badge, and the log form its + button opens
exercise: Bench Press
dateRange: 14
targetWeight: 100
targetReps: 8

With targetWeight and targetReps, a progressive-overload target appears above the table.

All parameters
Parameter Default What it does
exercise — Only this exercise
workout — Only this workout (note name)
exactMatch false Match the exercise name exactly
dateRange all Today and the previous N days
limit 50 Maximum rows; with sets, sets × 2 (two workouts)
sortBy date date, exercise, weight, reps or volume
sortOrder desc asc or desc
columns all Columns to show, e.g. ["date", "reps", "weight"]
showProtocol true Show the protocol badge column
showAddButton true Show the + button
targetWeight, targetReps — Show a progressive-overload target above the table
sets — Sets planned, counted by a workout-session block

Exercise names match loosely by default ("squat" finds "Squat (high bar)"); add exactMatch: true for only that exact name.

Sets on your phone

A workout-sets block is made for logging at the gym: today's sets of one exercise as rows to fill in. Each row shows what you did in the same set last time, so you type only what changed (an empty field logs that value) and tick the row. The set goes into the log, the row turns into a logged set, and the rest timer at the top starts on its own. A logged set's chevron changes its protocol and notes; ticking it again takes it back, with Undo for a few seconds.

A workout-sets card on a phone: four rows filled in with last time's values, then two sets ticked with the rest timer running, then a row opened to pick the rest-pause protocol and add a note
exercise: Squat
sets: 4
rest: 120

Insert workout sets from the command palette writes one for you, and the ⋮ menu edits it or its rest timer.

All parameters
Parameter Default What it does
exercise — The exercise (exact name)
workout the note name The workout the sets are logged under
sets as last time Rows to fill in (at least one); Add set adds more
targetWeight, targetReps — Hints when the exercise was never done, and a progressive-overload target
rest — Seconds of rest after each set; 0 for no timer. Unset: the workout-timer of the same section
timer.* — The rest timer's other options: timer.type, timer.preset, timer.rest, timer.rounds, timer.showControls, timer.sound

Charts and trends

A workout-chart block draws one measure over time: weight, volume, reps, estimated 1RM, duration, distance, pace or heart rate. The header says whether the trend is Increasing, Stable or Decreasing. Stable means the trend line moves less than 5% of the average over the whole period, so a slow, steady gain still counts as increasing. For pace, lower is better, and a falling line shows as improving. On a phone the chart becomes a table of the same values.

Use type: e1rm for the best daily estimated one-rep max (Epley: weight × (1 + reps / 30)). Only positive weights with integer reps from 1 to 12 count; warm-up and drop sets are excluded. Days without eligible sets are omitted. Estimates follow your kg/lb setting. The default strength chart remains volume.

exercise: Bench Press
type: e1rm
dateRange: 180

The API adds estimatedOneRepMax to getExerciseStats: the best estimate in the configured weight unit, or null when no eligible set exists. Existing PR fields and CSV columns are unchanged.

A bench press estimated 1RM chart with its increasing trend line on desktop, and the same values as a table on a phone

exercise: Squat
type: volume
dateRange: 90
showTrendLine: true
All parameters
Parameter Default What it does
exercise — Only this exercise
workout — Only this workout
type volume volume, weight, reps, e1rm, duration, distance, pace or heartRate
chartType exercise How each day's point is built (below)
dateRange 30 Days to include
limit — Only the latest N points
showTrendLine false Draw a trend line
showTrend true Show the trend header above the chart
showStats true Show average, best and lowest under the chart
title Trend <type> Chart title
height 4:3 300 (pixels) or any CSS length such as 50vh
exactMatch false Match the exercise name exactly
chartType Sets used Each day's point
exercise sets of exercise average
workout sets of workout total
combined sets of exercise within workout total
all every set (filters ignored) total

Dashboard and muscle heat map

A workout-dashboard block opens with four numbers: total workouts, weekly streak, total volume and personal records. Below them you get quick stats for the week, month and year, a volume trend, your recent workouts, protocol stats, planned vs. actual workout length and a training calendar: a year of training days, shaded by volume, with your current and best streak. A week counts towards the streak once it has the training days of your weekly goal (Settings → Weekly goal, 1 by default). On a phone, quick actions come first and the summary is a 2 × 2 grid.

The dashboard on a phone: summary, training calendar with this week's goal met, recent workouts and quick stats
title: Last three months
dateRange: 90
widgets: [summary, heatMap, volume, recentWorkouts]

To choose the widgets and their order without writing YAML, insert the dashboard with the Insert workout dashboard command, or open the ⋮ menu at the top right of an inserted dashboard and pick Edit dashboard.

Set Layout to Grid in that window to place each widget yourself, like items in an inventory: drag a widget to move it, drag its corner to make it wider or taller, and drop it under the grid to take it off. The keyboard works too: arrows move, Shift and arrows resize, Delete takes a widget off. The grid has as many columns as fit the width of your note; in a narrower pane the widgets are packed again in reading order, and on a phone they are stacked. Your layout is kept: when the note fits only one column (a phone), the window asks how many columns to edit, starting from the saved ones. The block keeps one line per widget (column, row, width, height):

layout: grid
columns: 3
grid.summary: 1 1 3 1
grid.heatMap: 1 2 2 2
grid.recentWorkouts: 3 2 1 1

The heat map shows which muscles you trained over the last week, month or year, front and back, by Volume, Sets or Reps. It's the quickest way to notice you've skipped legs for three weeks. Under it, a short training analysis warns you about imbalances, like a front that works much more than the back. It reads the muscle tags of your exercise pages. Bodyweight and timed exercises have no weight, so they light up only under Sets and Reps.

Muscle heat map for the week on a phone, front and back: quads, glutes and hamstrings trained, with the training analysis below
All parameters
Parameter Default What it does
title — Heading above the dashboard
dateRange all Only sets from the last N days
widgets all The widgets to show, in this order: summary, quickStats, heatMap, volume, recentWorkouts, protocolDistribution, protocolEffectiveness, duration, quickActions, fileErrors, muscleTags, trainingCalendar
layout list grid places each widget in its cells (see above)
columns — Grid: the columns the grid was made for
grid.<widget> — Grid: column, row, width and height of that widget
recentWorkoutsLimit 5 Workouts in the recent list
volumeTrendDays 30 Days in the volume trend chart
Muscle tags

Tags can be a list, a single word (tags: chest) or a comma-separated line (tags: chest, triceps).

Broad groups: chest, back, shoulders, biceps, triceps, forearms, traps, quads, hamstrings, glutes, calves, abs, core

Specific muscles have their own area of the body and count toward their group. A broad tag spreads over the whole area: chest lights all three parts of the chest a little, upper_chest lights only the top one fully.

Group Specific muscles
chest upper_chest, mid_chest, lower_chest
shoulders front_delts, side_delts, rear_delts
back lats, rhomboids, lower_back (or ql)
core obliques, serratus

Tags in your own language, like petto or schiena, work too. The plugin maps them to the groups above using muscle-tags.csv, next to your log. Edit it with Manage muscle tags (add, rename, search, spot duplicates) or by hand:

tag,muscleGroup,language
petto,chest,it
dorsali,lats,it

A tag that is already a group name (upper_chest, Upper chest, upper-chest) always works, even if muscle-tags.csv doesn't list it.

Timers

A workout-timer block is a countdown, interval or stopwatch timer. Save your usual rest times as presets. Link a timer to an exercise or workout and it restarts every time you log a set, so you don't have to touch it between sets. With autoStart: true it starts as soon as the note opens.

Two timers on a phone: an interval timer in its rest phase and a Tabata preset in the work phase of round 2

It beeps on iOS and Android too. Phones only allow sound after you've tapped the page, so a timer started by autoStart stays silent until you tap Start once.

Under Settings → Workout Planner → Timer device cues, Keep screen awake while a timer runs is on by default. It requests screen protection while at least one timer runs in the foreground, where the device allows it. Vibrate when a timer completes is off by default and adds a brief pulse at zero, independently of sound, on supported devices such as Android. iOS keeps the existing audio cue; web vibration is unavailable there. These features use browser APIs on a best-effort basis and have not yet been verified on physical Android/iOS devices. They do not provide background alarms. A timer with an id keeps running when you change notes; pause it or let it finish to release screen protection.

type: countdown
duration: 90
exercise: Bench Press

An interval timer can alternate work and rest. The display shows Work or Rest, and each phase starts with its own sound. Each round is its work followed by its rest, the last one included, so this Tabata runs 4:00:

type: interval
work: 20
rest: 10
rounds: 8

preset: Tabata (20 s work, 10 s rest, 8 rounds) and preset: EMOM (a round every minute for 10 minutes) are built in. A saved preset with the same name replaces them.

All parameters
Parameter Default What it does
type countdown countdown, interval or stopwatch
duration 30 Seconds (countdown; for interval the work of each round)
work — Interval: seconds of work per round (replaces duration)
rest 0 Interval: seconds of rest after each round's work
rounds 1 Rounds (interval)
sound true Beep when time is up
autoStart false Start as soon as the note opens
showControls true Show start, pause and reset
preset — Start from a preset (saved, Tabata or EMOM); parameters override it
exercise, workout — Restart the timer when you log a set for this exercise or workout
superset false Canvas export only: draw this exercise and the next one as a superset

Guided session

A workout-session block at the top of a workout note (command Insert guided session) walks you through it one exercise at a time: which set you're on, the target, what you did last time, a Log set button and the rest timer, which starts when you log a set.

A guided session on a phone: set 3 of 4 of the squat with the rest running on both the session and the sets card, the log form opened by Log set, then the next exercise with its rest timer running

```workout-session

```

## Squat

```workout-sets
exercise: Squat
sets: 4
targetReps: 8
targetWeight: 100
rest: 180
```

The plan is the note itself: each workout-log or workout-sets block with an exercise is a step, in the order they appear, with its sets, targetReps and targetWeight. The rest comes from the workout-sets block's own rest, else from the workout-timer in the same ## section (the default preset without one). The session and the sets card share one countdown. The session counts the sets you logged today in this workout, so it picks up where you left off when you reopen the note. An exercise without sets stays current until you log a set of a later one; Previous and Next move freely.

Workout duration

A workout-duration block estimates how long a workout note takes: the rest from its timers plus the time for each set, next to how long your last session really took.

Estimated duration card with rest time, set time and the last session
workout: Workouts/Push Day.md

workout can be a path in the vault, a path relative to this note, or just the note's name; leave it out to estimate the current note. Seconds per rep and per set come from Settings.

Exercise types

An exercise page is a note in your exercise folder. Its frontmatter says what the log form should ask for and which muscles the exercise trains. Create exercise page makes one for you.

---
exercise_type: strength
tags:
  - chest
  - triceps
---
exercise_type The log form asks for Also accepted
strength (default) reps, weight bodyweight, weights
timed duration duration, time, timer, interval, hold, isometric
distance distance, duration (optional) running, run
cardio duration, distance and heart rate (optional) —
custom only the fields you list under parameters —

Yoga works the same way: each pose is a timed exercise, so the form asks only how long you held it. The example notes include a morning yoga flow with a guided session.

A yoga flow on a phone: the guided session on Downward Dog, the log form asking only for the hold's duration, and the sets card with the first hold logged

For a sport that logs something else (a climbing grade, attempts, whether you sent it), make your own type in Settings → Exercise types: give it a name and pick its fields, built-in ones like reps and weight or new ones (number, text or yes/no). It then shows up in the type list when you create an exercise, which writes exercise_type: <your type> in the page. The built-in types can't be changed, but Duplicate starts a type from one. Deleting a type only stops offering it: exercises that use it keep their fields and logged sets.

type: works the same as exercise_type:. You can also add fields to one exercise under parameters, for example rounds for jump rope:

---
exercise_type: timed
parameters:
  - key: rounds
    label: Rounds
    type: number
    required: false
---

If you change an exercise's type after logging it, Convert exercise moves the existing sets over and lets you choose which old field goes where.

Your data

Every set is one row in workout_logs.csv, so you can open it in a spreadsheet, back it up, or sync it like any other file.

date,exercise,reps,weight,volume,origine,workout,timestamp,notes,protocol
2025-01-17T10:30:00.000Z,Bench Press,8,100,800,[[Push Day]],Push Day,1737138600000,,standard
Columns and editing by hand
Column Meaning
date When the set was logged (ISO 8601)
exercise, workout Exercise and workout name
reps, weight, volume Volume is reps × weight
origine Link to the note it was logged from
timestamp Unique ID of the row (milliseconds)
notes, protocol Free text and training technique

Exercise types with their own fields (duration, distance, heartRate, or your parameters) add columns at the end. The last column, weightUnit, is kg or lb: the unit of that row's weight and volume. An empty value means the unit in the settings.

If you edit the file by hand, keep the header row, and wrap any value that contains a comma, quote or line break in double quotes. Notes starting with =, +, - or @ are stored with a leading ' so spreadsheets don't run them as formulas; the plugin hides it again.

Everything stays in your vault. The plugin writes to the clipboard only when you click a copy badge (a muscle tag in the dashboard), and never reads it.

Dataview and Templater

The plugin exposes WorkoutPlannerAPI (also window.WorkoutPlannerAPI) once it has loaded.

const s = await WorkoutPlannerAPI.getExerciseStats("Bench Press");
dv.paragraph(`Best: ${s.prWeight} × ${s.prReps} on ${s.prDate}`);
API reference and more examples
Method Returns
getWorkoutLogs(filter?) Sets, each with date, exercise, reps, weight, volume, workout, notes, timestamp, protocol. weight and volume are in the settings unit; enteredWeight and enteredUnit are what was logged
getExerciseStats(exercise) estimatedOneRepMax, totalVolume, maxWeight, prWeight, prReps, prDate, totalSets, averageWeight, averageReps, lastWorkoutDate, trend
getExercises(filter?) Exercise names, sorted: the file names of your exercise pages (subfolders included), or the names in your log when you have no exercise pages. { tag: "chest" } keeps the exercises whose page has that tag, so it is empty without exercise pages.

getWorkoutLogs accepts exercise (partial, case-insensitive), workout, dateRange: { start, end }, protocol and exactMatch.

Recent squats, in Dataview:

const logs = await WorkoutPlannerAPI.getWorkoutLogs({
  exercise: "Squat",
  dateRange: { start: moment().subtract(30, "days").format("YYYY-MM-DD") },
});
dv.table(
  ["Date", "Reps", "Weight"],
  logs.map((l) => [l.date.slice(0, 10), l.reps, l.weight]),
);

In a Templater template, to start a note with your latest numbers:

## Squat

<%\*
const s = await WorkoutPlannerAPI.getExerciseStats("Squat");
tR += s.totalSets
? `Best ${s.prWeight} × ${s.prReps} (${s.prDate}), last session ${s.lastWorkoutDate}`
: "No squats logged yet";
%>

Settings

Set the CSV and exercise folders, the default weight unit, the weight step of the +/− buttons, timer presets, your own protocols (name, short label and color), and the seconds per rep and per set used by the duration estimate. Run all under Advanced runs every maintenance task after an upgrade.

Changing the weight unit doesn't relabel old sets: each set keeps the unit it was logged in.

All commands

Open the command palette (Ctrl/Cmd + P) and type the name.

Command What it does
Create workout log Log a set
Create example notes Add sample exercises, workouts, logs and a dashboard
Open getting started guide, Start the tour Open the guide in the examples
Show what's new Show what changed in each version
Insert workout chart / table / sets / timer / dashboard / duration Insert a block through a form
Insert guided session Insert a workout-session block at the cursor
Create exercise page New exercise page with type and tags
Add exercise block Add a section for an exercise with its sets block, with name autocomplete
Convert exercise Move an exercise's sets to another exercise type
Manage muscle tags Edit muscle-tags.csv
Generate tag reference Create a note listing every muscle tag
Audit exercise names Find the same exercise logged under different spellings
Export workout to canvas Lay out the current workout on an Obsidian canvas
Create CSV log file Create an empty log
Import from Strong or Hevy Add the sets of a Strong or Hevy CSV export to the log
Migrate exercise types, Add missing IDs to code blocks Maintenance after upgrading from older versions

Troubleshooting

  • Conflict with Workout Block (workout-block). Both plugins register workout-log code blocks and use workout_logs.csv as the default log file name. Disable one of the two plugins before using the other.

  • A table or chart is empty. Check the exercise name and the dateRange (charts default to the last 30 days). With exactMatch: true the name must match exactly.

  • An exercise is missing from the heat map. Its page needs muscle tags and must be in the exercise folder. Bodyweight and timed exercises show up only under Sets or Reps.

  • The log form asks for reps and weight for a plank. Set exercise_type: timed in the exercise page.

  • The timer makes no sound on my phone. Tap Start once; phones block sound until you touch the page.

Installation

From community plugins

  1. Open Settings → Community plugins
  2. Search for Workout Planner
  3. Select Install, then Enable

Manual

  1. Download main.js, manifest.json and styles.css from the latest release
  2. Create the folder your-vault/.obsidian/plugins/workout-planner/
  3. Copy the downloaded files into that folder
  4. Enable the plugin in Settings → Community plugins

Support

Workout Planner is free and open source. If it helps your training, you can buy me a coffee. Found a bug or missing something? Open an issue.

Every language except English is machine-translated, so some phrases may sound off. If yours reads strangely, corrections are welcome.

Credits

Charts use Chart.js (MIT). Workout Planner is released under the MIT License.

HealthExcellent
ReviewSatisfactory
About
Track any workout from your phone, from lifting and running to yoga: follow a guided session and see your progress in your notes with tables, charts, timers and a dashboard with PRs, trends and a muscle heat map. All in one CSV file.
ChartsTablesCSV
Details
Current version
3.3.2
Last updated
6 days ago
Created
Last year
Updates
15 releases
Downloads
3k
Compatible with
Obsidian 1.6.6+
Platforms
Desktop, Mobile
License
0BSD
Report bugRequest featureReport plugin
Sponsor
Buy Me a Coffee
Author
spatariuraresspatariurares
github.com/SpatariuRares
GitHubspatariurares
  1. Community
  2. Plugins
  3. Charts
  4. Workout Planner

Related plugins

Advanced Tables

Improved table navigation, formatting, and manipulation.

CSV Table

Render CSV data as a table within your notes.

Notion Bases

Turn any folder into a database — table, kanban board, gallery, calendar, timeline and list views powered by frontmatter.

Charts

Easily create interactive charts in your notes.

Sheet Plus

Create Excel-like spreadsheets and easily embed them in Markdown.

CSV Lite

Just open and edit a CSV file in workspace view, no more. Keep it simple.

Charts View

Visualize data from your notes with plots and graphs.

DataLoom

Weave together data from diverse sources into different views. Inspired by Excel Spreadsheets and Notion.so.

Tablite

A fast CSV/TSV editor with virtual scrolling, inline editing, column filtering, and auto encoding detection.

Macros

Nutrition and food tracker for your notes. Log meals, calories, macros and micronutrients. Search foods by name or barcode via FatSecret, USDA & Open Food Facts. Chart your diet & weight loss.