# incline.nvim: floating statuslines that shrink to fit

> incline.nvim is a Neovim plugin that renders a statusline as a floating window per window, so the line takes only as much width as it needs instead of spanning the window. It suits someone who wants the built-in winbar look with per window placement, and it depends on writing a render function in Lua.

**b0o/incline.nvim** — 🎈 Floating statuslines for Neovim

- Repository: https://github.com/b0o/incline.nvim
- Stars: 1,052 · Forks: 20
- Language: Lua
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/b0o-incline-nvim

## The difference from winbar is width, not presence

incline.nvim is a plugin for creating lightweight floating statuslines in Neovim, and it works with Neovim's global statusline, which is the :set laststatus=3 setting.

The README opens with the question that defines the project: why use Incline instead of Neovim's built-in winbar? The answer it gives is a list of four differences.

The first is space. Incline only takes up the amount of space it needs, leaving more room for your code. That is the whole premise, and it is a real difference rather than a cosmetic one. A winbar spans the full width of the window, so a short statusline still eats a line of vertical space and forces you to keep the information short enough to be readable rather than as long as you want. A floating statusline takes the width of its content.

The second is configurability. Incline is highly configurable and themeable using Lua, rather than through a string of statusline items.

The third is conditional display. The statusline can be shown or hidden dynamically based on cursor position, focus, buffer type, or any other condition you write.

The fourth is placement. It can be positioned at the top or bottom, and at the left or right side, of each window.

The plugin is written in Lua, is MIT licensed, and the repository carries a test workflow badge along with a test/ directory, a Makefile with a test target and a docs target, selene configuration for Lua linting and stylua configuration for formatting. The last release tag is v0.0.3 from April 2022, and the last push to the main branch was on 2026-05-07, so the code is being worked on well after the last tagged version.

## The render function is the whole configuration

The README makes a point that is easy to miss and important to internalise: the render function is the most important part of an Incline configuration. As the name suggests, it is called for each window in order to render its statusline.

The mental model offered is a React component. It is passed a table of props and returns a tree-like data structure describing the content and appearance of the statusline. The minimal example is:

```lua
render = function(props)
  local filename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(props.buf), ':t')
  local modified = vim.bo[props.buf].modified
  return {
    ' ',
    filename,
    modified and { ' *', guifg = '#888888', gui = 'bold' } or '',
    ' ',
    guibg = '#111111',
    guifg = '#eeeeee',
  }
end
```

The return value rules are worth reading carefully because they are the API. It can be nil, a string, or a table. A table can include strings, highlight properties such as foreground and background colour, or even nested tables, and nested tables can contain the same kinds of things, including more nested tables. If the render function returns nil, the statusline is hidden until the next time the function returns a non-nil value.

That last rule is what enables the conditional display feature. Returning nil is how you say not now, rather than rendering an empty string.

The props table gives you the buffer, the window, and whether the window has focus, and the full reference is in the :help incline-render topic in the documentation, which the README links to at a specific line in doc/incline.txt.

## The examples are configurations, not a settings dialog

The README ships three worked configurations, and reading them tells you more about the plugin's shape than any feature list would.

The first is icon plus filename, and it requires nvim-web-devicons. The interesting part is the contrast handling. The devicons call returns a file type icon and a colour, and the render function pairs the icon with a background of that colour and computes a foreground that stays legible against it, using helpers.contrast_color from the plugin's own helpers module. That is the kind of detail that separates a statusline that reads well from one that disappears into the background.

The second example adds Navic, the navigation breadcrumb plugin, and requires nvim-web-devicons and nvim-navic. The difference from the first is a condition: the breadcrumb is only built when props.focused is true, and the navic data is fetched with navic.get_data(props.buf) for that buffer, with a fallback to an empty list. So a window that does not have focus shows a shorter line, which is the conditional display feature in practice rather than in theory.

The third example adds diagnostics and a git diff summary, requires nvim-web-devicons and gitsigns.nvim, and is credited to a contributor with a link to the discussion where it was worked out. It reads the gitsigns status dictionary out of the buffer variable, counts the removed, changed and added entries, counts diagnostics by severity with vim.diagnostic.get, and appends the window number.

All three build a plain Lua table. There is no template language, no statusline item string, and no DSL, which is the point: the plugin renders what you return.

