Skip to content

Configuration Reference

Configuration lives in appsettings.json (committed) and appsettings.Production.json (production overrides). Any value can be overridden by an environment variable using the Section__Key convention — e.g. BotConfig__MinMessages=10.

Secrets (token, API keys, base64 credentials) are never committed. They come from environment variables sourced from the droplet's .env file.

BotConfig section

Authentication & core

Key Default Description
Token (env only) Discord bot token. Set via BotConfig__Token env var, never in JSON.

AWOL system

Key Default Description
AwolRoleName AWOL Role assigned to inactive users.
HqChannelName awol-list Channel where AWOL notifications are posted.
WindowDays 28 Default activity tracking window.
ShortWindowDays 14 Shorter window for roles in ShortWindowRoles.
ShortWindowRoles Guest,RCT Comma-separated roles that get the shorter window.
MinMessages 5 Min messages within window to stay active.
MinVoiceHours 1.0 Min voice hours within window to stay active.
AwolGraceDays 2 Days after AWOL assignment before HQ is notified.
CheckIntervalMinutes 180 How often AwolCheckService runs.
ExemptRoles Admin,Moderator,Retired,Bot,Bot Whisperer Comma-separated roles fully exempt from AWOL.
ReserveRoleName Reserve Reserve members are exempt from AWOL and /kick-awols. Tracked separately from ExemptRoles to keep the doctrinal meaning explicit.
MaxSingleSessionHours 12.0 Sessions exceeding this are clamped when computing activity.

Threshold logic

A user is flagged AWOL when they have both fewer than MinMessages and less than MinVoiceHours. Meeting either threshold keeps them safe.

Google integration

Key Default Description
GoogleCredentialsPath google-credentials.json Path to service account JSON.
GoogleSpreadsheetId (none) Spreadsheet ID for the gamertag log.
GoogleSheetName Gamertags Tab name within the gamertag spreadsheet.
RosterSpreadsheetId (none) Spreadsheet ID for the nightly roster export. Falls back to GoogleSpreadsheetId if empty.
RosterSheetName Roster Tab name for the roster export.
RosterExportHourUtc 6 UTC hour when the daily roster export runs.
RosterWindowDays 30 Activity window represented in the roster export.
RecruitSpreadsheetId (none) Spreadsheet ID for the recruit log.
RecruitSheetName Recruit Log Tab name for the recruit log.
GoogleCalendarId (none) Calendar ID synced with Apollo events.

Sharing the sheet with the service account

The service account email (in the credentials JSON) must be added as an Editor on every spreadsheet the bot writes to. Otherwise writes fail silently with a 403.

Events & voice channels

Key Default Description
EventsVoiceChannelName Events Display name of the primary events VC.
EventsVoiceChannelId 1419092374231056574 Snowflake of the primary events VC. Used as fallback for sessions recorded before CategoryId was added to VoiceSession.
EventsCategoryId 1428846421368508538 Category ID; any VC under this category counts toward event attendance. Required because temporary event VCs may be deleted before snapshots run.
EventsTextChannelName events Text channel name.
EventsTextChannelId 1427507402546217082 Snowflake of the events text channel.

Ranks & promotion

Key Default Description
RankRoles RCT,PVT,PFC,...,GA Ordered (low → high) list of rank role names.
PlatoonRoles Airborne Platoon,...,Havoc Platoon Recognised platoon roles.
CompEventMinRank CPT Min rank to use /comp-event.
PromoteDemoteMinRank MAJ Min rank to use /promote and /demote.
AwolKickMinRank MAJ Min rank to use /kick-awols.
BriefingNowMinRank BG Min rank to trigger the weekly briefing manually.

Auto-promotion

Key Default Description
AutoPromotionEnabled true Master kill-switch.
AutoPromotionDryRun false Global dry-run; logs decisions without applying.
AutoPromotionDryRunRanks (empty) Comma-separated ranks that should run dry while others promote for real.
AutoPromotionRunHourUtc 3 UTC hour for the daily auto-promotion sweep.
AutoPromotionAnnouncementChannel general-chat Channel name for promotion announcements.
AutoPromotionAnnouncementChannelId 1421928902963494922 Channel snowflake.
AutoPromotionEventBufferMinutes 30 Buffer before/after an event window for attendance counting.
AutoPromotionMinEventAttendanceMinutes 30 Min minutes attended for an event to count toward promotion.
EventAttendanceSnapshotIntervalMinutes 5 How often the snapshot service samples voice presence.
AttendanceCountingSources Clan Comma-separated set of sources counted toward attendance.

Reminders

Key Default Description
TicketCategoryName TICKET CENTER Category containing ticket channels.
TicketReminderDelayHours 24.0 Hours after open before a ticket reminder fires.
GuestReminderDelayDays 7 Days before a Guest is reminded to upgrade.
GuestReminderChannelName general-chat Where guest reminders are posted.
OnboardingReminderDelayHours 24.0 Hours after RCT assignment before onboarding reminder fires.
RulesChannelName rules Used in onboarding messaging.

Disboard bump reminder

Key Default Description
BumpReminderEnabled true Toggle.
BumpReminderDelayHours 2.5 Delay between Disboard bumps before reminding.
BumpReminderChannelId 1419819225287233547 Where to post the reminder.
DisboardBotId 302050872383242240 Disboard's user ID.
BumpReminderRestartGraceMinutes 60 After bot restart, suppress reminders this many minutes.

Apollo

Key Default Description
ApolloBotName Apollo Display name of the Apollo bot for capture filtering.

Claude section (Anthropic)

Key Default Description
ApiKey (env only) Anthropic API key. Set via Claude__ApiKey.
Model claude-sonnet-4-6 Model used for the weekly briefing.

WeeklyBriefing section

Key Default Description
OfficerChannelId 1499843996032438272 Channel where the briefing is posted.
RunOnDayUtc Sunday Day of week (UTC) for the run.
RunAtUtc 23:30 Time of day (UTC, HH:mm).
DryRun false Generate but don't post.
MaxOutputTokens 1500 Cap on the model's output length.

RedditLeads section

Key Default Description
Enabled true Toggle.
PollingIntervalMinutes 10 Poll cadence.
UserAgent ClanGuard/1.0 by xAP3XRONINx Required by Reddit. Must be unique and descriptive.
LeadsChannelId 1502432175059107973 Where leads are posted.
Subreddits (see appsettings) Comma-separated subreddit list.
MaxPostAgeHours 24 Ignore posts older than this.

See Reddit Leads for the matcher rules.

PatrolWatch section

Key Default Description
Enabled true Toggle.
LfgChannelId 1410345370910851243 Channel where squad-formed alerts are posted.
MinSquadSize 3 Minimum players in a VC to count as a squad.
DebounceSeconds 12 Wait period before firing to absorb rapid join/leave churn.
StoodDownLingerSeconds 60 Wait after squad falls below threshold before declaring "stood down".
MatchedGames (see appsettings) List of games tracked, each with display name, activity substrings, accent color, thumbnail.
ExcludedCategoryIds [1428846421368508538] Categories that don't fire alerts (e.g. EVENTS).
ExcludedChannelIds (list) Specific channels that don't fire alerts.

Logging section

Standard .NET logging config. The default is Information. Set Logging__LogLevel__Default=Debug (or per-namespace) for verbose output.

Environment variables on the droplet

In /opt/clanguard/.env:

DISCORD_BOT_TOKEN=... ANTHROPIC_API_KEY=...

These are read by docker-compose.yml and passed into the container as BotConfig__Token and Claude__ApiKey.

Override precedence

appsettings.json → appsettings.Production.json → environment variables ↑ wins