launchd experimental
mise can declare macOS user LaunchAgents in [bootstrap.macos.launchd.agents] and apply them with mise bootstrap launchd apply:
[bootstrap.macos.launchd.agents.my-sync]
program = "~/.local/bin/my-sync"
args = ["--watch"]
run_at_load = true
start_interval = 300
environment = { PATH = "/opt/homebrew/bin:/usr/bin:/bin" }
working_directory = "~"
stdout_path = "~/Library/Logs/my-sync.log"
stderr_path = "~/Library/Logs/my-sync.err.log"Each agent is written to ~/Library/LaunchAgents/dev.mise.<name>.plist and loaded with launchctl bootstrap gui/$UID ~/Library/LaunchAgents/dev.mise.<name>.plist. Agent names may contain letters, numbers, ., _, and -. mise owns only the plist files it creates with the dev.mise. label prefix.
Supported keys
| TOML key | launchd key |
|---|---|
program | ProgramArguments[0] |
args | ProgramArguments[1..] |
run_at_load | RunAtLoad |
keep_alive | KeepAlive |
start_interval | StartInterval |
environment | EnvironmentVariables |
working_directory | WorkingDirectory |
stdout_path | StandardOutPath |
stderr_path | StandardErrorPath |
kickstart | run launchctl kickstart |
program, working_directory, stdout_path, and stderr_path expand bare ~ and ~/ to the current user's home directory before writing the plist. args are passed through exactly as written.
Semantics
- Declarative and additive — agent names merge across the config hierarchy (global → project). A more local config replaces the full declaration for the same agent name.
- macOS-only — on other platforms the section is inert:
mise bootstrap launchd statuslists entries as skipped andmise bootstrap launchd applyignores them. - Manual application only — mise never writes or loads LaunchAgents implicitly; only
mise bootstrap launchd applyandmise bootstrapdo. - User agents only — mise writes to
~/Library/LaunchAgents. System daemons in/Library/LaunchDaemonsare not supported.
Commands
mise bootstrap launchd status # shows LaunchAgent state
mise bootstrap launchd status --json # machine-readable
mise bootstrap launchd status --missing # exit 1 if any agent is missing, changed, or unloaded
mise bootstrap launchd apply # write and load missing/changed agents
mise bootstrap launchd apply --dry-run # print the commands without running them
mise bootstrap launchd apply --yes # skip the confirmation promptstatus reports each agent as loaded, unloaded, differs, or missing. apply rewrites changed plists, unloads the old job if present, loads the new job, enables it, and runs kickstart only when kickstart = true.