Skip to content

Variables

A variable is a placeholder you write into a command response. When the command runs, the bot swaps it for a real value: the name of the viewer who typed it, your current category, a random number, a counter, a stored value of your own.

Commands covers writing a command and picking a variable from the chips under the response box. This page is the reference behind those chips: every variable the bot understands, and what each one actually returns.

There are two shapes, and both start with $:

  • A bare name, like $user, $args or $1. Only six variables have this form.
  • A group in parentheses, like $(uptime) or $(random 1 6). Everything after the first word inside the parentheses is that variable’s argument.

The five bare names that carry no argument also have a parenthesised twin, so $(user) and $user are the same thing. Use whichever reads better to you.

Three rules govern how a response is expanded, and all three matter:

Expansion happens once, left to right. Whatever a variable returns is dropped into the response as plain text and is never looked at again. A viewer who types $(urlfetch ...) as an argument to your command has typed a piece of text, not a variable: it lands in the response literally and nothing is fetched.

Anything the bot does not recognise is left alone. $5.99 survives as $5.99, and $(nonsense) posts as $(nonsense). Prices, handles and stray dollar signs are safe.

A variable the bot does recognise but cannot resolve becomes nothing at all. This is the one that bites, and it has its own note at the bottom of this page.

VariableWhat it expands toExample
$userThe display name of the viewer who ran the commandAda
$argsEverything typed after the command name!so Ada great stream gives Ada great stream
$1, $2, and so onThe first, second, and so on word after the command. Past the end of what was typed, nothing!so Ada great stream gives Ada for $1
$touserThe first word typed, and the viewer’s own name when they typed nothing!hug from Ada gives Ada
$query$args, URL encoded, for dropping into a $(urlfetch) addressred panda becomes red%20panda
$(userlevel)The viewer’s level: everyone, subscriber, vip, moderator or broadcastermoderator
$(userlocation)The location this viewer stored with !set locationBerlin
$(userdata key)Any other value this viewer stored with !set$(userdata pronouns) gives she/her
$(usertime)The current time in the timezone this viewer stored, blank if they have not stored one21:04:33
VariableWhat it expands toExample
$channelThe channel namepyre
$(provider)The platform this message arrived ontwitch
$(uptime)How long the stream has been running, or the word offline2 hours 14 mins
$(game)The current category. Kept even off air, so it reads back your last oneJust Chatting
$(title)The current stream titlefriday co-op runs
$(followage)How long the viewer has followed you, or not following. Add a name to ask about somebody else7 months 3 days
$(commands)The address of your public commands pagehttps://pyre.studio/s/yourname/commands
$(social discord)One configured link from your profile. The kinds are discord, youtube, x, instagram, tiktok, kick, facebook and websitehttps://discord.gg/example
$(socials)Every configured link at once, as Label: address, up to six of themDiscord: https://discord.gg/example · X: https://x.com/example

$(uptime), $(game), $(title) and $(followage) are read live from the platform using your own connection, so they need no third party service and no setup beyond having the platform connected.

Two limits are worth knowing before you build a command on them. $(followage) answers on Twitch only: neither Kick nor YouTube exposes a per follower follow date an app can read, so it comes back empty there rather than guessing. And $(game) is always empty on YouTube, which publishes no category for a live broadcast.

VariableWhat it expands toExample
$(random 1 6)A whole number between the two bounds, both included4
$(random.pick yes|no|maybe)One of the options, separated by |maybe
$(count)A counter that climbs by one every time this command runs47

Give $(random) its bounds the wrong way round and they are swapped for you, so $(random 6 1) behaves like $(random 1 6). Give it a single number and that is the only answer it can ever return.

$(count) keeps a separate tally for every command that uses it. The tally appears on the Variables & Counters page the first time the command fires, and you can correct it or delete it there.

VariableWhat it expands toExample
$(var name)The stored value of a variable you created$(var raidmsg) gives your raid message
$(setvar name value)Nothing. It stores the value and stays silent$(setvar lastboss Radahn) posts nothing
$(incrvar name)Adds one to a numeric variable and shows the new total. Add a number to step by more, or a negative number to count down$(incrvar deaths) gives 12

