Skip to main content

Garmin Double Progression

Reads what you actually lifted from Garmin Connect and advances the targets in your Garmin workouts automatically, using double progression.

Train, run one command, sync your watch. Next session's numbers are already waiting on it.

$ repwise update

Activity: Workout B (1234567890)
Updating: Workout B -> workout 111111111

  # EXERCISE               ACTION  SETS     BEFORE      AFTER     CONFIG WHY
* 1 Barbell Deadlift       advance 3    10 x 60 kg  ->  6 x 65 kg        hit 10 on every set, top of the range
* 2 Dumbbell Lateral Raise advance 3     12 x 8 kg  ->  13 x 8 kg note   add 1 rep
  3 Sit-up                 hold    3       11 reps  ==  11 reps          missed target, 10 on the worst set

Dry run: 2 step(s) would change. Re-run with --apply.

Quick start

You need workouts already built in Garmin Connect, and Python 3.14 or newer.

pipx install repwise

repwise import -o workouts.yaml   # build a config from your Garmin workouts
repwise update                    # after a session: see what would change
repwise update --apply --push     # write it, and send it to your watch

The first command that reaches Garmin asks for your email, password and MFA code, then caches the tokens Garmin issues so later runs do not. Your password is never written anywhere. The token is - in settings.garmin.token_store (defaulting to ~/.config/repwise), readable only by you - and until it expires it is as good as being logged in. repwise logout deletes it. See authentication.

Nothing is written to Garmin without --apply. A dry run is the default.

For Tab completion, add source <(repwise completion bash) to ~/.bashrc, or source <(repwise completion zsh) to ~/.zshrc after compinit.

The full walkthrough is in Getting started.

What it does

It compares what you performed against the target stored in Garmin and picks the next one. Every workout in your config is advanced from its own latest session, so training A and then B and running once brings both up to date:

  1. Start at the bottom of the rep range.
  2. Add a rep to every set each session.
  3. Once every set reaches the top of the range twice, add weight and reset to the bottom.
  4. If you missed the target, repeat it unchanged.
  5. A load only counts once you can carry it for the bottom of the range.

Three things it handles that a spreadsheet would not:

  • It judges progress by your weakest set. Extra reps on the easy sets do not pull the target somewhere you cannot repeat.
  • It eases you back after a stall. Miss a target twice and the session that finally beats it earns a rep on two of your four sets rather than on all of them, so you are not asked again for the jump that just failed. Set partial_progression: false if you would rather every set moved together.
  • It follows the weight you actually used. Bump the load mid-session and the new load is banked, not discarded.
  • It won't keep a load you didn't earn. Take the 4 kg dumbbells because the 3 kg pair was gone, come up short of the range, and your target stays where it was rather than following you onto a weight that was too heavy.

Each exercise also gets a one-line note on its Garmin step, such as 6-10 reps | +5 kg, so the watch shows what you are working towards and not just today's target. Notes you wrote yourself are left alone.

Your config is the workout

workouts.yaml decides what a workout is; Garmin keeps track of where each exercise has got to. Edit the file and the next run brings Garmin into line:

  • Write a workout that does not exist yet. Leave garmin_workout_id out and it is built in Garmin, then the id is written back into your file.
  • Reorder the exercises. The order in the file is the order on the watch. Add one and it is added; delete one and it is deleted.
  • Set the rests and the sets. Including the rest between exercises, which Garmin leaves as a wait for the lap button until you ask for a time.

An exercise that moves keeps everything it had, target included, because the step itself is moved rather than rebuilt. That is the difference between reordering your workout and quietly restarting your progression.

Nothing reaches Garmin without --apply, and a dry run prints every addition, removal and move first.

It also covers timed holds like planks, exercises the watch counts per side, and keeping an exercise in sync when it appears in more than one workout. Progression explains every decision it can make.

Commands

Command What it does
repwise update Advance targets from the latest session, and bring every workout in line with the config. Dry run by default
repwise update --apply --push Write all of that to Garmin and send it to your watch
repwise list Show your Garmin workouts and their ids
repwise import Build a workouts.yaml from your Garmin workouts
repwise check Check that your config names exercises Garmin actually has, that it still names the ones your workouts hold, and that every rep range fits what its weight step is really worth
repwise fetch workouts Download raw workout JSON
repwise fetch activities Download the raw JSON of the sessions you performed: the summary, the sets your watch recorded, and the workout each was run against
repwise fetch exercises Refresh Garmin's list of every exercise it knows, which check and update read
repwise logout Delete the cached Garmin token, so the next run logs in again

Any command takes -v to show debug output as well. Full flags and output for each are in Commands.

Your routine

Your routine lives in workouts.yaml: the exercises, their order, rep ranges, set counts, rests, and which Garmin workout each belongs to. Generate it with repwise import, or copy workouts.example.yaml - a complete working A/B full body split, annotated field by field.

It is the source of truth rather than a copy of one: update writes what it says to Garmin, and the only thing ever written back into it is an id Garmin issues for a workout it has just created.

That file is gitignored, so your routine and Garmin ids stay out of version control. Every field is described in Configuration.

Documentation

For users:

Page Contents
Getting started Install to first update, step by step
Commands Every command, flag, output marker and exit code
Configuration The workouts.yaml reference, and finding your exercise identifiers
Progression How the next target is decided, with worked examples
Troubleshooting Login problems, skipped exercises, known limitations

For contributors:

Page Contents
Architecture Module layout, dependency and data-flow diagrams
Garmin's API The undocumented payloads and endpoints, and their traps
Contributing Dev setup, tests, where to make a change
Releasing Commit message format, and how the version is derived from it

Licence

MIT.

Metadata

Release files for repwise 3.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for repwise 3.5.0
File Size Uploaded Provenance Actions
repwise-3.5.0.tar.gz 228.7 kB With provenance Details for repwise-3.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for repwise 3.5.0
File Interpreter ABI Platform Actions
repwise-3.5.0-py3-none-any.whl Python 3 none any Details for repwise-3.5.0-py3-none-any.whl

Total release size: 367.0 kB

Release files / repwise-3.5.0.tar.gz

Download URL repwise-3.5.0.tar.gz
Size 228.7 kB
Tags Source
SHA-256 checksum
How to use checksums
eaa08257ea97271a0c319150d62c053bfe8f2dac5d8720ab55a5ff2752d296e2
BLAKE2b-256 checksum
How to use checksums
e28d707eb617562a63d1f1a4d8805d877f26f8ab52a096fd544a54b55031ff68
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Release files / repwise-3.5.0-py3-none-any.whl

Download URL repwise-3.5.0-py3-none-any.whl
Size 138.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b5b41434b8e0a31effbbea30ac0113ba358af7a44e9a09c556568ec7a940c635
BLAKE2b-256 checksum
How to use checksums
6d3560c55e4e3c4b1165b2c304a11f2234039dc0c8ebc5bfd08b5a3965cab613
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Security for repwise 3.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for repwise-3.5.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page