Building from source
This page explains how to build and run Antimatter from its source code, to work on it or to make your own builds. It covers the server and the web interfaces, which live in one repository, then the Docker image and the apps.
What you need
- Go, at the version in
server/go.mod(1.26.7 at the time of writing). - Node.js and npm, at the versions in
.nvmrcandwebapp/package.json(Node 24.11.1 with npm 11.6.2). With mise, the repository'smise.tomlinstalls the right Node. - Docker with Compose: the development setup runs PostgreSQL and a few other services in containers.
- make, git, and a Linux or macOS machine.
- Memory: building the web interfaces is the heavy part. Plan for 16 GB of RAM; see Builds and memory.
git clone https://github.com/AntimatterChat/antimatter.git
cd antimatter
The repository holds the server in server/, the web interfaces in webapp/ (Fusion in webapp/fusion, classic in webapp/channels, shared packages in webapp/platform), and end-to-end tests in e2e-tests/.
Run a development server
cd server
make run
make run starts the development containers (PostgreSQL, Redis, a mail catcher and monitoring tools), links the web app builds into place, starts the server in the background with go run, and starts the web app's watcher, which rebuilds the classic interface as you edit it. Open http://localhost:8065 and create an account: the first one becomes the system admin.
Command (in server/) | What it does |
|---|---|
make run-server, make run-client | Start only the server, or only the web app watcher. |
make restart-server | Restart the server after changing Go code. |
make stop | Stop the server, the watcher and the containers. |
make debug-server | Run the server under the Delve debugger. |
make run-cli ARGS="-version" | Run a server command. |
make config-reset | Reset config/config.json to the defaults. |
make clean, make nuke | Remove build files; nuke also deletes the development data. |
The development database is postgres://mmuser:mostest_password@localhost/mattermost_test, the server's default data source. Choose which containers start with ENABLED_DOCKER_SERVICES, in a server/config.override.mk file or in your environment (see server/config.mk).
The web interfaces
In webapp/:
npm install # also builds the shared packages
npm run build # the classic interface, then Fusion
The builds land in webapp/channels/dist (classic) and webapp/fusion/dist (Fusion). make client in server/ links them as server/client and server/client-fusion, where the server serves them: classic under /static/, Fusion under /static/fusion/.
npm run run(ormake runinwebapp/) watches and rebuilds the classic interface. AddWATCH_FUSION=trueto rebuild Fusion too.npm run dev-server(make dev) runs webpack's development server instead: classic on port 9005, Fusion on port 9006.- To see one interface or the other in the browser, add
?webui=fusionor?webui=classicto any page's address.
Tests and checks
| Command | Where | What it does |
|---|---|---|
make test-server | server/ | The server's test suite, against the development containers. It takes a long time. |
make test-server-quick | server/ | Only the short tests. |
go test ./channels/app/... -run TestName | server/ | One package or test, with the containers running (make start-docker). |
make check-style | server/ | go vet, golangci-lint and the other Go checks. |
make test | webapp/ | The web app's unit tests (Jest), in every package. |
npm run test -- <pattern> | webapp/fusion | Some of Fusion's tests. |
make check-style, make check-types | webapp/ | ESLint and TypeScript. |
make i18n-extract | server/ and webapp/ | Updates the English string files after you add or change strings (see Translations). |
Run make modules-tidy rather than go mod tidy in server/.
Release archives
cd webapp && npm run build && cd ..
cd server
make build-linux # the antimatter and amctl binaries
make package-linux # dist/antimatter-linux-amd64.tar.gz and -arm64
make build builds the web interfaces and the Linux binaries in one go. The archive holds bin/antimatter, bin/amctl, a default config/config.json with a README.md on changing settings, both web interfaces, the templates, the fonts and the translations. Other platforms: make package-osx, make package-windows, make package-freebsd.
Bundled apps
A plain make package-linux builds an archive without apps. To bundle them, as the published releases do, fetch the signed app bundles first and pass their folder:
build/package/fetch-apps.sh "$HOME/release-apps" # needs gh, python3 and gpg
make package-linux PREPACKAGED_PLUGINS_DIR="$HOME/release-apps"
fetch-apps.sh downloads the latest GitHub release of each app listed in antimatter-docker's plugins.json, with its signature, and checks the signature against Antimatter's plugin key. By default it takes Whiteboard, Voice channels, Calls, AI chat (Agents), Todo, Polls, Notes, GIFs and Memes; AM_BUNDLED_APPS (repository names, separated by spaces) changes the list. Apps without a release, or without a signature, are skipped with a warning. The bundles land in the archive's prepackaged_plugins/.
.deb and .rpm packages
build/package/build-packages.sh <archive> <amd64|arm64> <version> <out-dir> turns a release archive into all-in-one .deb and .rpm packages, with nfpm. The admin guide describes what they install: see Install the .deb or .rpm package.
The release workflow
The server repository's antimatter-release.yml workflow does all of this on GitHub: on a v* tag it builds the archives and packages for amd64 and arm64, with SHA256SUMS, and publishes them as the tag's GitHub release (a prerelease for a version with a -). Run by hand, it numbers the build 0.9.0-dev.<run> and keeps the files as workflow artifacts. Each app repository has a release.yml workflow that publishes its signed bundle the same way.
The Docker image
The antimatter-docker repository builds the published images, the server with its apps, entirely inside Docker:
git clone https://github.com/AntimatterChat/antimatter-docker.git
cd antimatter-docker
scripts/build-all.sh # from the main branches on GitHub
SOURCES=local scripts/build-all.sh # from your checkouts next to this folder
VARIANT=next scripts/build-all.sh # the "next" image, with every Antimatter app
It needs Docker with buildx, Python 3, git and gpg, about 16 GB of RAM and 30 GB of disk. The result is loaded as ghcr.io/antimatterchat/antimatter:dev; try it with ANTIMATTER_IMAGE=ghcr.io/antimatterchat/antimatter:dev docker compose -f compose.local.yml up -d. plugins.json lists the apps and the versions built, and the repository's README explains the variants.
build-all.sh signs the bundled apps with the Antimatter signing key, and the image build refuses unsigned apps. Without that private key, which only the maintainers have, run the first steps alone: scripts/fetch-sources.sh, scripts/build-plugins.sh (app bundles in out/plugins/) and scripts/build-server.sh (server archives in out/server/).Builds and memory
The web interfaces are large webpack builds, and running out of memory is the most common build failure.
npm run buildbuilds the classic interface and Fusion one after the other, not together, to keep the peak lower. Don't run them in parallel yourself.- The minifier starts one worker per processor. On a machine with many cores and little memory, limit the processors the build sees:
taskset -c 0-5 npm run build. - If Node runs out of heap, raise its limit:
NODE_OPTIONS=--max-old-space-size=6144. The Docker build uses this value (BUILD_NODE_OPTIONSinbuild.env). - Avoid running the server's full test suite, a web build and a Docker build at the same time on a small machine.
The apps
Each app (plugin) has its own repository and Makefile; make dist builds its bundle. See Build, install and debug.
Desktop app
The desktop app is an Electron app. With Node.js 24 or later:
npm install --allow-git=all
npm run build # development build, into dist/
npm start # run it
npm run package:linux # packages into release/ (also package:windows, package:mac)
Build-time settings, such as servers to preconfigure, are in src/common/config/buildConfig.ts. Without an Apple certificate, set AM_MAC_ADHOC_SIGN=true to sign the macOS app ad hoc, without notarisation: Apple silicon Macs refuse unsigned code. The repository's release.yml workflow builds unsigned packages for Linux, Windows and macOS on a v* tag.
Mobile app
The mobile app is a React Native app; its README lists the commands (npm run ios, npm run android). To build your own copy you also need your own signing keys, a Firebase project for Android notifications, an APNs key for iOS, and a push proxy holding those credentials. The repository's release.yml workflow builds the Android APK and AAB and an unsigned iOS .ipa on a v* tag, without store accounts; its README lists the secrets that sign the Android build and set up Firebase.