A Discord bot that automates daily standups with GitHub integration. It DMs contributors at a scheduled time to collect updates, then compiles and posts them to a designated channel.
- Scheduled DM prompts — Automatically DMs all members with a configured role at a set time (CET, weekdays)
- Update collection — Contributors reply via DM with text updates, supporting multiple messages
- Compiled standup posts — All updates are formatted and posted to an output channel at standup time
- GitHub link detection — Recognizes
owner/repo#123shorthand and full GitHub URLs, enriches them with title/state via the API - GitHub activity summary — Includes open PRs and recent issues from connected repos in the standup post
/github-issueslash command — Search and reference GitHub issues directly from Discord with autocomplete
- Node.js 20+ (22 recommended)
- A Discord bot application (see setup below)
- A GitHub personal access token (for GitHub features)
- Go to the Discord Developer Portal
- Click "New Application" in the top right
- Give it a name (e.g. "Standup Bot") and click Create
- In your application, go to the Bot tab in the left sidebar
- Click "Reset Token" to generate a bot token
- Copy the token — you'll need it for
DISCORD_TOKENin your.env - You will only see this token once. If you lose it, you'll need to reset it again.
Still on the Bot tab:
- Scroll down to "Privileged Gateway Intents"
- Enable all three intents:
- Presence Intent — not strictly required, but useful for future features
- Server Members Intent — required to fetch members by role
- Message Content Intent — required to read DM message content
- Go to the OAuth2 tab in the left sidebar
- Under OAuth2 URL Generator, select the following scopes:
botapplications.commands
- Under Bot Permissions, select:
- Send Messages
- Send Messages in Threads
- Embed Links
- Read Message History
- Use Slash Commands
- Copy the generated URL at the bottom and open it in your browser
- Select your server and click Authorize
- The generated URL should be: https://discord.com/oauth2/authorize?client_id=1483136003450601744&permissions=277025474560&integration_type=0&scope=bot+applications.commands
To get Discord IDs, you need to enable Developer Mode:
- Open Discord Settings > Advanced > Enable Developer Mode
- Server ID: Right-click your server name in the sidebar > Copy Server ID
- Channel ID: Right-click the channel you want standup posts in > Copy Channel ID
- Role ID: Go to Server Settings > Roles > right-click the role > Copy Role ID
- Go to GitHub Settings > Developer settings > Personal access tokens > Fine-grained tokens
- Click "Generate new token"
- Give it a descriptive name (e.g. "standup-bot")
- Set the expiration as needed
- Under Repository access, select the repos you want the bot to access
- Under Permissions > Repository permissions, grant:
- Issues: Read
- Pull requests: Read
- Click Generate token and copy it for
GITHUB_TOKENin your.env
# Clone the repo
git clone <your-repo-url>
cd standup-bot
# Install dependencies
npm install
# Copy the example env and fill in your values
cp .env.example .envEdit .env with your values:
# Discord Bot
DISCORD_TOKEN=your-bot-token-here
DISCORD_SERVER_ID=123456789012345678
DISCORD_ROLE_ID=123456789012345678
DISCORD_OUTPUT_CHANNEL_ID=123456789012345678
ADMIN_USER_ID=123456789012345678
# Schedule (HH:mm in CET)
DM_TIME=09:00
STANDUP_TIME=12:00
STANDUP_DAYS=MON,TUE,WED,THU,FRI
# GitHub
GITHUB_TOKEN=ghp_your-token-here
GITHUB_REPOS=your-org/repo1,your-org/repo2| Variable | Description |
|---|---|
DISCORD_TOKEN |
Bot token from the Discord Developer Portal |
DISCORD_SERVER_ID |
The guild (server) ID where the bot operates |
DISCORD_ROLE_ID |
The role ID — members with this role will be prompted for updates |
DISCORD_OUTPUT_CHANNEL_ID |
The channel where compiled standups are posted |
ADMIN_USER_ID |
Your Discord user ID — only this user can run admin commands |
DM_TIME |
Time to DM contributors (HH:mm, CET timezone) |
STANDUP_TIME |
Time to post the compiled standup (HH:mm, CET timezone) |
STANDUP_DAYS |
Comma-separated days to run: MON,TUE,WED,THU,FRI (default: weekdays) |
GITHUB_TOKEN |
GitHub personal access token for API access |
GITHUB_REPOS |
Comma-separated list of owner/repo to track |
# Development (hot reload)
npm run dev
# Production
npm start
# Build to JavaScript
npm run build
npm run start:prod- At
DM_TIME(weekdays) — the bot DMs every member with the configured role, asking for their standup update - Contributors reply via DM — they can send multiple messages, reference GitHub issues (
owner/repo#123or full URLs), and mention other contributors - At
STANDUP_TIME— all collected updates are compiled into a formatted embed and posted to the output channel, with GitHub references enriched (title, state) and an activity summary of open PRs/issues
| Command | Description |
|---|---|
/github-issue |
Browse and reference GitHub issues from connected repos. Has autocomplete for repo selection and issue search. |
/test-prompt |
Manually trigger the DM standup prompt (admin only) |
/test-standup |
Manually trigger the compiled standup post (admin only) |
/standup-status |
Show current cycle status: who was prompted, who responded, who's pending (admin only) |
The admin commands above let you test the full cycle without waiting for cron:
- Run
npm run devto start the bot - Use
/test-promptin Discord — this sends DM prompts to all role members immediately - Reply to the bot's DM with a test update (try including
owner/repo#1to test GitHub refs) - Use
/standup-statusto verify your response was collected - Use
/test-standupto trigger the compiled standup post to the output channel
src/
├── index.ts # Entry point
├── config.ts # Environment config loader
├── types.ts # Shared TypeScript interfaces
├── bot.ts # Discord.js client setup
├── store.ts # In-memory update store
├── cron/ # Scheduled jobs
│ ├── index.ts # Cron registration
│ ├── dmPrompt.ts # DM prompt sender
│ └── standupPost.ts # Standup compiler & poster
├── collectors/
│ └── dmCollector.ts # DM reply handler
├── github/ # GitHub integration
│ ├── client.ts # Octokit instance
│ ├── links.ts # Link detection & enrichment
│ ├── issues.ts # Issue search & fetch
│ └── activity.ts # PR/issue activity summary
├── commands/ # Slash commands
│ ├── register.ts # Command registration
│ ├── handler.ts # Interaction router
│ └── githubIssue.ts # /github-issue command
└── formatters/ # Discord embed builders
├── standupEmbed.ts # Standup embed formatter
└── githubEmbed.ts # Issue/PR embed formatter
This project is licensed under the GNU General Public License v3.0. See LICENSE for details.