Note
This crate was forked from zzzgydi/auto-launch, adding more platforms support and features.
Auto launch any application or executable at startup. Supports Windows, macOS (Launch Agent, AppleScript, or SMAppService), and Linux.
If you find any bugs, welcome to PR or issue.
The parameters of AutoLaunch::new are different on each platform.
See the function definition or the demo below for details.
AutoLaunchBuilder helps to eliminate the constructor difference on various platforms.
use auto_launcher::*;
fn main() {
let auto = AutoLaunchBuilder::new()
.set_app_name("the-app")
.set_app_path("/path/to/the-app")
.set_macos_launch_mode(MacOSLaunchMode::LaunchAgentUser)
.build()
.unwrap();
auto.enable().unwrap();
auto.is_enabled().unwrap();
auto.disable().unwrap();
auto.is_enabled().unwrap();
}Linux supports two ways to achieve auto launch:
- XDG Autostart: Uses
.desktopfiles in~/.config/autostart/(default) - systemd user: Uses systemd user services in
~/.config/systemd/user/ - systemd system: Uses systemd system services in
/etc/systemd/system/
Both systemd modes require systemctl to be available in the environment.
use auto_launcher::{AutoLaunch, LinuxLaunchMode};
fn main() {
let app_name = "the-app";
let app_path = "/path/to/the-app";
// Use XDG Autostart (default method)
let auto = AutoLaunch::new(app_name, app_path, LinuxLaunchMode::XdgAutostart, &[] as &[&str]);
// Or use systemd user service
// let auto = AutoLaunch::new(app_name, app_path, LinuxLaunchMode::SystemdUser, &[] as &[&str]);
// Or use systemd system service
// let auto = AutoLaunch::new(app_name, app_path, LinuxLaunchMode::SystemdSystem, &[] as &[&str]);
// enable the auto launch
auto.enable().is_ok();
auto.is_enabled().unwrap();
// disable the auto launch
auto.disable().is_ok();
auto.is_enabled().unwrap();
}macOS supports five ways to achieve auto launch:
- Launch Agent (user): Uses plist files in
~/Library/LaunchAgents/(default). Runs as the current user. - Launch Agent (system): Uses plist files in
/Library/LaunchAgents/. Visible to all users, but still runs as the logged-in user (not root). Requires root/sudo to write. - Launch Daemon (system): Uses plist files in
/Library/LaunchDaemons/. Runs as root. Requires root/sudo to write. - AppleScript: Uses AppleScript to add login items.
- SMAppService: Uses the SMAppService API (macOS 13+).
Note:
- The
app_pathshould be an absolute path and exists. Otherwise, it will cause an error whenenable. - In case using AppleScript, the
app_nameshould be same as the basename ofapp_path, or it will be corrected automatically. - In case using AppleScript, only
--hiddenand--minimizedinargsare valid, which means that hide the app on launch. - In case using SMAppService,
app_nameandapp_pathcan be empty strings because it registers the running app. LaunchAgentSystemandLaunchDaemonSystemboth require the process to have root/sudo privileges when callingenable/disable.
use auto_launcher::{AutoLaunch, MacOSLaunchMode};
fn main() {
let app_name = "the-app";
let app_path = "/path/to/the-app.app";
// Use Launch Agent for current user (default, no elevated privileges needed)
let auto = AutoLaunch::new(app_name, app_path, MacOSLaunchMode::LaunchAgentUser, &[] as &[&str], &[] as &[&str], "");
// Or use Launch Agent for all users (runs as logged-in user, requires root to register)
// let auto = AutoLaunch::new(app_name, app_path, MacOSLaunchMode::LaunchAgentSystem, &[] as &[&str], &[] as &[&str], "");
// Or use Launch Daemon (runs as root, requires root to register)
// let auto = AutoLaunch::new(app_name, app_path, MacOSLaunchMode::LaunchDaemonSystem, &[] as &[&str], &[] as &[&str], "");
// Or use AppleScript
// let auto = AutoLaunch::new(app_name, app_path, MacOSLaunchMode::AppleScript, &[] as &[&str], &[] as &[&str], "");
// Or use SMAppService (macOS 13+)
// let auto = AutoLaunch::new(app_name, app_path, MacOSLaunchMode::SMAppService, &[] as &[&str], &[] as &[&str], "");
// enable the auto launch
auto.enable().is_ok();
auto.is_enabled().unwrap();
// disable the auto launch
auto.disable().is_ok();
auto.is_enabled().unwrap();
}On Windows, it will add registry entries under:
\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run(system)\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run(current user)\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run(Task Manager status)
It will also detect if startup is disabled inside Task Manager or the Windows settings UI, and can re-enable after being disabled in one of those.
Enable behavior is controlled by WindowsEnableMode:
Dynamic(default): try system-wide, fall back to current user on access deniedCurrentUser: write to current user onlySystem: write to system only (admin required)
use auto_launcher::{AutoLaunch, WindowsEnableMode};
fn main() {
let app_name = "the-app";
let app_path = "C:\\path\\to\\the-app.exe";
let auto = AutoLaunch::new(app_name, app_path, WindowsEnableMode::Dynamic, &[] as &[&str]);
// enable the auto launch
auto.enable().is_ok();
auto.is_enabled().unwrap();
// disable the auto launch
auto.disable().is_ok();
auto.is_enabled().unwrap();
}get_registered_app_path() reads the binary path from the on-disk registration file (plist / systemd unit / registry). Returns Ok(None) when no registration exists.
This is useful for detecting stale registrations after a package-manager upgrade — e.g. pitchfork uses it to auto-heal boot registrations on supervisor startup (jdx/pitchfork#707):
match auto.get_registered_app_path() {
Ok(Some(registered)) => {
if registered != current_bin {
// enable() overwrites the on-disk file with the current app_path.
// No need to disable() first — calling enable() directly ensures
// that if it fails, the stale registration is still present.
auto.enable()?;
}
}
Ok(None) => { /* not registered */ }
Err(e) => { /* read failed */ }
}MIT License. See the License file for details.