From c9254500f2ccb6fd0c9a095f05c2722888fe1e63 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 20 May 2026 09:07:35 +0000 Subject: [PATCH] fix(daemon): preserve curl-installer daemon as .bak instead of deleting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When `commandDaemonInstall` resolves to a system-managed binary (e.g. Homebrew, or a stale `/usr/local/bin/shelltime-daemon` on Linux), the cleanup branch previously deleted `~/.shelltime/bin/shelltime-daemon` outright. Combined with `install.bash` running `shelltime daemon reinstall` on upgrades, this caused the freshly-extracted daemon binary to be removed โ€” and any subsequent `daemon install` would re-download it from GitHub releases. Rename the curl-installer copy to `shelltime-daemon.bak` instead. The existing `.bak` recovery branch at the top of `commandDaemonInstall` restores it on the next run, so once the user clears the stale system binary the daemon binary returns with no network fetch needed. --- commands/daemon.install.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/commands/daemon.install.go b/commands/daemon.install.go index 8c2fd3f..7d9a742 100644 --- a/commands/daemon.install.go +++ b/commands/daemon.install.go @@ -61,16 +61,20 @@ func commandDaemonInstall(c *cli.Context) error { color.Green.Printf("โœ… Found daemon binary at: %s\n", daemonBinPath) } - // If we picked a system-managed binary but a stale curl-installer copy - // still lives under ~/.shelltime/bin, remove it so future resolution - // stays unambiguous. + // If we picked a system-managed binary but a curl-installer copy still + // lives under ~/.shelltime/bin, rename it to shelltime-daemon.bak rather + // than delete it. Future resolution stays unambiguous AND the .bak + // recovery branch above can restore it on the next `daemon install` โ€” + // no GitHub re-download when the user later clears the system binary. curlDaemonPath := model.GetCurlInstallerDaemonPath() if daemonBinPath != curlDaemonPath { if info, statErr := os.Stat(curlDaemonPath); statErr == nil && !info.IsDir() { - if rmErr := os.Remove(curlDaemonPath); rmErr == nil { - color.Yellow.Printf("๐Ÿงน Removed stale curl-installer daemon at %s\n", curlDaemonPath) + preservedPath := curlDaemonPath + ".bak" + _ = os.Remove(preservedPath) + if rnErr := os.Rename(curlDaemonPath, preservedPath); rnErr == nil { + color.Yellow.Printf("๐Ÿ“ฆ Preserved curl-installer daemon as %s (auto-restores on next `daemon install`).\n", preservedPath) } else { - color.Yellow.Printf("โš ๏ธ Could not remove stale daemon at %s: %v\n", curlDaemonPath, rmErr) + color.Yellow.Printf("โš ๏ธ Could not preserve curl-installer daemon at %s: %v\n", curlDaemonPath, rnErr) } } }