···48484949Restray also works without the GUI on MacOS/Linux. Run `restray daemon` to run just the built-in scheduler (no tray GUI), or use one-shot commands for other things. Run `restray --help` for the full command list.
50505151-Linux users: systemd unit files are included (`packaging/linux/restray.service` for system-wide, `packaging/linux/restray-user.service` for per-user). If you use NixOS, a `services.restray` module is also exported from the flake :)
5151+Linux users/packagers: systemd unit files are included (`packaging/linux/restray.service` for system-wide, `packaging/linux/restray-user.service` for per-user). If you use NixOS, a `services.restray` module is also exported from the flake :)
5252+5353+For Linux system-wide setups, you can run commands against the same config/state as the system service with `restray --system ...`, or explicitly with `restray --config /etc/restray --state /var/lib/restray ...`. This is useful for manually running operations using the system-wide config. You will need to have elevated priviledges though (run with sudo)
52545355## Configuration
5456
+50-9
cmd/restray/main.go
···55 "log"
66 "os"
77 "runtime"
88+ "strings"
89910 "fyne.io/systray"
1011 "github.com/gen2brain/beeep"
···1718 systemStateDir = "/var/lib/restray"
1819)
19202121+func applyRuntimeContext(configDir, stateDir string, setHome bool) {
2222+ if configDir != "" {
2323+ configDirOverride = configDir
2424+ }
2525+ if stateDir != "" {
2626+ dataDirOverride = stateDir
2727+ }
2828+ if setHome && dataDirOverride != "" {
2929+ os.Setenv("HOME", dataDirOverride)
3030+ }
3131+}
3232+3333+func parsePathFlag(args []string, i *int, name string) string {
3434+ if value, ok := strings.CutPrefix(args[*i], name+"="); ok {
3535+ if value == "" {
3636+ log.Fatalf("restray: %s requires a non-empty value", name)
3737+ }
3838+ return value
3939+ }
4040+ if *i+1 >= len(args) {
4141+ log.Fatalf("restray: %s requires a value", name)
4242+ }
4343+ *i++
4444+ return args[*i]
4545+}
4646+2047func preParseGlobalFlags() (verbose bool, remaining []string) {
2148 args := os.Args[1:]
4949+ var system bool
2250 for i := 0; i < len(args); i++ {
2323- switch args[i] {
5151+ arg := args[i]
5252+ switch arg {
2453 case "-v", "--verbose":
2554 verbose = true
2626- case "-c", "--config":
2727- if i+1 < len(args) {
2828- configDirOverride = args[i+1]
2929- i++
3030- }
3155 case "--system":
3256 if runtime.GOOS != "linux" {
3357 log.Fatalf("restray: --system is not supported on %s", runtime.GOOS)
3458 }
3535- configDirOverride = systemConfigDir
3636- dataDirOverride = systemStateDir
5959+ system = true
3760 default:
3838- remaining = append(remaining, args[i])
6161+ switch {
6262+ case arg == "-c" || arg == "--config" || strings.HasPrefix(arg, "--config="):
6363+ applyRuntimeContext(parsePathFlag(args, &i, "--config"), "", false)
6464+ case arg == "--state" || strings.HasPrefix(arg, "--state="):
6565+ applyRuntimeContext("", parsePathFlag(args, &i, "--state"), false)
6666+ default:
6767+ remaining = append(remaining, arg)
6868+ }
3969 }
7070+ }
7171+ if system {
7272+ configDir := configDirOverride
7373+ if configDir == "" {
7474+ configDir = systemConfigDir
7575+ }
7676+ stateDir := dataDirOverride
7777+ if stateDir == "" {
7878+ stateDir = systemStateDir
7979+ }
8080+ applyRuntimeContext(configDir, stateDir, true)
4081 }
4182 return verbose, remaining
4283}