I’d like to create a home service that spawns a long-running program in the background (specifically, my bar) when I start a graphical session. However, I also like to compartmentalize my config, so I’d like avoid spawning it manually through my window manager’s startup. This was easy in NixOS since it uses systemd and I could just define a systemd script that was wanted by graphical-session.target, but I can’t find an equivalent on guix system with shepherd
Loving lisp by the way! Much nicer than nix
dgr
January 2, 2026, 5:35pm
2
Not sure but I would go with a shepherd user service depending on some service that detects if the graphical session is running.
Caution code is generated slop and not tested at all!
(define (file-exists? path)
(catch #t
(lambda () (not (null? (run* (string-append "test -e " path)))))
(lambda (exn) #f)))
(define (process-running? user proc-names)
(let loop ((names proc-names))
(cond
((null? names) #f)
((not (null? (run* (string-append "pgrep -u " user " -x " (car names))))) #t)
(else (loop (cdr names))))))
(define graphical-session-ready
(service
(name 'graphical-session-ready)
(description "Wait until a graphical session is detected")
(start
(lambda ()
(let* ((user (user-login-name))
(uid (user-uid))
(wayland-sockets (map (lambda (n) (string-append "/run/user/" (number->string uid) "/wayland-" (number->string n))) '(0 1 2 3)))
(x11-sockets '("/tmp/.X11-unix/X0" "/tmp/.X11-unix/X1"))
(graphical-procs '("Xorg" "Xwayland" "weston" "mir" "kwin_wayland" "gnome-shell" "plasmashell")))
(let loop ()
(if (or (any file-exists? wayland-sockets)
(any file-exists? x11-sockets)
(process-running? user graphical-procs))
#t
(begin (sleep 1) (loop))))))))
The service polls every second.
It checks if any Wayland socket or X11 socket exists for the user.
Or if any known graphical session process is running under the user.
When any of these conditions is true, the service reports readiness.
Other services (like bar) can depend on this service
I probably overcomplicated this a lot so maybe better ask in guile on Libera.chat if there’s a better method