Skip to main content

early-init.el

early-init.el is loaded before package.el runs, before the first frame is drawn, and before init.el is evaluated. Anything that must happen that early lives here; everything else lives in init.el or one of the lisp/init-*.el modules.

Garbage collection

The GC threshold is bumped to “effectively never” during startup; init-core restores a 16 MiB runtime value.

Bidirectional text

Jotain targets LTR-only usage, so disable the bidirectional reordering and parenthesis algorithms — they otherwise run on every redisplay and are measurable on large files.

Load preference

Prefer newer source files to stale .elc in batch mode only. Interactive sessions keep .elc preference for speed.

package.el and use-package

package.el stays on and package-quickstart is enabled — Nix (and, in dev, devenv) already provides most packages via load-path, so startup is fast without any trickery. use-package is built in on Emacs 29+, so the only thing we configure before init.el loads is imenu support and use-package-always-ensure.
package-quickstart-file must be pinned here, not in init.el: startup.el runs its automatic package-activate-all between early-init.el and init.el, and looks up the quickstart file at whatever path package-quickstart-file holds at that moment. Leaving it at its default puts the file outside var/, and Emacs never finds it on later startups — quickstart ends up paying its refresh + byte-compile cost on every package-install without providing any actual speedup. With use-package-always-ensure set to t, every use-package block defaults to “install if missing”. Built-ins must opt out with :ensure nil.

Silencing a quickstart false-positive

package-quickstart-refresh (called after every package-install via package--quickstart-maybe-refresh) internally re-calls package-initialize, which trips the “Unnecessary call to package-initialize in init file” warning even though the call is legitimate. Emacs’s own code can’t distinguish that internal self-call from a user one, so we suppress the warning type directly:

Frame chrome

GUI chrome is disabled in default-frame-alist before the first frame is drawn — this is much faster than toggling the modes off afterwards.

Byte-compiler noise

Silence obsolete-symbol warnings from third-party packages we do not control. Real warnings still surface.

Font caches

Trade a bit of RAM for smoother redisplay.

Native compilation

On Emacs 30 with native compilation available, keep the eln-cache out of the config directory, silence the firehose of async warnings during init, and crank native-comp speed.

Tree-sitter grammars

Nix sets TREE_SITTER_DIR to point at the grammar bundle produced by default.nix; early-init.el picks it up and wires it into treesit-extra-load-path.

Terminal aliases

Ghostty advertises TERM=xterm-ghostty, but Emacs does not ship term/xterm-ghostty.el. Aliasing to xterm-256color makes term/xterm.el load instead, restoring modifyOtherKeys and 24-bit colour. This must be set in early-init.el because tty-run-terminal-initialization fires before init.el.
Last modified on August 23, 2026