## The plugin is a thin renderer, and the surface area is small

The repository layout shows how little there is to learn. There is a lua/ directory for the plugin code, a doc/ directory for the help files, a test/ directory, a scripts/ directory, a Makefile, an .editorconfig, and the selene and stylua configuration files for linting and formatting Lua.

The Makefile has two targets and both delegate to a script:

```
test:
	./scripts/test.sh
```

```
docs:
	./scripts/docs.sh
```

The docs target is the more interesting of the two, because it means the :help topics are generated rather than hand maintained. That matters for a plugin whose entire configuration surface is a function signature and a return value convention, because the help file is the reference for that convention and it can fall out of step with the code otherwise.

The plugin is worth understanding as a different kind of Neovim extension from most statusline plugins. Those usually give you a config table of segments, a set of condition functions, and their own idea of how to compute widths and colours. incline.nvim gives you a window and a function, and it handles the floating window, the placement, and the sizing to fit the content you returned. Everything else is yours.

The trade is a genuine one. You get precise control and no imposed vocabulary, and you give up a ready-made look. For a plugin whose selling point is that the line shrinks to fit, that division of labour is coherent.

## What the versioning history says about the project

The release history is short and it is the main thing to weigh before adopting the plugin.

There are two tags, v0.0.2 on 2022-04-15 and v0.0.3 on 2022-04-29. Both are pre-release numbers in the 0.0.x range, which in the Lua plugin ecosystem conventionally means the API is not settled. Yet the last push to the main branch was on 2026-05-07, more than four years later.

So the repository is alive and the tags are not. The likely reason is the common one for a plugin of this kind: a breaking change in the middle, or simply that the author stopped tagging. Either way, the practical consequence is that a plugin manager that installs a version, rather than the default branch, will give you the 2022 code, and the code in the repository today may behave differently.

If you install it, install from the default branch and read the source if something does not match the README, and the repository is small enough that reading the lua/ directory is a reasonable thing to do.

For context on the ecosystem position, the topics cover neovim, neovim-plugin, neovim-statusline, neovim-ui, neovim-winbar, nvim, nvim-plugin, vim and winbar, and the README points to a discussion category for user-contributed configurations, which is where most of the practical knowledge about this plugin now lives rather than in the documentation.

## Conclusion

Adopt incline.nvim if you like the idea of a winbar but want the line sized to its content rather than stretched across the window, and if you are comfortable writing a render function in Lua, since that function is the entire configuration surface. Do not adopt it if you want a statusline plugin that works without configuration, because nothing renders until you supply one. Before you commit, check the Neovim version you run, since the plugin is written against the modern API and the repository shows no release since v0.0.3 in April 2022, and read the incline-render help topic, which is where the props table and the return value rules are documented in full.

## FAQ

### What does incline.nvim do that Neovim's winbar does not?

It only takes up the amount of space it needs, leaving more room for your code, it is configurable and themeable in Lua, it can be shown or hidden dynamically based on cursor position, focus, buffer type or any other condition, and it can be positioned at the top or bottom and left or right of each window. It works with the global statusline set through `:set laststatus=3`.

### How do I configure the incline.nvim statusline?

With a render function passed to the setup call. It is called for each window with a props table and returns nil, a string, or a table of strings, highlight properties and nested tables describing the content. The README compares it to a React component, and the full reference is in the `:help incline-render` topic.

### How do I hide the incline.nvim statusline conditionally?

Return nil from the render function. The statusline is then hidden until the next time the function returns a non-nil value, which is how the plugin supports showing it based on cursor position, focus, buffer type or any other condition.

### Which plugins do the incline.nvim examples depend on?

The icon and filename example requires nvim-web-devicons, the icon, filename and Navic example also requires nvim-navic, and the diagnostics plus git diff example requires gitsigns.nvim alongside nvim-web-devicons. The README also points to a discussion category for user-contributed configurations.

## Sources

- [b0o/incline.nvim on GitHub](https://github.com/b0o/incline.nvim)
- [Issues](https://github.com/b0o/incline.nvim/issues)
- [License: MIT](https://github.com/b0o/incline.nvim/blob/main/LICENSE)
- [README](https://github.com/b0o/incline.nvim/blob/main/README.md)
- [Releases](https://github.com/b0o/incline.nvim/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/b0o-incline-nvim
