Skript has exactly three loops, and they divide the territory cleanly: repeat when you know how many times, for each when you have a list of things, and while when you know the condition to keep going. Each one takes an indented body, announces itself in the trace with ↻, and can be cut short by stop.
repeat N times
The counted loop is for fixed, known repetition:
set drumroll to "" repeat 3 times add "ta-" to drumroll add "daa!" to drumroll log "{drumroll}"
▶ example.skript — Skode Skript · local simulation ● event: script → name: Demo ✎ set drumroll → = "" ↻ repeat 3 times → ✎ add to drumroll → = "ta-" ✎ add to drumroll → = "ta-ta-" ✎ add to drumroll → = "ta-ta-ta-" ✎ add to drumroll → = "ta-ta-ta-daa!" • log → ta-ta-ta-daa! ✔ done in 2.1ms
repeat 1 time is accepted too — the interpreter does not make you pluralise against your grammar instincts. What the counted loop deliberately lacks is a loop counter of its own; when the body needs to know which pass it is on, keep one honestly:
set attempt to 0 repeat 3 times increase attempt by 1 log "attempt number {attempt}"
▶ example.skript — Skode Skript · local simulation ● event: script → name: Demo ✎ set attempt → = 0 ↻ repeat 3 times → ✎ increase attempt → = 1 • log → attempt number 1 ✎ increase attempt → = 2 • log → attempt number 2 ✎ increase attempt → = 3 • log → attempt number 3 ✔ done in 2.1ms
for each, revisited
You met for each in the lists chapter; it is the workhorse of the three. One more pattern worth showing — a loop body that decides, combining iteration and branching into the shape most real automations take:
when a new lead arrives for each threshold in 1000, 500, 100 if budget is at least threshold then log "clears the {threshold} bar"
▶ example.skript — Skode Skript · local simulation ● event: lead.created → name: Ada Lovelace · phone: +1 555 0100 · email: [email protected] ↻ for each threshold in [1000, 500, 100] → 3 items ✗ if budget is "at least threshold" → no ✗ if budget is "at least threshold" → no ✗ if budget is "at least threshold" → no ✔ done in 2.1ms
Note that the loop variable threshold is doing real work inside the condition — loop variables are full citizens, not just interpolation fodder.
while — and the thousand-pass promise
The condition loop keeps going as long as its condition holds:
set countdown to 5 while countdown is above 0 log "T-minus {countdown}" decrease countdown by 1 log "liftoff"
▶ example.skript — Skode Skript · local simulation ● event: script → name: Demo ✎ set countdown → = 5 ↻ while countdown above 0 → • log → T-minus 5 ✎ decrease countdown → = 4 • log → T-minus 4 ✎ decrease countdown → = 3 • log → T-minus 3 ✎ decrease countdown → = 2 • log → T-minus 2 ✎ decrease countdown → = 1 • log → T-minus 1 ✎ decrease countdown → = 0 • log → liftoff ✔ done in 2.1ms
while is the one loop that can, in principle, run forever — the body above must change countdown, or the condition never fails. Every programmer alive has written that bug at least once, so Skript refuses to let it be catastrophic: a while loop is capped at 1,000 passes. This program forgets to change c; the interpreter stops it and asks exactly the question you need:
set c to 0 while c is below 5 log "spinning"
✗ line 2: the "while c below 5" loop ran 1000 times — it looks infinite (does the loop change what it checks?)
This is the sandbox philosophy in one example: in a general-purpose language an infinite loop hangs the process; in an automation platform it could hang much more than that. In Skript it is a polite, specific error, and everything around it keeps running. (The trace itself has a similar guard — beyond four hundred lines it truncates its display while the program continues — so even a heavy legitimate loop cannot bury you in output.)
Choosing the right loop
A rule of thumb that has never failed anyone: say the sentence out loud first.
- "Do this three times" →
repeat 3 times - "Do this for each channel" →
for each ch in channels - "Keep going while there's budget left" →
while budget is above 0
If the sentence does not fall naturally into one of those shapes, the odds are excellent that you do not need a loop at all — automations mostly react once, to one event, and the loop you were about to write belongs in the platform (a segment, a broadcast, a scheduled flow) rather than in the skript. The loops are here for when the logic truly is iterative; the language just makes sure that even then, it stays legible and bounded.