Packages
Jotain is a “use-package + Nix” configuration: Nix (or, in development, the devenv shell) 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 — built through
emacsPackagesForindevenv.nix(e.g.claude-code-ide,combobulate, the tree-sitter grammars). 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
devenv.nix defines a small set of Elisp packages that are not on any archive (MELPA, GNU ELPA, NonGNU ELPA), so Nix builds them directly and puts them on load-path:
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+.
use-package ... :ensure nil blocks in the relevant init-*.el module.
The devenv shell
Running insidedevenv shell (or via direnv / .envrc) gives you the same Emacs that just build-bare produces, plus claude-code-ide, combobulate, and all tree-sitter grammars. devenv.nix enables the custom languages.emacs-lisp module (from nix/devenv-emacs-lisp.nix) which also provides eask-cli; ellsp (LSP) and elsa (static analyser) are off by default — toggle them in devenv.nix if you want them.
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:
overrideScope block in devenv.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.