❌

Vista elenco

2.5 Admins 320: Dining on Goose

di: Joe
8 Ottobre 2026 ore 18:52

Google offers a few pennies to web publishers to make up for stealing their content and not sending them any traffic, the tech we’d try to use after the apocalypse, why Jim doesn’t virtualise his clients’ desktops, and setting up Volume Shadow Copy so your users can restore their own files.

 

Plugs

Support us on patreon and get an ad-free RSS feed with some early episodes

FreeBSD: The Hidden Cost of Upgrading in Production

 

News/discussion

Google’s early attempt to pay websites for AI answers is struggling

 

 

 

 

 

 

 

 

See our contact page for ways to get in touch.

 

FoLug - Linux Day Cesena 2026

8 Ottobre 2026 ore 15:21
Sabato 24 ottobre a Cesena, dalle 9:00 alle 18:30, si terrà il LinuxDay 2026 con una serie di conferenze e la possibilità di provare pc Linux recuperati, quì trovi il programma completo. L’evento è organizzato dall’associazione “Trashware Cesena” da anni attiva nel recupero di pc destinati allo smaltimento, la configurazione con Linux e la consegna …

GNU Guix: Extending Guix

8 Ottobre 2026 ore 10:58

Guix is all about empowering people, so it should come as no surprise that one can extend it with new guix commands. You can show the commands available in your current Guix through the help command:

$ guix help

If you are using a recent Guix, there are a number of extensions at your disposal, they are available as individual packages, and as a meta-package providing a collection of extensions. Try them out with:

$ guix shell guix guile guix-extension-collection

I'm adding the guix and guile packages to the shell because we want the different Guile and Guix search paths to be adjusted in the shell. To know more about why this is needed, read Search Paths.

You will notice that the help menu has been extended with information about the available extensions:

$ guix help

...

  extension commands
    explore   interactively explore a Guix System configuration
    removals  keep up to date with package removals
    compose   docker compose compatibility layer
    toys      Explore packages and services through REST API
    xsearch   search for packages using a fast Xapian cache

...

Since this blog post is called "Extending Guix", let's write an extension, shall we?

How does Guix locate extensions?

Guix locates extensions by looking up GUIX_EXTENSIONS_PATH. Recently Guix has introduced a new way of writing extensions. The old way would search extensions under /path/to/guix/extensions and the extensions modules would be named (guix extensions NAME). The new schema expects extensions to be under /path/to/SCHEMA_VERSION; the name of the module will still be (guix extensions NAME).

The advantage of this new schema is the Guix can treat the extension module as a standard Guile module, meaning that the runtime is able to find the compiled .go file of the extension. The old schema was relaying on runtime evaluation; the load machinery was not handling compiled files. This has a considerable improvement on performance, so you are encouraged to update any old extension to the new schema.

Writing an extension

Enough introductions, let's write a basic extension.

The first step is to create the project structure. Remember that the extension machinery expects modules to be named (guix extensions NAME).

We start by creating, in our project root, the directories for the extension.

$ mkdir -p guix/extensions

Now, we create the file guix/extensions/hello.scm with the following contents:

(define-module (guix extensions hello))

A blank canvas...

We import (guix scripts) to get the define-command macro. We declare it and export it so the extension machinery can find the command in the public interface of the module.

