I want to update Emacs from the command line so I created the following function to help with this:

;;; update.el -- Update Emacs from the command line

(defun update-emacs ()
  "Update Emacs without interaction, to be used from the command line."
  (defun perform-emacs-update ()
    (switch-to-buffer "*Packages*")
    (declare-function package-menu-mark-upgrades "package.el.gz")
    (declare-function package-menu-execute "package.el.gz")
    (package-menu-execute t))
  (add-hook 'package--post-download-archives-hook 'perform-emacs-update)

(provide 'update-emacs)

Then I run Emacs with these parameters:

$ emacs --batch --eval '(load "~/.emacs.d/update.el")' --eval '(update-emacs)'

However it doesn't run the hook for some reason. I get this output instead

Loading ~/.emacs.d/update.el (source)... Setting ‘package-selected-packages’ temporarily since "emacs -q" would overwrite customizations

This code works fine when I execute it from an already running Emacs. How can I get it to run in batch mode?

1 Answer 1


The documentation gives the answer.

Don't run this hook directly. It is meant to be run as part of package--update-downloads-in-progress.

As a rule, -- in the name is an indication that it's a private unit not intended to be used by us mere mortals.

If you collect your packages to upgrade into a list, then a function like this should work.

(dolist (p my-packages)
      (when (not (package-installed-p p))
        (package-install p)))
  • I see, I did not realize that about -- thanks for the tip. Also, concerning "If you collect your packages to upgrade into a list", that is the part I was trying to get from the private function. Any idea how to get the list of packages that need to be updated? Nov 10, 2021 at 1:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.