Building and testing
Prerequisites
- Python 3.14 and uv (see
server/pyproject.toml; uv can install Python for you) - Node.js 22 and npm
- LiveKit server 1.13 (
livekit-serverbinary), for running a local stack and the end-to-end tests - Docker, only if you want to test the deployment
Repository layout
| Path | Contents |
|---|---|
server/ |
Python server, package tolktak. __main__.py is the tolktak-server entry point and app.py builds the FastAPI application; api/ (HTTP and WebSocket handlers), store/ and db.py (database access and schema migrations, SQLite or PostgreSQL), realtime.py (WebSocket hub), livekit.py (tokens, webhooks, API calls), web/ (website), copydb.py (the copy-db command). Tests are in server/tests/. |
client/src/main/ |
Electron main process: window, tray, hotkeys, screen and audio capture, updater. |
client/src/preload/ |
The IPC bridge exposed to the renderer. |
client/src/renderer/ |
UI (ui/), voice and video (voice.ts, audio/), API client, translations (i18n/). |
client/e2e/ |
Playwright end-to-end tests. |
tools/voice-scores/ |
DNSMOS, PESQ and STOI thresholds for voice-quality.spec.ts. |
perf/ |
CPU and memory regression runs of the client on Linux (perf.yml). |
deploy/ |
The Compose setup and an nginx example. |
See Architecture for how the pieces fit together.
Server
cd server
uv sync
uv run ruff check . && uv run ruff format --check . && uv run ty check
uv run pytest
The tests use a temporary SQLite database and need no external services. To run every test against PostgreSQL as well, point TOLKTAK_TEST_POSTGRES at a database you can use for that:
TOLKTAK_TEST_POSTGRES=postgres://tolktak:secret@127.0.0.1:5432/tolktak_test uv run pytest
The release version is written into tolktak/_version.py when the Docker image is built (build argument VERSION); a checkout reports 0.1.0-dev. The build argument REPOSITORY, which the release workflow sets to the repository it runs in, decides whose GitHub releases the server follows for updates, so a fork's server follows the fork.
server/Dockerfile builds two images. The default target, full, is d4enst/tolktak with livekit-server inside; --target server is d4enst/tolktak-server, the server alone:
docker build -t tolktak server
docker build --target server -t tolktak-server server
Running a local stack
The server starts LiveKit itself, with generated keys, as the d4enst/tolktak image does. It runs the livekit-server found on your PATH: download it from the LiveKit releases, or on macOS run brew install livekit.
Chromium ignores loopback ICE candidates, so LiveKit must advertise a real network address of your machine, even when everything runs locally. Replace 192.168.1.20 below with your LAN address:
cd server
TOLKTAK_EMBEDDED_LIVEKIT=1 TOLKTAK_REGISTRATION=open NODE_IP=192.168.1.20 uv run tolktak-server
The server listens on :8080 and keeps its data, including the LiveKit keys, in server/data/. Open http://localhost:8080 to register the first account. All server variables are listed in Configuration.
Client
cd client
npm ci
npm start # build once and launch Electron
Enter localhost:8080 as the server address. Addresses on localhost and private networks default to http://, everything else to https://.
| Script | What it does |
|---|---|
npm run build |
Bundle main, the preloads, the renderer and the launch window into dist/ with esbuild |
npm run watch |
Rebuild on every change; run npx electron . in another terminal and restart it to pick up changes |
npm start |
Build and launch the app |
npm run typecheck |
Type-check the whole client with tsc |
npm run test:e2e |
Run the Playwright tests (see below) |
npm run dist:win |
Build the Windows NSIS installer and zip into release/ (run on Windows) |
npm run dist:win:zip |
Build only the portable Windows zip (works from Linux) |
npm run dist:mac |
Build macOS .dmg and .zip for arm64 and x64 (run on macOS) |
npm run dist:linux |
Build the Linux AppImage and .deb |
Environment variables for the client:
| Variable | Used by | Effect |
|---|---|---|
TOLKTAK_DEFAULT_SERVER |
build | Prefills the server address on the login screen, for builds made for one community |
NODE_ENV=production |
build | Minifies the bundle and drops source maps |
TOLKTAK_USER_DATA |
app | Uses a different profile directory, so several instances can run side by side |
TOLKTAK_NO_UPDATES |
app | Disables the update check in a packaged build |
Releases are built by .github/workflows/release.yml when a v* tag is pushed: it builds the installers for all three platforms, publishes them to GitHub Releases, pushes both images to Docker Hub (d4enst/tolktak, d4enst/tolktak-server) and GHCR (ghcr.io/d4enst/...), and attaches deploy/install.sh, deploy/compose.yaml and deploy/example.env to the release. Docker Hub needs the repository secrets DOCKERHUB_USERNAME and DOCKERHUB_TOKEN. latest moves only on stable releases.
Servers pick up a published release by themselves and apps follow their server (see Maintenance), so two things in a release matter besides the code. When a release changes the API in a way older apps cannot handle, raise MIN_CLIENT_VERSION in server/tolktak/updates.py to the oldest app version that still works: older apps then update before they connect. For an urgent security release, raise it to the release's own version and add <!-- tolktak:urgent --> to the release notes, so servers in auto mode install it at once instead of waiting until nobody is in voice.
End-to-end tests
The tests in client/e2e/ start a real stack: they start tolktak-server from server/ on port 18080, start livekit-server with a generated configuration on ports 17880 and 17881, and serve the renderer bundle from client/dist on port 18090. Nothing on the server side is mocked. Media assertions look at real decoded frames, audio levels and RTP statistics, not at what the UI shows.
cd client
npm run build
LIVEKIT_BIN=/path/to/livekit-server npx playwright test
Notes:
LIVEKIT_BINpoints to the LiveKit binary.CHROMIUM_PATHselects a Chromium build instead of the one Playwright installs (npx playwright install chromium).- The specs that launch Electron (
electron.spec.ts,audio.spec.ts,chat.spec.ts) need a display. On a headless Linux machine, run them underxvfb-run -a. - The network-loss tests in
resilience.spec.tsdrop traffic withiptablesand must run as root. - The test locale is
ru-RUand the specs look up Russian UI labels, so keep both translations in sync when you change a string the tests use. long.spec.tsis a long watch-together session, skipped unlessLONG_MIN=<minutes>is set.E2E_VERBOSE=1prints the server and LiveKit logs.
Voice quality and resource checks
These run in CI and can be run locally the same way:
voice-quality.spec.ts,voice-worklet.spec.tsanddenoise.spec.tsrender the shipped noise suppressors offline. With uv installed,voice-quality.spec.tsalso scores the output withtools/voice-scores/score.pyagainstthresholds.json(runuv sync --project ../tools/voice-scoresonce).voice-cpu.spec.tsmeasures the CPU cost of each preset in Electron; on Linux run it underxvfb-run -a.perf/ci.shstarts the stack with real Electron clients, measures idle and call scenarios and checks them againstperf/baseline/ci-linux.json. It needsLIVEKIT_BIN, the server environment (uv syncinserver/) and Xvfb. A single run:perf/run.sh voice --clients 2 --duration 40.
Windows capture tests
client/e2e/windows.spec.ts checks screen sharing on a real Windows PC: that a shared window's audio reaches viewers without the voices of the room, and which video encoder is actually used. It runs only on Windows with TT_API set.
-
Install the server and download LiveKit:
cd server uv sync --no-devPut
livekit-server.exefrom the LiveKit releases into the samebin\folder at the repository root. -
Start the stack from the repository root. The script picks your LAN address, writes the configuration and database to
data\, and prints the API address:powershell -ExecutionPolicy Bypass -File client\e2e\windows\start-stack.ps1 -
Build the client and run the tests:
cd client npm ci; npm run build $env:TT_API = "http://<lan-ip>:8080" npx playwright test e2e/windows.spec.ts
Results are written to windows-results.json, gpu-results.json and hw-results.json in client/ (or in TT_RESULTS_DIR).
client/e2e/windows/windows-probe.ps1 is a read-only script that collects the Windows build, CPU, GPU and driver, displays and audio devices into tolktak-probe.txt on the desktop. Attaching its output helps when reporting capture problems.