Minimal discord moderation assistant manager.
See COMMANDS.md for detailed command reference.
/flag target:<@user> message:<text>- Flag mods about a user, tracks toward kick quorum/unflag target:<@user>- Remove your flag about a user
/nominate add name:<text>- Nominate someone for membership/nominate list- List all current nominations and their state/mod nominate add name:<text> nominator:<@user>- Moderator: Add nomination on behalf of someone/mod nominate remove name:<text>- Moderator: Remove a nominee/mod nominate start [name:<text>]- Moderator: Start discussion for specific nominee or next in queue/mod nominate discussion hours:<number>- Moderator: Set discussion duration for current nominee/mod nominate cleanup- Moderator: Complete cleanup early and cleanup channels for nominee in CLEANUP state
- Anonymous Flagging System: Members can flag problematic users anonymously
- Nomination System: Automated membership nomination workflow with:
- Discussion channels (24 hours)
- Vote channels with EasyPoll integration (48 hours)
- Automatic quorum calculation (40% of members)
- Pass threshold (80% yes votes)
- Cleanup period (7 days)
The bot integrates with EasyPoll for anonymous voting in the nominate feature.
- Go to discord.com/developers/applications
- New Application → Name it → Bot → Add Bot
- Token: Reset Token → Copy for
DISCORD_TOKEN - Application ID: General Information → Copy for
DISCORD_APP_ID - Privileged Gateway Intents:
- ✅ Enable
MESSAGE CONTENT INTENT(required to read EasyPoll embeds) - ❌ Keep
PRESENCE INTENTdisabled - ❌ Keep
SERVER MEMBERS INTENTdisabled
- ✅ Enable
- In Discord Developer Portal, go to your app
- Left sidebar → OAuth2 → URL Generator
- Select Scopes (what the bot can do):
- ✅
bot- Allows bot to join servers - ✅
applications.commands- REQUIRED for slash commands
- ✅
- Select Bot Permissions (what bot can access):
- ✅
View Channels- See channels in the server - ✅
Send Messages- Post announcements and results - ✅
Manage Channels- Create discussion/vote channels - ✅
Read Message History- Only reads EasyPoll messages for vote parsing - Total permissions value: 2064 (or use Administrator for all permissions)
- ✅
- Scroll down → Copy the generated URL
- Open URL in browser → Choose your server → Authorize
Important: If you get "Unknown Integration" errors when using slash commands, re-invite the bot with the applications.commands scope.
cp .env.example .env
open .envFollow instructions to fill in all values.
*Enable Developer Mode: Discord Settings → Advanced → Developer Mode
- Node.js 20+
- PostgreSQL 15+
- Bun (package manager)
brew install postgresql@15
brew services start postgresql@15# Connect as default user
psql postgres
# In psql, create user and database:
CREATE USER gary WITH PASSWORD 'password';
CREATE DATABASE gary OWNER gary;
GRANT ALL PRIVILEGES ON DATABASE gary TO gary;
\qcd apps/bot
bun install
bunx prisma db push
bun run devThe easiest way to run Gary with all dependencies.
- Docker and Docker Compose installed
# Copy example env and fill in your values
cp apps/bot/.env.example .env
# Start Gary with PostgreSQL
docker compose up -d
# View logs
docker compose logs -f gary# Start services
docker compose up -d
# Stop services
docker compose down
# Rebuild after code changes
docker compose up -d --build
# View logs
docker compose logs -f
# Reset database (caution: deletes all data)
docker compose down -v
docker compose up -dYou can also run Gary without building locally:
# Pull and run with your own PostgreSQL
docker run -d \
--name gary-bot \
-e DATABASE_URL=postgresql://user:pass@host:5432/gary \
-e DISCORD_TOKEN=your_token \
-e DISCORD_APP_ID=your_app_id \
-e GUILD_ID=your_guild_id \
-e GOVERNANCE_CHANNEL_ID=channel_id \
-e GENERAL_CHANNEL_ID=channel_id \
-e MOD_FLAG_CHANNEL_ID=channel_id \
-e MOD_COMMS_CHANNEL_ID=channel_id \
-e GUILD_SALT=your_salt \
ghcr.io/its-everdred/gary:latestSelf-host or use a service like Railway.
Railway Setup:
- Fork this repo to your GitHub
- railway.app → Start New Project → Deploy from GitHub repo
- Add service → Database → Add PostgreSQL
- Click on your app → Variables → Add all variables from step 3
- Important: Set
DATABASE_URL=${{Postgres.DATABASE_URL}} - Settings → Generate Domain (for health checks)
- Deploys automatically on git push