A variable is a named container for a value. In Skript you create one, and later change it, with the same word: set.
set counter to 0 set counter to counter + 1 set counter to counter + 1 log "counter is {counter}"
▶ example.skript — Skode Skript · local simulation ● event: script → name: Demo ✎ set counter → = 0 ✎ set counter → = 1 ✎ set counter → = 2 • log → counter is 2 ✔ done in 2.1ms
The right-hand side of set … to … can be any expression: a literal value, arithmetic, string joining, another variable, or a mix. The trace prints every set with the value it stored, which makes variables pleasantly un-mysterious: you can watch each one change.
One namespace, on purpose
Here is the design decision that makes Skript variables feel different from other languages: variables and event fields live in the same namespace. When a lead event carries name and budget, those are simply names your program can read — and set can create new names right beside them:
when a new lead arrives set budget_with_tax to budget * 1.18 log "{name}: {budget} becomes {budget_with_tax}"
▶ example.skript — Skode Skript · local simulation ● event: lead.created → name: Ada Lovelace · phone: +1 555 0100 · email: [email protected] ✎ set budget_with_tax → = 1416 • log → Ada Lovelace: 1200 becomes 1416 ✔ done in 2.1ms
There is no ceremony separating "their data" from "your data", because in an automation the distinction rarely earns its keep. A consequence worth knowing: set budget to 0 inside a rule overwrites your view of the event's field for the rest of that run. That is occasionally exactly what you want, and occasionally a bug; the trace makes either case visible.
Little courtesies: set the counter to 1 and set its status to "vip" work too — Skript quietly ignores a leading the or its in the name, because forcing you to un-say natural English would be against its religion.
Growing and shrinking
You can always write set n to n + 1, but arithmetic-as-sentence is nicer, so Skript has three growth idioms:
set n to 10 increase n by 5 decrease n by 3 add 8 to n log "n is {n}"
▶ example.skript — Skode Skript · local simulation ● event: script → name: Demo ✎ set n → = 10 ✎ increase n → = 15 ✎ decrease n → = 12 ✎ add 8 to n → = 20 • log → n is 20 ✔ done in 2.1ms
All three appear in the trace with their result, and increase/decrease on a name that does not exist yet treats it as 0 — handy for counters you have not bothered to initialise.
add … to … is the most interesting of the three: it is type-smart. Added to a number it does addition, as above; added to a string it appends; added to a list (next chapter) it pushes a new item on the end. One sentence, three sensible meanings — the value on the receiving end decides.
set label to "Lead" add "-2026" to label log "{label}"
▶ example.skript — Skode Skript · local simulation ● event: script → name: Demo ✎ set label → = "Lead" ✎ add to label → = "Lead-2026" • log → Lead-2026 ✔ done in 2.1ms
The unset-name rule
What happens if you use a name that was never set? Most languages answer with an error, some with a special nothing-value. Skript answers like English: an unset name is just a word.
set plan to pro log "the plan is {plan}"
▶ example.skript — Skode Skript · local simulation ● event: script → name: Demo ✎ set plan → = "pro" • log → the plan is pro ✔ done in 2.1ms
There is no variable called pro, so pro means the word "pro" — which is surely what the author of that line intended. The same forgiveness means a typo'd variable name will not crash your program; it will flow through as text. That is a deliberate trade: automations should degrade gently, not fall over. The trace and interpolation's kept-braces behaviour are your typo detectors, and Chapter 14 shows how to test suspicious paths deterministically.
Two names with reserved meanings
Two names are reserved: score and heat, produced by the AI scoring action you will meet properly in Chapter 12. They are special because reading them always consults the interpreter's own scoring result — writing set score to 90 will not fool a later score is hot check (pin the score honestly with the --score option instead). Treat them as the interpreter's contribution to the namespace.
Everything else — event fields, your counters, your labels, your lists — is yours, mutable, and visible in every trace line that touches it.