The Ghostty Discord Bot, humorlessly named "Ghostty Bot."
It originally powered the invite system during Ghostty's private beta period, successfully inviting ~5,000 people. It now serves as the community's helper bot, making development discussion and community moderation more efficient.
Warning
The bot is tailor-made for the Ghostty community and will most definitely be unsuitable for other servers. If you're looking to use similar features, you should consider looking for a more general-purpose bot, or forking this project and modifying it to suit your needs. That said, the core intent of this guide is to help contributors set up their development environment for building and testing new features. Contributions are the goal, not standalone usage.
The bot is built and deployed using Nix. While it's possible to develop the bot without it, the preferred and supported method is through a Nix-based workflow. To that end:
- The bot must successfully build and run using the Nix setup.
- If you're developing outside of Nix, you are responsible for troubleshooting
any issues that arise.
As a tip: as long as no changes are made to the project's configuration (e.g. build dependencies), if the bot successfully runs outside of Nix, it will most likely work within Nix as well.
- Go to the Discord Developer Portal.
- Click on the "New Application" button.
- Pick a name for your bot.
On your newly created bot's dashboard:
- Go to "Bot" on the sidebar.
- Click on the "Reset Token" button.
- Save the newly generated token for later.
- Under "Privileged Gateway Intents", enable:
- Server Members Intent
- Message Content Intent
- Go to "OAuth2" on the sidebar.
- Under "OAuth2 URL Generator", select the
bot
scope. - Under "Bot Permissions" that appears, choose the following permissions:
- Attach Files
- Manage Messages
- Manage Roles
- Manage Threads
- Manage Webhooks
- Send Messages
- Use External Apps
(your URL should contain a1125917892061184
bitfield forpermissions
)
- Use the generated URL at the bottom of the page to invite the bot to your server.
A GitHub token is necessary for the bot's Entity Mentions feature.
You can get one in two ways:
- On GitHub, go to Settings > Developer settings > Personal access tokens > Tokens (classic) > Generate new token, or use this link: Generate new token. As the bot only accesses public repositories, it doesn't require any scopes.
- If you have the
gh
CLI installed and authenticated, rungh auth token
.
The following channels will be necessary:
#help
: a forum channel#media
: a text channel#showcase
: a text channel
The following roles will be necessary (both requiring the Manage Messages permission):
mod
helper
Create a .env
file in the root of the project based on .env.example
.
Below are explanations for each variable:
- channel/role IDs from step 3:
BOT_HELP_CHANNEL_ID
BOT_MEDIA_CHANNEL_ID
BOT_SHOWCASE_CHANNEL_ID
BOT_MOD_ROLE_ID
BOT_HELPER_ROLE_ID
BOT_TOKEN
: the Discord bot token from step 1.GITHUB_ORG
: the GitHub organization name.GITHUB_REPOS
: a comma-separated list ofprefix:repo_name
pairs used for entity mention prefixes. Themain
/bot
/web
prefixes aren't exactly fixed, but some of the bot logic assumes these names (e.g. defaulting tomain
).GITHUB_TOKEN
: the GitHub token from step 2.SENTRY_DSN
: the Sentry DSN (optional).
Run the bot with:
$ python -m app
...
After you've made your changes, run the linter and formatter:
$ ruff check
$ ruff format
This bot runs on Python 3.12+ and is managed with Poetry. To get started:
- Install Poetry (e.g. via uv or pipx).
- Install the project and run the bot:
$ poetry install
- Run the bot:
$ poetry run python -m app ...
- After you've made your changes, run the linter and formatter:
$ poetry run ruff check $ poetry run ruff format
components/
is a place for all dedicated features, such as message filters or entity mentions. Most new features should become modules belonging to this package.config.py
handles reading and parsing the environment variables and the local.env
file. Although a standalone module, it's typically accessed through asetup.py
re-export for brevity:-from app import config -from app.setup import bot +from app.setup import bot, config
core.py
loads thecomponents
package and houses the code for handling the most standard bot events (e.g.on_ready
,on_message
,on_error
).setup.py
creates the Discord and GitHub clients.utils.py
contains utility functions not exactly tied to a specific feature.__main__.py
initializes Sentry (optional) and starts the bot.
A command for linking Ghostty documentation with autocomplete and an optional message option:
Automatic links to Ghostty's GitHub issues/PRs/discussions ("entities") when a
message contains GitHub-like mentions (#1234
). It reacts to message edits and
deletions for 24 hours, while also providing a "🗑️ Delete" button for 30 seconds
in case of false positives. Mentioning entities in other repos is also supported
with prefixes:
web
for ghostty-org/website, e.g.web#78
bot
for ghostty-org/discord-bot, e.g.bot#98
main
for ghostty-org/ghostty (default), e.g.main#2137
or just#2137
The bot also keeps a TTR cache to avoid looking up the same entity multiple times (with data being refetched 30 minutes since last use), making the bot more responsive (the example below can take ~7s on the first lookup and ~0.5ms on subsequent lookups).
This feature takes care of keeping the #showcase
and #media
channels clean.
The bot will delete any message:
- without an attachment in
#showcase
- without a link in
#media
It will also DM users about the deletion and provide an explanation to make it less confusing:
Used for moving messages to more fitting channels (e.g. off-topic questions
in #development
to #tech
).
Ghostty troubleshooting questions can be turned into #help
posts with a
related feature: