Shepherd equivalent to graphical-session.target?

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 :slightly_smiling_face:

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 :robot: 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 :wink: