A Discord bot built around a Cyberpunk TTRPG fixer character. Yu-Jin watches the door, keeps a favor ledger, and notices when people go quiet. All settings are configurable per-guild via slash commands.
cp .env.sample .env # then fill in your credentials
npm install
npm run register # one-time: register slash commands with Discord
npm start| Variable | Description |
|---|---|
DISCORD_TOKEN |
Bot token from the Discord Developer Portal |
APP_ID |
Application ID |
ANTHROPIC_API_KEY |
Anthropic API key for Yu-Jin's AI responses |
GUILD_ID |
(Optional) Register commands to a specific guild for instant updates during development |
DATA_DIR |
(Optional) Directory for guild-config.json. Set to /data on Railway to persist config to a Volume across redeploys. |
| Script | Description |
|---|---|
npm start |
Run the bot |
npm run dev |
Run with auto-reload via nodemon |
npm run register |
Register slash commands with Discord |
npm test |
Run unit tests |
Sets the text channel where voice join notifications and scheduled messages are posted. Requires Manage Guild permission.
Sets a user to mention in every voice join notification. Requires Manage Guild permission.
Removes the mention user. Notifications will still post, just without a ping. Requires Manage Guild permission.
Sets how often Yu-Jin posts a random message to the notify channel. Pass minutes:N, or use /stop-schedule to disable. Requires Manage Guild permission.
Stops scheduled random messages. Requires Manage Guild permission.
Turns off voice join notifications. Requires Manage Guild permission.
Track favors between server members. Available to all members.
/favor log @user reason:... direction:i-owe|they-owe— Log a new favor/favor list [@user]— List unsettled favors involving you (or another user)/favor settle @user— Mark the oldest unsettled favor between you and a user as settled
Watch for users who have gone quiet. Requires Manage Guild permission.
/absence watch @user days:N— Alert if a user hasn't joined voice in N days/absence unwatch @user— Stop watching a user/absence list— Show all watched users and their last-seen dates
Shared quest board, visible to the whole server.
/quest add name:... description:...— Add a new quest/quest list [status:...]— List quests, optionally filtered by status/quest update quest:... status:...— Update quest status (creator or Manage Guild only)/quest delete quest:...— Delete a quest (creator or Manage Guild only)
Statuses: Not Started, In Progress, Completed.
Talk to Yu-Jin directly via slash command.
/ask message:...— Send a message; Yu-Jin replies in-channel with conversation memory
You can also @mention the bot or reply to one of her messages to start or continue a conversation. She remembers up to 10 exchanges per user (in-memory, resets on bot restart).
The bot runs as a persistent process (Gateway WebSocket) and must be always-on. It is hosted on Railway — connected to this GitHub repo, with environment variables set in the Railway dashboard. Railway redeploys automatically on every push to main.
Watch Paths: Configure the Railway service to watch only bot files (e.g. index.js, config.js, commands.js, package.json, *.json) so pushes that only affect web/ don't trigger an unnecessary redeploy.
Yu-Jin connects to Discord via the Gateway API (WebSocket) and listens for VOICE_STATE_UPDATE events. When a human user joins a voice channel, it picks a random message from join-messages.json and posts it to the configured notification channel.
It also supports:
- Periodic random messages sourced from
messages.json, on a configurable interval per guild; generated by AI when available, falling back to the JSON list - Favor ledger stored per-guild in
guild-config.json - Absence detection — a daily check that pings watched users who haven't joined voice within their configured threshold
- Quest board — per-guild quest tracker with status tracking
- AI conversation — @mention or reply to the bot to talk to Yu-Jin; also available via
/ask. Uses Claude Haiku with per-user conversation memory (resets on restart)
Guild preferences are stored in guild-config.json (created at runtime, gitignored).
A static Next.js site (Tailwind CSS + MDX) with a home page, user guide, Terms of Service, and Privacy Policy. Deployed to Vercel with Root Directory set to web in the Vercel project settings.
cd web
npm install
npm run dev # localhost:3000
npm run build # generates out/Content pages live in web/content/. web/content/guide.mdx mirrors docs/USERGUIDE.md — keep both in sync when updating.
