Launching Emacs
Current state: the devenv shell provides tooling only; there is no
emacsbinary in it (see the top-of-file note indevenv.nix). The direct-launch recipes (just run,just debug,just tty,just daemon,just client,just client-tty,just quick) were removed along with it. The supported launch path isjust run-built: build Emacs via Nix, then launch it with this configuration. Other docs pages that mention launching point back at this note.
Jotain supports three launch patterns. Pick the one that matches the task — they're complementary, not alternatives.
One-shot
A fresh emacs process every time. Loads the full Jotain config; pays package-init cost on every launch.
just run-built # build for this platform, then launch result/bin/emacs
just run-built-debug # same, with --debug-init and debug-on-error
just run-built auto-detects the platform, builds the full distribution (just build; on aarch64-linux the full terminal-only distribution via just build-nox-full), and launches ./result/bin/emacs --init-directory=<repo>, so it never touches ~/.emacs.d. The first invocation pays a nix build (usually a binary-cache pull); reruns launch straight from ./result.
Best for sanity checks and trying out config changes. Avoid for day-to-day editing — the startup cost adds up.
Daemon + client
Start Emacs once as a server; reuse it via lightweight clients. The first frame is slow; every frame after is instant.
In the repo (development)
The just daemon / just client / just client-tty recipes were removed (no Emacs in the dev shell; see the note above). The manual equivalent uses the Nix-built binary:
just build # or let a previous `just run-built` leave ./result behind
./result/bin/emacs --fg-daemon --init-directory="$PWD" # foreground daemon
./result/bin/emacsclient -c # graphical client frame
./result/bin/emacsclient -t # terminal client frame
The daemon blocks; run it in another terminal (or under tmux) and connect with emacsclient from elsewhere. Launching with --init-directory=<repo> keeps it isolated from ~/.emacs.d.
Stop the daemon with C-c in its terminal, or from any client:
./result/bin/emacsclient -e '(kill-emacs)'
As an installed user (home-manager)
The services.jotain module ships:
- A systemd user service (Linux) or launchd agent (macOS) that runs
emacs --fg-daemon. Enabled viaservices.jotain.startWithUserSession. jotain-editor—emacsclient --ttywith a-nwfallback. Set as$EDITORwhenservices.jotain.defaultEditor = true.jotain-visual—emacsclient --create-frame. Set as$VISUAL.jotctl {start|stop|status|restart|logs}— manage the daemon itself (wrapslaunchctlon macOS, thejotainsystemd user service on Linux). Always onPATHwhen the module is enabled.- A
.desktopentry (jotain-client.desktop) for launching a GUI client from your application menu, enabled byservices.jotain.client.enable.
See Module Options in the appendix for the full option reference.
Shell aliases
Inspired by Rahul Juliato's launching-emacs-terminal post, the module can install short aliases for the daemon and clients:
services.jotain = {
enable = true;
shellAliases.enable = true;
# shellAliases.prefix = "j"; # for "jemd"/"jem"/"jemg"
};
| Alias | Expands to |
|---|---|
emd |
emacs --fg-daemon (wrapped) |
em |
jotain-editor (emacsclient --tty) |
emg |
jotain-visual (emacsclient -c) |
The aliases are written to programs.bash.shellAliases, programs.zsh.shellAliases, and programs.fish.shellAliases — pick up whichever shell home-manager already manages.
Managing the daemon (jotctl)
emd starts a foreground daemon; to manage the supervised daemon (the launchd agent on macOS, the jotain systemd user service on Linux) use jotctl, which is always on PATH when the module is enabled — independent of shellAliases.enable:
| Command | macOS (launchd) | Linux (systemd --user) |
|---|---|---|
jotctl status |
launchctl print … (default) |
systemctl --user status jotain |
jotctl start |
launchctl bootstrap / kickstart |
systemctl --user start jotain |
jotctl stop |
launchctl bootout |
systemctl --user stop jotain |
jotctl restart |
launchctl kickstart -k |
systemctl --user restart jotain |
jotctl logs |
launchd state + note¹ | journalctl --user -u jotain -f |
¹ The launchd agent sets no StandardOutPath, so macOS doesn't capture the daemon's stdout; jotctl logs prints the launchd state instead.
Quick edit (-Q -nw)
When you need a stripped-down Emacs — editing /etc/hosts over SSH, fixing a typo in a 200 MB log file, demonstrating something with no muscle-memory key bindings — bypass Jotain entirely (the just quick recipe was removed; use any emacs on the host, or the Nix-built one):
./result/bin/emacs -Q -nw --eval "(load-theme 'wombat t)"
This is the pattern Rahul Juliato describes in basic-emacs-alias. -Q skips early-init.el, init.el, site-lisp, and ~/.emacs.d/; -nw keeps it in the current terminal; the wombat theme line is the one concession to readability on dark terminals.
To get the same effect anywhere, add an alias to your shell:
alias eq='emacs -Q -nw --eval "(load-theme '\''wombat t)"'
Which one to use
| Situation | Use |
|---|---|
| First-time setup, sanity checks | just run-built |
| Day-to-day editing, fast frame opens | daemon + em/emg |
| Sysadmin SSH session, ad-hoc edit | emacs -Q -nw alias |
| Debugging a config regression | just run-built-debug |