Skip to content

gaurav219/lsp_explain.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

lsp-explain

AI-powered LSP diagnostic explanations for Neovim — Get intelligent explanations of compiler errors and warnings directly in your editor, powered by Google's Gemini API.

Overview

lsp-explain is a Neovim plugin that uses AI to explain LSP diagnostics (errors, warnings, info) in your code. When you hover over an error, it uses an LLM to:

  • 📝 Provide a clear summary of what went wrong
  • 🔍 Identify root causes with confidence levels
  • 🛠️ Suggest fixes with step-by-step guidance
  • 📊 Generate code patches when applicable
  • 💾 Cache responses for repeated diagnostics

Screenshots

lsp-explain UI showcase 1

lsp-explain UI showcase 2

Architecture

This project consists of two main components:

Backend (Go)

A lightweight HTTP server that:

  • Receives LSP diagnostic information from Neovim
  • Sends requests to Google's Gemini API for analysis
  • Caches responses using an in-memory LRU cache
  • Returns structured JSON responses with explanations and fixes

Key files:

  • cmd/main.go — Server entry point
  • internal/api/handlers.go — HTTP request handlers
  • internal/api/types.go — Request/response schemas
  • internal/llm/gemini.go — Gemini API client
  • internal/cache/cache.go — LRU response cache

Installation

Prerequisites

  • Neovim 0.9.0+
  • Go 1.25.6+
  • Google Gemini API key

Step 1: Start the Backend

cd /path/to/nvim_plugin
source env.sh  # if you have local config

# Set your API key
export GEMINI_API_KEY="your-gemini-api-key"

# Run the server (defaults to 127.0.0.1:7777)
go run cmd/main.go

Environment variables:

  • GEMINI_API_KEY — (required) Your Google Gemini API key
  • GEMINI_MODEL — (default: models/gemini-2.5-flash) Gemini model to use
  • LSP_EXPLAIN_ADDR — (default: 127.0.0.1:7777) Server address and port
  • LSP_EXPLAIN_TIMEOUT — (default: 30s) Request timeout

Step 2: Install the Neovim Plugin

Using your favorite plugin manager. For example, with lazy.nvim:

{
  "path/to/lsp-explain.nvim",
  config = function()
    require("lsp_explain").setup({
      endpoint = "http://127.0.0.1:7777",
      timeout_ms = 30000,
      context_lines = 60,
      include_hover = true,
      show_raw_on_error = true,
    })
  end,
}

Usage

Commands

  • :LspExplain — Explain the diagnostic under the cursor
  • :LspFix — Apply the last suggested fix (if a patch was provided)

Workflow

  1. Open a file with diagnostics in Neovim
  2. Position cursor on a diagnostic error/warning
  3. Run :LspExplain
  4. View the explanation popup with root causes and fix suggestions
  5. Optionally run :LspFix to apply the suggested patch

Configuration

require("lsp_explain").setup({
  endpoint = "http://127.0.0.1:7777",  -- Backend endpoint
  timeout_ms = 30000,                  -- Request timeout in ms
  context_lines = 60,                  -- Lines of context before/after diagnostic
  include_hover = true,                -- Include LSP hover info
  show_raw_on_error = true,            -- Show raw JSON if parsing fails
})

API Specification

POST /explain

Request:

{
  "language": "go",
  "provider": "gopls",
  "file_path": "/path/to/file.go",
  "workspace_root": "/path/to/workspace",
  "file_sha": "sha256hash",
  "tooling": {
    "go_version": "1.21",
    "gopls_version": "v0.14.0"
  },
  "diagnostic": {
    "message": "undefined: myVar",
    "severity": "error",
    "range": {
      "start": { "line": 42, "character": 10 },
      "end": { "line": 42, "character": 15 }
    }
  },
  "code_context": {
    "before": "...",
    "snippet": "if myVar {",
    "after": "..."
  }
}

Response:

{
  "summary": "Clear explanation of the error",
  "root_causes": [
    {
      "cause": "Description of the root cause",
      "confidence": 0.95,
      "evidence": ["Supporting evidence 1", "Evidence 2"]
    }
  ],
  "fixes": [
    {
      "title": "Fix title",
      "steps": ["Step 1", "Step 2"],
      "confidence": 0.9,
      "risk": "safe",
      "patch": "unified diff patch",
      "why_it_works": "Explanation of why this fix works"
    }
  ],
  "notes": [],
  "meta": {
    "cache_hit": false,
    "model": "models/gemini-2.5-flash"
  }
}

GET /health

Simple health check endpoint.

Response:

{
  "ok": true,
  "timestamp": "2026-01-25T10:00:00Z",
  "model": "models/gemini-2.5-flash"
}

Caching

The backend maintains an LRU cache (default: 256 entries) to avoid redundant API calls for identical diagnostics. Cache keys are based on:

  • Model name
  • Language & provider
  • File SHA256 hash
  • Diagnostic message
  • Line & character range

Development

Building

go build -o lsp-explain cmd/main.go

Running Tests

go test ./...

Troubleshooting

"Invalid JSON from backend"

The model output may not be valid JSON. Check:

  1. Your GEMINI_API_KEY is correct
  2. The backend logs for API errors
  3. Try with a different model via GEMINI_MODEL env var

"No diagnostic under cursor"

  • Ensure your LSP client (e.g., gopls, rust-analyzer) is running
  • Run :LspInfo in Neovim to check LSP status

Backend won't start

  • Verify Go 1.25.6+ is installed
  • Check GEMINI_API_KEY environment variable is set
  • Ensure port is not already in use

License

This project is licensed under the MIT License — see LICENSE for details.

Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

About

A NeoVim plugin integrated with an LLM for explanations and fixes for errors/diagnostics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors