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 Emacs 31 mainline build (the emacs.nix default), the store path is bit-for-bit identical to pkgs.emacs-git from nix-community/emacs-overlay, so the public binary cache (nix-community.cachix.org) is hit and nothing recompiles from source.

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
For git/unstable/igc variants the first build will fail and report the expected hash. Re-run with --argstr hash "sha256-..." (or edit emacs.nix to pin it).

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 exposed as .#jylhis-emacs-packages and just build-jylhis-full, but remains experimental until the Meson fork reliably byte-compiles all bundled Emacs packages.

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 May 25, 2026