Welcome to Rift
Everything you need to get started, learn the interface, format messages, and connect your own apps using webhooks.
What is Rift?
Rift is a chat platform by ModemINC built for communities and teams. It has servers, channels, voice chat, direct messages, and a powerful message formatting system - all wrapped in a fast, clean interface.
Creating an Account
Go to modeminc.com/rift/signup and enter a username, email, and password.
Once signed in, you'll land in the main app. You can join a server right away using an invite link, or create your own.
Set up your profile in Settings - Profiles: choose a display name, upload an avatar, and write a bio.
The Desktop App
Rift has a native Windows desktop app that runs in the system tray and supports voice, screen share, and OS notifications.
Download
Download and run ModemInstaller from cdn.modeminc.com/ModemInstaller.exe. It installs the Rift launcher (RiftDownloader.exe) which downloads Rift and keeps it up to date automatically.
Startup options
In Settings - Windows you can enable:
- Launch on Windows Startup - Rift starts automatically when you log into Windows.
- Start Minimized - when launching on startup, Rift opens to the system tray instead of showing the window. Toggle this alongside Launch on Startup.
Dashboard Links
The Rift dashboard supports ?page= URL parameters so you can deep-link directly to any section. Share a link or bookmark any of the pages below.
| URL | Opens |
|---|---|
modeminc.com/rift/dashboard | Dashboard (last visited server) |
modeminc.com/rift/dashboard?page=discovery | Server Discovery |
Invite links
Server invite links use the path /rift/invite/{code}. Any member with Create Invite permission can generate one from Server Settings.
https://modeminc.com/rift/invite/{code}
User profiles
Every Rift user has a public profile page at:
https://modeminc.com/rift/users/{username}
Bot invite links
Share this link with server owners to let them install your bot:
https://modeminc.com/rift/bot-invite/{bot_id}
Interface Overview
The Rift interface has four main areas:
| Area | What it does |
|---|---|
| Server Rail (far left) | Icons for every server you're in. Click to switch servers. The + button creates or joins a server. |
| Channel Sidebar | Lists all channels in the current server, grouped by category. DMs are shown here too when no server is selected. |
| Messages Area | The main chat area for the selected channel. |
| Members Sidebar | Shows who's in the server and their online status. Click a member to see their profile. |
Settings
Click the gear icon at the bottom of the channel sidebar to open Settings. Tabs cover your profile, account, appearance, notifications, voice & video, and (in the desktop app) Windows-specific options.
Servers
Creating a server
Click the + button in the server rail, then choose Create a Server. Give it a name and an optional icon. Rift automatically creates a General text channel and a General voice channel to get you started.
Joining a server
Click + and choose Join a Server, then paste an invite link. You can also click a direct invite URL (e.g. modeminc.com/rift/invite/abc123).
Inviting people
Right-click any text channel and select Invite People, or go to Server Settings - Invites - Create Invite. Share the link anywhere.
Server Settings
Click the server name at the top of the channel list to open the server menu, then choose Server Settings. From here you can:
- Edit the server name and icon
- Manage roles and permissions
- View and manage members
- Create and manage webhooks
- Set up moderation rules
- Submit the server to the Discovery page
Roles & Permissions
Roles control what members can do. Go to Server Settings - Roles to create roles, set permissions, and assign colors. The @everyone role applies to all members. Roles higher in the list have more authority over lower roles.
Channels
Create a channel by clicking + next to a category name in the channel list. Choose a type:
| Type | Description |
|---|---|
| Text | Standard chat channel. Members send messages, react, reply, and share files. |
| Voice | Join to talk with others. Supports video and screen share. |
| Announcement | Only members with the right permission can post. Good for server-wide news. |
| Forum | Posts with titles and tags. Members reply to individual posts. |
| Rules | A read-only numbered list of server rules. |
| Log | Audit log for bot/webhook messages. Read-only in the UI. Messages auto-delete after 24 hours. |
Channel Permissions
Right-click a channel and select Edit Channel, then go to Permissions. You can allow or deny specific actions for individual roles or members - for example, making a channel read-only for everyone except moderators.
Messaging
Sending a message
Click in the message bar at the bottom of the channel and start typing. Press Enter to send. Use Shift+Enter for a new line without sending.
Replying
Hover over a message and click the reply arrow to reply directly to it. Your message will show a reference to the original above it.
Editing & Deleting
Hover over your own message to reveal the action bar in the top-right corner. Click the pencil to edit or the trash to delete. Server moderators can delete any message.
Reactions
Hover over a message and click the smiley face icon. Pick an emoji from the picker. Click an existing reaction to add yours too. Click your own reaction again to remove it.
Pinning messages
Moderators can pin important messages. Right-click a message (or use the action bar) and select Pin Message. View pinned messages by clicking the pin icon in the channel header.
Formatting toolbar
Click the A icon above the message input to open the format toolbar. It has buttons for Bold, Italic, Underline, Strike, Code, Code Block, Spoiler, Color, Rainbow, Glow, Bar graph, Circle graph, Gauge, and Stat block.
Attachments
Click the + icon in the message bar to attach a file. Images and videos are embedded inline. Files are stored with their original filename.
Direct Messages
Click a user's avatar or username anywhere in Rift to open their profile, then click Send Message. DMs appear in the left sidebar when you're not in a server.
You can also use the friends panel (the person icon in the server rail) to manage friend requests and open DMs with friends.
Voice & Video
Click a voice channel in the sidebar to join. A control bar appears at the bottom with:
- Mute - toggle your microphone on and off
- Deafen - mute all incoming audio
- Video - share your camera
- Screen Share - share your screen or a specific window (desktop app only)
- Leave - disconnect from the voice channel
Click a user's avatar in the voice channel to adjust their volume for you locally.
Markdown Formatting
Rift supports standard markdown syntax in all messages and webhooks. Formatting is rendered client-side - the server stores raw text.
| Syntax | Result |
|---|---|
**bold** | Bold text |
*italic* | Italic text |
~~strikethrough~~ | Strikethrough |
||spoiler|| | Hidden until clicked |
`inline code` | Inline monospace code |
```lang + newline + code + ``` | Syntax-highlighted code block |
 | Embedded image |
