diff --git a/src/ClaudeDo.Installer/Core/AutostartShortcut.cs b/src/ClaudeDo.Installer/Core/AutostartShortcut.cs new file mode 100644 index 0000000..f417b16 --- /dev/null +++ b/src/ClaudeDo.Installer/Core/AutostartShortcut.cs @@ -0,0 +1,26 @@ +using System.IO; + +namespace ClaudeDo.Installer.Core; + +public static class AutostartShortcut +{ + public const string FileName = "ClaudeDo Worker.lnk"; + + public static string DefaultStartupDir => + Environment.GetFolderPath(Environment.SpecialFolder.Startup); + + public static string PathIn(string startupDir) => Path.Combine(startupDir, FileName); + + public static void Install(string startupDir, string workerExe) + { + Directory.CreateDirectory(startupDir); + var workingDir = Path.GetDirectoryName(workerExe) ?? startupDir; + ShortcutFactory.CreateShortcut(PathIn(startupDir), workerExe, workingDir, "ClaudeDo background worker"); + } + + public static void Remove(string startupDir) + { + var path = PathIn(startupDir); + if (File.Exists(path)) File.Delete(path); + } +} diff --git a/tests/ClaudeDo.Installer.Tests/AutostartShortcutTests.cs b/tests/ClaudeDo.Installer.Tests/AutostartShortcutTests.cs new file mode 100644 index 0000000..bde032a --- /dev/null +++ b/tests/ClaudeDo.Installer.Tests/AutostartShortcutTests.cs @@ -0,0 +1,57 @@ +using System.IO; +using ClaudeDo.Installer.Core; + +namespace ClaudeDo.Installer.Tests; + +public class AutostartShortcutTests +{ + private static string TempDir() + { + var dir = Path.Combine(Path.GetTempPath(), "cdautostart-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + return dir; + } + + [Fact] + public void Install_creates_lnk_with_expected_name() + { + var startup = TempDir(); + var workerDir = TempDir(); + try + { + var workerExe = Path.Combine(workerDir, "ClaudeDo.Worker.exe"); + File.WriteAllText(workerExe, ""); + + AutostartShortcut.Install(startup, workerExe); + + Assert.True(File.Exists(Path.Combine(startup, AutostartShortcut.FileName))); + } + finally { Directory.Delete(startup, true); Directory.Delete(workerDir, true); } + } + + [Fact] + public void Remove_deletes_existing_lnk() + { + var startup = TempDir(); + var workerDir = TempDir(); + try + { + var workerExe = Path.Combine(workerDir, "ClaudeDo.Worker.exe"); + File.WriteAllText(workerExe, ""); + AutostartShortcut.Install(startup, workerExe); + + AutostartShortcut.Remove(startup); + + Assert.False(File.Exists(Path.Combine(startup, AutostartShortcut.FileName))); + } + finally { Directory.Delete(startup, true); Directory.Delete(workerDir, true); } + } + + [Fact] + public void Remove_is_noop_when_missing() + { + var startup = TempDir(); + try { AutostartShortcut.Remove(startup); } // must not throw + finally { Directory.Delete(startup, true); } + } +}