The line
Everything before the first comma is the exercise name; everything after it describes the work. Names can contain apostrophes, ampersands, hyphens, parentheses, and digits — Farmer's Carry, Clean & Jerk, Squat (Paused), 21s Curl — because only the comma ends the name.
Push Up, 20 Bench Press, 5x[12,10,8,6,4] @[95,110,125,140,155]lb @8rpe tempo 30X1 //3:00
The parts of a line come in a fixed order: volume, then @ intensities, then tempo, then the rest interval. A line like Squat, 3x5 rest 2:00 tempo 30X1 won't parse — tempo belongs before the interval.
A few lowercase unit words (kg, lb, rm, rpe, rir) can't appear as standalone words in a name — capitalize them (KB Swing, KG Swing) and they're fine. Periods, slashes, and plus signs aren't name characters.
Sets & reps
| You write | It means |
|---|---|
| 20 | one set of 20 reps |
| 3x10 | 3 sets of 10 reps |
| 3x8-12 | 3 sets of 8–12 reps |
| 3xAMAP | 3 sets of as many reps as possible |
| 3X5 | x is case-insensitive |
Sets default to 1 when omitted. The x hugs its numbers — 3 x 5 with spaces won't parse. Rep counts must be whole numbers but may be zero — 3x0 records a round you got none of, while 3x2.5 is rejected. Set counts must be positive; 0x5 is rejected. AMAP ("as many as possible") is the max-effort rep count — note that in volume position it's AMAP, not AMRAP (that's a section header — see below).
Rep lists & rest-pause
A bracket list after x gives each set its own rep count. Inside a list, 8+4 is rest-pause: 8 reps, a few breaths, then 4 more to finish the set.
Bench Press, 5x[12,10,8,6,4] Leg Press, 3x[12,12,8+4]
Lists work in most value positions — reps, loads, efforts, rests, even distances with the unit outside the bracket: Row, [500,400,300]m.
Time, distance & calories
| You write | It means |
|---|---|
| Row, 500m | distance: m, km, mi, yd, ft |
| Plank, 0:30 | duration in minutes:seconds |
| Plank, 3x90s | seconds, minutes (min), hours (h) |
| Bike, 3x15cal | calories |
| Row, 3x250m in 1:00 | each 250m raced against 1:00 |
| Run, 2mi in 14:00 | a time cap on the whole distance |
Volume isn't limited to reps — any distance, duration, or calorie count works, with or without a set count. in attaches a time budget to the work itself (the space after in is required). Durations accept tenths: 1:55.7.
Unilateral work
Split Squat, 3x10/side Lunge, 3x10/leg DB Press, 3x10/arm
A per-side marker means "per side" — exactly one of /side, /leg, or /arm, directly after the volume.
Load
| You write | It means |
|---|---|
| @185lb | pounds — @185 bare also means lb |
| @62.5kg | kilograms (also g, and pd for pood) |
| @bw | bodyweight |
| @1.5bw | 1.5× bodyweight |
| @50%bw | half bodyweight |
| @135-155lb | a load range |
| @[95,110,125,140,155]lb | per-set loads |
| @[35lb,16kg,53lb] | lists can mix units |
| @24inch | any word works as an equipment unit |
| @2orange | colors are units too (bands, plates) |
@ attaches the load. Unit keywords are lowercase — @100LB parses, but the parser treats "LB" as a custom equipment unit rather than pounds. Distance and duration targets can be intensities as well: Run, 4x400m @800m or Row, 3x250m @0:45.
Effort — RPE, RIR & rep max
| You write | It means |
|---|---|
| @8rpe | rate of perceived exertion, 1–10 (8.5 works) |
| @8-9rpe | an RPE range |
| @2rir | two reps in reserve |
| @3rm | your 3-rep max |
| @80%1rm | 80% of your 1-rep max |
| @90%5RM | 90% of your 5-rep max |
| @[7.5,8,8.5]rpe | per-set efforts |
Always anchor a percentage to the rep max it's a percentage of: @70%1rm, @90%5RM. A bare percent like @70% doesn't say 70% of what — if you mean 70% effort, that's @7rpe; if you mean load, write @70%1rm. (The parser accepts the bare form and currently reads it as %1rm, so be explicit about which one you intend.)
A line takes one load and, optionally, one effort: Squat, 3x5 @225lb @8rpe prescribes the load and the effort it should feel like. A time target can ride along too: Deadlift, 1x3 @155lb @8rpe in 0:20. More than one load or more than one effort on the same line won't parse.
Pace, speed & heart rate
| You write | It means |
|---|---|
| @6:00/mi | pace (also /km, /mile, /kilometer) |
| @18mph | speed (also kph, km/h) |
| @150bpm | heart rate |
| @80%hrmax | percent of max heart rate |
| @[6:00,5:45,5:30]/mi | per-set paces |
For cardio, the intensity is a rate. Ramp it per set with a list, or hold it steady for the whole piece.
Tempo
Squat, 3x5 @135lb tempo 30X1 rest 2:00 Bench Press, 3x8 tempo 3-1-3
Four digits — eccentric, pause, concentric, pause — where X means explosive: 30X1 is 3 seconds down, no pause, explode up, 1-second squeeze. The hyphenated 3-1-3 form works too. The keyword is lowercase tempo, it sits after the intensities and before the interval, and the code starts with a digit.
Rest & intervals
| You write | It means |
|---|---|
| rest 2:00 | clock starts when the set ends |
| rest 90 | bare numbers are seconds (90s works too) |
| /0:30 | shorthand for rest 0:30 |
| every 1:00 | clock includes the work — EMOM-style |
| //3:00 | shorthand for every 3:00 |
| //:30 | colon shorthand for every 0:30 |
| rest [2:00,2:30,3:00] | per-set rests |
| every 400m | distance-based intervals |
The words choose the semantics: rest and / are exclusive (rest starts after the work), every and // are inclusive (the next set starts on the mark, work included). A line with no interval simply has no prescribed clock.
Progressions
| You write | It means |
|---|---|
| 5x5++1 | reps climb by 1 per set: 5,6,7,8,9 |
| 10x10--1 | reps fall by 1 per set |
| @100++5lb | load climbs 5 lb per set |
| rest 2:00--0:15 | rest shrinks 15s per set |
| 4x400m++200m | distance grows per set |
| 5x0:30++0:10 | duration grows per set |
| 5x5**2 | multiply per set: 5,10,20,40,80 |
| 5x24\\2 | divide per set: 24,12,6,3,… |
++ and -- write a ramp without listing every step; ** and \\ multiply and divide. Progressions are type-matched — numbers step by numbers, durations by durations, distances by distances.
Rounds & circuits
A 3 Rounds, header loops through the indented lines beneath it. The header can carry its own clock — rest 2:00 between rounds, or every 2:30 to start each round on the mark. (The trailing comma on headers is optional.)
3 Rounds, rest 2:00 Squat, 5 @135lb Push Up, 10 @bw
A one-line superset separates exercises with semicolons: 3 rounds, Push Up, 10 @bw; Bench Press, 5 @5rm.
Inside a rounds section, a bare bracket list distributes per round rather than per set, and nesting goes a level deeper when each round has its own sets:
10 Rounds, Push Up, [2,4,6,8,10,12,14,16,18,20] @bw 4 rounds, Bench Press, [3,2,1]x[10,8,6] @[135,145,155]lb rest [2:00,3:00,4:00]
Short intensity lists pad with their last value. Exercises themselves can rotate round by round: ..N holds an entry for N rounds, %%N strides, and *[…] loops the list.
6 rounds, [Squat..2, Lunge..2, Dip..2], 10 @bw *[Push Up, Dip], 10 @bw
AMRAP, EMOM, For Time & ladders
12:00 AMRAP, Push Up, 10 @bw Air Squat, 15 @bw 10:00 EMOM, Push Up, 10 @bw For Time, Burpee, 50 @bw 21-15-9, Thruster, @95lb Pull Up, @bw
12:00 AMRAP, — as many rounds as possible in the time; bare minutes (12 AMRAP,) work too. 10:00 EMOM, — one round every minute on the minute; whole minutes only. For Time, — one round, done as fast as possible.
A rep-scheme ladder like 21-15-9, needs at least three counts. Under it, lines can drop their volume — the scheme supplies the reps — and explicit-volume lines like Run, 200m mix in unchanged.
Divisions
~ Warm Up ~ Air Squat, 10 @bw ~ Main Effort ~ Deadlift, 5x5 @155lb rest 1:30
A ~ Name ~ line on its own names everything that follows, until the next marker. An empty marker (~ ~) closes the current division without opening a new one. Division names allow letters, digits, spaces, and & - _ +.
How Impulse reads it
The language describes the work; the app resolves it against you. These behaviors sit on top of the notation itself.
Exercise names are free text. Write any name you like — when you save a workout with a name the library doesn't know, Impulse asks you to link it to an existing exercise (as an alias), rename it, create it, or skip. Linking is what powers autocomplete, muscle attribution, bodyweight factors, and exercise history, so it's worth the click. Renaming an exercise later rewrites it in your saved notation.
Percentages estimate effort, not load. @85%1rm doesn't look up your max and compute a weight — the app converts percentage prescriptions into an effort estimate (an RPE) when it summarizes and charts your training. @90%5RM is first re-anchored to its 1RM equivalent.
Bodyweight resolves against you. @bw uses your most recent logged body weight, and exercises carry a bodyweight load factor (a push up loads roughly 0.64× bodyweight) so bodyweight work counts toward tonnage honestly. If a workout needs your bodyweight and doesn't have it, Impulse prompts you when you finish.
Results need an absolute anchor. Feel-based intensities — rpe, rir, rm, %1rm — are prescription vocabulary. When you log what actually happened, pair them with something concrete: a weight, a distance, a duration, or @bw. 5 @8rpe can't be a result; 5 @225lb @8rpe can.
The editor is on your side. It highlights the parts of each line, completes exercise names from your own library along with grammar suggestions, explains what it expected when a line doesn't parse yet, and marks half-typed lines as "keep typing" rather than errors. And when you perform a workout, the app writes notation back for you — logged times splice in as in 0:33 and measured rests as rest 2:37, so your results read in the same language as your plans.
Sharp edges
| You write | It means |
|---|---|
| 3 x 5 | spaces around x break it — write 3x5 |
| in1:00 | the space after in is required |
| 3x2.5 | rep counts must be whole numbers (0 is fine) |
| 0x5 | set counts must be positive |
| @100kgs | rejected with a hint — the unit is kg |
| 10:30 EMOM, | EMOM takes whole minutes only |
| Tempo 30X1 | the keyword is lowercase tempo |
| 3xAMRAP | in volume position it spells AMAP |
| 21-15, | a ladder needs at least three counts |
| Squat, @135lb | volume-less lines only work under a ladder header |
The editor flags all of these as you type, with a hint about what it expected next.

Comments
Everything from
#to the end of the line is stripped before parsing — whole-line or trailing, they never affect the plan.