Configuration
Most configuration happens in the web dashboard. A handful of per-user DM commands are also available.
Web Dashboard
After installing Morgenruf, visit https://<your-api-domain>/dashboard to configure
your workspace. All workspace-level settings live here.
Standup channel
The channel where the daily summary is posted after responses are collected. Make sure you have
also run /invite @Morgenruf in that channel so the bot can post there.
Schedule
Three settings control when standups fire:
- Time β 24-hour time at which participants receive their standup DM (e.g.
09:00) - Timezone β IANA timezone for the workspace schedule (e.g.
America/New_York,Europe/Berlin). Individual members can override this with thetimezoneDM command. - Days of week β which days to run standups (default: MonβFri)
Custom questions
The question list is fully editable in the dashboard under Edit Standup β Questions. You can add, remove, and reorder questions. The default set is:
- What did you work on yesterday?
- What are you working on today?
- Any blockers or anything the team should know?
- How are you feeling today? π π π (mood β always last)
The mood question (π/π/π) is a fixed final question and is always tracked in analytics regardless of your custom question list.
Reminder
Set a number of minutes before standup time to send a heads-up DM to each participant
(e.g. 15 means "reminder 15 minutes before standup"). Set to 0 to disable reminders.
Members
The Members section in the dashboard controls who participates in standups. Add or remove team members here. Only listed members receive standup DMs and appear in analytics.
Edit window
Number of hours after submission during which a user can edit their standup answers. After this window closes, responses are locked. Default is 2 hours.
DM Commands
Open a direct message with @Morgenruf in Slack and send any of the following commands. These are per-user commands β they affect only you, not the whole workspace.
| Command | Description |
|---|---|
standup |
Start your standup right now, without waiting for the scheduled time. |
skip |
Skip today's standup β you won't receive a standup DM today. |
timezone America/New_York |
Set your personal timezone override. The standup DM will arrive at the configured time in your timezone, not the workspace default. Use any IANA timezone name. |
help |
Show available commands. |
There are no config channel, config time, config timezone, config days, or config questions DM commands. All workspace-level configuration is done in the web dashboard at /dashboard.
Example: trigger standup now
Example: skip today
Example: set personal timezone
Analytics & Export
The Analytics tab in the dashboard shows a per-member participation table. Switch between a 7-day and 30-day view to see who's been submitting standups and who's been skipping.
To export standup data as a CSV, click the Export CSV button in the Analytics tab. You can optionally filter by date range before exporting.
Webhooks
Morgenruf can POST a signed payload to your endpoint whenever a standup is completed. Register webhook endpoints in the dashboard under the Webhooks tab.
Event: standup.completed
Each request includes an HMAC-SHA256 signature header:
X-Morgenruf-Signature: sha256=<hex-digest>
http
Example payload:
{
"event": "standup.completed",
"team_id": "T012AB3CD",
"user_id": "U056EF7GH",
"timestamp": "2025-01-15T09:03:42Z",
"answers": {
"yesterday": "Finished the auth refactor.",
"today": "Writing tests for new API endpoints.",
"blockers": "None.",
"mood": "π"
}
}
json
Verify the signature by computing HMAC-SHA256(secret, request_body) and comparing it to the value in the header. Reject requests where the signature doesn't match.
Weekly Digest Email
Every Sunday at 6:00 PM (workspace timezone), Morgenruf sends a weekly digest email to the workspace admin. The email includes:
- Total responses for the week
- Overall participation percentage
- Per-member breakdown with a π’ bar chart
Weekly digest emails require RESEND_API_KEY to be set in your environment. Without it, digest emails are silently skipped. See the Environment Variables section below.
Environment Variables
If you're self-hosting, set these environment variables in your
.env file or container environment.
| Variable | Required | Description |
|---|---|---|
SLACK_CLIENT_ID |
β Required | Client ID from your Slack app's Basic Information page. |
SLACK_CLIENT_SECRET |
β Required | Client Secret (32 hex chars). Keep this secret β never commit to source control. |
SLACK_SIGNING_SECRET |
β Required | Signing Secret (32 hex chars). Different from the Client Secret. Found under Basic Information in your Slack app settings. |
DATABASE_URL |
β Required | PostgreSQL connection string, e.g. postgresql://user:pass@host:5432/db |
APP_URL |
β Required | Public HTTPS URL of this instance (no trailing slash), e.g. https://api.your-domain.com. Used for OAuth redirect URIs and webhook callbacks. |
FLASK_SECRET_KEY |
β Required | Secret key for Flask session signing. Generate with: openssl rand -hex 32 |
RESEND_API_KEY |
Optional | API key for Resend. Required for welcome emails and weekly digest emails. Emails are silently skipped if omitted. |
PORT |
Optional | HTTP port to listen on. Defaults to 3000. |
LOG_LEVEL |
Optional | Logging verbosity: DEBUG, INFO, or WARNING. Defaults to INFO. |
Keep your secrets safe. Never commit SLACK_CLIENT_SECRET, SLACK_SIGNING_SECRET, or FLASK_SECRET_KEY to source control. Use a .env file (gitignored) or a secrets manager.