Is there any rule by which the user can determine whether the package configuration requires :init
or :config
?
2 Answers
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.

- 12,383
- 43
- 69
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)
:init
(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 :) )
-
4Modifying 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 Feb 27 '18 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 Feb 27 '18 at 17:38 -
3
:config
is not too late - that's exactly whendired-mode-map
is first defined. You're probably just putting it in the wronguse-package
form ofdired-ranger
instead ofdired
, wheredired-mode-map
is defined. This might also explain why your:bind
does not work. Basically, either you are doing something wrong oruse-package
has a bug. Do not confuse local keybindings andeval-after-load
with global keybindings of autoloaded commands/keymaps. – Basil Feb 27 '18 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 loadingdired
->dired-ranger
using:after
. – Maxim Kim Feb 28 '18 at 06:47
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 Apr 20 '23 at 21:48