guix commands let you specify package lists on the command
line. This is convenient, but as the command line becomes longer and
less trivial, it quickly becomes more convenient to have that package
list in what we call a manifest. A manifest is some sort of a
“bill of materials” that defines a package set. You would typically
come up with a code snippet that builds the manifest, store it in a
file, say manifest.scm, and then pass that file to the
-m (or --manifest) option that many
commands support. For example, here’s what a manifest for a simple
package set might look like:
;; Manifest for three packages. (specifications->manifest '("gcc-toolchain" "make" "git"))
Once you have that manifest, you can pass it, for example, to
guix package to install just those three packages to your
profile (see -m option of
guix package -m manifest.scm
... or you can pass it to
guix shell (see
-m option of
guix shell) to spawn an ephemeral
guix shell -m manifest.scm
... or you can pass it to
guix pack in pretty much the same
way (see -m option of
You can store the manifest under version control, share it with others
so they can easily get set up, etc.
But how do you write your first manifest? To get started, maybe you’ll
want to write a manifest that mirrors what you already have in a
profile. Rather than start from a blank page,
can generate a manifest for you (see
# Write to 'manifest.scm' a manifest corresponding to the # default profile, ~/.guix-profile. guix package --export-manifest > manifest.scm
Or maybe you’ll want to “translate” command-line arguments into a
manifest. In that case,
guix shell can help
guix shell --export-manifest):
# Write a manifest for the packages specified on the command line. guix shell --export-manifest gcc-toolchain make git > manifest.scm
In both cases, the --export-manifest option tries hard to generate a faithful manifest; in particular, it takes package transformation options into account (see Package Transformation Options).
Note: Manifests are symbolic: they refer to packages of the channels currently in use (see Channels). In the example above,
gcc-toolchainmight refer to version 11 today, but it might refer to version 13 two years from now.
If you want to “pin” your software environment to specific package versions and variants, you need an additional piece of information: the list of channel revisions in use, as returned by
guix describe. See Replicating Guix, for more information.
Once you’ve obtained your first manifest, perhaps you’ll want to customize it. Since your manifest is code, you now have access to all the Guix programming interfaces!
Let’s assume you want a manifest to deploy a custom variant of GDB, the GNU Debugger, that does not depend on Guile, together with another package. Building on the example seen in the previous section (see Defining Package Variants), you can write a manifest along these lines:
(use-modules (guix packages) (gnu packages gdb) ;for 'gdb' (gnu packages version-control)) ;for 'git' ;; Define a variant of GDB without a dependency on Guile. (define gdb-sans-guile (package (inherit gdb) (inputs (modify-inputs (package-inputs gdb) (delete "guile"))))) ;; Return a manifest containing that one package plus Git. (packages->manifest (list gdb-sans-guile git))
Note that in this example, the manifest directly refers to the
git variables, which are bound to a
object (see package Reference), instead of calling
specifications->manifest to look up packages by name as we did
use-modules form at the top lets us access the core
package interface (see Defining Packages) and the modules that
git (see Package Modules). Seamlessly,
we’re weaving all this together—the possibilities are endless, unleash
The data type for manifests as well as supporting procedures are defined
(guix profiles) module, which is automatically available
to code passed to -m. The reference follows.
Data type representing a manifest.
It currently has one field:
This must be a list of
manifest-entry records—see below.
Data type representing a manifest entry. A manifest entry contains essential metadata: a name and version string, the object (usually a package) for that entry, the desired output (see Packages with Multiple Outputs), and a number of optional pieces of information detailed below.
Most of the time, you won’t build a manifest entry directly; instead,
you will pass a package to
below. In some unusual cases though, you might want to create manifest
entries for things that are not packages, as in this example:
;; Manually build a single manifest entry for a non-package object. (let ((hello (program-file "hello" #~(display "Hi!")))) (manifest-entry (name "foo") (version "42") (item (computed-file "hello-directory" #~(let ((bin (string-append #$output "/bin"))) (mkdir #$output) (mkdir bin) (symlink #$hello (string-append bin "/hello")))))))
The available fields are the following:
Name and version string for this entry.
A package or other file-like object (see file-like objects).
item to use, in case
item has multiple outputs
(see Packages with Multiple Outputs).
List of manifest entries this entry depends on. When building a profile, dependencies are added to the profile.
Typically, the propagated inputs of a package (see
propagated-inputs) end up having a corresponding manifest entry
in among the dependencies of the package’s own manifest entry.
The list of search path specifications honored by this entry (see Search Paths).
List of symbol/value pairs. When building a profile, those properties get serialized.
This can be used to piggyback additional metadata—e.g., the transformations applied to a package (see Package Transformation Options).
A promise pointing to the “parent” manifest entry.
This is used as a hint to provide context when reporting an error
related to a manifest entry coming from a
Concatenate the manifests listed in lst and return the resulting manifest.
Return a manifest entry for the output of package package,
where output defaults to
"out", and with the given
properties. By default properties is the empty list or, if
one or more package transformations were applied to package, it is
an association list representing those transformations, suitable as an
The code snippet below builds a manifest with an entry for the default
output and the
send-email output of the
Return a list of manifest entries, one for each item listed in packages. Elements of packages can be either package objects or package/string tuples denoting a specific output of a package.
Using this procedure, the manifest above may be rewritten more concisely:
Return a manifest for the development inputs of package for system, optionally when cross-compiling to target. Development inputs include both explicit and implicit inputs of package.
Like the -D option of
guix shell -D), the
resulting manifest describes the environment in which one can develop
package. For example, suppose you’re willing to set up a
development environment for Inkscape, with the addition of Git for
version control; you can describe that “bill of materials” with the
(use-modules (gnu packages inkscape) ;for 'inkscape' (gnu packages version-control)) ;for 'git' (concatenate-manifests (list (package->development-manifest inkscape) (packages->manifest (list git))))
In this example, the development manifest that
package->development-manifest returns includes the compiler
(GCC), the many supporting libraries (Boost, GLib, GTK, etc.), and a
couple of additional development tools—these are the dependencies
guix show inkscape lists.
(gnu packages) module provides higher-level facilities
to build manifests. In particular, it lets you look up packages by
Given specs, a list of specifications such as
"guile:debug", return a manifest. Specs have the format that
command-line tools such as
guix install and
package understand (see Invoking guix package).
As an example, it lets you rewrite the Git manifest that we saw earlier like this:
(specifications->manifest '("git" "git:send-email"))
Notice that we do not need to worry about
the right set of modules, and referring to the right variables.
Instead, we directly refer to packages in the same way as on the command
line, which can often be more convenient.