Installation

Jotain uses Nix to build Emacs from source, driven by a Justfile task runner. Development assumes a devenv shell — enter it with devenv shell (no .envrc is tracked; direnv users can create their own).

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 plain nix-build, which evaluates default.nix — a thin flake-compat wrapper around flake.nix — and builds packages.<system>.default: the full jotainEmacsPackages distribution (Emacs + use-package-scanned packages + tree-sitter grammars + the Info manual) assembled by nix/mk-overlay.nix. The distribution's Emacs is the emacs-overlay unstable variant (the Emacs 31 release branch); thanks to the cache-parity invariant in emacs.nix its store path matches nix-community/emacs-overlay's prebuilt emacs-unstable, so the base Emacs is a binary-cache hit from nix-community.cachix.org (and the mainline variant from Hydra) — nothing recompiles from source.

Build Matrix

Jotain ships exactly four builds — {x86_64, aarch64} × {Linux, Darwin}: on Linux a pgtk/Wayland GUI and a terminal-only build; on Darwin a patched NS/Cocoa GUI (system-appearance, round-undecorated-frame, and fix-ns-x-colors patches applied by default — always built from source) and a terminal-only build. X11/Lucid/GTK3-x11/Motif/Athena and the macport fork are not supported; emacs.nix asserts those configurations away.

just build           # full distribution: Emacs 31 (unstable) + every grammar (default)
just build-nox-full  # full terminal-only distribution (same attr the nix-on-droid module ships)
just build-bare      # bare Emacs from emacs.nix — the platform's matrix GUI
just build-nox       # --without-x --without-ns (terminal only, bare)
just build-git       # bleeding-edge master from git.savannah.gnu.org
just build-igc       # feature/igc3 MPS incremental GC branch
just build-igc-ccache # igc via ccacheStdenv (for from-source platforms; see emacs.nix)
just build-perf      # CPU-tuned perf build: -O3 -march/-mtune (opt-in; off every binary cache)
just build-android   # bare aarch64-linux nox — kept for cache-parity testing

Or call nix-build directly — default.nix exposes the flake packages, and the bare-Emacs builds target emacs.nix with any argument the file accepts:

nix-build                                                # full distribution
nix-build -A emacs                                       # bare Emacs only
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

git/unstable/igc build the revision pinned by emacs-overlay and are binary-cache hits on Linux and for the terminal-only Darwin build. The Darwin GUI is patched by default and therefore always compiles from source. 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. They all install the cache-friendly emacs.nix build by default:

{
  imports = [ inputs.jotain.homeManagerModules.default ];

  services.jotain.enable = true;
}

services.jotain.package swaps in any other Jotain-shaped distribution — for example the terminal-only build:

{
  imports = [ inputs.jotain.homeManagerModules.default ];

  services.jotain = {
    enable = true;
    package = inputs.jotain.packages.${system}.emacs-nox;
  };
}

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-built 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-built          # build for this platform, then launch result/bin/emacs
just run-built-debug    # same, with --debug-init and debug-on-error

The devenv shell provides tooling only — Emacs itself is not in the shell, and the direct-launch recipes (just run, just debug, just tty, …) are disabled stubs. See the current-state note in Launching Emacs for details and the daemon + client pattern.

C-x C-f /docs/ · manual · man · info · ☾ theme