The next-gen module manager and desktop shell for ActivityWatch, built with Tauri. Replaces the legacy aw-qt (Python/Qt).
- Simpler builds — No more PyInstaller.
npx tauri buildproduces deb, rpm, AppImage, .app, and MSI from one codebase. - Embedded server — Runs aw-server-rust in-process; no separate server binary needed.
- Modern stack — Rust + WebView instead of Python + Qt, with native code-signing and updater support.
- Cross-platform — Builds for Linux, macOS, and Windows including ARM64.
- Mobile future — Tauri supports iOS and Android, enabling future mobile ActivityWatch builds.
aw-tauri bundles everything needed to run ActivityWatch into a single application:
- Embedded server — Runs
aw-server-rustin-process (no separate server binary needed) - Module manager — Discovers, starts, stops, and monitors watcher processes (aw-watcher-afk, aw-watcher-window, etc.)
- System tray — Tray icon with menu to open the dashboard, toggle modules, and access config/log folders
- WebView dashboard — Opens the aw-webui dashboard in a native window
- Crash recovery — Exponential backoff restart for crashed modules (up to 3 retries)
- Single instance — Only one aw-tauri process runs at a time via lockfile detection
- Autostart — OS-native autostart registration (macOS AppleScript, Linux XDG, Windows registry), toggleable from the tray menu
- Cross-platform — Builds for Linux (deb, rpm, AppImage), macOS (.app), and Windows (MSI) including ARM64
- Tauri v2 prerequisites (system dependencies)
- Node.js (for Tauri CLI and aw-webui build)
- Rust (stable toolchain)
# Clone with submodules (aw-webui)
git clone --recursive https://github.com/ActivityWatch/aw-tauri.git
cd aw-tauri
# Install Node dependencies
npm install
# Run in development mode
make dev
# Build release binary
make buildaw-tauri reads its config from a TOML file:
| Platform | Path |
|---|---|
| Linux | ~/.config/activitywatch/aw-tauri/config.toml |
| macOS | ~/Library/Application Support/activitywatch/aw-tauri/config.toml |
| Windows | %APPDATA%\activitywatch\aw-tauri\config.toml |
A default config is generated on first run. Example:
port = 5600
discovery_paths = [
"/home/user/.local/bin",
"/home/user/.local/share/activitywatch/aw-tauri/modules",
"/home/user/aw-modules",
]
[autostart]
enabled = true
minimized = true
modules = [
"aw-watcher-afk",
"aw-watcher-window",
{ name = "aw-sync", args = "daemon" },
]
[module_args]
"aw-watcher-vscode" = "--poll-interval 30"Key settings:
port— Server port (default: 5600)discovery_paths— Additional directories to search foraw-*module binariesautostart.enabled— Register for OS autostart on login. Also toggleable at runtime via Start at login in the tray menu, which updates the OS registration and writes the new value back here. Editing it by hand takes effect on the next launch, in both directions (setting it tofalseremoves an already-registered login item)autostart.minimized— Start minimized to tray (iffalse, opens dashboard on launch)autostart.modules— Modules to start automatically. Each entry can be a string ("aw-watcher-afk") or an object with args ({ name = "aw-sync", args = "daemon" })module_args— Default args by module name, used when a module is launched from the tray menu or restarted after a crash. Lets you set args for a module without adding it toautostart.modules(e.g.aw-watcher-vscodeabove is launched manually from the tray, but still gets its args). If a module is listed in both places, the inline args on itsautostart.modulesentry take precedence.
Note: On Linux with Wayland, the default modules are aw-awatcher instead of aw-watcher-afk + aw-watcher-window (auto-detected via XDG_SESSION_TYPE / WAYLAND_DISPLAY).
Logs are written to:
| Platform | Path |
|---|---|
| Linux | ~/.cache/activitywatch/aw-tauri/log/aw-tauri.log |
| macOS | ~/Library/Logs/activitywatch/aw-tauri/aw-tauri.log |
| Windows | %LOCALAPPDATA%\activitywatch\Logs\aw-tauri\aw-tauri.log |
Log rotation happens automatically at 32 MB, keeping the 5 most recent rotated logs.
Environment variables:
AW_DEBUG=1— Enable debug-level loggingAW_TRACE=1— Enable trace-level logging (very verbose)
┌─────────────────────────────────────────────┐
│ aw-tauri │
│ │
│ ┌───────────┐ ┌─────────────────────────┐ │
│ │ Tray Icon │ │ WebView (aw-webui) │ │
│ │ + Menu │ │ │ │
│ └─────┬─────┘ └─────────────────────────┘ │
│ │ │
│ ┌─────┴──────────────────────────────────┐ │
│ │ Module Manager │ │
│ │ (discover, start, stop, restart) │ │
│ └─────┬──────────────────────────────────┘ │
│ │ │
│ ┌─────┴──────────────────────────────────┐ │
│ │ aw-server-rust (embedded) │ │
│ │ Rocket HTTP on :5600 │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
│
│ spawns child processes
▼
┌──────────────┐ ┌──────────────────┐ ┌─────────┐
│ aw-watcher- │ │ aw-watcher- │ │aw-sync │
│ afk │ │ window │ │ daemon │
└──────────────┘ └──────────────────┘ └─────────┘
aw-tauri/
├── src-tauri/
│ ├── src/
│ │ ├── main.rs # Entry point — calls lib::run()
│ │ ├── lib.rs # Application setup: Tauri builder, server, tray, config
│ │ ├── manager.rs # Module manager: discovery, lifecycle, crash recovery
│ │ ├── autostart.rs # Start-at-login: OS registration kept in sync with config
│ │ ├── dirs.rs # Platform-specific directory resolution
│ │ └── logging.rs # Log setup with fern, rotation at 32 MB
│ ├── build.rs # Build script — requires AW_WEBUI_DIR env var
│ ├── Cargo.toml # Rust dependencies
│ ├── capabilities/ # Tauri v2 capability declarations
│ └── .cargo/config.toml # Sets AW_WEBUI_DIR to ../aw-webui/dist
├── aw-webui/ # Git submodule → ActivityWatch/aw-webui
├── Makefile # Build orchestration
├── package.json # Node.js config (Tauri CLI)
└── .pre-commit-config.yaml
lib.rs — The core of the application. Sets up:
- Config loading from TOML (with first-run defaults)
- aw-server-rust embedded via
build_rocket()on an async Tauri runtime - WebView window navigated to
http://localhost:{port}/ - System tray with Open Dashboard / Modules submenu / Start at login / Quit
- Single-instance enforcement via lockfile watching
autostart.rs — Start-at-login control on top of tauri-plugin-autostart:
- Reconciles the OS login item with
[autostart] enabledat startup, in both directions - Backs the Start at login tray item and the
get_autostart_enabled/set_autostart_enabledcommands - Every mutation applies the OS change, reads it back to confirm, then persists it to the config file — rolling the OS change back if the write fails, so the two can't drift apart
- Persists by patching the
enabledkey in place, preserving comments and formatting elsewhere in the file
manager.rs — Process manager for ActivityWatch modules:
- Discovery: Scans
PATH+ configureddiscovery_pathsfor executables matchingaw-*prefix. On Unix, checks execute permission; on Windows, looks for.exefiles. Excludes known non-module binaries (aw-tauri, aw-client, aw-server, etc.) - Lifecycle: Starts modules as child processes, tracks PIDs, handles start/stop from tray menu
- Crash recovery: On non-zero exit, restarts with exponential backoff (2s, 4s, 8s). After 3 consecutive crashes, stops and notifies the user
- Parent monitoring (Unix): Creates a pipe so child processes are terminated if the parent dies
- Job objects (Windows): Assigns children to a job object with
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE - aw-notify special handling: Runs with
--output-onlyflag, parses JSON notification output, and uses Tauri's notification API to display them natively
dirs.rs — Platform-aware directory resolution for config, data, logs, and runtime paths. Uses the dirs crate for standard locations. Includes Android stubs for future mobile support.
logging.rs — Logging via fern with colored console output. Log rotation at 32 MB with 5 rotated copies kept.
aw-tauri searches for aw-* executables in these locations:
| Platform | Paths |
|---|---|
| Linux | ~/bin, ~/.local/bin, $XDG_DATA_HOME/activitywatch/aw-tauri/modules, ~/aw-modules, $PATH |
| macOS | ~/aw-modules, /Applications/ActivityWatch.app/Contents/MacOS, /Applications/ActivityWatch.app/Contents/Resources, $PATH |
| Windows | C:\Users\{user}\aw-modules, C:\Users\{user}\AppData\Local\Programs\ActivityWatch, %PATH% |
Additional paths can be added via discovery_paths in the config.
Install Tauri v2 prerequisites for your platform, plus Node.js and Rust.
make dev # Run in development mode (hot-reload for Rust)
make build # Build release binary
make format # Format Rust code (cargo fmt)
make check # Run cargo check + clippy
make precommit # Run format + check (same as pre-commit hooks)
make package # Package built binary into dist/npm install— Installs Tauri CLImake prebuild— Initializes aw-webui submodule, builds aw-webui (cd aw-webui && make build), generates tray iconsAW_WEBUI_DIRenv var (set insrc-tauri/.cargo/config.toml) points the build toaw-webui/dist/npm run tauri build— Compiles Rust code + bundles into platform-specific packages
The repo uses pre-commit with these hooks:
cargo fmt— Rust formattingcargo clippy -- -D warnings— Lint with warnings as errorscargo check— Compilation checkend-of-file-fixer— Ensure files end with newlinecheck-added-large-files— Block files > 500 KB
cd src-tauri && cargo testCurrently tests cover directory resolution (dirs.rs). More test coverage is welcome.
If aw-tauri fails to start with "Port 5600 is already in use", another ActivityWatch server (or aw-tauri instance) is running. Stop it first, or change the port in your config.
Check that your watcher binaries are in one of the discovery paths or add a custom path to discovery_paths in your config. On Unix, ensure the binaries have execute permission.
If the dashboard shows a blank page, the aw-webui assets may not have been built. Run cd aw-webui && make build and restart.