neovim/neovim
Development workflow
The day-to-day cycle that turns a clean checkout into a merged PR.
1. Branch
Always work on a feature branch, never on master. CONTRIBUTING.md is explicit about this.
git checkout master
git pull origin master
git checkout -b fix/lsp-progress-leakSet the blame ignore file once per clone so git blame skips the bulk-format commits:
git config blame.ignoreRevsFile .git-blame-ignore-revs2. Build
For active development use a debug build:
make CMAKE_BUILD_TYPE=DebugFor a quick rebuild after editing C, just run make again — Ninja will only rebuild touched translation units. After editing the Lua data files (options.lua, eval.lua, ex_cmds.lua, auevents.lua, vvars.lua, keycodes.lua) or the API headers, you also have to rebuild because the C tree consumes generated headers.
Edits under runtime/lua/vim/_core/ are precompiled to bytecode. To iterate without rebuilding, run with --luamod-dev:
VIMRUNTIME=./runtime ./build/bin/nvim --luamod-dev3. Test
Before committing, run the relevant tests locally. The two paths in order of speed:
TEST_FILE=test/functional/lua/diagnostic_spec.lua make functionaltest
TEST_FILTER='vim.diagnostic.set' make functionaltest
make functionaltest # the full functional suite, slower
make unittest # FFI-based unit tests
make test # everythingThe full matrix (oldtest, valgrind, ASAN/UBSAN) runs in CI on every push. Reproduce locally only when you have to.
4. Lint and format
Before pushing:
make format # apply clang-format/stylua to changed files
make lint # all linters
make lintdoc # if you changed runtime/doc/*.txtmake lint runs the same checks that CI runs. If it passes locally and CI fails, the most common reason is a stale .deps/ directory — make distclean && make usually fixes it.
5. Commit
Use conventional commits. The structure is:
type(scope): short imperative subject
Problem:
What's broken or missing, in one or two sentences.
Solution:
How this commit fixes it, in one or two sentences.Types in active use: build, ci, docs, feat, fix, perf, refactor, revert, test, vim-patch. Scopes are free-form but conventional ones are lsp, treesitter, tui, lua, api, extmark, float, lint, vim-patch, etc.
If AI was used in any capacity to produce the change, append a trailer (AGENTS.md):
AI-assisted: <tool name>For breaking changes, use ! and add a BREAKING CHANGE: footer:
refactor(provider)!: drop support for Python 2
BREAKING CHANGE: refactor to use Python 3 features since Python 2 is no longer supported.make lintcommit validates the commit message format.
6. Push and open PR
Push to your fork, open a PR against neovim/neovim:master. Mark it as Draft until you're done iterating.
git push -u origin fix/lsp-progress-leak
gh pr create --draft --base masterTitle format follows the commit message. PR description ≈ commit body. Tests are required; mark the box.
7. Address review
Force-pushing onto your branch is fine and expected. Maintainers will pull the latest tip; there's no need to add review-fixup commits unless the change is large.
When the PR is ready:
- Squash-merge for single-meaningful-commit PRs.
- Merge (no squash) for multi-commit PRs that should preserve their structure.
Maintainers make the merge call.
Source navigation tips
The repo is large enough that grep-and-pray is not always enough. The recommended setup:
- Build with compile_commands.
build/compile_commands.jsonis generated by CMake. The repo's.clangdfile points at it; any LSP-aware editor (including Neovim itself withnvim-lspconfig) gets cross-file go-to-def. - Use clangd. It is the LLM of cross-references — it indexes the whole tree, including generated headers in
build/src/nvim/auto/. runtime/doc/dev_arch.txtis the architecture map. It is short, dense, and current. Read it before deep diving.- Read top-of-file comments. Module-specific notes live at the top of
terminal.c,undo.c,marktree.c,memline.c,regexp.c, etc. They are usually short and pointed.
Working with Vim patches
A non-trivial fraction of commits are vim-patch: — porting a single change from upstream Vim. The workflow is documented in runtime/doc/dev_vimpatch.txt. The driver script is scripts/vim-patch.sh. Subjects look like vim-patch:9.2.0416: ... so they are easy to grep for.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.