Before you start
In guided setup, Bring commands over is optional. Review the commands you want before importing; your other bot can stay in place. Help recognises current imported flows, including your renamed or edited commands, and keeps the same records. A normal command alone is not evidence of an import.
This guide maps what you already built in Nightbot onto the closest thing in Bloopbot, so you are not starting from a blank page. Your commands can come across automatically: see Import your commands. Everything in Bloopbot is a flow — a trigger, optional checks and one or more actions you draw on a canvas — so “add a command” and “add a filter” both mean building or installing a small flow rather than typing one line into a settings box.
Commands and permissions
Nightbot’s !commands add, its -ul= userlevel and its -cd= cooldown become a trigger and, where you need one, a check node in front of your reply:
| In Nightbot | In Bloopbot | Notes |
|---|---|---|
A custom command (!commands add !name reply) | A flow with a Chat command trigger (create your first chat command) | The trigger’s Command field holds the word without the prefix, Prefix holds the character before it (! by default), and Also responds to is a comma-separated alias list — the same job as Nightbot’s -a=. |
-ul=owner / -ul=moderator / -ul=twitch_vip / -ul=everyone | A Who can trigger check between the trigger and the action, with At least set to broadcaster, moderator, VIP or everyone | That is Bloopbot’s full ladder for this check — broadcaster, moderator, VIP, subscriber, everyone. There is no separate follower level. |
-ul=regular (Nightbot’s Regulars list) | A Has a role check, Roles left at its default Regulars | A different check node from Who can trigger: Has a role reads Viewers › Regulars (or any other role you name), and the broadcaster and moderators pass it by default too. The Regulars-only command template wires this up for you — see recognise regular viewers. |
-cd=<seconds> | A Cooldown check, with a duration set on Whole channel, Per viewer, or both | Nightbot’s one number is closest to a channel-wide cooldown. A per-viewer cooldown, and letting moderators or yourself skip it, are Bloopbot additions — see add permissions and cooldowns. |
| Spam filters (links, caps, symbols, blacklist) | The channel-wide filters on Moderation, each with its own thresholds, exemptions and response | These are settings that apply to every message, not something you draw — see set up moderation helpers. |
Timers (!commands posted on an interval, with an interval and a chat-lines setting) | A flow with an On a timer trigger | Set the interval in minutes, or specific days and a time of day, and optionally require that chat has moved since the last fire — see post a recurring chat message. |
Song requests (!songrequest, !sr, played from Nightbot’s own YouTube/SoundCloud dashboard player) | The Song requests flow pack, playing through your own linked Spotify account | Different service and a different source library: Nightbot plays YouTube and SoundCloud links from its dashboard player; Bloopbot plays Spotify tracks through your own Spotify Premium account — see let chat request songs. Song requests may not be available on your channel yet — check what your plan includes. |
Variables
Nightbot’s $(…) tokens and Bloopbot’s $(…) tokens look alike on purpose, but they don’t all come from the same place — Bloopbot’s come from the specific step that hands them on, mostly the trigger:
| Nightbot | Bloopbot | Notes |
|---|---|---|
$(user) | $(user) — a Chat command trigger’s “Who typed it” | Same syntax, same meaning: whoever ran the command. |
$(touser) | $(touser) — “First word, or the viewer” | Also literally named touser in Bloopbot. Falls back to the person who typed the command when there is no first word, and drops a leading @. |
$(query) | $(query) — “Everything after the command” | Same job: the whole rest of the message after the command word. |
$(1) … $(9) (positional arguments) | $(1) … $(9) work the same way in any flow text field | All nine work, the same as Nightbot — the Starter pack’s own !deaths +5 counter reads the amount as $(3). Only $(1) (“First word after the command”) and $(2) (“Second word”) appear in the trigger’s own tray and Insert… menu; $(3) onward you type by hand. |
$(channel) | $(channel) — your channel’s name | Your channel’s login name, in any flow started by chat or a Twitch event. A timer has no chat line behind it, so there it’s empty. |
$(userid) | $(userid) | The ID of whoever ran the command. |
$(command), $(provider) | Plain text | The importer writes them out: $(command) becomes the command itself, such as !discord, and $(provider) becomes twitch. |
$(count) (auto-incrementing per-command counter) | A declared variable plus a Set a variable action, read back as $(var.name) | Not automatic: you declare the variable once on Variables, then a Set a variable step adds to it. The Starter pack’s own !deaths counter is built exactly this way — see keep a counter with variables. |
$(twitch $(channel) "{{game}}") | $(data.stream.category) — the Stream group’s Category in the Insert… menu | Your current category, kept up to date whether you’re live or offline. |
$(twitch $(channel) "{{title}}") | $(data.stream.title) | Your current stream title. |
"{{viewers}}", "{{followers}}", "{{subscriberCount}}" | $(data.stream.viewers), $(data.channel.followers), $(data.channel.subscribers) | Viewers is 0 while you’re offline. The follower count has no thousands separator. |
"{{name}}", "{{displayName}}", "{{url}}" | $(channel), and https://twitch.tv/$(channel) for the link | Your channel’s login name, which Twitch shows in lowercase. |
$(twitch $(channel) "{{uptimeLength}}") | $(data.stream.started_at_ago) — how long ago in the Stream group | A human string like “3 hours”. It keeps counting after the stream ends, so pair it with a Stream status check if you only want it while live. The importer adds that check for you. |
$(urlfetch url) | A Web request action, whose answer becomes a value later steps can use | Not an inline token — it’s a step on the canvas, and the channel has to switch Web requests on before it can run. Web requests may not be available on your channel yet — check what your plan includes. The importer does this for you when a reply has one $(urlfetch https://…), including $(urlfetch json https://…). |
$(eval …) picking a random line | A Pick at random step, set to One from a list | Type one option per line; the reply reads the pick. There is no way to run your own JavaScript. |
$(time timezone "format"), $(countdown …), $(countup …) | No direct equivalent | Bloopbot has no live clock or timezone-formatting token. An On a timer trigger firing at a set time of day covers most of what a scheduled $(time) announcement was doing. |
$(twitch $(touser) …) about someone else, $(userlevel), $(querystring), $(weather), $(lastfm), $(steam) and the game-rank lookups | No direct equivalent | A shoutout that reads another channel’s game becomes Bloopbot’s own shoutout: the importer offers it on the review. |
A field that says it accepts variables shows an Insert… menu listing exactly what that step can read, so you don’t have to remember the exact token by hand.
Import your commands
Bloopbot can read the commands on your channel’s public Nightbot command list and turn each one into a flow for you. You don’t sign in to Nightbot, and nothing changes in Nightbot.
- Open the importer. Set up your bot asks about them in its first step when it finds your Nightbot commands, and Bring your commands over is on Tutorials any time from Tutorials (it then asks which bot you used). Or go to Flows → Marketplace → From another bot. Or follow bring my Nightbot commands straight from here.
- Choose Nightbot. Bloopbot lists every command Nightbot has for the Twitch account you signed in with.
- Read each row. It shows the command, who could use it, its cooldown, and its reply as Bloopbot will send it. A warning line means something didn’t carry over exactly. Some rows offer Use Bloopbot’s shoutout (or clip, quote, giveaway entry) beside Keep your reply. Bloopbot picks one for you when it’s sure the command does that job; you can switch either way before you bring it over.
- Untick anything you don’t want. Tick Turn on now for a command you want answering chat straight away. Everything else arrives paused.
- Press Bring these over. Each command becomes its own flow called
!command (from Nightbot)on your Flows page.


What each command becomes:
- The user level becomes a Who can trigger check, or a Has a role check for regulars. The cooldown becomes a Cooldown check on Whole channel.
$(user),$(touser),$(query),$(channel),$(userid)and$(1)to$(9)stay as they are.$(command)and$(provider)are written out.$(count)becomes a counter variable named after the command. It starts at Nightbot’s current count, so a death counter at 37 carries on from 37.$(twitch $(channel) "…")is rewritten field by field:{{game}}becomes your current category,{{title}}your title,{{viewers}},{{followers}}and{{subscriberCount}}the counts, and{{name}},{{displayName}}and{{url}}your channel. SoNow playing $(twitch $(channel) "{{game}}")saysNow playing Minecraft.{{uptimeLength}}becomes how long the stream has been live. While you’re offline, the command stays quiet instead of saying so.- A reply with a single
$(urlfetch https://…)or$(customapi https://…)gets a Web request step that fetches the address first, and the Chat message puts the answer where the token was. Check the address before you turn it on. - A Nightbot alias, such as
!dcrunning!discord, becomes an extra word on!discord’s Also responds to instead of a flow of its own.
Some rows can’t go live straight away. Their Turn on now box is greyed out, and the command is brought over paused, as written, for you to finish in the editor:
- a token Bloopbot doesn’t have, such as
$(time)or$(eval)(see Variables for what to use instead); - a
$(urlfetch), which now arrives as a Web request step: check the address it calls before you turn it on; - a command Nightbot answered with no prefix, which in Bloopbot answers to
!plus the word; - a reply that starts with a chat command such as
/announce.
The importer doesn’t bring over timers, spam filters, your Regulars list or song requests. Rebuild those as below. A regulars-only command still arrives with its Has a role check, so add your regulars on Viewers › Regulars.
You can run the importer again after you add commands in Nightbot. A command you already brought over shows Already brought over, and one a flow here already answers shows You already have. Neither is ticked. If you tick a You already have row, it arrives paused beside your existing flow, so you can pick which one to keep on.
Recreate your top commands
Use this for anything the importer couldn’t bring over, or to start from Bloopbot’s own ready-made flows. Do it once your channel is signed in.
- Open Flows, press Marketplace, and add the Starter pack. It brings ready-made command and event flows you can review, rename or leave paused — nothing goes live until you turn it on. Its own counter (
!deaths, with mods adding to it via!deaths +) is a working example of a Nightbot-style tally, built from a declared variable and a Set a variable action. - For a command Starter doesn’t cover, press + New flow → Start blank, add a Chat command trigger, and connect a Chat message action with your reply text.
- Add a Who can trigger, Has a role or Cooldown check in front of the action for anything that was moderator-only, regulars-only or rate-limited in Nightbot.

A worked example — a public !discord command with a moderator-only !setdiscord to update the link, the way many channels run it in Nightbot:
- On Variables, declare a text variable named
discord_urlwith your current invite link as its starting value. - Build a flow: Chat command (
discord) → Chat message readingJoin us: $(var.discord_url). - Build a second flow: Chat command (
setdiscord) → Who can trigger (At least: moderator) → Set a variable (discord_url, set to$(query)) → Chat message readingDiscord link updated. - Save both, then test as below before you rely on them live.

Recreate timers and filters
For a Nightbot timer, add an On a timer trigger to a new flow and connect it to a Chat message; set the interval, or specific days and a time. Nightbot’s timers fire on an interval, optionally gated by a minimum number of chat lines since the last fire — Bloopbot’s closest match is Only if chat has moved, a simpler yes/no version of the same idea, not a lines-per-interval count. See post a recurring chat message.
For Nightbot’s spam filters, open Moderation and configure the equivalent filter directly — links, caps, symbols, emotes and the blacklist are channel-wide settings in Bloopbot too, not something you build as a flow. Give each one the thresholds and exemptions you had in Nightbot, save, and watch chat before turning on several at once. See set up moderation helpers.
Turn off the old bot
Once a Bloopbot flow or filter is live and doing the same job, turn off the matching Nightbot command, timer or filter — in the Nightbot dashboard, not here. Two bots answering the same command, posting the same timer, or filtering the same message both duplicate the reply and can make moderation logs confusing about which bot acted.
When you’re ready to retire Nightbot entirely, use its dashboard’s Part Channel button (or the !part/!leave chat command) to remove it from your Twitch chat, and consider /unmod-ing its account in Twitch chat once it has left. If Nightbot ever posted an overlay-style alert (song request now-playing, follow shout-outs) through a browser source in OBS, also remove that source once Bloopbot’s own overlay is doing the job, so the two don’t draw over each other.
Check it before you rely on it
Bloopbot draws a clear line between a simulated check and something that actually reaches Twitch:
- Test fire, in the flow editor’s top bar, runs the flow as a dry run and records what would have happened — it does not post to real chat and does not touch a real viewer’s cooldown or points.
- A real check means typing the command in your own Twitch chat (or triggering the real event) and watching for the actual reply, exactly once.
Do both: Test fire to check the wiring, then one real message in chat to confirm nothing else is still answering the same command.
Troubleshooting
- The importer says Nightbot has no channel for you. Bloopbot looks for the Nightbot channel of the Twitch account you signed in with. If you used Nightbot on a different Twitch account, its commands can’t be imported here, so rebuild them as above.
- The importer says the Nightbot channel belongs to a different Twitch account. A channel with your name on Nightbot is linked to another Twitch account, so Bloopbot won’t read it.
- An imported command shows
$(time …)or another token in chat. It was one of the rows with a warning. Open its flow and replace the token, using Variables. - You get two replies. Nightbot and Bloopbot are both still answering the same command or timer. Turn off the one you’re retiring — see “Turn off the old bot” above.
- The command does nothing. Check the flow is live rather than paused, and that a Who can trigger, Has a role or Cooldown check isn’t quietly stopping it for the account you’re testing with. Fix a flow or connection walks through the rest.
- The reply shows
$(var.discord_url)or$(user)literally, instead of the value. The variable was never declared on Variables, or the token is misspelled — check it against the Insert… menu on that field rather than retyping it from memory. - The reply shows
[count: use $(var.…) — see docs/flows.md §3b]. That’s Bloopbot’s deliberate placeholder for a literal$(count)left over from Nightbot — there is nothing to count without a declared variable. Replace it with a variable and a Set a variable step, as in “Recreate your top commands” above. - A moderator-only or regulars-only command answers for everyone, or nobody. Confirm the Who can trigger or Has a role check sits on the wired path between the trigger and the action, and that its passing output — not its failing one — leads to your reply.
Was this guide helpful?
Thanks. Your answer helps us decide which guides to improve.