Skip to main content

Packages

Jotain is a “use-package + Nix” configuration: Nix provides most packages on load-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 the use-package declarations and maps them to the emacs-overlay package set; archive-absent packages (e.g. claude-code-ide, combobulate) are built in nix/extra-packages.nix. These also use :ensure nil because Nix already put them on the load path.
  • MELPA / NonGNU ELPA fallback — every other use-package block. use-package-always-ensure is t (set in early-init.el), so these default to “install if missing” without any extra boilerplate. Archives are registered in init.el:

Tree-sitter grammars

When built with default.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 from nix/design-pin.nix, the single pin shared with the website’s vendored CSS.
  • claude-code-ide — fetched from manzaltu/claude-code-ide.el, built with websocket and web-server as runtime dependencies (transient is built in to Emacs 30+).
  • combobulate — fetched from mickeynp/combobulate; all its dependencies (seq, map, treesit) are built in to Emacs 30+.
  • majutsu — Magit-style porcelain for Jujutsu (jj), wired in init-vc.el.
  • tagref — Emacs integration for the tagref cross-reference checker.
All are consumed by 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 in devenv.nix); build and launch the editor with just run-built.

Adding a new package

Most of the time you just need a use-package block in the appropriate init-*.el module — :ensure t is implicit thanks to use-package-always-ensure:
If the package is not on any archive, add it to 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.
Last modified on August 23, 2026