These read and write the same store the Variables card manages, so a value you set from chat shows up on the page and the other way round.

VariableWhat it expands toExample
$(points)The loyalty balance of the viewer who ran the command250
$(pointsname)The name you gave your currencyembers
$(quote)A random quote. Give it a number for a specific one$(quote 5) gives quote five

$(points) always reports the balance of the person who typed the command. It ignores anything you pass it, so $(points someoneelse) still answers for the viewer.

VariableWhat it expands toExample
$(time)The time now. Give it a timezone, then optionally a format$(time Europe/Berlin) gives 21:04:33
$(countdown target)How long until a date, in words. Once the date is past it says 0 seconds4 days, 2 hours
$(countup target)How long since a date, in words1 year, 3 months
$(math expression)The result of a sum$(math (2+2)*3) gives 12

$(time) takes an IANA timezone name such as Europe/Berlin or America/Chicago. With no format it gives HH:mm:ss; with one it understands YYYY, MM, DD, HH, mm and ss, so $(time Europe/Berlin YYYY-MM-DD) gives 2026-08-20. A timezone it does not recognise gives nothing rather than the wrong time.

$(countdown) and $(countup) take either a full date such as 2026-12-24T18:00:00Z or a plain epoch number.

$(math) is arithmetic and only arithmetic: numbers, + - * / % and parentheses. Anything else in the expression, a letter or a semicolon or a function call, makes the whole thing return nothing. That is deliberate, and it is why $(math) is safe to expose to chat through $1.

VariableWhat it expands toExample
$(urlencode text)The text, URL encodedred%20panda
$(urldecode text)The reverse. Malformed input gives nothingred panda
$(references !other)The raw response of another of your commands, inserted oncepulls in your !discord response
$(urlfetch address)The body of an https requestwhatever the address returns
$(eval expression)The result of a small JavaScript expression, run in a locked down sandbox$(eval 1+1) gives 2

$(urlfetch) works with any public https address. It cannot reach private, loopback or cloud metadata addresses, which is what stops a command from being pointed at Pyre’s own infrastructure. Bare variables inside the address are filled in before the request goes out, so $(urlfetch https://example.com/api?q=$query) works as written.

$(references) inserts another command’s response as it is written, not as it would have been expanded, and the inserted text is never expanded either. A command that references itself returns its own raw body once and cannot loop.

$(eval) receives your expression as source, but any viewer supplied variable in it arrives as a quoted string, never as code. That keeps a viewer from injecting JavaScript through an argument, and it means a number you meant to do maths on needs Number($1) around it.

VariableWhat it does
$(settitle text)Sets your stream title
$(setgame name)Sets your category, resolved by name on each platform

These two change your channel rather than your message, so they carry their own gate. The action fires only when the person who typed the command is a moderator or above, whatever the command’s own Who can use it setting says. A viewer running an everyone command that contains one of them gets nothing and changes nothing. A blank value is ignored too, so a mistyped !title can never wipe your title.

Both live on Variables & Counters in the sidebar, one card each.

The Variables & Counters page with a Variables card holding empty Key and Value fields, the naming rules beneath them and an Add / update button over a line reading No variables yet, and a Counters card reading No counters yet, one appears the first time a command using the count variable fires
  1. Pick the channel in the channel selector at the top of the portal if you are working on a channel you moderate rather than your own.

  2. Open Variables & Counters.

  3. Fill in Key and Value in the Variables card and press Add / update. Keys allow letters, numbers, underscores, dots and hyphens, up to 60 characters. Values are shortened to fit 2000 characters, and you can store up to 200 variables.

  4. Re-add an existing key to change its value. There is no separate edit: adding a key that already exists replaces it.

  5. Correct a counter in the Counters card by typing a new number and pressing Save, or remove one with Delete.

Counters are your own channel only. On a channel you moderate the card is still there, with a note in place of the table. Variables are available to a delegated Manager; an Editor or Read-only moderator sees the table but no add form and no delete buttons.