Skip to main content

Command Palette

Search for a command to run...

Portable emacs config without crazy load time

Updated
3 min read
Portable emacs config without crazy load time

Imagine you can just use package-install to install any Emacs package and have a painless way to reinstall the same packages when you move to a new system.

usually what happens is when you install some package, Emacs modifies your custom-set-variables block to include the newly installed package in the package-selected-packages variable. But this does not anything special to install these packages on a new system (as far as I know). So when you are on a new system you still have to manually install all the packages present in this block to get your Emacs running without any issues.

So I wrote a script that I can just run on a new system which would read the package-selected-packages variable and install all the relevant packages for me.

Let's go over how to get this set up.

Step 1: have a separate custom-file

Add the following to your Emacs config to make sure the auto-generated custom-set-variables block is saved to a separate file.

(setq custom-file "~/.emacs.d/custom.el")
(load custom-file)

Step 2: Create the eslip script to do the package installation

Create a file called sync.el in your Emacs configuration folder with the following contents.

(require 'package)

(load-file "~/.emacs.d/custom.el")
(print package-selected-packages)
;; Add melpa
(add-to-list 'package-archives
             '("melpa-stable" . "https://melpa.org/packages/") t)

(package-initialize)
;; refresh packages
(setq my/package-refreshed-p nil)
(defun my/refresh-contants ()
    (unless my/package-refreshed-p
      (progn
    (package-refresh-contents)
    (setq my/package-refreshed-p t))))

(dolist (pkg package-selected-packages)
  (condition-case err
      (progn
    (let ((pkg-name (symbol-name pkg)))
      (eval (if (package-installed-p pkg)
            (print (concat pkg-name " already installed!"))
          (progn
            (print  (concat  "Installing: " pkg-name))
            (my/refresh-contants)
            (package-install pkg))))))
    (error
     (message "Failed to install package: %s. Error: %s" pkg err))))

This script will go through all the packages listed in package-selected-packages and install any that aren’t already on the system.

The key thing here: we don’t call this script during regular Emacs startup. That means package-refresh-contents is never called when Emacs is starting up normally. So no extra load times! You only run this sync.el script when setting up a new system or installing your packages. The rest of the time, Emacs stays fast as usual.

Step 3: Create a shell file to run the elisp script without launching Emacs

  • Create an empty file with the following contents for example in ~/.emacs.d/sync
#!/bin/bash
emacs -q --script ~/.emacs.d/sync.el
  • Make it executable:
$ sudo chmod +x ~/.emacs.d/sync

That’s it! Now, running ~/.emacs.d/sync will install any packages listed in your custom-set-variables block.

Conclusion

This technique is actually inspired by Doom Emacs. Alternatively, you could use use-package with :ensure t to handle package installation automatically. But honestly, I find that approach makes your config pretty beefy when you have a lot of packages. Adding a use-package block for everything feels clunky. And yeah, it might avoid the need for this script, but I like the simplicity of just listing the packages and not having to write a bunch of boilerplate.

This setup works perfectly for me—it's lightweight, avoids the usual slowdowns, and gets my Emacs ready in no time!

L

Was curious to try a new online casino, so I gave Bizzo a go. The platform is user-friendly, with a wide selection of games to keep things fun. The bonuses were what made the experience even better – a generous welcome offer and plenty of promotions. This site is popular in Australia, which gave me peace of mind. The bonuses really made my time here more enjoyable, and I’m happy I decided to give it a try.

More from this blog

B

bmax

25 posts