# modmailbot: a Discord ticketing system that replies through staff channels

> Modmail for Discord turns a user's direct message into a modmail thread that staff can answer in a private channel. The JavaScript project runs on Node 24, keeps its state in SQLite or MySQL, and grows through plugins and snippets, but it asks you to own the bot lifecycle yourself.

**Dragory/modmailbot** — Modmail Bot is a bot for Discord that makes it easier for users to contact moderators and admins for help.

- Repository: https://github.com/Dragory/modmailbot
- Stars: 784 · Forks: 725
- Language: JavaScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/dragory-modmailbot

## A DM becomes a modmail thread, not a direct message to staff

The problem modmailbot addresses is narrow and real. On a busy Discord server, users need help, and the two normal routes both fail. Messaging a moderator privately means waiting for one person to notice, and pinging publicly in the channel exposes the question to everyone, including the person asking it. Modmailbot removes both the bottleneck and the exposure by acting as the intermediary. A user opens a direct message with the bot, and the content is relayed into a channel the staff side calls a modmail thread. Staff reply in that thread, and the replies are delivered back to the user in their direct message. From the user's point of view the whole exchange happens in DMs, while staff get a shared, reviewable record. The README names the design inspiration directly, calling it a ticketing system inspired by Reddit's modmail system, and it frames the tool as making it easier for users to contact moderators and admins for help. That framing matters for expectations. This is not a support desk with SLAs, routing rules or a customer-facing portal. It is a relay with a thread per correspondent, and the value comes from the fact that staff can see and answer a queue together rather than each user chasing a single moderator in private.

## The package manifest pins an eris fork and Node 24

Before anything runs, look at what the project actually depends on, because the manifest contains two choices that narrow who can deploy it. The Discord library is not the stock eris package. It is an aliased fork:

```json
"eris": "npm:@mivir/eris-modmailbot-fork@0.18.0-fix",
```

That line means the code imports eris from a different package name entirely, pinned to a specific version of a fork maintained for this bot. A reader expecting a standard Discord library install will get something else here, and the fork is where the thread mechanics are likely to live. The second constraint is the runtime. The manifest requires:

```json
"engines": {
  "node": ">=24.0.0"
}
```

Node 24 or newer, not Node 18 and not Node 20. The rest of the dependency list tells you the shape of the project: knex for database migrations, sqlite3 and mysql2 for the two supported database engines, ini and json5 for configuration parsing, ajv for schema validation, moment and humanize-duration for time formatting, marked for rendering message text, express and helmet for the web-facing parts, and knub-command-manager for the command layer. Plugins and snippets are documented in the docs folder, and a plugin API surface exists at src/pluginApi.js, since the manifest carries a script that turns that file into docs/plugin-api.md with jsdoc2md. The tooling is coherent, but it is the tooling of a project that expects a competent operator rather than a one-click installer.

## First run: copy the example config, install, then start the entry point

The repository ships a config.example.ini at the top level and a knexfile.js for database work. The README points to docs/setup.md for the setup procedure and to docs/configuration.md for the configuration reference, so the configuration keys themselves are described in docs rather than in the README itself. The start commands are defined in the package manifest:

```json
"start": "node src/index.js",
"start-dev": "NODE_ENV=development node --inspect=0.0.0.0:9229 src/index.js",
"watch": "NODE_ENV=development node --watch --inspect=0.0.0.0:9229 src/index.js",
"lint": "oxlint ./src",
"run-migrations": "knex migrate:latest"
```

The entry point is src/index.js, so a plain run is `node src/index.js` after an install. Two details deserve attention before you start anything. First, the development scripts bind the inspector to 0.0.0.0 on port 9229, which exposes the debugger on every interface rather than on loopback alone. That is convenient on a laptop and a hazard on a shared host, so keep those scripts for local work. Second, the `test` script is a placeholder that prints an error and exits with code 1, so `npm test` failing tells you nothing about the bot's state. Linting is real, using oxlint over ./src. For the database, `knex migrate:latest` applies the migrations under db/, and a matching migration can be scaffolded with `knex migrate:make`. The repo also carries a start.bat for Windows and a modmailbot-pm2.json for running the process under the pm2 process manager, which are the two deployment paths visible in the file list. Expect to pick one of those and own the process.

## The SQLite file is yours to back up before every update

The README is unusually direct about one operational risk: always take a backup of your db/data.sqlite file before updating the bot. That line tells you the default storage engine is a local SQLite file under db/, and that upgrade steps can rewrite it. The migration scripts in package.json confirm the schema is versioned through knex, with a `create-migration` script to add one, so the data shape does change over releases. The README also documents a two-step upgrade for anyone running a build from before February 2018: update to v2.30.1 first, run the bot once, and only then move to v3.0.0. That is a schema-era migration, not a cosmetic one, and it is a good warning about how far the data model has moved since the early days. The mysql2 dependency means MySQL is also a supported option, and for a shared or multi-node deployment that is the safer choice, since a SQLite file is a local artifact and a backup is a copy. If you keep SQLite, treat the backup as part of the release, not as an occasional chore. The README does not document a rollback procedure, so decide in advance how you would restore, and test it once before you need it.

## Plugins and snippets extend the bot without touching src

Two extension points sit alongside the core. The docs folder carries dedicated pages for snippets and for plugins, and the manifest includes a script that regenerates the plugin API documentation straight from src/pluginApi.js:

```json
"generate-plugin-api-docs": "jsdoc2md -t docs/plugin-api-template.hbs src/pluginApi.js > docs/plugin-api.md"
```

