Is there any rule by which the user can determine whether the package configuration requires :init or :config?


2 Answers 2


Is there any rule by which the user can determine whether the package configuration requires :init or :config?

There is no general rule which applies to all settings and packages; you just need to familiarise yourself with the meaning of these keywords by reading the README file of use-package.

In summary, the :init block is run at startup, as if you had placed its constituent forms at the top-level (i.e. outside of a typical call to use-package) of your user-init-file. This means they are always run, regardless of whether the corresponding package has been loaded or not.

The :config block, on the other hand, is run after the corresponding package has been loaded, by way of the eval-after-load mechanism.

As such, you can improve your startup time by moving applicable long-running settings from :init to :config. If you need to modify a variable which is only defined after loading a particular package, you similarly need to place this in the :config block. Some variables, such as gnus-home-directory, need to be set before their corresponding package is loaded, so they should be placed in :init. I strongly advise putting all applicable add-hook/remove-hook calls in the :init block, as hooks can be modified even when unbound, and this affords more modularity to your setup.

You can often avoid having to figure out where to place a particular setting by using the new :custom keyword, or by using the Easy Customization interface directly.

  • I know this thread is old, but use-package is a famous package and i really have a problem understanding this. C-h f use-package tells me :init code is run before package has been loaded, but the github page of vertico (famous emacs package) tells to run (vertico-mode) in :init and it works? How can (vertico-mode) be successfully evaluated if the package is not yet loaded???
    – Matthias
    Commented Apr 20, 2023 at 11:11
  • @Matthias That's because vertico-mode is probably autoloaded, i.e. Emacs knows where to find it when it is called. See the section on autoloading in (info "(emacs) Lisp Libraries").
    – Basil
    Commented Apr 20, 2023 at 21:48

I am not sure if there is a general rule (apart from "use :init for preconfiguration before actual package loading and use :config for other, well, configuration").

But I for myself use :init when, for example, I want to add some other mode map keybindings to use functions from "this" package. And still want "this" package to be lazy loaded.

Here is the example of lazy loading of dired-ranger:

(use-package dired-ranger
  :commands (dired-ranger-copy dired-ranger-paste dired-ranger-move)
  (add-hook 'dired-mode-hook
            (lambda ()
              (define-key dired-mode-map (kbd "M-w") 'dired-ranger-copy)
              (define-key dired-mode-map (kbd "C-y") 'dired-ranger-paste)
              (define-key dired-mode-map (kbd "C-c C-y") 'dired-ranger-move))))

P.S.: If there is no :defer, :commands, :mode and others that makes package loading lazy, then :init and :config should be more or less the same (but :init will be evaluated earlier :) )

  • 4
    Modifying key bindings in a mode hook means they are run every time you open a buffer in that mode. You only need to modify key bindings once, after the package is loaded. You can use the :bind keyword for this, or modify the key bindings in the :config block.
    – Basil
    Commented Feb 27, 2018 at 14:29
  • Indeed, never thought about it. But :config is too late -- lazy loading will not apply my bindings. And :bind with :map doesn't actually bind it.
    – Maxim Kim
    Commented Feb 27, 2018 at 17:38
  • 3
    :config is not too late - that's exactly when dired-mode-map is first defined. You're probably just putting it in the wrong use-package form of dired-ranger instead of dired, where dired-mode-map is defined. This might also explain why your :bind does not work. Basically, either you are doing something wrong or use-package has a bug. Do not confuse local keybindings and eval-after-load with global keybindings of autoloaded commands/keymaps.
    – Basil
    Commented Feb 27, 2018 at 17:55
  • @Basil, thx, you're right. My problem was that I have set use-package-always-ensure and when I try to use-package dired it fails to fetch it from elpa. But having :ensure nil there solves the problem and I can set up chained package loading dired -> dired-ranger using :after.
    – Maxim Kim
    Commented Feb 28, 2018 at 6:47

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.