CLI tool that archives Mattermost channel messages to local markdown files.
Each channel is written to <output_dir>/<channel>/YYYY/MM/YYYY-MM-DD.md.
State is tracked in <output_dir>/state.json so interrupted runs resume
where they left off.
- Python 3.11+
- uv (package manager)
git clone <repo-url>
cd <cloned-dir>
make buildThis installs the tool and its dependencies into a local .venv.
Copy the example config and edit it:
cp config.example.toml config.tomlconfig.toml fields:
| Field | Required | Description |
|---|---|---|
server_url |
yes | Mattermost server URL, no trailing slash (e.g. https://chat.example.com) |
access_token |
no* | Personal access token. Can be set via MM_ACCESS_TOKEN env var instead |
team |
yes | Team name or 26-character team ID |
channels |
yes | List of channel names or IDs to archive |
earliest_date |
yes | Oldest date to retrieve on first run, YYYY-MM-DD (UTC) |
output_dir |
yes | Directory to write files into. Must already exist and be writable |
max_retries |
no | Retry attempts on HTTP 429 rate limiting. Default: 5 |
*access_token is required either in the config file or via the environment variable.
In Mattermost: Profile > Security > Personal Access Tokens > Create Token.
export MM_ACCESS_TOKEN="your-token"The env var takes precedence over any access_token value in the config file.
uv run mattermost-archiveThis reads ./config.toml by default. To specify a different config file:
uv run mattermost-archive /path/to/config.tomlThe first run performs a full backfill from earliest_date to today,
fetching messages newest-first. Progress is written to disk as each day
completes. Expect a lot of API pages for large channels.
Press Ctrl-C to stop. Progress is saved to state.json after each
completed day. Re-run the tool to continue the backfill from where it
stopped -- already-archived days are not re-fetched.
Once the backfill is complete, re-running fetches only messages newer than the last archived post. The most recent day's file is updated in-place.
Each day file looks like:
# channel-name - 2026-04-15
**[2026-04-15T09:12:34Z] Alice Smith**: Good morning
**[2026-04-15T09:15:02Z] Bob Jones** *(reply)*: Morning!
**[2026-04-15T10:00:00Z] System**: Alice Smith joined the channel.
Messages from bots and webhooks that use Slack-style attachments are
rendered from props.attachments fields when the message body is empty.
make test # pytest with coverage (80% minimum enforced)
make lint # ruff check + format check
make typecheck # pyright strict
make clean # remove .venv and build artifacts