aw-server-rust: ActivityWatch Server in Rust
aw-server-rust is a Rust rewrite of the original Python aw-server, built to run ActivityWatch's REST API backend with less overhead than the Python version. Reach for it if you already run ActivityWatch and want the compiled binary instead of a Python process; skip it if you depend on the Swagger/OpenAPI API explorer, since that's not built yet in this version.
What is aw-server-rust?
aw-server-rust is the Rust implementation of the ActivityWatch server, the local backend that ActivityWatch's trackers and watchers report activity data to over a REST API. It replaces the original Python aw-server, storing and syncing time-tracking data for the ActivityWatch desktop app and its browser extensions. The project also includes aw-sync-rust, a companion sync component documented separately in its own subdirectory README.
Core Capabilities
- ✓Rust reimplementation of aw-server, built via Cargo (`cargo build --release`) or a `make build` target that also builds the web assets
- ✓Serves a REST API backend for ActivityWatch's trackers and watchers, listening on port 5600 by default (5666 in testing mode)
- ✓Configurable through a TOML file at `~/.config/activitywatch/aw-server-rust/config.toml`, covering listen address, port, and CORS origins
- ✓CORS allow-list that by default accepts the server's own origin, the official ActivityWatch Chrome extension, and any Firefox extension, with regex rules for adding custom origins
- ✓Ships alongside aw-sync-rust, a companion component for syncing data, documented in its own subdirectory README
- ✓MPL-2.0 licensed and tagged on GitHub for REST API, sync, and time-tracking use
Building and Installation
Building aw-server-rust requires Cargo. Run `cargo build --release` from the project root and the compiled binary lands at `./target/release/aw-server-rust`. If you'd rather build the bundled web assets in the same step, run `make build` instead. For local debugging, `cargo run --bin aw-server` compiles and starts the server directly, though this launches it in testing mode on port 5666 rather than the production port 5600. If you're pairing a development build with `aw-qt`, copy the release binary into your virtualenv's bin folder with `cp target/release/aw-server ../venv/bin/aw-server-rust` so the tray app picks up your custom build.
Strengths
- ✓Compiles to a single native binary, so running the backend doesn't require a Python interpreter or virtualenv the way the original aw-server does
- ✓CORS handling is spelled out precisely in the config file (default origins, regex rules for sideloaded extensions) instead of leaving cross-origin behavior implicit
- ✓Ships as part of the same ActivityWatch ecosystem, so it works as a drop-in replacement for the Python backend when paired with `aw-qt`
- ✓MPL-2.0 licensing keeps the source open while still permitting linking from separate proprietary modules, friendlier than a stronger copyleft license for anyone embedding it
Current Missing Features
- △The README lists exactly one feature gap versus the Python aw-server: there's no built-in Swagger/OpenAPI API explorer, so you can't browse the REST endpoints interactively without reading the source or separate API docs
- △Setup documentation stops at build and configuration: the README doesn't cover deploying it as a standalone service (systemd unit, Docker image, etc.), so anything past `cargo run` or `make build` is on you
- △It's a companion piece to the wider ActivityWatch project, not a standalone product: on its own it's a REST API backend with no UI, and you still need `aw-qt` or another watcher to feed it activity data
- △MPL-2.0 is file-level copyleft, a smaller commitment than GPL but still something to check before bundling this binary into a closed-source product
Other ActivityWatch Server Implementations
Frequently Asked Questions
aw-server-rust runs the backend that stores and serves ActivityWatch's time-tracking data over a REST API, replacing the original Python aw-server so watchers like aw-qt and browser extensions have a compiled Rust process to report activity events to.
You add allowed origins to the `cors` (exact match) or `cors_regex` (pattern match) arrays in aw-server-rust's config.toml. By default it already accepts the server's own origin, the official Chrome extension, and any Firefox extension, so you only need these for sideloaded extensions or a custom web UI.
The README names one gap: aw-server-rust doesn't yet include a Swagger/OpenAPI API explorer, which the Python aw-server has for browsing REST endpoints interactively.
aw-server-rust is released under the MPL-2.0 license, Mozilla's file-level copyleft license.
aw-server-rust listens on port 5600 by default, and switches to port 5666 automatically when started in testing mode via `cargo run`.
The problem it solves
The original aw-server backend for ActivityWatch runs on Python, which means anyone self-hosting it needs a Python environment and a virtualenv set up alongside the tracker. aw-server-rust removes that dependency: it ships a compiled Rust binary you build with Cargo, so the REST API backend that stores and serves your time-tracking events doesn't need a Python runtime running alongside the aw-qt tray app.
Best use cases
- •Running as the local backend for a standard ActivityWatch install, paired with `aw-qt` and its watchers, when you want a lower-overhead Rust binary instead of the Python server
- •Self-hosting your own time-tracking data end to end: activity events stay on your machine, served only over the REST API you configure
- •Developing a custom web dashboard or browser extension against the ActivityWatch REST API, using the CORS config to allow your own origin during development
- •Syncing activity data between machines via the companion aw-sync-rust component, per its own subdirectory README
Who should try it — and who should skip
Try aw-server-rust if you already use ActivityWatch and want its backend running as a single compiled binary instead of a Python process — it's a straightforward swap if you're comfortable building from source with Cargo. Skip it if you need the Swagger/OpenAPI API explorer for interactive endpoint browsing, or if you'd rather not build from source at all.
