Protocol Buffers development tools for Neovim.
Note: This plugin was built with Claude Code.
- Compile on save - Auto-run protoc when .proto files are saved
- VSCode workspace support - Reads and respects
.vscode/settings.jsonconfigurations - Language-agnostic - Works with any protoc output language (Go, Python, Java, etc.)
- Linting - Integration with buf, protolint, and api-linter
- Formatting - Built-in formatter or use clang-format/buf format
- Breaking change detection - Compare schemas against git refs
- Field renumbering - Automatically renumber message fields and enum values
- Schema visualization - Display dependency graphs for proto files
- Async execution - Non-blocking compilation and linting
- Neovim 0.10+
- protoc (Protocol Buffers compiler) - required
- buf, protolint, or api-linter (optional, for linting)
- clang-format (optional, for formatting)
- git (optional, for breaking change detection)
Using lazy.nvim:
{
"amirmohammad2003/nvim-protobuf",
dev = true, -- If developing locally
config = function()
require("nvim-protobuf").setup({
-- Your configuration here
})
end,
}Example configuration in your init.lua:
require('nvim-protobuf').setup({
protoc = {
path = 'protoc',
options = {
'--go_out=./gen',
'--go-grpc_out=./gen',
'--proto_path=.',
},
compileOnSave = true,
},
includes = {
'${workspaceFolder}/proto',
'${workspaceFolder}/third_party',
},
formatOnSave = false,
formatter = {
enabled = true,
type = 'builtin', -- 'builtin', 'clang-format', or 'buf'
},
externalLinter = {
linter = 'buf', -- 'none', 'buf', 'protolint', or 'api-linter'
runOnSave = false,
},
breaking = {
enabled = false,
againstGitRef = 'main',
},
})The plugin automatically reads .vscode/settings.json from your workspace root. VSCode settings take precedence over Neovim configuration.
Example .vscode/settings.json:
{
"protobuf.protoc.path": "protoc",
"protobuf.protoc.options": [
"--go_out=./gen",
"--go-grpc_out=./gen",
"--proto_path=."
],
"protobuf.protoc.compileOnSave": true,
"protobuf.includes": [
"${workspaceFolder}/proto"
],
"protobuf.formatOnSave": false,
"protobuf.externalLinter.linter": "buf",
"protobuf.externalLinter.runOnSave": false
}- VSCode settings (
.vscode/settings.json) - highest priority - User Neovim config (
setup()call) - Plugin defaults - lowest priority
The plugin supports VSCode-style variable substitution:
${workspaceFolder}- Workspace root directory${file}- Current file path${fileDirname}- Current file's directory${fileBasename}- Current file name${fileBasenameNoExtension}- File name without extension${env:VAR_NAME}- Environment variables
Example:
{
"protobuf.protoc.options": [
"--go_out=${workspaceFolder}/gen",
"--proto_path=${workspaceFolder}/proto"
]
}:ProtobufCompile [file]- Compile current or specified proto file:ProtobufCompileAll- Compile all proto files in workspace:ProtobufLint- Run configured linter on current file:ProtobufFormat- Format current proto file:ProtobufBreaking [ref]- Check breaking changes against git ref:ProtobufRenumber- Renumber fields and enums:ProtobufGraph- Show schema dependency graph:ProtobufReloadConfig- Reload configuration
Enable compile-on-save in your configuration:
require('nvim-protobuf').setup({
protoc = {
compileOnSave = true,
},
})Or in .vscode/settings.json:
{
"protobuf.protoc.compileOnSave": true
}Configure a linter:
require('nvim-protobuf').setup({
externalLinter = {
linter = 'buf',
runOnSave = true,
},
})Supported linters:
- buf - Modern Protobuf tooling
- protolint - Protobuf linter
- api-linter - Google API linter
The plugin supports three formatting backends:
- Built-in - Simple indentation-based formatter (no dependencies)
- clang-format - Uses clang-format for formatting
- buf - Uses buf format
Configure formatter:
require('nvim-protobuf').setup({
formatOnSave = true,
formatter = {
enabled = true,
type = 'clang-format', -- or 'buf' or 'builtin'
},
})Check for breaking changes against a git reference:
:ProtobufBreaking main
:ProtobufBreaking HEAD~1Or enable automatic detection:
require('nvim-protobuf').setup({
breaking = {
enabled = true,
againstGitRef = 'main',
},
})View dependency graph:
:ProtobufGraphPress q or Esc to close the graph window.
The plugin integrates with Neovim's native diagnostic system. Errors and warnings from protoc, linters, and breaking change detection are displayed as diagnostics with virtual text, signs, and in the quickfix list.
Diagnostic sources:
protoc- Compilation errorsbuf/protolint/api-linter- Linter warningsbreaking-changes- Breaking change violations
require('nvim-protobuf').setup({})Then create .vscode/settings.json in your project.
require('nvim-protobuf').setup({
protoc = {
path = 'protoc',
options = {
'--go_out=./gen',
'--go_opt=paths=source_relative',
'--go-grpc_out=./gen',
'--go-grpc_opt=paths=source_relative',
'--proto_path=.',
},
compileOnSave = true,
},
includes = { '${workspaceFolder}/proto' },
externalLinter = {
linter = 'buf',
runOnSave = true,
},
})require('nvim-protobuf').setup({
protoc = {
options = {
'--python_out=./gen',
'--pyi_out=./gen',
'--proto_path=.',
},
compileOnSave = true,
},
})Make sure protoc is installed and in your PATH:
protoc --versionInstall from: https://protobuf.dev/downloads/
Check that:
.vscode/settings.jsonexists in your workspace root- The file contains valid JSON (JSONC with comments is supported)
- Run
:ProtobufReloadConfigto reload settings
Debug workspace root detection:
:lua print(require('nvim-protobuf.utils').find_workspace_root())Check that diagnostics are enabled:
require('nvim-protobuf').setup({
diagnostics = {
enabled = true,
virtual_text = true,
},
})Ensure the formatter is installed and enabled:
require('nvim-protobuf').setup({
formatOnSave = true,
formatter = {
enabled = true,
},
})