> ## Documentation Index
> Fetch the complete documentation index at: https://docs.krithiv.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Playing and setup

> How to join a Murder Mystery lobby, follow day and night, and self-host the bot with Docker or the local Python tools.

Use the first part of this page to play. Use the second part to run the bot on your own machine.

Also see [roles](/projects/murder-mystery/roles), [items](/projects/murder-mystery/items), [commands](/projects/murder-mystery/commands), and [server settings](/projects/murder-mystery/settings).

## Join a game

Create a lobby with `!create` or `/create`. The host message has **Join & Play**, **Spectate instead**, and **Allow DMs from this bot**.

<Steps>
  <Step title="Allow direct messages">
    Press **Allow DMs from this bot** if the join DM does not arrive. That button is the failsafe. Night actions and your role are still sent as DMs.

    **Allow DMs from this bot** is a user install: `integration_type=1` and `scope=applications.commands`. The bot does not receive or store that OAuth grant.
  </Step>

  <Step title="Share the lobby code">
    Codes look like `MM-7F2A`. Other people join with `!join MM-7F2A` or `/join`. Use `!list` or `/list` to see open codes.
  </Step>

  <Step title="Stay in one lobby">
    A person can only be in one lobby, and only once. Use `!leave` before you join another.
  </Step>
</Steps>

Discord administrators add `-overwriteAdminWarning` when joining, for example `!join MM-7F2A -overwriteAdminWarning`.

The host can force-start with `!forceStart` (`!ownerstart` or `!fs`). Slash: `/force-start`. Starting a specific code with `!startGame` or `/start-game` is limited to the lobby host or someone with `admin.game.startGame`. The full list is on the [commands](/projects/murder-mystery/commands) page.

## Where messages go

Public status stays in the server’s setup channel, or in the channel where the lobby was created. The bot does not create a channel, category, role, or voice channel per game. Each status message is tagged with the lobby code and shows the phase, day, player count, weather, and moon.

Private roles, night menus, shop use, and whispers are DMs. Joining also sends a DM. If Discord blocks that DM, the status channel mentions the player and shows **Allow DMs from this bot**.

## Day

<Steps>
  <Step title="Open the day">
    The status channel announces the new day. Private night results stay in DMs.
  </Step>

  <Step title="Report overnight deaths">
    If someone died overnight, the status channel says so without revealing secret roles.
  </Step>

  <Step title="Pay gold">
    Gold per day starts at 1, increases by 1 every 3 days, and increases again when 5 or fewer players remain. Everyone receives that day’s gold.
  </Step>

  <Step title="Vote">
    Vote with `!vote` or `/vote`. The player with the most votes is executed. Executing the murderer wins the game for the town.
  </Step>

  <Step title="Move to night">
    The status channel shows the coming weather and moon. Night prompts go out by DM. The status channel only says that night has started.
  </Step>
</Steps>

## Night

Shop with `!shop` and `!buy`, or `/shop` and `/buy`, in your DM. Item costs are on the [items](/projects/murder-mystery/items) page.

Role abilities use a menu in the DM. Typing the option number still works. When the murderer or werewolf attacks someone, the doctor gets **Heal them** and **Let them die**.

## Leveling

`!level` and `/level` show XP for this server. A finished game grants `5 × day count` XP, plus 20 for a murderer, werewolf, or fool win, or 10 for a villager win. The next level costs `(level + 1) × 5 × level` XP.

## Add the bot to a server

Guild install. Replace the application id if you self-host:

