Batppuccin is an opinionated Emacs port of the Catppuccin color scheme. It aims to follow the official Catppuccin style guide closely while being structured idiomatically for Emacs.
The name is a play on my last name (Batsov) + Catppuccin (cat -> bat). So, that's essentially @bbatsov's take on Catppuccin.1
The official catppuccin/emacs port has some fundamental issues that are hard to fix incrementally:
- Registers a single
catppuccintheme and switches flavors via a global variable + reload function. This breaks standardload-themeworkflows, theme-switching packages likecircadian.el, and any tooling that expects one theme = one entry incustom-theme-load-path. Batppuccin defines four proper themes (batppuccin-mocha,batppuccin-latte, etc.) that work withload-themeout of the box. - Loads color definitions from an external file using
load-file-name, which is nil in certainload-themecode paths (e.g., when Emacs hasn't marked the theme as safe yet). This causes the theme to fail to load entirely for some users. - No semantic color layer -- faces reference raw palette colors directly, making it hard to reason about color assignments or adjust them systematically.
I think this is partly because the official Emacs port uses Catppuccin's Whiskers template tool to generate the Elisp from a .tera template. That's great for keeping ports in sync across editors, but it means the generated code doesn't follow Emacs conventions. It doesn't sit well with me.
font-lock-variable-name-faceis set to the default text color, making variables indistinguishable from surrounding text. The style guide assigns distinct colors to variables and properties.- All
outline-*levels use the same blue, so org-mode headings and any outline-based hierarchy look flat. The style guide specifies a rainbow cycle (red, peach, yellow, green, sapphire, lavender). org-blockforces a green foreground on all unstyled code inside source blocks, instead of inheriting the default text color.- Search match highlighting uses aggressive red backgrounds where the style guide calls for teal.
- Minibuffer prompt uses a subdued gray (
subtext0) instead of a prominent color.
Multiple faces (dired+, diredfl, tree-sitter, whitespace, helm) are set to #ff00ff magenta as a "TODO" placeholder. These show up as literal hot pink in real usage.
No support for vertico, marginalia, embark, transient, flycheck, doom-modeline, cider, corfu, or several other widely-used packages.
Batppuccin follows the conventions established in zenburn-emacs and emacs-tokyo-night-theme:
- One theme file per flavor. Each variant (
batppuccin-mocha-theme.el,batppuccin-latte-theme.el, etc.) is a thin wrapper that loads the shared infrastructure and applies its palette. Standard Emacs theme machinery works without any special glue. - Shared infrastructure in
batppuccin.el. Color palettes for all four flavors, the face application function, and adefcustomfor user color overrides all live in one file. Adding a new variant means defining a color alist and a ~10-line wrapper. - All 26 canonical Catppuccin colors with exact hex values from the spec, plus derived colors for diff backgrounds, selection, cursor line, and the heading rainbow cycle.
- Follows the Catppuccin style guide for syntax highlighting (mauve for keywords, green for strings, blue for functions, peach for constants, sky for operators, yellow for types, overlay2 for comments, rosewater for the cursor) and editor UI (lavender for active line numbers, teal for search backgrounds, red/green/blue at low opacity for diffs).
- Broad face coverage out of the box -- built-in Emacs faces plus magit, vertico, corfu, marginalia, embark, orderless, consult, transient, flycheck, flymake, cider, company, evil, mu4e, notmuch, doom-modeline, treemacs, web-mode, and more.
Clone the repo and add it to your load path:
(add-to-list 'custom-theme-load-path "/path/to/batppuccin-emacs")Then load any flavor:
(load-theme 'batppuccin-mocha t)(package-vc-install "https://github.com/bbatsov/batppuccin-emacs")
(load-theme 'batppuccin-mocha t)(use-package batppuccin-mocha-theme
:vc (:url "https://github.com/bbatsov/batppuccin-emacs" :rev :newest)
:config
(load-theme 'batppuccin-mocha t))| Flavor | Description |
|---|---|
batppuccin-mocha |
The darkest variant |
batppuccin-macchiato |
Dark |
batppuccin-frappe |
Medium-dark |
batppuccin-latte |
Light |
Override any color across all flavors:
(setq batppuccin-override-colors-alist
'(("bat-base" . "#000000")
("bat-text" . "#ffffff")))The override alist takes precedence over the built-in palette. Color names match the canonical Catppuccin names with a bat- prefix (e.g., bat-rosewater, bat-mauve, bat-surface0).
Disable heading scaling if you prefer uniform sizes in org, markdown, shr, and info:
(setq batppuccin-scale-headings nil)After changing any of these options, run M-x batppuccin-reload to apply them without restarting Emacs.
M-x batppuccin-select-- pick a flavor interactively and load itM-x batppuccin-reload-- reload the current theme after changing optionsM-x batppuccin-list-colors-- display all palette colors with samples (prefix arg to pick a variant)
If you need to reference theme colors in your own configuration, there are a couple of options.
Look up a single color:
(batppuccin-get-color "bat-blue")Or bind the entire palette as local variables with batppuccin-with-colors:
(batppuccin-with-colors
(set-face-attribute 'some-face nil :foreground bat-blue))You can also hook into theme loads with batppuccin-after-load-hook -- each function receives the theme name as its argument:
(add-hook 'batppuccin-after-load-hook
(lambda (_theme)
(batppuccin-with-colors
(set-face-attribute 'my-face nil :foreground bat-teal))))Batppuccin pairs well with packages that switch themes based on the time of day or your OS appearance setting:
- auto-dark tracks your OS dark/light mode and switches themes to match:
(use-package auto-dark
:config
(setq auto-dark-dark-theme 'batppuccin-mocha
auto-dark-light-theme 'batppuccin-latte)
(auto-dark-mode 1))- circadian switches on a time-based schedule (e.g. sunrise/sunset):
(use-package circadian
:config
(setq circadian-themes '((:sunrise . batppuccin-latte)
(:sunset . batppuccin-mocha)))
(circadian-setup))See Automatic Light/Dark Theme Switching for a deeper look at both approaches.
GNU General Public License v3.0. See COPYING for details.
Footnotes
-
Naming is hard, but it should also be fun! ↩