Emacs package management with straight.el and use-package
Jeff Kreeftmeijer
Posted on August 16, 2021
Emacs includes a package manager named package.el
, which installs packages from the official Emacs Lisp Package Archive, named GNU ELPA. GNU ELPA hosts a selection of packages, but most are available on MELPA, which is an unofficial package archive that implements the ELPA specification. To use MELPA, it has to be installed by adding it to the list of package.el
package archives.
The built-in package manager installs packages through the package-install
function. For example, to install the "evil-commentary" package from MELPA, call package-install
inside Emacs:
M-x
package-install
<RET>
evil-commentary
<RET>
Straight.el
Straight.el is an alternative package manager that installs packages through Git checkouts instead of downloading tarballs from one of the package archives. Doing so allows installing forked packages, altering local package checkouts, and locking packages to exact versions for reproducable setups.
Installation
The Getting started section in the straight.el README provides the bootstrap code to place inside ~/.emacs.d/init.el
in order to install it:
;; Install straight.el
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
Straight.el uses package archives like GNU ELPA as registries to find the linked repositories to clone from. Since these are checked automatically, there's no need to add them to the list of package archives.
While package.el loads all installed packages on startup, straight.el only loads packages that are referenced in the init file. This allows for installing packages temporarily without slowing down Emacs' startup time on subsequent startups.
To create a truly reproducable setup, disable package.el in favor of straight.el by turning off package-enable-at-startup
. Because this step needs to happen before package.el gets a chance to load packages, it this configuration needs to be set in the early init file:
;; Disable package.el in favor of straight.el
(setq package-enable-at-startup nil)
With this configuration set, Emacs will only load the packages installed through straight.el.
Usage
To use straight.el to install a package for the current session, execute the straight-use-package
command:
M-x
straight-use-package
<RET>
evil-commentary
<RET>
To continue using the package in future sessions, add the straight-use-package
call to ~/.emacs/init.el
:
(straight-use-package 'evil-commentary)
To update an installed package, execute the straight-pull-package
command:
M-x
straight-pull-package
<RET>
evil-commentary
<RET>
To update the version lockfile, which is used to target the exact version to check out when installing, run straight-freeze-versions
:
M-x
straight-freeze-versions
<RET>
Use-package
Use-package is a macro to configure and load packages in Emacs configurations. It interfaces with package managers like package.el or straight.el to install packages, but is not a package manager by itself.
For example, when using straight.el without use-package, installing and starting evil-commentary requires installing the package and starting it as two separate steps:
(straight-use-package 'evil-commentary)
(evil-commentary-mode)
Combined with use-package, the installation and configuration are unified into a single call to use-package
:
(use-package evil-commentary
:config (evil-commentary-mode))
Aside from keeping configuration files tidy, having package configuration contained within a single call allows for more advanced package setups. For example, packages can be lazy-loaded, keeping their configuration code from executing until the package they configure is needed.
Installation
To install use-package with straight.el, use straight-use-package
:
;; Install use-package
(straight-use-package 'use-package)
Using straight.el with use-package
By default, use-package uses package.el to install packages. To use straight.el instead of package.el, pass the :straight
option:
(use-package evil-commentary
:straight t)
To configure use-package to always use straight.el, use use-package
to configure straight.el to turn on straight-use-package-by-default
1:
;; Configure use-package to use straight.el by default
(use-package straight
:custom (straight-use-package-by-default t))
Now, installing any package using use-package uses straight.el, even when omitting the :straight.el
option.
Having both straight.el and use-package installed and configured to work together, the straight-use-package
function isn't used anymore. Instead, all packages are installed and configured through use-package.
Usage
Use the use-package
macro to load a package. If the package is not installed yet, it is installed automatically:
(use-package evil-commentary)
Use-package provides keywords to add configuration, key bindings and variables. Although there are many more options, some examples include :config
, :init
, :bind
, and :custom
:
-
:config
and:init
: The:config
and:init
configuration keywords define code that's run right after, or right before a package is loaded, respectively.For example, call
evil-mode
from the:config
keyword to start Evil after loading its package. To turn offevil-want-C-i-jump
right before evil is loaded (instead of adding it to the early init file), configure it in the:init
keyword:
(use-package evil :init (setq evil-want-C-i-jump nil) :config (evil-mode))
-
:bind
: Adds key bindings after a module is loaded. For example, to useconsult-buffer
instead of the built-inswitch-to-buffer
after loading the consult package, add a binding through the:bind
keyword:
(use-package consult :bind ("C-x b" . consult-buffer)
-
:custom
: Sets customizable variables. The variables set through use-package are not saved in Emacs' custom file. Instead, all custom variables are expected to be set through use-package. In an example from before, the:custom
keyword is used to set thestraight-use-package-by-default
configuration option after loading straight.el:
(use-package straight :custom (straight-use-package-by-default t))
Summary
The resulting ~/.emacs.d/init.el
file installs straight.el and use-package, and configures straight.el as the package manager for use-package to use:
;; Install straight.el
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
;; Install use-package
(straight-use-package 'use-package)
;; Configure use-package to use straight.el by default
(use-package straight
:custom (straight-use-package-by-default t))
The ~/.emacs.d/early-init.el
file disables package.el to disable its auto-loading, causing all packages to be loaded through straight.el in the init file:
;; Disable package.el in favor of straight.el
(setq package-enable-at-startup nil)
This is the only configuration set in the early init file. All other packages are installed and configured through use-package, which makes sure to load configuration options before packages are loaded, if configured with the :init
keyword.
Footnotes
1 Calling use-package
would normally install straight.el, but since it's already installed, the installation is skipped and the configuration is set. Here, the call to use-package
is only used to configure straight.el, by setting the straight-use-package-by-default
option.
Posted on August 16, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.