#include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <gpiod.h>
 #include <signal.h>
 #include <stdbool.h>
 #include <stdio.h>
                fflush(stdout);
        }
 }
+
+static struct gpiod_line *libgpiod_line;
+
+static void
+libgpiod_out(bool state)
+{
+
+       if (gpiod_line_set_value(libgpiod_line, state) == -1)
+               err(1, "gpiod_line_set_value");
+}
+
+static void (*outfn)(bool) = &dummy_out;
+
 static void
 record_tick()
 {
 
        if (sigprocmask(SIG_BLOCK, &signals_to_block, &saved_mask) != 0)
                err(1, "sigprocmask(block)");
-       dummy_out(true);
+       (*outfn)(true);
        record_tick();
        errno = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
        if (errno != 0)
                err(1, "clock_nanosleep");
-       dummy_out(false);
+       (*outfn)(false);
        if (sigprocmask(SIG_SETMASK, &saved_mask, NULL) != 0)
                err(1, "sigprocmask(restore)");
 }
        }
 }
 
+static void
+init_libgpiod(char const *gpio_name)
+{
+
+       libgpiod_line = gpiod_line_find(gpio_name);
+       if (libgpiod_line == NULL)
+               err(1, "GPIO line '%s'", gpio_name);
+       if (gpiod_line_request_output(libgpiod_line, "clunk", false) == -1)
+               err(1, "requesting '%s'", gpio_name);
+}
+
 static void
 alrm_handler(int signo)
 {
        if (localtime_r(&ts.tv_sec, &displayed) == NULL)
                err(1, "localtime_r");
        displayed.tm_sec = (displayed.tm_sec >= 30) ? 30 : 0;
-       while ((opt = getopt(argc, argv, "f:s:")) != -1) {
+       while ((opt = getopt(argc, argv, "f:g:s:")) != -1) {
                switch (opt) {
                case 'f':
                        statefile = optarg;
                case 's':
                        statestr = optarg;
                        break;
+               case 'g':
+                       init_libgpiod(optarg);
+                       break;
                }
        }
        if (statefile != NULL)