Packages
Jotain is a “use-package + Nix” configuration: Nix provides most packages onload-path, so use-package finds them without touching the network; anything Nix does not ship falls through to MELPA at install time.
Provenance
-
Built-in to Emacs 30+ — always opt out of installation with
:ensure nil. -
Provided by Nix — the distribution (
nix/mk-overlay.nix) scans theuse-packagedeclarations and maps them to the emacs-overlay package set; archive-absent packages (e.g.claude-code-ide,combobulate) are built innix/extra-packages.nix. These also use:ensure nilbecause Nix already put them on the load path. -
MELPA / NonGNU ELPA fallback — every other
use-packageblock.use-package-always-ensureist(set inearly-init.el), so these default to “install if missing” without any extra boilerplate. Archives are registered ininit.el:
Tree-sitter grammars
When built withdefault.nix (the full distribution — just build and friends), Jotain ships every tree-sitter grammar in nixpkgs via emacsPackagesFor emacs |> withPackages (epkgs: [ epkgs.treesit-grammars.with-all-grammars ]). The grammar bundle is exposed through TREE_SITTER_DIR; early-init.el picks that up and adds it to treesit-extra-load-path so every built-in *-ts-mode finds its grammar out of the box.
Packages that live in Nix
nix/extra-packages.nix defines the Elisp packages that are not on any archive (MELPA, GNU ELPA, NonGNU ELPA), so Nix builds them directly via trivialBuild from pinned revisions and puts them on load-path:
ghostel— Ghostty terminal integration.jylhis-emacs-themes— the design-system themes; their revision comes fromnix/design-pin.nix, the single pin shared with the website’s vendored CSS.claude-code-ide— fetched frommanzaltu/claude-code-ide.el, built withwebsocketandweb-serveras runtime dependencies (transientis built in to Emacs 30+).combobulate— fetched frommickeynp/combobulate; all its dependencies (seq,map,treesit) are built in to Emacs 30+.majutsu— Magit-style porcelain for Jujutsu (jj), wired ininit-vc.el.tagref— Emacs integration for thetagrefcross-reference checker.
use-package ... :ensure nil blocks in the relevant init-*.el module and wired into the distribution by nix/mk-overlay.nix.
The devenv shell
The devenv shell provides tooling only — linters, language servers, the docs chain, fonts. Emacs itself is not in the shell (see the top-of-file note indevenv.nix); build and launch the editor with just run-built.
Adding a new package
Most of the time you just need ause-package block in the appropriate init-*.el module — :ensure t is implicit thanks to use-package-always-ensure:
nix/extra-packages.nix with trivialBuild so it is built from a pinned GitHub revision and available on load-path, then declare it with :ensure nil in the module.
One invariant to know: the Nix side (nix/use-package.nix) parses the Elisp — it does not evaluate it. use-package forms must stay top-level (not wrapped in when/let/macros) and not :disabled, or the package silently drops out of the Nix-provided set even though the Elisp still works interactively.