# Shepherd equivalent to graphical-session.target?

**URL:** <https://forum.systemcrafters.net/t/shepherd-equivalent-to-graphical-session-target/1868>\
**Category:** Guix\
**Created:** [December 30, 2025, 2:34am UTC](https://forum.systemcrafters.net/t/shepherd-equivalent-to-graphical-session-target/1868 "2025-12-30T02:34:08Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![ced4rtree](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.systemcrafters.net/ced4rtree/32/821_2.png) [@ced4rtree](https://forum.systemcrafters.net/u/ced4rtree)\
**Post date:** [December 30, 2025, 2:34am UTC](https://forum.systemcrafters.net/t/shepherd-equivalent-to-graphical-session-target/1868/1 "2025-12-30T02:34:08Z")

</div>

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 🙂

---

<div class="post-metadata">

**Author:** ![dgr](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.systemcrafters.net/dgr/32/394_2.png) [@dgr](https://forum.systemcrafters.net/u/dgr)\
**Post date:** [January 2, 2026, 5:35pm UTC](https://forum.systemcrafters.net/t/shepherd-equivalent-to-graphical-session-target/1868/2 "2026-01-02T17:35:21Z")

</div>

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!

```scheme
(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 😉
