4.3 Hooks

The :hook keyword allows adding functions to hooks. It takes one argument of the form hooks, specifying one or more functions to add to one or more hooks. For the purposes of :hook, the name of hook variables should always exclude the ‘-hook’ suffix. It is appended automatically for you, to save some typing.

For example, consider the following use-package declaration that sets up autoloads for company-mode from the ‘company’ package, and adds ‘company-mode’ to prog-mode-hook:

(use-package company
  :commands company-mode
  :init
  (add-hook 'prog-mode-hook #'company-mode))

Using :hook, this can be simplified to:

(use-package company
  :hook (prog-mode . company-mode))

Here, :hook will automatically set up autoloads for the company-mode command, so there is no need to use :commands.

The :hook keyword will also assume that the name of the function you want to add is the same as the package name with ‘-mode’ appended to it. Taking this into account, you can simplify the above to the equivalent:

(use-package company
  :hook prog-mode)

You can also provide a list of hooks. When multiple hooks should be applied, the following examples are all equivalent:

(use-package company
  :hook (prog-mode text-mode))

(use-package company
  :hook ((prog-mode text-mode) . company-mode))

(use-package company
  :hook ((prog-mode . company-mode)
         (text-mode . company-mode)))

(use-package company
  :commands company-mode
  :init
  (add-hook 'prog-mode-hook #'company-mode)
  (add-hook 'text-mode-hook #'company-mode))

One common mistake when using :hook is to forget to omit the ‘-hook’ suffix, which, as already explained, is appended automatically. Therefore, the following will not work, as it attempts to add a function to non-existent prog-mode-hook-hook:

;; DOES NOT WORK
(use-package ace-jump-mode
  :hook (prog-mode-hook . ace-jump-mode))

If you do not like this behavior, you can customize the user option use-package-hook-name-suffix to nil. The value of this variable is ‘"-hook"’ by default.

The use of :hook, as with :bind, :mode, :interpreter, etc., causes the functions being hooked to implicitly be read as :commands. This means that they will establish interactive autoload definitions for that module, if not already defined as functions), and so :defer t is also implied by :hook.