powerful but friendly backup program that runs in your tray, powered by restic devins.page/restray
go restic system-tray
2

Configure Feed

Select the types of activity you want to include in your feed.

feat: bundle restic with macos `.app`

downloaded and bundled at build time. still recommend to have a restic binary in path managed by like homebrew or something for latest version

intergrav (Jul 1, 2026, 6:47 AM EDT) ee71ecf0 785cd74d

+39 -2
+1 -1
README.md
··· 34 34 35 35 To install, grab a build artifact for your OS and architecture from the [repository's tags](https://tangled.org/devins.page/restray/tags). On MacOS you'll need to [remove quarantine](https://disable-gatekeeper.github.io#disabling-gatekeeper-for-one-application-only) from the `.app`, since I can't pay Apple $100/year to sign it. Sorry. 36 36 37 - Restray requires [restic](https://restic.net) installed to your PATH on MacOS/Linux, so install it with your package manager. On Windows, Restray can download and manage it's own restic binary itself if it isn't already in PATH. 37 + On MacOS, a restic binary is downloaded and bundled to the `.app` at build time, though I'd recommend installing restic to your path so you have the latest version. On Windows, Restray can download and update it's own restic binary itself if it isn't already in PATH. On Linux, you should install restic with your package manager. 38 38 39 39 _If you're a Nix/NixOS/Nix-darwin user, I also provide package/module in the project's [flake](https://tangled.org/devins.page/restray) for Linux and MacOS._ 40 40
+19
cmd/restray/restic.go
··· 41 41 if p := managedRestic(); p != "" { 42 42 resticPath = p 43 43 resticManaged = true 44 + return 45 + } 46 + if p := bundledRestic(); p != "" { 47 + resticPath = p 44 48 } 45 49 }) 46 50 return resticPath, resticManaged 51 + } 52 + 53 + func bundledRestic() string { 54 + if runtime.GOOS != "darwin" { 55 + return "" 56 + } 57 + exe, err := os.Executable() 58 + if err != nil { 59 + return "" 60 + } 61 + p := filepath.Join(filepath.Dir(exe), "..", "Resources", "restic") 62 + if _, err := os.Stat(p); err == nil { 63 + return p 64 + } 65 + return "" 47 66 } 48 67 49 68 func findResticFromShell() string {
+19 -1
justfile
··· 111 111 esac 112 112 113 113 _package-darwin arch: 114 + #!/usr/bin/env bash 115 + set -e 114 116 rm -rf {{dist}}/Restray.app 115 117 mkdir -p {{dist}}/Restray.app/Contents/MacOS {{dist}}/Restray.app/Contents/Resources 116 118 cp {{bin}}/{{app}}-{{version}}-darwin-{{arch}} {{dist}}/Restray.app/Contents/MacOS/Restray 117 119 cp packaging/darwin/Info.plist {{dist}}/Restray.app/Contents/Info.plist 118 120 cp packaging/darwin/restray.icns {{dist}}/Restray.app/Contents/Resources/restray.icns 119 - cd {{dist}} && zip -r {{app}}-{{version}}-darwin-{{arch}}-app.zip Restray.app 121 + just _fetch-restic-darwin {{arch}} 122 + cp {{bin}}/restic-darwin-{{arch}} {{dist}}/Restray.app/Contents/Resources/restic 123 + chmod +x {{dist}}/Restray.app/Contents/Resources/restic 124 + (cd {{dist}} && zip -r {{app}}-{{version}}-darwin-{{arch}}-app.zip Restray.app) 120 125 rm -rf {{dist}}/Restray.app 126 + 127 + _fetch-restic-darwin arch: 128 + #!/usr/bin/env bash 129 + set -e 130 + out="{{bin}}/restic-darwin-{{arch}}" 131 + [ -f "$out" ] && exit 0 132 + mkdir -p {{bin}} 133 + tmp=$(mktemp -d) 134 + trap 'rm -rf "$tmp"' EXIT 135 + version=$(curl -fsSL https://api.github.com/repos/restic/restic/releases/latest | grep '"tag_name"' | head -1 | cut -d'"' -f4 | sed 's/^v//') 136 + curl -fsSL -o "$tmp/restic.bz2" "https://github.com/restic/restic/releases/download/v${version}/restic_${version}_darwin_{{arch}}.bz2" 137 + bunzip2 -c "$tmp/restic.bz2" > "$out" 138 + chmod +x "$out" 121 139 122 140 _package-windows arch: 123 141 mkdir -p {{dist}}