Skip to content

plexus/batppuccin-emacs

 
 

Repository files navigation

Batppuccin

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

Why Another Catppuccin Theme?

The official catppuccin/emacs port has some fundamental issues that are hard to fix incrementally:

Architectural Problems

  • Registers a single catppuccin theme and switches flavors via a global variable + reload function. This breaks standard load-theme workflows, theme-switching packages like circadian.el, and any tooling that expects one theme = one entry in custom-theme-load-path. Batppuccin defines four proper themes (batppuccin-mocha, batppuccin-latte, etc.) that work with load-theme out of the box.
  • Loads color definitions from an external file using load-file-name, which is nil in certain load-theme code 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.

Style Guide Deviations

  • font-lock-variable-name-face is 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-block forces 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.

Placeholder Colors in Production

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.

Missing Face Coverage

No support for vertico, marginalia, embark, transient, flycheck, doom-modeline, cider, corfu, or several other widely-used packages.

Approach

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 a defcustom for 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.

Installation

From Source

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

(package-vc-install "https://github.com/bbatsov/batppuccin-emacs")
(load-theme 'batppuccin-mocha t)

use-package (with package-vc)

(use-package batppuccin-mocha-theme
  :vc (:url "https://github.com/bbatsov/batppuccin-emacs" :rev :newest)
  :config
  (load-theme 'batppuccin-mocha t))

Flavors

Flavor Description
batppuccin-mocha The darkest variant
batppuccin-macchiato Dark
batppuccin-frappe Medium-dark
batppuccin-latte Light

Customization

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.

Interactive Commands

  • M-x batppuccin-select -- pick a flavor interactively and load it
  • M-x batppuccin-reload -- reload the current theme after changing options
  • M-x batppuccin-list-colors -- display all palette colors with samples (prefix arg to pick a variant)

Programmatic Access

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))))

Automatic Light/Dark Switching

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.

License

GNU General Public License v3.0. See COPYING for details.

Footnotes

  1. Naming is hard, but it should also be fun!

About

An opinionated Emacs port of the Catppuccin color scheme

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Emacs Lisp 100.0%