systemd experimental
mise can declare Linux systemd user services in [bootstrap.linux.systemd.units] and apply them with mise bootstrap systemd apply:
[bootstrap.linux.systemd.units.my-sync]
description = "sync files"
exec_start = "~/.local/bin/my-sync --watch"
after = ["network-online.target"]
wants = ["network-online.target"]
environment = { PATH = "/usr/local/bin:/usr/bin:/bin" }
working_directory = "~"
restart = "on-failure"
restart_sec = "5s"
standard_output = "append:%h/.local/state/my-sync.log"
standard_error = "journal"Each unit is written to ~/.config/systemd/user/dev.mise.<name>.service and managed with systemctl --user. Unit names may contain letters, numbers, ., _, -, and @. mise owns only the service files it creates with the dev.mise. prefix.
Supported keys
| TOML key | systemd key |
|---|---|
description | Description |
after | After |
wants | Wants |
exec_start | ExecStart |
environment | Environment |
working_directory | WorkingDirectory |
restart | Restart |
restart_sec | RestartSec |
standard_output | StandardOutput |
standard_error | StandardError |
wanted_by | WantedBy |
start | run systemctl --user restart |
exec_start and working_directory expand bare ~ and ~/ to the current user's home directory before writing the service file. wanted_by defaults to ["default.target"]; set wanted_by = [] to write the unit and disable any previous enablement. start defaults to true; set start = false to write and enable without keeping the unit running.
Semantics
- Declarative and additive — unit names merge across the config hierarchy (global → project). A more local config replaces the full declaration for the same unit name.
- Linux-only — on other platforms the section is inert:
mise bootstrap systemd statuslists entries as skipped andmise bootstrap systemd applyignores them. - User services only — mise writes to
~/.config/systemd/userand usessystemctl --user. System services in/etc/systemd/systemare not supported. - Target user only — run mise as the user that owns the services, with an active systemd user bus.
sudo miseis skipped becausesystemctl --userwould target the wrong user manager. - Manual application only — mise never writes or starts systemd services implicitly; only
mise bootstrap systemd applyandmise bootstrapdo.
Commands
mise bootstrap systemd status # shows systemd user service state
mise bootstrap systemd status --json # machine-readable
mise bootstrap systemd status --missing # exit 1 if any unit is missing, changed, or inactive
mise bootstrap systemd apply # write and start missing/changed units
mise bootstrap systemd apply --dry-run # print the commands without running them
mise bootstrap systemd apply --yes # skip the confirmation promptstatus reports each unit as active, inactive, differs, or missing. apply rewrites changed service files, runs systemctl --user daemon-reload, enables units with wanted_by, disables units with wanted_by = [], and restarts them when start = true or stops them when start = false.