init.el is deliberately tiny. Its only jobs are:
lisp/ on the load-path.
custom-file at var/custom.el so M-x customize has somewhere to scribble.
require each module in the right order. Archive refresh is not on the startup path — there is no background warm-up at all; archives are fetched only on demand.
Everything else — GC, encoding, theme, modeline, keybindings, package configuration — lives in early-init.el or one of the lisp/init-*.el modules.
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/") t)
Nix provides most packages via load-path, so use-package finds them without touching the network. The archives above only come into play for packages that Nix does not ship.
Registering an archive performs no I/O, and nothing in the config refreshes the archive index at launch. A download happens only when it is actually needed:
package-install — including the :ensure t path — calls package--archives-initialize, which reads the on-disk cache under elpa/archives/ and downloads only when that cache is empty.
M-x package-refresh-contents and M-x list-packages refresh when you ask them to.
So a fresh Nix deployment, where every :ensured package is already on load-path, starts up without contacting MELPA at all.
(add-to-list 'load-path (expand-file-name "lisp" user-emacs-directory))
(setq custom-file (locate-user-emacs-file "var/custom.el"))
custom.el is write-only: Jotain never loads it back. The declarative config in git remains the single source of truth; the file exists only so M-x customize has somewhere to scribble without touching init.el.
init.el then requires each module in order. See Modules for what each file owns and the full load order.
(require 'init-core) ; GC, encoding, var/ paths, sane defaults (require 'init-keys) ; Global keymap and leader-key setup (require 'init-ui) ; Theme, modeline, fonts, frame tweaks (require 'init-tabs) ; Workspace tabs via tab-bar-mode (require 'init-help) ; helpful + built-in help tweaks (require 'init-docs) ; Surface jotain.info under C-h i (require 'init-editing) ; Electric pairs, delsel, whitespace, region tools (require 'init-completion) ; Vertico, marginalia, orderless, consult, corfu (require 'init-navigation) ; Dired + dirvish, project, windmove, winner (require 'init-vc) ; vc + magit + diff-hl + forge (require 'init-prog) ; prog-mode, treesit, eglot, flymake, eldoc, compile (require 'init-snippets) ; tempel snippets + eglot-tempel LSP expansion (require 'init-project) ; project + projection + compile-multi (require 'init-devenv) ; devenv.sh: tasks, processes, env, LSP, MCP (require 'init-ai) ; eca, claude-code-ide, gptel, mcp (require 'init-shell) ; eshell, comint, ielm (require 'init-terminal) ; ghostel terminal + tty integration (kkp, clipetty) (require 'init-systems) ; sops, logview, auth-source-1password (require 'init-writing) ; jinx, markdown-mode, denote, pdf-tools (require 'init-org) ; org, org-modern, capture templates (require 'init-lang-nix) (require 'init-lang-rust) (require 'init-lang-python) (require 'init-lang-go) (require 'init-lang-web) ; TS/TSX/CSS/HTML/JSON/web-mode (require 'init-lang-devops) ; Dockerfile, terraform, just, ansible (require 'init-lang-data) ; yaml, csv, sql, jinja2, gnuplot (require 'init-lang-systems) ; C/C++, CMake, Meson, Haskell, Zig