From a619b3792282e6e38d7a056841313efe9602c697 Mon Sep 17 00:00:00 2001 From: Mathis Maquenne <124215603+mathismqn@users.noreply.github.com> Date: Mon, 23 Jun 2025 20:03:56 -0400 Subject: [PATCH] feat(watcher): add macOS autostart support via launchd --- cmd/root.go | 13 ++++++++- internal/watcher/autostart.go | 37 +++++++++++++++++++++++++ internal/watcher/install_mac.go | 48 +++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 internal/watcher/autostart.go create mode 100644 internal/watcher/install_mac.go diff --git a/cmd/root.go b/cmd/root.go index 7624167..350568e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,7 +1,11 @@ package cmd import ( + "fmt" + "os" + "github.com/mathismqn/godeez/internal/config" + "github.com/mathismqn/godeez/internal/watcher" "github.com/spf13/cobra" ) @@ -17,8 +21,15 @@ var RootCmd = &cobra.Command{ PersistentPreRunE: func(cmd *cobra.Command, args []string) error { var err error appConfig, err = config.New(cfgPath) + if err != nil { + return err + } - return err + if err := watcher.EnsureAutostart(); err != nil { + fmt.Fprintf(os.Stderr, "Warning: failed to install autostart for watcher: %v\n", err) + } + + return nil }, } diff --git a/internal/watcher/autostart.go b/internal/watcher/autostart.go new file mode 100644 index 0000000..dad1ae4 --- /dev/null +++ b/internal/watcher/autostart.go @@ -0,0 +1,37 @@ +package watcher + +import ( + "os" + "path/filepath" + "runtime" + "strings" +) + +func EnsureAutostart() error { + if isAutostartInstalled() || isTemporaryExecutable() { + return nil + } + + return installAutostart() +} + +func isAutostartInstalled() bool { + switch runtime.GOOS { + case "darwin": + path := filepath.Join(os.Getenv("HOME"), "Library", "LaunchAgents", "com.godeez.watch.plist") + _, err := os.Stat(path) + + return err == nil + default: + return false + } +} + +func isTemporaryExecutable() bool { + exe, err := os.Executable() + if err != nil { + return true + } + + return strings.Contains(exe, "go-build") +} diff --git a/internal/watcher/install_mac.go b/internal/watcher/install_mac.go new file mode 100644 index 0000000..440e4ce --- /dev/null +++ b/internal/watcher/install_mac.go @@ -0,0 +1,48 @@ +//go:build darwin + +package watcher + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" +) + +func installAutostart() error { + exe, err := os.Executable() + if err != nil { + return err + } + exe, err = filepath.EvalSymlinks(exe) + if err != nil { + return err + } + + plist := fmt.Sprintf(` + + + + Label + com.godeez.watch + ProgramArguments + + %s + watch + run + + RunAtLoad + + KeepAlive + + +`, exe) + + path := filepath.Join(os.Getenv("HOME"), "Library", "LaunchAgents", "com.godeez.watch.plist") + if err := os.WriteFile(path, []byte(plist), 0644); err != nil { + return err + } + + return exec.Command("launchctl", "load", path).Run() +}