(define-module (guix extensions hello)
  #:use-module (guix scripts)
  #:export (guix-hello))

(define-command (guix-hello . args)
  (category extension)
  (synopsis "say hello")
  (display "hello, I'm a Guix extension!\n"))

With this, we already have a working Guix extension. We can run the extension like this from the root of the project.

$ GUIX_EXTENSIONS_PATH=$PWD guix hello
hello, I'm a Guix extension!

Since we would like our extension to be discoverable by users, we will add a help message which will make the extension display in the guix help menu.

We will use (srfi srfi-37) to write the option parser, and (guix ui) for the internationalized strings; you will see that I import these modules when I show you the complete extension. Let's focus on the option definitions:

(define (show-help)
  (display (G_ "Usage: guix hello\n"))
  (display (G_ "Just say hello, it's not that complicated.\n"))
  (display (G_ "
      --help             display this message"))
  (newline))

(define %options
  (list (option '(#\h "help") #f #f
                (lambda args
                  (leave-on-EPIPE (show-help))
                  (exit 0)))))

Since we are only handling the arguments for showing the help message, we just need to call the parser at the start of the command:

(define-command (guix-hello . args)
  (category extension)
  (synopsis "say hello")
  (parse-command-line args %options (list '()))
  (display "hello, I'm a Guix extension!\n"))

Here you have the complete extension module:

(define-module (guix extensions hello)
  #:use-module (guix scripts)
  #:use-module (guix ui)
  #:use-module (srfi srfi-37)
  #:export (guix-hello))

(define (show-help)
  (display (G_ "Usage: guix hello\n"))
  (display (G_ "Just say hello, it's not that complicated.\n"))
  (display (G_ "
      --help             display this message"))
  (newline))

(define %options
  (list (option '(#\h "help") #f #f
                (lambda args
                  (leave-on-EPIPE (show-help))
                  (exit 0)))))

(define-command (guix-hello . args)
  (category extension)
  (synopsis "say hello")
  (parse-command-line args %options (list '()))
  (display "hello, I'm a Guix extension!\n"))

With that, our extension will be present when we ask Guix for help:

$ GUIX_EXTENSIONS_PATH=$PWD guix help

...

  extension commands
    hello  say hello

It also takes a --help flag:

$ GUIX_EXTENSIONS_PATH=$PWD guix hello --help
Usage: guix hello
Just say hello, it's not that complicated.

      --help             display this message

Packaging a Guix extension

At the time of writing, we don't have a dedicated Guix build-system for extensions. Fortunately, the guile-build-system is close enough for this use case.

Let's make a package definition for our new hello extension that uses our local sources. Create a guix.scm file at the root of the project with the following contents:

(use-modules (gnu packages package-management)
             (guix build-system guile)
             (guix gexp)
             (guix git-download)
             (guix packages)
             ((guix licenses) #:prefix license:))

(define vcs-file?
  ;; Return true if the given file is under version control.
  (or
   (git-predicate
    (dirname (canonicalize-path
              (assq-ref (current-source-location) 'filename))))
   (const #t)))

(define-public guix-hello
  (package
    (name "guix-hello")
    (version "0.0.0-git")
    (source (local-file (assume-valid-file-name ".")
                        "pin-checkout"
                        #:recursive? #t
                        #:select? vcs-file?))
    (build-system guile-build-system)
    (arguments
     (list
      #:scheme-file-regexp
      #~(lambda (file stat)
          (and ((file-name-predicate #$default-scheme-file-regexp)
                file stat)
               (not ((file-name-predicate "^(guix|channels|manifest)\\.scm$")
                     file stat))))
      #:phases
      #~(modify-phases %standard-phases
          (add-after 'build 'move-to-extension-directory
            (lambda _
              (with-directory-excursion #$output
                (mkdir-p "share/guix/extensions/1.5/guix/extensions")
                (rename-file (string-append "share/guile/site/"
                                            (target-guile-effective-version)
                                            "/guix/extensions/hello.scm")
                             "share/guix/extensions/1.5/guix/extensions/hello.scm")))))))
    (native-inputs (list guix))
    (inputs (list (lookup-package-input guix "guile")))
    (home-page "https://codeberg.org/guix-extensions")
    (synopsis "Make Guix say hello")
    (description
     "This extension provides the @command{guix hello} command,
which makes Guix say hello.")
    (license license:gpl3+)))

guix-hello

We can test this new extension like this:

$ guix shell -CW -f guix.scm -- guix hello

The flags passed to guix shell are the following:

  • -C (--container): To prevent your environment from interfering.
  • -W (--nesting): To bring the current Guix you are using into the container so it can load the extension.

Since this example is using the new extension scheme, the guix command you are running must be at or newer than commit de069958fc.

Closing words

I hope you find this small introduction to Guix extensions useful and that you start to write your own Guix extensions.

I would like to encourage everyone reading this to submit their extensions to the guix-extensions Codeberg organization. The idea is to make this organization a central hub for everyone to participate in the development of useful extensions for the community.

❌