Recently I’ve switched back to Linux, after having used macOS for the past 9 years. While I was generally happy with my overall macOS experience, I was also disappointed that Emacs simply didn’t work as well there, as it does on Linux for various reasons.

When I was a Linux user I’d always run Emacs as a daemon (server) and I’d connect this daemon from multiple instances of emacsclient. This was both elegant and efficient - my clients started instantly and shared access to everything that was running on the daemon instance. While this was doable to some extent in macOS, it never worked quite as well for me, and I abandoned that workflow eventually. Now, however, I’m back! Time to revive the workflow!

Historically I ran the Emacs daemon by adding something like this to my shell init (e.g. .bashrc):

export ALTERNATE_EDITOR=''
alias e='emacsclient --tty'

The magic is in the first line - leaving ALTERNATE_EDITOR blank. That way the first time I ran emacsclient it’d start an Emacs daemon and connect to it. Many people preferred to make the daemon a “proper” service that they can start, restart and monitor, but this felt like an overkill to me. I’ve noticed, however, that Emacs 26.1 bundles a systemd unit, so it’s now trivial to control your Emacs daemon with systemd. It all boils down to running this command:

$ systemctl --user enable --now emacs

Run this command with your regular user (or whatever user account you want to be running Emacs). Don’t run it as root, though! You’ll get a message that the unit file was copied to /usr/lib/systemd/user/emacs.service and you can examine it if you’re curious:

[Unit]
Description=Emacs text editor
Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/

[Service]
Type=simple
ExecStart=/usr/bin/emacs --fg-daemon
ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)"
Environment=SSH_AUTH_SOCK=%t/keyring/ssh
Restart=on-failure

[Install]
WantedBy=default.target

Pretty straightforward.

At this point your Emacs daemon is up and you can connect to it using both terminal clients (emacsclient -t) and GUI clients (emacsclient -c). You might also want to create some desktop icon that runs emacsclient -c, instead of emacs. You might also want to set both EDITOR and VISUAL to emacsclient -t:

export EDITOR='emacsclient -t'
export VISUAL='emacsclient -t'

I typically add two more aliases just to be on the safe side:1

alias vi='emacsclient -t'
alias vim='emacsclient -t'

One thing to keep in mind is that when you’re running Emacs in this manner it won’t read your user environment variables (at least not those coming from your .bash_profile and .bashrc). That’s why it’s a good idea to install the popular package exec-path-from-shell.

Alternatively you can use one of systemd’s own mechanisms for setting environment variables - e.g. environment.d. The Arch Linux Wiki has a few good examples of using environment.d and also mentions other approaches that you can consider.

That’s all I have for you today. I hope you’ve learned something useful. In parentheses we trust!

  1. Old habits die hard.