My Garmin watch is diligent about strength training in exactly one way: it knows when I lifted. It records my heart rate for the whole session and it can even feel each set start and stop — a burst of work, a rest, another burst. What it cannot tell you is what any of those bursts were. Open a strength activity in Garmin Connect and you get a tidy list of sets, every one of them labelled "Unknown", with no reps and no weight.

Meanwhile the app I actually log my lifts in — Strong — knows precisely what I did, set by set, and has no way to put that on my Garmin. It exports to Apple Health, but Apple Health has no data model for "barbell bench press, 8 reps, 75 kg", so all that survives the trip is duration and a calorie estimate. The set data evaporates.

So I have two systems each holding half of the same workout, and a stubborn refusal between them. This is the kind of gap that nags at me until I close it.

The obvious approaches are all slightly wrong

The first instinct is to build a file and upload it. Garmin accepts FIT files, and the FIT format genuinely supports strength sets — exercise category, reps, weight, the lot. So: take Strong's export, write a FIT, upload it.

Except an upload creates a new activity. Now I have two: the one my watch recorded, with the heart rate, and a second one with the sets and no heart rate, sitting next to it with the same start time. Garmin often rejects the second as a duplicate; when it doesn't, you've got a mess. The thing I want to enrich is the activity that already exists.

The next idea is to merge: download the original FIT, splice the Strong sets into it, re-upload, delete the original. I actually built this. It works. But it's fragile in the way that "delete the real thing and replace it with one you generated" is always fragile — and Strong doesn't record a wall-clock time per set, so aligning its sets onto the watch's timeline is guesswork.

I was most of the way down that road when I went looking at what Garmin Connect's own web interface does. Because you can edit sets there, by hand, in the browser. Which means there's an endpoint.

Edit it in place

There is: setActivityExerciseSets. You GET an activity's sets, change the array, PUT it back. It's the API behind the "edit sets" button, and it does exactly what I want — it edits the activity that already exists. The heart rate, the GPS, the timing, the activity's whole identity: untouched. I'm only rewriting the one thing the watch left blank.

This reframes the entire problem. I'm not building files or merging timelines or deleting anything. I'm filling in blanks. The watch already detected the set structure — the bursts and rests, with real timestamps — and I just drop Strong's exercise, reps and weight into the slots it found. When the watch didn't break the session into sets (sometimes it just logs one long block), I synthesise the sets from Strong instead. Either way: one activity, enriched, reversible.

A few things had to be reverse-engineered to make it real, and each had a small trap:

The bit I'm happiest with

The actual day-to-day interface is a little terminal UI. Two panes — my Strong workouts on the left, my Garmin strength activities on the right. Move the cursor to a workout and it auto-highlights the closest activity by start time and shows the gap (usually a minute or two). Hit m and it enriches it. Anything already done is green with a tick, so I can see at a glance what's synced and what isn't. Every write backs up the original first, so u puts it back.

It's a deeply unglamorous tool that does one thing, and now my lifts show up on my Garmin the way runs always have — heart rate and the actual sets, in one place, with no duplicate activity polluting the history.

The code is on GitHub: strong-garmin-sync. Usual disclaimers apply — it leans on a private Strong API and an unofficial Garmin Connect client, it's for getting at your own data, and it could break the moment either side changes anything. It's not affiliated with Strong or Garmin. But it scratches the itch, and the itch is gone.