[https://discord.com/oauth2/authorize?client\_id=1452886075621249024\&permissions=137439332416\&integration\_type=0\&scope=applications.commands+bot](https://discord.com/oauth2/authorize?client_id=1452886075621249024\&permissions=137439332416\&integration_type=0\&scope=applications.commands+bot)

`client_id` is the Discord application id. The scope includes `applications.commands`. Enable the **Message Content** and **Server Members** intents.

The invite grants Add Reactions, Send Messages, Embed Links, Attach Files, Read Message History, Use External Emojis, and Use External Sounds. It does not ask for Manage Channels, Manage Roles, Manage Messages, or Move Members.

Support server: [discord.gg/kriti](https://discord.gg/kriti).

## Run it yourself

### Requirements

* Docker, or Python 3.11+
* A Discord application with the **Message Content** and **Server Members** intents enabled
* A bot token

<Warning>
  Keep the token in `.env` on the machine that runs the bot. When you report an issue, leave the token out. A deletion request should include the server id and user id, still without a token. Details are on [bot privacy](/projects/murder-mystery/privacy).
</Warning>

### Quick start

<Steps>
  <Step title="Clone the repository">
    The public source is [Krithiv-7/Murder-Mystery-Bot-main](https://github.com/Krithiv-7/Murder-Mystery-Bot-main). More projects are on [justkrithiv](https://github.com/justkrithiv).

    ```bash theme={null}
    git clone https://github.com/Krithiv-7/Murder-Mystery-Bot-main.git
    cd Murder-Mystery-Bot-main
    cp .env.example .env
    ```
  </Step>

  <Step title="Add the token">
    Put your token in `.env`:

    ```env theme={null}
    DISCORD_TOKEN=your-token
    ```
  </Step>

  <Step title="Start the bot">
    ```bash theme={null}
    docker compose up -d
    docker compose logs -f bot
    ```
  </Step>
</Steps>

Stop the stack, restart it, or update after a pull:

```bash theme={null}
docker compose down
```

```bash theme={null}
docker compose restart
```

```bash theme={null}
git pull
docker compose build --pull
docker compose up -d
```

Other useful commands:

```bash theme={null}
docker compose ps
docker compose logs -f
```

### Data on disk

Persistent files live in `./data` (the SQLite database and heartbeat). The database uses WAL mode and an in-memory cache so many servers can read settings without waiting on disk. Backups are written to `./backups`. Logs are written to `./logs`. Those directories are mounted into the container, so `docker compose down` does not delete them.

Write a backup:

```bash theme={null}
docker compose exec bot python -m core.cli backup
```

That writes `backups/backup-YYYY-MM-DD.sqlite`. To restore, stop the bot, replace `data/bot.sqlite` with that file, and start the bot again.

Import an older `data.json` without deleting it:

```bash theme={null}
docker compose exec bot python -m core.cli migrate
```

The first SQLite startup also imports `data.json` automatically when the database has no guilds yet.

### Configuration

Environment defaults live in `.env`. Each server can override the prefix and the game timers from `!settings` or the settings panel. See [server settings](/projects/murder-mystery/settings).

| Variable | Purpose |
| - | - |
| `DISCORD_TOKEN` | Bot token. Required. |
| `DATABASE_URL` | Default `sqlite:///data/bot.sqlite` |
| `BOT_PREFIX` | Default prefix when a server has not chosen one |
| `LOG_LEVEL` | `INFO` by default |
| `MMB_STORAGE` | `sqlite` (default), `json`, or `mongo` |
| `MMB_TESTING_BOT` | `true` skips official-server-only setup |

MongoDB is optional. Install it with `pip install pymongo dnspython` and set `MMB_STORAGE=mongo`. The default Docker setup does not run MongoDB.

### Local development

```bash theme={null}
make install
make test
make lint
make run
```

`make run` uses the local Python environment. `make docker` starts Compose. Tests do not connect to Discord.

## If something fails

* `ERROR: DISCORD_TOKEN is missing.` Add the token to `.env` and run `docker compose up -d` again.
* The bot is online but ignores `!` commands. Enable the **Message Content** intent, and check that an admin has not disabled the command in the settings panel.
* The invite scope includes `applications.commands`. Enable the **Message Content** and **Server Members** intents before you invite the bot.
* A player never receives role DMs. Joining sends a DM. If Discord blocks it, the status channel mentions that player and shows **Allow DMs from this bot**.
* `docker compose ps` shows the container as unhealthy. Wait for the start period, then check `docker compose logs -f bot`. The health check only looks at a heartbeat file written by the running bot.
* Discord administrators join with `-overwriteAdminWarning`, for example `!join MM-7F2A -overwriteAdminWarning`.
* `!startGame <code>` and `/start-game` are for the lobby host or someone with `admin.game.startGame`. The host can force-start the active lobby with `!forceStart` (`!ownerstart` or `!fs`). A person can only be in one lobby. Use `!leave` before joining another.


## Related topics

- [Murder Mystery Bot privacy](/projects/murder-mystery/privacy.md)
- [Murder Mystery Bot](/projects/murder-mystery/overview.md)
- [Server settings](/projects/murder-mystery/settings.md)
- [Items](/projects/murder-mystery/items.md)
- [Roles](/projects/murder-mystery/roles.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.