Keep your Discord account online 24/7 with a status that changes by itself. Schedule it ("π busy at school", MonβFri 07:50β16:00), cycle it, or both, from your menu bar or a cheap VM.
Warning
Use at your own risk. Automating a regular user account ("self-botting") violates Discord's Terms of Service and can get your account suspended or banned. This project is for educational purposes and comes with no warranty. Prefer an account you can afford to lose. Never share your token: anyone who has it controls your account.
- π’ Always online: holds a persistent gateway connection with heartbeats and automatic reconnect (exponential backoff).
- ποΈ Schedules: per-weekday time windows with their own status text, emoji and online state (online / idle / do not disturb). Overnight ranges like
23:30β06:30work. - π Rotation: when no schedule matches, it cycles through your list of statuses every N seconds, forever.
- π Timezone-aware: IANA timezones, daylight saving handled.
- π Custom emoji: unicode, custom and animated Discord emoji.
- π₯οΈ Tray / menu bar app: no window, no Dock or taskbar icon. Pause, resume and reload from the tray.
- π³ Server-friendly: Docker image and compose file for a VM, or run it under pm2.
- πͺΆ Tiny: one runtime dependency (
ws), JSON config.
Requires Node.js 18+.
git clone https://github.com/koryei/Bombastatus.git
cd Bombastatus
npm install
cp config.example.json config.json # edit your schedules and statuses
cp .env.example .env # put your DISCORD_TOKEN in here
npm run tray # menu bar / system tray app
# or
npm start # plain terminal process (good for servers)In a browser (the desktop app hides DevTools), open discord.com/app β F12 β Network β filter api β click any request to discord.com/api β copy the authorization request header. Paste it into .env:
DISCORD_TOKEN=your-token-here
Changing your Discord password invalidates the token. Keep .env private; it is already in .gitignore.
npm run tray puts a small dot in your macOS menu bar or Windows/Linux system tray.
| Dot | Meaning |
|---|---|
| π’ Green | Online |
| π Orange | Connecting / reconnecting |
| βͺ Grey | Paused (account is offline) |
| π΄ Red | Problem (missing or rejected token, bad config) |
The menu shows the current status and has Pause / Resume, Reload config, shortcuts to open config.json and .env, Start at login (installed app only) and Quit. On first run it creates config.json and .env if they're missing.
Download an installer from the Releases page (.dmg, .exe or .AppImage), or build one yourself:
npm run dist # output in dist/The installed app stores config.json and .env in its per-user app-data folder; use the tray menu to open them. Set BOMBASTATUS_HOME to use a different folder.
I don't pay for Apple/Microsoft code-signing certificates, so your OS will warn you the first time. This is expected.
macOS: if you see "Bombastatus" is damaged and can't be opened or "can't be verified", the file is fine. macOS is just blocking a downloaded app that isn't notarized. Drag it to Applications, then run this once in Terminal:
xattr -cr /Applications/Bombastatus.appThen open it normally. (Alternative: try to open it, then go to System Settings β Privacy & Security and click Open Anyway.)
Windows: on the SmartScreen "Windows protected your PC" screen, click More info β Run anyway.
Linux: make the AppImage executable and run it: chmod +x Bombastatus-*.AppImage && ./Bombastatus-*.AppImage.
If you'd rather not trust a prebuilt binary, run it from source instead.
config.json (see config.example.json):
{
"timezone": "America/New_York",
"defaultPresence": "online",
"rotationIntervalSeconds": 60,
"schedules": [
{
"name": "school",
"days": ["mon", "tue", "wed", "thu", "fri"],
"start": "07:50",
"end": "16:00",
"status": { "text": "busy at school", "emoji": "π", "presence": "dnd" }
}
],
"rotation": [
{ "text": "free right now", "emoji": "π’" },
{ "text": "dm me", "emoji": "π¬" }
]
}| Key | Meaning |
|---|---|
timezone |
IANA zone such as America/New_York. Defaults to the machine's zone. |
defaultPresence |
online, idle, dnd or invisible when an entry doesn't set its own. |
rotationIntervalSeconds |
How often the rotation advances. Minimum 15, to stay clear of rate limits. |
schedules[] |
name, optional days (monβ¦sun; default every day), start / end (HH:MM, 24h), and status (text, emoji, presence). First match wins. |
rotation[] |
Statuses cycled forever when no schedule matches. Each has text, emoji and optional presence. |
emoji can be a unicode emoji or a custom Discord emoji. For a custom one, type \:emojiname: in Discord and copy the result (<:pepe:123456789012345678>, or <a:name:id> for animated):
{ "text": "vibing", "emoji": "<a:dance:987654321098765432>" }Custom emoji may require Nitro or membership in the emoji's server, depending on Discord's rules.
Docker (recommended for a VM):
cp config.example.json config.json && cp .env.example .env # then edit both
docker compose up -d --build
docker compose logs -fpm2:
npm install --omit=dev && npm i -g pm2
pm2 start src/index.js --name bombastatus
pm2 save && pm2 startupGood hosts: Oracle Cloud Always Free, any ~$4/mo VPS, a Raspberry Pi, or your own Mac using the tray app. Serverless platforms won't work, because a persistent connection is required.
config.json βββΊ schedule engine βββΊ runner βββΊ gateway client βββΊ Discord
(rules) (picks status (ticks (heartbeat,
for "now") 1/sec) reconnect, presence)
src/schedule.js is pure logic with unit tests; the runner only talks to Discord when the chosen status actually changes.
Token rejected/ red dot: the token is wrong or was invalidated by a password change. Copy a fresh one.- Status doesn't show for others: confirm you're not set to invisible, and that custom emoji are allowed for your account.
- Discord emailed me about a new login: expected when connecting from a new machine or VM. Verify it in your normal client.
- macOS says the app is "damaged": run
xattr -cr /Applications/Bombastatus.apponce, then open it. See First launch. Electron failed to install correctly: deletenode_modules/electronand runnpm installagain. If it persists, runnode node_modules/electron/install.js.
npm test # unit tests (node:test, no extra tooling)
npm run tray # run the tray app from sourceSee CONTRIBUTING.md. Security notes are in SECURITY.md, and release notes in CHANGELOG.md.