Docs/Plugins/Moderation Logs
Moderation Logs
Route 109 action types into the channels you choose, with per-channel subscriptions and custom formats.
The mod log turns everything that happens - moderation actions, message edits and deletions, member joins and leaves, role and channel changes, config edits - into readable log lines in the channels you choose.
plugins:
modlog:
channels:
674638168474915242:
includes: [] # empty = subscribe to everything
701234567890123456:
includes: [MESSAGE_DELETE, MESSAGE_EDIT]
709876543210987654:
excludes: [MESSAGE_DELETE] # everything except
ignored_channels: [665875009507426304]
ignored_users: [] # hide a user's own actions and events about them
ignored_staff: [] # hide a staff member entirely, both directions
new_member_threshold: 900 # flag accounts younger than this (seconds)
Setup checklist
- Create a private log channel and give HepBoat View Channel, Send Messages, Embed Links, Attach Files, and Read Message History.
- Open Mod Log, add the channel, and choose everything or a small event set. An empty include list means everything; it does not mean nothing.
- Subscribe the first test channel to Config updated and Message edited.
- Save a harmless config change, then edit a test message. Confirm both entries arrive with the expected context.
- Choose Plain text or Embeds, timestamps, timezone, and compact mode per channel.
- Add ignored channels or users only after the positive test. Broad ignore lists are a common reason a healthy log appears silent.
- Split high-volume events into another channel if needed. Use includes for a narrow log and excludes for an everything-except log.
- If custom formats are granted, customize one low-risk event and test it before changing a frequently emitted action.
Routing
Each channel under channels subscribes with includes (only these) or
excludes (everything but these). Action names are stable identifiers like
MEMBER_BAN, MESSAGE_DELETE, CONFIG_UPDATE - the dashboard's Mod Log
page lists all of them grouped by category with pickers, which beats typing
them.
ignored_channels suppresses noise at the source - nothing posts about
events in those channels (a bot channel's message deletes, for example).
Threads count as the channel they live under, so ignoring a channel also
ignores everything in its threads and forum posts. It is safe to list your
mod log channel itself: that hides staff cleanup happening inside it (the
usual reason to list it) while every other channel's events still post
there as normal.
The two user lists differ in direction, and picking the right one matters:
ignored_users ignores a user's own actions and the events about them -
their message edits and deletes, their joins and leaves, their nickname
changes, and moderation taken on them. It does not hide things they do
to other users: if they warn someone or delete someone else's message, that
entry is about the other user, so it still logs. Use it for noisy bots and
users whose events you simply don't want in the log.
ignored_staff is for when you want a staff member's work kept out of
the log too. It covers everything ignored_users covers, plus the other
direction: infractions they issue, messages they delete, commands they run,
tag and config edits they make - none of it posts. The actions themselves
still happen and infractions are still recorded against the target; only the
log lines are skipped. Two caveats: bulk purges log a channel-level line
that never names who ran them, and actions taken through Discord's own UI
(a manual ban from the member list, for example) carry no actor for the bot
to match, so those log as they always did.
Both lists take user IDs or role IDs - a role entry covers every member who currently holds that role, so you can stealth your whole mod team with one line instead of maintaining a list of people.
Smart behaviour you get for free
- Debounce - when the bot itself causes an event (a censor deletion, a purge), you get one purposeful log line, not a burst of raw events.
- Attribution - actions carry the moderator, the reason, and the infraction number where relevant.
- Message archives - bulk deletions link a web archive of the removed messages instead of flooding the log.
Native Discord AutoMod
HepBoat also logs Discord's own AutoMod: every rule trigger
(AUTOMOD_ACTION - what matched, what Discord did about it) and every rule
create, update, or delete land in the mod log like any other event, so your
AutoMod activity and your bot activity read as one audit trail.
The dashboard's AutoMod page lists your server's native rules - keyword
lists, mention limits, and the rest - straight from Discord. With the
AUTOMOD_DASH feature you can also create, edit, toggle, and delete rules
from that page; without it the page stays read-only and the logging above
keeps working regardless.
Recently added events
Worth subscribing if your log predates them:
- Unbanned - the bot lifting a ban (command, appeal approval, or the dashboard), with the moderator and reason. The gateway's own Member unbanned event still covers unbans done by hand in Discord.
- Timeout removed by a mod -
!untimeout, separate from the plain Timeout cleared entry that covers a timeout simply expiring. - Lockdown enabled manually / Lockdown lifted manually - the
!raid onand!raid offcommands, naming the moderator. - Member arrested (economy lockout) / Member pardoned - the games economy lockout applied by staff or by a failed bank heist, and the early release from it.
- Message deleted (no stored copy) - see below. Most servers want this on.
Deleted messages we have no copy of
Some deleted messages cannot be described. HepBoat keeps a rolling archive of messages so a delete can show you who wrote it and what it said, but that archive does not cover everything: other bots' messages are never stored, and messages older than the archive window have aged out. When one of those is deleted, Discord tells us only three things - which channel, the message id, and (from the id) when it was posted.
Those deletes used to post as a full Message deleted entry with the author, the content and the id all reading "unknown", which took six lines to say nothing. They now post as their own event, Message deleted (no stored copy), as a single line with the three facts we have:
🗑️ Message deleted in #general - no stored copy, sent August 22, 2026 5:50 AM (16 hours ago), id 1540659380528353411
Keep it on if you want a complete record of deletions, including bot cleanup. Turn it off, with excludes or by leaving it out of an includes list, if you only care about deletions you can actually act on. Turning it off does not affect normal Message deleted entries.
One thing to know: ignored_users cannot filter these. Ignoring a user hides
events about that user, and here there is no author to compare against, so a
noisy bot's deletes cannot be filtered that way. Your two options are turning
this event off, or adding the channel to ignored_channels if you do not want
anything from it.
Per-channel options
Each channel in plugins.modlog.channels takes more than an event list:
mode: PLAINwrites one line per event;mode: PRETTYwrites embeds. The dashboard calls this Plain text / Embeds.richpromotes named actions to an embed inside an otherwise plain channel, for the handful you want to stand out.compacttightens the plain one-liners.timestampsprefixes each entry with the time, rendered intimezone.exclude_categorydrops everything from channels under a category, the category-wide counterpart toignored_channels.
Custom formats
With the MODLOG_CUSTOM_FORMAT feature, any action's rendering can be
overridden per server (custom), in both plain and pretty modes. The
dashboard's format builder starts you from the current format - hit
Customize on any event and the plain one-liner and the full embed load
ready to edit, with a Discord-style preview updating live against sample
data as you type. You control everything the bot can render: the embed's
title, text, author line and icon, thumbnail, color, footer, and up to 25
fields you can rename, reorder, and set inline or full-width. A "Load
default" button per section takes that half back to the shipped format,
and the editor warns about placeholders that would not resolve.
Pick one of your log channels above the event list to browse just the events that channel receives - handy on a busy setup. Formats themselves always apply server-wide.
An override only replaces the parts you actually fill in. Anything you leave blank keeps the shipped default, so a format that changes just the plain one-liner still gets the standard embed fields on a channel set to pretty mode, and clearing a section back to empty restores the default rather than rendering nothing.
Overrides save and stage even before the feature is granted; the bot uses the defaults until then.
Troubleshooting
- The channel receives nothing: check channel permissions and whether the event is included, excluded, or ignored at the channel, category, user, or staff level.
includes: []looks empty in YAML: it deliberately subscribes to everything.- Bot actions produce duplicate raw events: report the exact action and both log lines. The debounce layer should replace them with one purposeful event.
- Manual Discord actions lack a moderator name: Discord may not provide an actor on the gateway event.
- A custom format saves but defaults render: the server needs
MODLOG_CUSTOM_FORMATfor the override to execute. - One long event never appears: check posting permission and whether Discord rejected an embed or attachment in that channel.
Commands
Arguments in {curly braces} are required. Arguments in [square brackets] are optional.
| Command | What it does |
|---|---|
/modlog hush |
Silence modlog output in this guild until unhushed. |
/modlog unhush |
Re-enable modlog output after a hush. |