Skip to main content

Installation

Jotain uses Nix to build Emacs from source, driven by a Justfile task runner. Development assumes a devenv shell (managed by direnv via .envrc, or entered manually with devenv shell).

Prerequisites

All just recipes assume the devenv shell is active. If you do not use direnv, prefix any command with devenv shell --, e.g. devenv shell -- just check.

Building Emacs

The default build targets the current system and includes every tree-sitter grammar from nixpkgs:
just build
This runs nix-build --argstr system <current-system> default.nix, which wraps emacs.nix with emacsPackagesFor ... withPackages to add treesit-grammars.with-all-grammars. For the plain mainline build (the emacs.nix default), the store path is bit-for-bit identical to nixpkgs’ default pkgs.emacs, so the official binary cache is hit and nothing recompiles from source; the git-based variants are likewise cache hits from nix-community/emacs-overlay’s nix-community.cachix.org.

Build Variants

Every emacs.nix argument is forwarded through default.nix. The Justfile provides shortcuts for the common flavours:
just build          # mainline Emacs 31 + every grammar (default)
just build-bare     # bare Emacs from emacs.nix — no grammars
just build-jylhis   # bare github:jylhis/emacs Meson fork
just build-pgtk     # --with-pgtk (pure GTK, Wayland)
just build-gtk3     # --with-x-toolkit=gtk3 (X11 + GTK3)
just build-nox      # --without-x --without-ns (terminal only)
just build-macport  # jdtsmith/emacs-mac fork (Darwin only)
just build-git      # bleeding-edge master from git.savannah.gnu.org
just build-igc      # feature/igc3 MPS incremental GC branch
just build-android  # aarch64-linux nox (Termux)
Or call nix-build directly with any argument the emacs.nix file accepts:
nix-build default.nix                                    # mainline + grammars
nix-build default.nix --arg withTreeSitterGrammars false # grammars off
nix-build emacs.nix  --arg withNativeCompilation false   # no native-comp
nix-build emacs.nix  --arg variant '"git"'               # master
nix-build emacs.nix  --arg variant '"igc"'               # MPS GC branch
nix-build emacs.nix  --arg variant '"macport"'           # macOS macport fork
git/unstable/igc build the revision pinned by emacs-overlay and are binary-cache hits. Only when pinning a custom commit via --argstr rev "..." does the first build fail and report the expected hash to pass back via --argstr hash "sha256-...".

Installing from a Consumer Flake

Jotain exposes Home Manager, NixOS, and nix-darwin modules. The default backend stays on the cache-friendly emacs.nix build:
{
  imports = [ inputs.jotain.homeManagerModules.default ];

  services.jotain.enable = true;
}
To install the same Jotain setup on the github:jylhis/emacs Meson fork, select the fork backend:
{
  imports = [ inputs.jotain.homeManagerModules.default ];

  services.jotain = {
    enable = true;
    emacsBackend = "jylhis";
  };
}
Downstream flakes can override the fork source by following the jylhis-emacs input:
inputs.jotain.url = "github:jylhis/jotain";
inputs.my-emacs-fork = {
  url = "github:jylhis/emacs/my-branch-or-rev";
  flake = false;
};
inputs.jotain.inputs.jylhis-emacs.follows = "my-emacs-fork";
The bare fork package is checked directly. The full fork-backed package set is not exposed as a flake packages output, because the Meson fork still crashes while byte-compiling some bundled Emacs packages. It remains reachable via the Home Manager services.jotain.emacsBackend = "jylhis" option (which consumes the jylhisEmacsPackages overlay attribute directly) for those who want to exercise that experimental path.

nix-on-droid (Android)

Jotain also ships a nix-on-droid module for running Emacs on Android (Termux/proot). Android is headless under proot, so the module installs a terminal-only (-nw) Emacs into environment.packages and wires EDITOR/VISUAL to an emacsclient wrapper — there is no systemd daemon, launchd agent, or GUI frame.
{
  imports = [ jotain.nixOnDroidModules.default ];

  services.jotain.enable = true;
}
Switch it in with nix-on-droid switch --flake .#default. See nixOnDroidConfigurations.default in Jotain’s flake.nix for a complete example wiring.
Like the NixOS / nix-darwin module (module-system.nix), this module installs the curated Jotain Emacs package — Jotain’s Emacs packages, tree-sitter grammars, themes, and Info manual are on the load-path — but it does not install Jotain’s own early-init.el / init.el / lisp/. To have Emacs boot the full Jotain configuration, point it at the config with --init-directory (the way just run does) or layer the Home Manager module through nix-on-droid’s home-manager.config, which installs the config into a writable ~/.config/emacs. A bare --init-directory into the read-only Nix store will not work, because Jotain writes var/, elpa/, and eln-cache/ under user-emacs-directory.

Overriding nixpkgs

Downstream flakes may pin a different nixpkgs (release branches 24.05+ through unstable) by following the input:
inputs.jotain.inputs.nixpkgs.follows = "nixpkgs";
emacs.nix gates the Emacs build flags that newer make-emacs.nix versions introduced, so the modules still evaluate and build on older releases. Note that on 24.05 pkgs.emacs is Emacs 29 while Jotain’s Elisp targets Emacs 30/31 — the build succeeds, but full runtime behaviour is only guaranteed on the pinned unstable.

Running

Jotain is designed to be launched out of its own checkout via --init-directory, so it never touches ~/.emacs.d.
just run                # launch Emacs with this config (GUI)
just debug              # same, with --debug-init and debug-on-error
just tty                # -nw terminal session (exercises kkp + clipetty)
just run-built          # build for this platform, then launch result/bin/emacs
just run simply invokes emacs --init-directory=<repo>. The devenv shell ships the same Emacs that just build-bare produces, so running inside direnv is usually enough for day-to-day use — no nix-build required.
Last modified on July 9, 2026