The default Emacs mode-line is functional but visually dated and hard to configure. sleek-modeline replaces it with a minimal, elegant alternative that surfaces the most relevant information while keeping the implementation small and straightforward.
- Minimal, left/right-aligned layout.
- Configurable size / height via a box property.
- Buffer name with optional icon and modified-state highlighting.
- Major mode display with suffix indicators stripped.
- Modal editing state marker (
evilandmeowsupport). - Line ending indicator (shown only for file-backed buffers).
- Version control segment: branch name with icon and state-aware coloring.
- Diagnostics segment: error, warning and info counts (support both
flycheckandflymakeintegration). - Project name segment (supports both
projectileand the built-inproject.el). - LSP indicator segment (supports both
eglotandlsp-modebackends). - Optional
nerd-iconssupport throughout, with Unicode fallbacks when unavailable. - Optionally blank the mode-line on inactive windows, or hide it entirely in chosen major modes.
- Adapts to theme changes automatically.
sleek-modeline is available on MELPA. With MELPA in your package-archives, install it with M-x package-install RET sleek-modeline RET, or use one of the declarative recipes below.
(use-package sleek-modeline
:ensure t
:config
(sleek-modeline-mode 1))Using use-package’s built-in :vc keyword (Emacs 30.1+):
(use-package sleek-modeline
:vc (:url "https://github.com/abidanBrito/sleek-modeline"
:branch "main")
:config
(sleek-modeline-mode 1))On Emacs 29, fetch the same recipe with M-x package-vc-install RET https://github.com/abidanBrito/sleek-modeline RET.
Or with =straight.el=:
(use-package sleek-modeline
:straight (sleek-modeline
:type git
:host github
:repo "abidanBrito/sleek-modeline")
:config
(sleek-modeline-mode 1))git clone https://github.com/abidanBrito/sleek-modeline.git ~/path/to/sleek-modelineWith use-package:
(use-package sleek-modeline
:load-path "~/path/to/sleek-modeline"
:config
(sleek-modeline-mode 1))Or without use-package:
(add-to-list 'load-path "~/path/to/sleek-modeline")
(require 'sleek-modeline)
(sleek-modeline-mode 1)All options live under M-x customize-group RET sleek-modeline. Here are the main ones:
| Variable | Default | Description |
|---|---|---|
sleek-modeline-size | small | Mode-line height: small, medium or large. |
sleek-modeline-height | nil | Custom box height in pixels. Overrides sleek-modeline-size when set. |
sleek-modeline-show-icons | t | Show nerd-icons throughout. Requires nerd-icons. |
sleek-modeline-background | nil | Custom mode-line background color. If nil, derives from default face. |
sleek-modeline-edge-padding | 2 | Number of spaces added at the left and right edges. |
sleek-modeline-highlight-modified-buffer-name | t | Highlight the buffer name when it has unsaved changes. |
sleek-modeline-show-modal-state | nil | Show a modal editing state marker (evil / meow). |
sleek-modeline-separator | " » " | Separator string between right-side segments. |
sleek-modeline-suppress-default-mouse | t | Disable Emacs’ stock mode-line mouse actions and echo-area hints, keeping only the segment bindings sleek-modeline adds. |
sleek-modeline-disabled-modes | nil | List of major modes for which the mode-line is hidden. Matches with derived-mode-p, so descendant modes are also covered. |
sleek-modeline-hide-inactive is the master switch: when non-nil, every segment is blanked on non-selected windows and the bar blends into the buffer background. The bar keeps its height, so that changing focus never shifts the window layout.
| Variable | Default | Description |
|---|---|---|
sleek-modeline-hide-inactive | nil | Blank the entire mode-line on non-selected windows. |
The options below instead hide individual segments when the mode-line belongs to a non-selected window.
| Variable | Default | Description |
|---|---|---|
sleek-modeline-hide-file-icon-inactive | nil | Hide the file icon in inactive mode-lines. |
sleek-modeline-hide-major-mode-inactive | nil | Hide the major mode name in inactive mode-lines. |
sleek-modeline-hide-line-ending-inactive | nil | Hide the line ending style in inactive mode-lines. |
sleek-modeline-hide-modal-inactive | nil | Hide the modal state marker in inactive mode-lines. |
Top-level switches for optional segments. Disabling one prevents its package from being loaded.
| Variable | Default | Description |
|---|---|---|
sleek-modeline-enable-diagnostics | t | Enable the diagnostics (Flycheck) segment. |
sleek-modeline-enable-project | t | Enable the project name segment. |
sleek-modeline-enable-lsp | t | Enable the LSP indicator segment. |
| Variable | Default | Description |
|---|---|---|
sleek-modeline-vc-show-icon | t | Show a branch icon. Requires nerd-icons. |
sleek-modeline-vc-use-github-icon | nil | Use the GitHub mark icon instead of the git branch icon. |
sleek-modeline-vc-show-status-symbol | t | Append a symbol indicating VC state: ~ modified, + added, - removed, ! conflict, ↓ needs update, ? unregistered. |
sleek-modeline-hide-vc-icon-inactive | nil | Hide the VC icon in inactive mode-lines. |
sleek-modeline-hide-vc-branch-inactive=| =nil | Hide the VC branch name in inactive mode-lines. |
| Variable | Default | Description |
|---|---|---|
sleek-modeline-diagnostics-show-info | t | Show info-level diagnostics. |
sleek-modeline-diagnostics-error-symbol | "✕" | Symbol for errors. |
sleek-modeline-diagnostics-warning-symbol | "▲" | Symbol for warnings. |
sleek-modeline-diagnostics-info-symbol | "●" | Symbol for info notes. |
sleek-modeline-diagnostics-ok-symbol | nil | Symbol shown when the buffer is clean. |
| Variable | Default | Description |
|---|---|---|
sleek-modeline-hide-project-name-inactive | nil | Hide the project name in inactive mode-lines. |
| Variable | Default | Description |
|---|---|---|
sleek-modeline-lsp-symbol | "LSP" | Fallback text when nerd-icons is unavailable or icons are off. |
sleek-modeline-lsp-show-name | nil | Show the LSP server name next to the icon. |
sleek-modeline-hide-lsp-inactive | nil | Hide the LSP indicator in inactive mode-lines. |
(use-package sleek-modeline
:straight (sleek-modeline
:type git
:host github
:repo "abidanBrito/sleek-modeline")
:custom
(sleek-modeline-size 'medium)
(sleek-modeline-show-modal-state t)
(sleek-modeline-separator " | ")
(sleek-modeline-vc-use-github-icon nil)
(sleek-modeline-diagnostics-ok-symbol "✓")
(sleek-modeline-disabled-modes '(dired-mode vterm-mode help-mode))
:config
(sleek-modeline-mode 1))Several segments respond to the mouse. Hovering shows a short tooltip in the echo area. A couple also react to clicks.
| Segment | Hover shows | Click |
|---|---|---|
| Buffer name | The file path, or a note when the buffer is not file-backed. | N/A |
| Major mode | A hint to list minor modes. | mouse-1 pops up a menu of active minor modes, and selecting one describes it. |
| Version control | The VC backend and, for Git, commits behind/ahead of the upstream. | N/A |
| Project | The project backend and its root directory. | N/A |
| Line ending | The line-ending convention. | N/A |
| LSP | The active LSP server name. | N/A |
Dragging the mode-line with mouse-1 resizes the window, just as in stock Emacs. Setting sleek-modeline-suppress-default-mouse to t (the default) disables Emacs’ other built-in mode-line mouse actions and their echo-area hints, but leaves the segment tooltips and drag-to-resize intact.
Segments are self-registering: each built-in segment calls sleek-modeline-register-segment at load time, and you can register your own the same way.
/NOTE:/ a segment is a function that returns a (propertized) string or nil, along with a plist describing where it goes.
(defun my-clock-segment ()
"Return the current time, or nil to display nothing."
(format-time-string "%H:%M"))
(sleek-modeline-register-segment 'clock
:fn 'my-clock-segment
:side 'right
:priority 5
:separator t)Registering a segment under a :name that already exists replaces it, so you can override a built-in segment by re-registering its name. The mode-line format is built when sleek-modeline-mode is enabled; after registering, removing, or reprioritising a segment while the mode is already on, call M-x sleek-modeline-refresh to recompute the format in place. Segments that need to install their own hooks through :on-enable should be added before enabling the mode.
Supported keys:
| Key | Description |
|---|---|
:name | Symbol uniquely identifying the segment. Re-using a name replaces the existing segment. |
:fn | Symbol naming the display function. It takes no arguments and returns a string or nil. |
:side | left or right. |
:priority | Integer ordering within a side. Lower values sit closer to the outer edge. |
:separator | nil for no suffix, t for the standard sleek-modeline-separator, or a literal string to append after a non-nil result. |
:condition | Optional variable that must be non-nil for the segment to display. |
:on-enable | Optional function called when sleek-modeline-mode activates (e.g. to add hooks). |
:on-disable | Optional function called when sleek-modeline-mode deactivates (e.g. to remove them). |
Built a segment you like? Please open an issue and send a pull request. See Contributing first.
Contributions are welcome. Please open an issue before sending a pull request. See CONTRIBUTING.org for the full workflow and guidelines.
When reporting a bug, include:
- Your Emacs version (
M-x emacs-version). - Your
sleek-modelinesettings. - Steps to reproduce the issue.
This repository is released under the MIT license. See LICENSE for more information.