So the plugin surface is a real, documented contract rather than a convention, and the API documentation is derived from the source rather than maintained by hand. That has a practical consequence for a server operator: a plugin that needs behaviour the core does not expose can be written against a supported interface, and you can regenerate the reference after an upgrade to see what changed. Snippets are the lighter of the two mechanisms, documented separately, and are the usual home for small reusable pieces of bot behaviour. The repository also contains a public community resources repository linked from the README, which is where shared plugins and guides live. For anyone running a single server, this extension layer is often the deciding factor between modmailbot and a purpose-built script, because it keeps customisation out of the core codebase and makes it survive an upgrade. It is also the point at which you take on responsibility for whatever you install.

## Where modmailbot is the wrong tool

This project fits communities that talk to each other rather than businesses with customers. It has no notion of a service level, no assignment or escalation queue, no analytics on response times, and no customer-facing portal, because nothing in the repository suggests any of those exist. If your moderators are volunteers who answer when they feel like it, that is fine. If you need an answer within a stated window, with an audit trail attached to a ticket number, this is the wrong shape of tool. The dependency set reinforces the point: there is no billing module, no multi-tenant routing, no admin web console beyond the express and helmet pairing used for its own web surface. A second failure mode is operational. You are running a Discord bot on a shared or long-lived Node process, holding a Discord token and a database, with an inspector port available in development mode. If nobody on your team wants to own that, the operational cost will exceed what the bot saves. A third limitation is the one the README itself surfaces: it warns that a very old installation cannot jump straight to v3.0.0 and requires the v2.30.1 step first, which means an inherited or stale deployment may need more care than a clean install.

## Compared with a plain staff channel, the difference is routing and record

The realistic alternative is not another bot so much as the way many Discord communities handle this already: a dedicated support channel where users post publicly and staff answer in place. The difference in approach is specific and worth stating plainly. A support channel keeps the exchange visible to every member, so the requester is exposed, staff have to answer in front of the audience, and the conversation is interleaved with everything else posted in the channel. Modmailbot inverts that: the user is in a direct message, the staff are in a thread, and the two sides are joined by the bot. That buys privacy for the requester and a clean per-user transcript for staff. It also costs you the ambient visibility of a public channel, since nobody outside staff sees that help is happening, and it adds a moving part, the bot itself, between the user and the staff. If your community prefers open, public support, modmailbot may be more machinery than the problem needs. If your community needs private reporting channels or per-user history, the plain channel cannot give you that, and that is the gap this project fills.

## Release history is recent, and the upgrade notes live in CHANGELOG.md

The project is not dormant. The last push was on 2026-10-22, and the recent releases include v3.11.0 on 2026-07-27, v3.10.0 on 2026-04-26 and v3.9.0 on 2026-04-25. The package manifest version is 3.11.0, matching the newest release, and the top-level CHANGELOG.md plus the release notes link in the README are where each change is recorded. Two releases landing on consecutive days in April 2026 suggests a workflow where a fix ships immediately after a feature, which is worth checking against the changelog when you plan an upgrade. Because the version is at 3.11.0 and the data model has changed repeatedly, the README's instruction to back up db/data.sqlite before updating is the part to honour, and the docs folder keeps a dedicated updating.md page for the step-by-step path. The project also keeps documentation on privileged intents, which matters on Discord because a bot that cannot read messages or send them in DMs will appear to work at startup and then fail quietly on the one feature you care about. Set that up correctly the first time.

## Conclusion

Adopt modmailbot if your Discord community needs per-user transcripts, a private staff reply channel and a plugin layer without writing a bot from scratch. Skip it if you want a managed product with a support contract, if you cannot host a Node 24 process and a database, or if you need features the docs folder does not describe, because the setup docs are the only guide and the SQLite file is yours to back up and migrate. Before rollout, read docs/setup.md and docs/configuration.md end to end, copy config.example.ini rather than writing a config from scratch, confirm your database connection matches your knexfile.js setup, and test a real DM to a test server before you point staff at it.

## FAQ

### What is modmailbot and who is it for?

It is a Discord ticketing system that relays a user's direct messages into modmail threads where staff can reply. It is aimed at Discord server moderators and admins who want users to reach them without messaging them individually or pinging publicly.

### What does modmailbot need to run?

The package manifest requires Node 24 or newer and installs an aliased fork of the eris Discord library, npm:@mivir/eris-modmailbot-fork@0.18.0-fix, plus knex and either sqlite3 or mysql2 for storage. The entry point is src/index.js, started with `node src/index.js`.

### How do I update modmailbot without losing data?

The README says to always take a backup of your db/data.sqlite file before updating, and it points to docs/updating.md for the full procedure. If your build predates February 2018, you must update to v2.30.1 and run the bot once before moving to v3.0.0.

### Can modmailbot be extended with custom behaviour?

Yes. The repository documents both snippets and plugins, and the plugin API lives at src/pluginApi.js, with a script in package.json that regenerates docs/plugin-api.md from it using jsdoc2md. A community resources repository linked from the README collects shared plugins and guides.

## Sources

- [Dragory/modmailbot on GitHub](https://github.com/Dragory/modmailbot)
- [Issues](https://github.com/Dragory/modmailbot/issues)
- [License: MIT](https://github.com/Dragory/modmailbot/blob/master/LICENSE)
- [README](https://github.com/Dragory/modmailbot/blob/master/README.md)
- [Releases](https://github.com/Dragory/modmailbot/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dragory-modmailbot
