Lifecycle hooks

Hooks are blocks of logic that run at moments in a workout's lifecycle. They read what happened — reps, weights, whether you hit your targets — and write back training-max and state changes that make a program adapt from session to session.

This is the complete reference. For a gentler introduction, start with Progressions & hooks.

The two hook kinds

HookFiresTypical job
on_setmid-workout, as you finish each setPre-fill the next set (autoregulation)
on_completeafter a unit (exercise / day / week) is fully doneDecide progression — bump a TM, update state

on_set is meant to run during a workout; on_complete runs when you complete the session.

on_set is parsed and validated but not yet evaluated at runtime. The compiler accepts on_set blocks (inline or supplied by a macro), but the app currently drives behavior from on_complete only — next_set_weight / next_set_reps are not applied yet. Write on_set logic if you like, but don't depend on it taking effect today.

Hook scopes

on_complete can be attached at three scopes. They are evaluated in this order when a session completes:

  1. Exercise — once per completed exercise block.
  2. Day — once, after every exercise in the day.
  3. Week — once, only on the session that completes the last day of the week.

State writes thread forward: a state change made by an exercise hook is visible to the day hook, and the day's writes are visible to the week hook.

Program-level on_complete is parsed but not evaluated. The grammar accepts a top-level on_complete block, but the app does not run it at workout completion — don't rely on it. Use exercise, day, or week scope instead.

Variables by scope

Every variable is a number (booleans are 1/0). Weights are in the lifter's own unit and are never converted. Which variables exist depends on the scope, because day- and week-level hooks have no single "current set" to report.

Exercise on_complete

VariableMeaning
completed1 if every working set hit its target
completed_repsReps logged on the final working set
total_repsTotal reps across all working sets
target_repsTarget reps (a range's minimum)
current_weightWeight on the final working set
set_index / set_countIndex / count of working sets
failed_setsWorking sets that fell short of target
rpe_logged / rir_loggedRPE / RIR logged on the final set (0 if none)
is_amrap1 if the final set was AMRAP
is_pr1 if this exercise set a PR this session
estimated_1rmEstimated 1RM from the heaviest set
week_index / day_index1-based position in the program
session_countTotal sessions completed in this enrollment
sum_volumeWeight × reps across this exercise's sets
unit_is_metric1 for kg, 0 for lbs

Plus tm.self (this exercise's training max), tm.<exercise> (any TM in the tm { } block), and state.<name> (any declared state variable).

Day on_complete

Day hooks see only program-context variables — no per-set data, and no tm.self:

week_index, day_index, session_count, day_volume (weight × reps across the whole day), unit_is_metric, and state.<name>.

Week on_complete

Everything a day hook sees, plus week_volume (weight × reps across every session in the week).

on_set outputs

on_set is intended to run mid-workout and expose the in-progress set context. The two variables it may write are the only way to influence the next set (note the runtime caveat above — these outputs aren't applied yet):

Writable outputEffect
next_set_weightPre-fills the weight of the next set
next_set_repsPre-fills the target reps of the next set

What a hook may write

TargetAllowed inNotes
tm.selfexercise on_completeThis exercise's training max
tm.<exercise>exercise on_completeAny TM declared in tm { }
state.<name>any scopeAny variable declared in state { }
next_set_weight / next_set_repson_set onlyPre-fill the next set

Anything else is rejected at compile time. In particular, deep paths like state.x.y and reserved keys (__proto__, constructor, prototype, hasOwnProperty) are forbidden.

Runtime caveats

These rules are enforced when the app evaluates your hooks. A hook can be syntactically valid yet silently do nothing if it ignores them.

Deload weeks

On a deload week, on_complete hooks are suppressed by default so a back-off week doesn't trigger progression. on_set still runs. Re-enable on_complete with hooks: enabled at the week (or day) level:

A real example

This is the 5/3/1 main-lift progression: on the week-3 AMRAP top set, if you hit at least one rep, bump the training max by the unit-correct amount.

Next, see how to package logic like this into a reusable rule on the progression macros page, or skim the language reference for the full grammar.