Whenever I use emacsclient, I tend to use it without a file argument. This is because my emacs file finder is generally better than my shell file finder.

Unfortunately, when emacsclient is not given a file argument, neither server-visit-hook nor server-switch-hook are fired, and I'm left without crucial bits of server setup.

How can I work around this limitation?

EDIT: Added example code.

(let ((my/evil-mode-line-face-cookies nil))
  (defun my/evil-set-mode-line-face (&rest args)
    (cl-destructuring-bind (bg-color fg-color)
        (pcase evil-state
          (`normal  '("white" "blue"))
          (`emacs   '("white" "green"))
          (`insert  '("black" "grey"))
          (`visual  '("white" "cyan"))
          (`replace '("white" "red"))
          (other    '("grey"  "black")))
      (mapc #'face-remap-remove-relative my/evil-mode-line-face-cookies)
      (setq my/evil-mode-line-face-cookies
            (list (face-remap-add-relative
                   `((:foreground ,fg-color :background ,bg-color)

                   `((:foreground ,fg-color)

(add-hook 'post-command-hook #'my/evil-set-mode-line-face)
(add-hook 'after-make-frame-functions #'my/evil-set-mode-line-face)
  • What do you do in those hooks? If you are using dired as your file finder, then you could simply pass the directory as your argument.
    – suvayu
    Sep 9, 2015 at 8:50
  • @suvayu I do things like initialize clipboard handlers and xterm-mouse-mode, which are specific to the current frame. I also set some faces depending on the current display's color capabilities.
    – PythonNut
    Sep 9, 2015 at 17:36
  • 1
    You could move those to before-make-frame-hook or after-make-frame-functions. Then you would have the advantage of your customisations working also in a normal session.
    – suvayu
    Sep 9, 2015 at 19:51
  • @suvayu those hooks aren't run for terminal sessions.
    – PythonNut
    Sep 10, 2015 at 0:08
  • PythonNut: Sure they are. You just need to both run the function directly in your init file, and also add it to the hook, as unless you start emacs as a daemon, the initial frame is created before your init file runs.
    – phils
    Sep 10, 2015 at 0:40

2 Answers 2


after-make-frame-functions is what I use in these situations.

Here's an example, adapted from https://stackoverflow.com/a/5066313/324105

(defun my-frame-behaviours (&optional frame)
  "Make frame- and/or terminal-local changes."
  (with-selected-frame (or frame (selected-frame))
    ;; do things...
;; Evaluate immediately (for non-daemon emacs), and also
;; upon frame creation (for new terminals via emacsclient).
(add-hook 'after-make-frame-functions 'my-frame-behaviours)
  • This is not working for the specific case of adding relative face remaps based on the current evil-state. I have no idea why.
    – PythonNut
    Sep 10, 2015 at 15:16
  • Add an example to the question?
    – phils
    Sep 10, 2015 at 20:28
  • I've added it (with some simplifications).
    – PythonNut
    Sep 10, 2015 at 20:32
  • Oh well it's obviously because I'm not including your (with-selected-frame ...) bits. Sorry about that.
    – PythonNut
    Sep 10, 2015 at 20:36
  • That may have been due to my starting with example code which was all about terminal-local changes, and which consequently didn't include that wrapper (because the frame wasn't actually important on that occasion). Glad to hear it's working now.
    – phils
    Sep 10, 2015 at 21:56

Another, possibly more hacky, solution:

(defun my/server-init (&rest args)
  (message "Initializing the server!"))
(advice-add 'server-execute :after #'my/server-init)

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.