no-neck-pain.nvim: centering a Neovim buffer by opening two side windows
☕ Dead simple yet super extensible zen mode plugin to protect your neck.
At a glance
- What is it?
- no-neck-pain.nvim keeps the focused buffer at a fixed width in the middle of the screen by opening an empty window on each side, and it does so without touching your splits, tabs or keymaps, with every option optional.
- Who is it for?
- Adopt no-neck-pain.nvim if your neck hurts because your code sits in a corner of a wide monitor, since the plugin changes the viewport without rewriting your layout, and if you run Neovim 0.10 or later so the main branch applies to you. Do not adopt it on Neovim 0.9 or older without moving to the 2.x or 1.x branch, and do not adopt it if you need the centered width to follow your textwidth or colorcolumn settings without configuring them.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Lua, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two empty windows instead of a resized split
The mechanism is worth stating before anything else, because it explains both the plugin's usefulness and its limits. no-neck-pain.nvim does not resize the window you are editing. It opens an empty window on each side of the focused window, so the code you are looking at sits in the middle of the screen at a fixed width.
That is a different operation from centring a split. Nothing about your existing splits, tabs or keymaps is changed, which is the property the documentation leads with. The plugin composes with what you already have instead of reinterpreting it.
The user base is narrow and self evident: people who work in a wide terminal, on a laptop with an external display, or with a file tree open beside their code, and who want the text they are reading in the physical middle rather than wherever the window manager put it. The name is blunt about the motivation.
It is a view level change, and everything the plugin does is at that level. It does not touch your buffer contents, your undo history, or how your code is organised.
One command to toggle, one setup call to configure
The plugin works with no configuration at all. Running :NoNeckPain centers the current window, and running it again returns to your normal layout. That is the whole quick path, and the README presents it as the first feature.
If you want to change defaults, you call setup() once in your config. The README's example sets the centered width to 120 columns, enables the default keymaps, and turns the plugin on when Neovim starts:
require("no-neck-pain").setup({
width = 120,
mappings = { enabled = true },
autocmds = { enableOnVimEnter = true },
})Every option is optional, and the in-editor help is the reference: :h NoNeckPain.options lists the plugin options and :h NoNeckPain.bufferOptions lists the side buffer options. A Showcase page in the project wiki carries a screenshot for the common ones, which is faster than reading source for a setting whose effect is visual.
The command and the keymap are two views of the same action. With mappings.enabled set to true, the plugin creates the mappings it does not have set to false, including a toggle on <Leader>np.
Width arithmetic and the terminal that is too narrow
The width option accepts an integer, or the strings textwidth or colorcolumn, and it defaults to 100. The default for minSideBufferWidth is 10, which represents the lowest width a side buffer should have.
The reasoning behind minSideBufferWidth is spelled out in the option's own comment and is worth reading, because it explains a behaviour that otherwise looks like a bug. If your terminal is wide, say 210 columns, and you set width to 100, each side buffer ends up with a width of 50. Resize the terminal to half the screen and each side buffer would be 5 columns wide, which the comment describes as noise rather than something useful. The minimum keeps those slivers from appearing.
The hard limit is on the other side. The comment on the width option states that when the terminal width is less than the width option, the side buffers won't be created. If your terminal is narrower than the width you asked for, the plugin does not shrink your window and squeeze the sides; it does nothing.
That is a sensible choice for a layout plugin, since a centered window that is wider than the screen would be useless, but it does mean the plugin can appear inert without explanation if your width setting is larger than your terminal.
Side buffers that double as scratch pads
The empty windows are not purely decorative. The side buffers can be colored, which is a way of marking the edges of your working area, or they can be used as scratch pads that save to a file.
A scratch pad changes the nature of the side window. Instead of being an empty buffer you ignore, it holds text you write beside your code, and that text persists because it is saved to a file. The plugin documentation treats this as a first class use, and the integration list in the README mentions file trees, symbol panels, neotest, nvim-dap-ui and dashboards, which is the plugin cooperating with the other parts of a real editing setup rather than fighting them for space.
There is one interaction to know about. The skipEnteringNoNeckPainBuffer option, which defaults to true, makes entering one of the side buffers automatically skip it and move to the next available buffer. The comment notes that this setting is omitted when the scratch pad is enabled, which makes sense: a buffer you are supposed to type into should not be skipped the moment you enter it.
The fallbackOnBufferDelete option, default true, handles another edge of the same feature. When you delete the main no-neck-pain buffer with :bd or :bdelete, the plugin does not simply switch off. It falls back on the newly focused window and refreshes the state by re-creating the side windows if necessary.
Autocmds that can turn the plugin on for you
The autocmds table controls when the plugin engages on its own, and it is the part of the configuration with the sharpest edges.
enableOnVimEnter, default false, enables the plugin when Neovim starts. If the main window is a side tree such as NvimTree, or a dashboard, the command is delayed until a valid window is found, and the command is cleaned up once it has run successfully once.
The value can also be the string safe, which debounces the plugin before enabling it. The documentation recommends safe in two situations: if you use a dashboard plugin, or something else that also triggers when Neovim is entered, and if you usually use commands such as nvim +line file, which are executed after Neovim has been entered.
That recommendation is a design note about Neovim's startup order rather than about this plugin's internals. Without the debounce, two things can want the focused window at the same moment, and the winner is decided by timing.
Two other autocmds round out the behaviour. enableOnTabEnter, default false, enables the plugin when you enter a new tab, and deliberately does not trigger when you come back to an existing tab, to avoid interfering with your decisions. reloadOnColorSchemeChange, default true, reloads the plugin configuration after a colorscheme change, which matters because the side buffers can be colored and the colors have to be reapplied.
Version branches matched to Neovim releases
The compatibility policy is unusually explicit for a plugin this small, and it is stated in the features list rather than buried in the wiki.
The current line requires Neovim 0.10 or later. For Neovim 0.7 and 0.8, the README directs you to a frozen 1.x branch, and for 0.9 to a 2.x branch. Frozen means what it says, and that is the important part for anyone still on an older Neovim: the fix is available, but it will not receive further work.
The release history reflects the pace of the current line. Version 3.0.4 was tagged on 2026-09-26, 3.0.3 on 2026-09-25 and 3.0.2 on 2026-09-24, three tags inside three days. The repository is not archived, and the last push was on 2026-09-26, matching the newest tag.
The installation snippets make the same point from the other side. The README asks you to pin a release with the snippets and tells you to remove the version pin to follow main. Pinned, you get a fixed behaviour and can upgrade deliberately. Unpinned, you get whatever the branch currently contains, which for a plugin this actively tagged is a different experience.
The build and test setup behind the plugin
The repository is small but the tooling around it is thorough, and it tells you how the project treats itself.
The Makefile drives everything. An all target chains documentation, lint, luals and test. The test targets are generated from a list of suite names, which covers API, autocmds, buffers, callbacks, colors, commands, config_validation, constants, event, helpers_coverage, integrations, log, mappings, options, regression_issues, scratchpad, splits, state_access_regression, state_edge_cases, tabs and width_calculations. Each suite runs headless Neovim against a minimal init file and executes a mini.test file.
The suite list is the interesting part, because it maps directly onto the plugin's behaviour: width_calculations for the arithmetic described earlier, state_edge_cases and regression_issues for the fiddly transitions, integrations for the cooperation with other plugins.
There are race and nightly variants, the test race target repeats the run up to five times to surface ordering problems, and the nightly target switches to a nightly build. Linting is handled by stylua with a stylua.toml, static analysis by lua-language-server configured through .luarc.json with the version pinned in .luals-version, and .luacheckrc is present for luacheck. Documentation is generated rather than written by hand, which is why the help tags are complete.
The licence is MIT, and the tree also carries CHANGELOG.md, FUNDING.yml, AGENTS.md and CLAUDE.md, which suggests the project keeps notes aimed at both humans and coding agents.
Editorial conclusion
Adopt no-neck-pain.nvim if your neck hurts because your code sits in a corner of a wide monitor, since the plugin changes the viewport without rewriting your layout, and if you run Neovim 0.10 or later so the main branch applies to you. Do not adopt it on Neovim 0.9 or older without moving to the 2.x or 1.x branch, and do not adopt it if you need the centered width to follow your textwidth or colorcolumn settings without configuring them. Before you install, verify two things in your own configuration: that the terminal is actually wider than the width option, because the side buffers are not created below it, and whether you want the plugin enabled on startup with enableOnVimEnter, which the documentation warns can collide with a dashboard plugin or with commands such as nvim +line file.
Frequently asked questions
How do I install no-neck-pain.nvim in Neovim?
With lazy.nvim the README shows { "shortcuts/no-neck-pain.nvim", version = "*" }, with packer.nvim use({ "shortcuts/no-neck-pain.nvim", tag = "*" }), with vim-plug Plug 'shortcuts/no-neck-pain.nvim', { 'tag': '*' }, and with nixvim plugins.no-neck-pain.enable = true. Remove the version pin to follow main instead of a tagged release.
How do I toggle no-neck-pain.nvim without configuring it?
Run :NoNeckPain to center the current window and run it again to return to your normal layout. If you enable the mappings in setup(), the same toggle is bound to <Leader>np by default.
How do I set the centered width of no-neck-pain.nvim to 120 columns?
Call require("no-neck-pain").setup({ width = 120 }) in your config. The width option also accepts the strings textwidth and colorcolumn, and defaults to 100.
Which Neovim versions does no-neck-pain.nvim support?
The current line requires Neovim 0.10 or later. For Neovim 0.7 and 0.8 the README points to a frozen 1.x branch, and for 0.9 it points to the 2.x branch.
Can the side windows of no-neck-pain.nvim be used as scratch pads?
Yes. The side buffers can be colored or used as scratch pads that save to a file, and the skipEnteringNoNeckPainBuffer option, which skips side buffers on entry by default, is omitted when the scratch pad is enabled.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/shortcuts-no-neck-pain-nvim)Was this useful?