Getting started
Ruby is a small framework on top of discord.py. It's made for single-server bots. It gives you a ready-made bot class (RubyBot), so your bot is only a config file and a folder of cogs.
What you need
- Python 3.14 or newer
- uv (pip works too, but these docs use uv)
- A MongoDB server (local, Docker/Podman, or Atlas)
- A bot application from the Discord Developer Portal
Privileged intents
Ruby turns on the Message Content and Server Members intents by default, so you need to enable both on your bot's Bot page in the Developer Portal. If you don't, Discord refuses the connection.
MongoDB
Technically MongoDB isn't required to run Ruby, but some cogs assume it works, so it's recommended.
Make a bot project
Ruby isn't on PyPI yet, so add it straight from Codeberg:
uv init --bare ruby-bot # --bare is recommended, because otherwise uv creates an src directory
cd ruby-bot
uv add "ruby @ git+https://codeberg.org/NotHMRC/Ruby"Create everything Ruby expects:
mkdir -p cogs
echo "TOKEN=discord-token-here" > .env
touch config.yaml # empty config worksYour project should end up looking like this:
my-bot/
├── pyproject.toml
├── .env # secrets: token and database
├── config.yaml # everything else
└── cogs/ # your features, one file eachRuby reads config.yaml, .env and cogs/ from the current working directory, and writes bot.log there too. Always start the bot from inside the project folder. At this point, you can start Ruby with uv run ruby, but it won't do much until we add a cog.
Secrets: .env
TOKEN=your-bot-token
MONGO_URI=mongodb://user:password@localhost:27017TOKEN is required. If MONGO_URI is left out, PyMongo connects to localhost:27017 with no login.
DANGER
Never commit .env. Add it to your .gitignore.
Settings: config.yaml
Start from Ruby's config.example.yaml. None of the sections are required.
name: "rubybot" # used for the logger and the database name
friendly_name: "Ruby Bot" # what people see
prefix: "r!"
owners: [123456789012345678] # your user id
server:
id: 123456789012345678
name: "Test Server"
invite: "https://discord.gg/example"
channels:
log: 123456789012345678 # recommended, use 0 for no log channelEvery option is listed on the Configuration page.
Your first cog
Create cogs/hello.py:
from typing import TYPE_CHECKING
from discord.ext import commands
from discord.ext.commands import Context
from ruby.utils import success
if TYPE_CHECKING:
from ruby import RubyBot
class Hello(commands.Cog, name="hello"):
def __init__(self, bot: "RubyBot") -> None:
self.bot = bot
@commands.hybrid_command(name="hello", description="Say hello.")
async def hello(self, ctx: Context) -> None:
await success(ctx, f"Hello, {ctx.author.display_name}!")
async def setup(bot: "RubyBot") -> None:
await bot.add_cog(Hello(bot))Run it
uv run rubyuv run -m ruby does the same.
Then type r!hello (or /hello) in your server. You can also mention the bot instead of using the prefix (@My Bot hello).
Next steps
- Writing cogs: config, database, strings and checks
- Errors and replies:
success(),error()and what Ruby does when a command fails - Deploying: running it in a container