[label](https://url) | Hyperlink |
| bare URL | Auto-linked |
@username | User mention |
@everyone / @here | Mass mention |
Rift Widgets
Rift has custom formatting tags that go beyond markdown. Use them in messages or webhook content. All widget tags are processed before markdown.
Colored text
Wrap text in a color name or hex code:
[red:This text is red] [#6c63ff:This text is purple] [orange:Warning!]
Rainbow text
[rainbow:Hello Rift!]
Each character cycles through a set of colors.
Glow text
[glow:purple:Online] [glow:#22c55e:Success]
Bar graph
[bargraph:75%:green] [bargraph:40%:#4ecbff]
Inline horizontal progress bar. Value is 0-100%.
Circle graph
[circlegraph:50%:orange]
SVG circular progress ring with percentage in the center.
Gauge
[gauge:80%:red]
Semicircular speedometer-style gauge.
Stat block
[stat:Username:kipi9876] [stat:Account Age:7957 days][stat:Time Spent:6 minutes]
Small card with a label above a value. Stack multiple on one line to make a stat row.
Pill badge
[pill:ONLINE:green] [pill:ERROR:#ef4444]
Rounded colored badge - useful for status labels alongside other content.
What are Webhooks?
A Rift webhook is a URL you can POST JSON to and a message appears in your channel instantly. You need a Rift account to create one, but once created any app or script can use the URL - no login required to post.
Each webhook has a name shown as the message author (with an APP badge), an optional avatar, a secret URL, and a channel it posts into.
Creating a Webhook
Click the server name at the top of the channel list and open Server Settings.
Go to the Webhooks tab. Enter a name (e.g. "GitHub Bot"), choose a channel, and click Create Webhook.
Click Copy next to the generated URL. Save it somewhere safe - that URL is your credential.
The webhook URL looks like:
https://rift.modeminc.com/v1/webhooks/{id}/{secret}
You can also manage webhooks here: rename, change avatar, refresh the secret, or delete.
Sending Messages
Send a POST to your webhook URL with a JSON body. Only Content-Type: application/json is required.
Fields
| Field | Required | Description |
|---|---|---|
| content | required | The message text. Max 2000 characters. All Rift formatting works here. |
Quick test
curl -X POST YOUR_WEBHOOK_URL \ -H 'Content-Type: application/json' \ -d '{"content": "Hello from a webhook!"}'
With widgets
Use Rift widgets to build rich messages. Stat blocks are especially useful for join/leave notifications:
{
"content": "Gav2011 has joined the server.\n[stat:Username:Gav2011][stat:Account Age:7957 days]\n[stat:Time Spent:6 minutes]"
}
Code Examples
# Simple message curl -X POST YOUR_WEBHOOK_URL \ -H 'Content-Type: application/json' \ -d '{"content":"Deployment complete"}' # With formatting curl -X POST YOUR_WEBHOOK_URL \ -H 'Content-Type: application/json' \ -d '{"content":"**Build #42 passed** [pill:OK:green]"}' # Stat block notification curl -X POST YOUR_WEBHOOK_URL \ -H 'Content-Type: application/json' \ -d '{"content":"Server alert!\n[stat:CPU:89%][stat:RAM:74%][bargraph:89%:red]"}'
const WEBHOOK = 'YOUR_WEBHOOK_URL'; async function notify(content) { await fetch(WEBHOOK, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content }) }); } // Simple alert notify('Server restarted'); // Rich stat notification notify(`Gav2011 joined.\n[stat:Username:Gav2011][stat:Level:42][stat:Playtime:166h]`); // CI/CD status notify(`**Deploy complete** on \`main\` [pill:LIVE:green]\nhttps://myapp.com`);
import requests WEBHOOK = "YOUR_WEBHOOK_URL" def notify(content: str): requests.post(WEBHOOK, json={"content": content}).raise_for_status() # Simple notify("Backup complete") # Stat block notify( "Gav2011 left the server.\n" "[stat:Username:Gav2011][stat:Account Age:7957 days][stat:Time Spent:6 minutes]" ) # GitHub Actions import os notify( f"**{os.environ['GITHUB_WORKFLOW']}** finished on `{os.environ['GITHUB_REF_NAME']}` [pill:PASSED:green]" )
package main import ( "bytes"; "encoding/json"; "net/http" ) const webhook = "YOUR_WEBHOOK_URL" func notify(content string) { body, _ := json.Marshal(map[string]string{"content": content}) http.Post(webhook, "application/json", bytes.NewReader(body)) } func main() { notify("Deploy complete [pill:LIVE:green]") notify("Tests failed [pill:FAIL:red]") }
What are Bots?
Rift bots are automated accounts your code controls. They appear in chat with a BOT badge next to their name and can send messages, react to messages, read channel history, and listen to real-time events via WebSocket - all from a server you write yourself.
Unlike webhooks (which only post messages), bots are full participants. They see everything happening in a server in real time and can respond intelligently.
MESSAGE_CREATE, REACTION_ADD, MEMBER_JOIN, VOICE_JOIN and more over a WebSocket gateway.Creating an Application
Go to the Developer Portal and sign in with your Rift account.
Click + New Application. Enter a name (2-32 characters) and an optional description, then click Create.
Your bot token is shown once only. Copy it immediately and store it somewhere safe - you cannot view it again. If you lose it, regenerate it from the portal (which invalidates the old token).
Optionally upload a profile picture for your bot by clicking the avatar in Manage.
Token format
Bot tokens look like:
rbt_bot_XXXXXXXXXXXXXXXXXX.YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
Use it as an Authorization header in every API call:
Authorization: Bot rbt_bot_XXXX.YYYY
Installing a Bot
Each bot has an invite link that server owners use to add it:
https://modeminc.com/rift/bot-invite/{bot_id}
Copy your invite link from the Developer Portal (the Copy Invite Link button on your app card). When a server owner opens it they can choose which of their servers to add the bot to.
A server member with Manage Server permission can also install via the API directly:
# Server owner installs the bot (uses user JWT, not bot token) curl -X POST https://rift.modeminc.com/v1/api/bots/{bot_id}/install \ -H 'Authorization: Bearer {user_jwt}' \ -H 'Content-Type: application/json' \ -d '{"server_id": "srv_abc123"}'
To remove the bot from a server:
curl -X DELETE https://rift.modeminc.com/v1/api/bots/{bot_id}/install/{server_id} \ -H 'Authorization: Bearer {user_jwt}'
Real-time Gateway
Connect your bot to the WebSocket gateway to receive events in real time. Your bot will receive events for every server it is installed in.
Connecting
wss://rift.modeminc.com/v1/bot/gateway?token={bot_token}
Bot prefix). The Authorization header approach also works if your WebSocket client supports it: Authorization: Bot {token}.
READY event
Immediately after connecting you receive a READY event with your bot info and the list of server IDs you are in:
{
"type": "READY",
"payload": {
"bot": {
"id": "bot_XXXX",
"name": "My Bot",
"avatar_hash": "1234567890",
"verified": false
},
"guilds": ["srv_abc", "srv_xyz"]
}
}
Events
| Event type | When it fires |
|---|---|
message_create | A message is sent in any channel in a server the bot is in |
message_update | A message is edited |
message_delete | A message is deleted |
reaction_add | A user adds an emoji reaction |
reaction_remove | A user removes a reaction |
member_join | A user joins a server |
member_leave | A user leaves or is kicked from a server |
voice_state_update | A user joins or leaves a voice channel |
presence_update | A member's online status changes |
Event shape
All events follow the same envelope:
{
"type": "message_create",
"payload": {
"id": "msg_XXXX",
"channel_id": "ch_XXXX",
"content": "Hello!",
"timestamp": 1748800000,
"author": {
"id": "usr_XXXX",
"username": "gavin",
"avatar_hash": "abc",
"bot": false
}
},
"meta": { "server_id": "srv_XXXX", "channel_id": "ch_XXXX", "timestamp": 1748800000 }
}
JavaScript example
const BOT_TOKEN = 'rbt_bot_XXXX.YYYY'; const ws = new WebSocket( `wss://rift.modeminc.com/v1/bot/gateway?token=${BOT_TOKEN}` ); ws.addEventListener('message', (event) => { const { type, payload, meta } = JSON.parse(event.data); if (type === 'READY') { console.log('Connected as', payload.bot.name); } if (type === 'message_create' && !payload.author.bot) { // Reply to "!ping" if (payload.content === '!ping') { sendMessage(payload.channel_id, 'Pong!'); } } }); async function sendMessage(channelId, content) { await fetch( `https://rift.modeminc.com/v1/bot/channels/${channelId}/messages`, { method: 'POST', headers: { 'Authorization': `Bot ${BOT_TOKEN}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ content }) } ); }
REST API
All bot REST endpoints are under https://rift.modeminc.com/v1/bot/ and require the header:
Authorization: Bot {your_bot_token}
Get bot info
GET /v1/bot/me
List guilds (installed servers)
GET /v1/bot/guilds
List channels in a server
GET /v1/bot/guilds/{server_id}/channels
List members in a server
GET /v1/bot/guilds/{server_id}/members
Get voice states in a server
GET /v1/bot/guilds/{server_id}/voice
Read messages
GET /v1/bot/channels/{channel_id}/messages?limit=50
| Param | Description | |
|---|---|---|
| limit | optional | Number of messages to return. Max 100, default 50. |
Send a message
POST /v1/bot/channels/{channel_id}/messages Content-Type: application/json { "content": "Hello from my bot!" }
| Field | Description | |
|---|---|---|
| content | required | Message text. Max 2000 characters. All Rift widget formatting supported. |
Delete a message
Bots can only delete their own messages.
DELETE /v1/bot/channels/{channel_id}/messages/{message_id}
Add a reaction
POST /v1/bot/channels/{channel_id}/messages/{message_id}/reactions/{emoji}
URL-encode the emoji: %F0%9F%91%8D for π, %E2%9D%A4%EF%B8%8F for β€οΈ.
Edit a message
Bots can only edit their own messages.
PATCH /v1/bot/channels/{channel_id}/messages/{message_id} Content-Type: application/json { "content": "Edited text" }
Assign / change a member's roles
Requires the manage_roles permission. Replaces the member's roles with the list you send (send an empty array to clear them).
PUT /v1/bot/guilds/{server_id}/members/{user_id}/roles Content-Type: application/json { "role_ids": ["role_abc", "role_def"] }
Add a single role to a member
Requires the manage_roles permission. Adds just this one role, leaving the member's other roles untouched. Returns the member's full role_ids after the change.
PUT /v1/bot/guilds/{server_id}/members/{user_id}/roles/{role_id}
Remove a single role from a member
Requires the manage_roles permission. Removes just this one role.
DELETE /v1/bot/guilds/{server_id}/members/{user_id}/roles/{role_id}
Add / remove several roles at once
Requires the manage_roles permission. Adds and/or removes multiple roles in a single atomic request, leaving the member's other roles untouched. Prefer this over firing several single-role calls in parallel - those can race and clobber each other. Returns the member's full role_ids after the change.
PATCH /v1/bot/guilds/{server_id}/members/{user_id}/roles Content-Type: application/json { "add": ["role_a", "role_b", "role_c"], "remove": ["role_x"] }
Kick a member
Requires the kick_members permission.
DELETE /v1/bot/guilds/{server_id}/members/{user_id}
Create a channel
Requires the manage_channels permission. type is one of text, voice, stage, announcement, forum, rules, log (defaults to text).
POST /v1/bot/guilds/{server_id}/channels Content-Type: application/json { "name": "general", "type": "text", "topic": "optional", "category_id": "optional" }
Delete a channel
Requires the manage_channels permission.
DELETE /v1/bot/channels/{channel_id}
Move a member to another voice channel
Requires the move_members permission. Works for both mesh and SFU voice channels.
POST /v1/bot/guilds/{server_id}/voice/{user_id}/move Content-Type: application/json { "to_channel_id": "ch_xxxx" }
Disconnect a member from voice
Requires the move_members permission.
POST /v1/bot/guilds/{server_id}/voice/{user_id}/disconnect
Error responses
| Status | Meaning |
|---|---|
401 | Missing or invalid bot token |
403 | Bot is not installed in that server |
404 | Channel or message not found |
400 | Validation error (e.g. content too long) |
Verified Bot Badge
Any user can create a bot and use it right away - no approval required. The β VERIFIED badge is an optional distinction for bots that are widely used, well-maintained, and serve a clear purpose.
Verified bots display a green checkmark next to the BOT badge in every message they send.
Open the Developer Portal and find your application.
Click Apply for Verified Badge. Write a short reason describing your bot's purpose and how many servers it's in.
The Rift team reviews the application. Approved bots get the badge applied immediately and it appears in all past and future messages.
What is RiftScript?
RiftScript is a tiny automation language built into every server. With it you can react to messages, hand out (or remove) roles, post replies, and move members between voice channels - all without running a bot. The server owner and administrators can edit it under Server Settings β Code. (Because a script can hand out roles, it's intentionally locked to that level - a regular moderator can't use it to elevate themselves.)
It is deliberately simple and safe: there are no loops, variables, or network access, so it can run on every message and reaction without slowing your server down or doing anything you didn't write. One script lives per server and runs automatically once saved and enabled.
New to it? The editor has a row of Templates (Welcome, Reaction role, AFK command, and more) - click one to drop a ready-made rule into your script, then tweak the names to match your server.
on β¦ (a trigger), followed by a { β¦ } block of actions. Comments start with # or // and can be on their own line or at the end of a line.
# When anyone says "ping", reply with pong
on message "ping" {
reply "pong π"
}
Triggers
A trigger decides when a rule runs. Text matching is case-insensitive.
on message "hello" # message is exactly "hello" on message contains "spoiler" # message contains the word on message starts "!" # message starts with "!" on reaction "β " # β added to ANY message on reaction "β " on "msg_id" # β added to ONE specific message on unreaction "β " # β REMOVED from a message (also: on removereaction) on unreaction "β " on "msg_id" # β removed from ONE specific message on join # a member joins the server on leave # a member leaves the server
The member who sent the message, added or removed the reaction, or joined is called the actor - actions like giverole and movevoice apply to them. on unreaction is the mirror of on reaction: pair them to give a role when someone reacts and take it back when they un-react.
on reaction "β
" on "the_id". Without on "id", the rule fires for that emoji on every message.
Conditions
Wrap actions in an if block to run them only when a condition is true. Add not to invert it.
if hasrole "Pong Master" { β¦ } # actor has this role
if hasrole "Mod", "Admin" { β¦ } # actor has ANY of these roles
if not hasrole "Muted" { β¦ } # actor does NOT have the role
if inchannel "general", "chat" { β¦ } # event was in any of these channels
if isowner { β¦ } # actor is the server owner
"Pong Master". List several, comma-separated, and the condition is true if any match - e.g. if hasrole "Mod", "Admin". Names or copied ids both work.
Add an else { β¦ } block to run something when the condition is false:
on message "!verify" {
if hasrole "Verified" {
reply "You're already verified β
"
} else {
giverole "Verified"
reply "You're verified now! π"
}
}
Actions
Actions are what a rule does. Most take one quoted value; a few (delete, removeallroles) take none.
reply "text" # reply to the triggering message
send "text" # post in the same channel
send "mod-log" "text" # post into a named channel instead
react "π" # add a reaction to the triggering message
delete # delete the last message this rule sent
delete "msg_id" # delete one specific message
wait "5" # pause 5 seconds before the next action
giverole "Verified" # give the actor a role
removerole "Muted" # remove a role from the actor
removeallroles # strip every role from the actor
movevoice "AFK" # move the actor into a voice channel
moveallvoice "General" "AFK" # move EVERYONE from one voice channel to another
post "https://your-api.com" "{}" # POST a JSON body to a URL
get "https://your-api.com/ping" # GET a URL
delete with no value removes the last message this rule sent this run; if the rule hasn't sent one yet, it removes the message that triggered it. Give it a message id to delete a specific message (it must be in your server). wait "5" pauses before the next action - handy for a temporary message: reply "Verifyingβ¦", giverole "Verified", wait "3", delete. Waits are capped (up to 10s each, 20s total per run).
Give send two values to target another channel: the first is the channel, the second is the message. The channel must be a text or announcement channel in the same server.
on join / on leave there is no triggering message, so reply and react do nothing - use send "channel" "text" to post a welcome/goodbye. giverole and movevoice work and apply to the member who joined or left. {user} is their name.
Names or IDs
Anywhere you name a role or channel (giverole, removerole, movevoice, and the send target) you can use either its name or its copied ID. Right-click a role or channel and choose Copy ID to paste it in - handy when two roles share a name or a name has tricky characters.
on reaction "β
" {
giverole "role_a1b2c3d4" # by id
giverole "Verified" # or by name - both work
}
Calling an external API (post / get)
post "url" "json" sends a JSON POST; get "url" sends a GET. Use them to call your own webhook or API when something happens. The URL and body can include {user} / {mention}.
on message "!deploy" {
if hasrole "Maintainer" {
post "https://api.yoursite.com/deploy" "{\"by\":\"{user}\"}"
reply "Deploy triggered."
}
}
on message "!status" {
get "https://api.yoursite.com/ping"
}
http/https URLs are allowed, requests time out after 5 seconds, and the response is never read back into Rift - a script can trigger your API but can't pull data back in.
Inside any reply or send text you can use placeholders and references:
{user}- the member's name (plain text){mention}- pings the member (renders as a clickable @mention){args}- everything the member typed after the command word{arg1},{arg2}, β¦ - each individual word after the command- paste a channel id (
ch_β¦) and it becomes a clickable #channel link
Arguments let you build commands that take input. They work in any value - including role/channel names - so a member can type the value:
# A member types: !role Movie Night
on message starts "!role " {
giverole "{args}" # gives the "Movie Night" role
reply "Gave you {args} π¬"
}
# A member types: !say hello everyone
on message starts "!say " {
if hasrole "Mod" { send "{args}" }
}
For on message starts "β¦", {args} is the text after the trigger word. For on message contains it's the whole message, and for an exact on message "β¦" there are no arguments.
Variables
Store a value with set name = "value" and reuse it anywhere as {name}. The value can include arguments and other placeholders, and is worked out at the moment you set it. Variables live for a single run of the script (they are not saved between messages).
on message starts "!hi " {
set who = "{arg1}"
giverole "Member" "{who}"
reply "Welcome {who}! π"
}
Targeting another member
By default giverole, removerole, removeallroles and movevoice act on the member who triggered the rule. Add a target as the last value - a user id, username, or an argument - to act on someone else (they must be a member of your server):
giverole "Muted" "usr_abc123" # give a role to a specific member
removeallroles "{arg1}" # a member types: !wipe usr_abc123
movevoice "AFK" "{arg1}" # move a named member to AFK
Moving a whole voice channel
moveallvoice "fromVC" "toVC" moves everyone currently in one voice channel into another - so you can build your own command:
# a mod types: !moveall General AFK (names or channel ids both work)
on message starts "!moveall " {
if hasrole "Mod" {
moveallvoice "{arg1}" "{arg2}"
}
}
if hasrole "Mod" or if isowner so a regular member can't run !wipe on someone else.
on join {
giverole "Newcomer"
// greet them and point to the rules channel
send "welcome" "Welcome {mention}! Please read the rules in ch_0syK4QTs3kAc π"
}
reply and send are posted as {ServerName}_RiftScript. They're saved like normal messages, so they survive reloads and a moderator can delete them. reply always posts in the channel that triggered it; to post elsewhere use send "channel" "text" with a channel name or id. Each event runs at most 25 actions.
For react, type a : in the Code editor to open an emoji picker, or paste any emoji directly. You can also react with a plain word - it's stored as-is.
Examples
Only let one role get a reply (everyone else is ignored):
on message "ping" {
if hasrole "Pong Master" {
reply "pong π"
react "π"
}
}
Reaction roles - react on one specific message (copy its ID first) to self-assign a role:
on reaction "β
" on "msg_aBc123" {
giverole "Verified"
}
on reaction "π" on "msg_aBc123" {
giverole "Announcements"
}
Owner-only command to wipe all of your own roles:
on message "!resetmyroles" {
if isowner {
removeallroles
reply "All your roles were removed."
}
}
Move yourself to the AFK channel with a command:
on message "!afk" {
movevoice "AFK"
}
Welcome new members and auto-assign a starter role; say goodbye when they leave:
on join {
giverole "Newcomer"
send "welcome" "Welcome to the server, {user}! π"
}
on leave {
send "welcome" "{user} just left. π"
}
Log a keyword to a separate mod channel:
on message contains "report" {
send "mod-log" "{user} mentioned a report."
}
Auto-react to feedback posts, but only in one channel:
on message contains "feedback" {
if inchannel "suggestions" {
react "π"
react "π"
}
}
Limits
RiftScript only does the specific triggers, conditions, and actions listed on this page - it's not a general-purpose programming language.
- Scoped to your server. A script only ever touches its own server's roles, channels, members, and messages - never other servers, DMs, or accounts.
- Outbound requests are write-only.
postandgetcan call externalhttp/httpsAPIs, but the response is never read back into Rift - a script can trigger your API, not pull data back in. - Bounded execution. Each event runs at most 25 actions, there are no loops, and a script that fails to parse never runs.
- Owner/admin only. Because a script can hand out roles, only the server owner and administrators can edit it.
HTML Pages
An HTML channel renders a custom web page (or an embedded external URL) right inside a server. They're created and edited by the Rift owner, and the page runs in a locked-down sandbox: it can use scripts, forms and popups, but it cannot read your token, your messages, or anything else in Rift.
Theme API
So your page can match the user's Rift appearance, Rift sends the current theme to your page with postMessage. Listen for it:
<script>
window.addEventListener('message', (e) => {
if (e.data && e.data.rift === true && e.data.type === 'theme') {
// e.data.theme is "light", "dark", or "custom"
document.documentElement.dataset.theme = e.data.theme;
}
});
// Optional: ask for the theme immediately on load instead of waiting.
parent.postMessage({ rift: true, type: 'getTheme' }, '*');
</script>
- Rift sends the theme once when your page loads, and again every time the user changes their theme - so you can re-style live, no refresh needed.
themeis one of"light","dark", or"custom". "System" resolves to"dark", and all the premium themes (Core, Quantum, Lofi, etc.) report as"custom"- treatcustomas dark unless you have your own palette.- You can request the current theme at any time by posting
{ rift: true, type: 'getTheme' }toparent; Rift replies with the same theme message.
Core & Quantum
Rift is free. Core and Quantum unlock extra features for power users.
For full pricing details, feature comparisons, and to subscribe, visit the Rift Pricing page.