A Neovim plugin for integrating with Simon Willison's llm CLI tool.
https://github.com/user-attachments/assets/d8c9b2f8-4617-4534-9a64-05a2447d9380
https://github.com/user-attachments/assets/b326370e-5752-46af-ba5c-6ae08d157f01
https://github.com/user-attachments/assets/2fc30538-6fd5-4cfa-9b7b-7fd7757f20c1
:LLM):LLMConfig) with views for:pip install llm or brew install llm)This plugin uses Lua 5.2+ APIs (table.unpack) for forward compatibility. Neovim bundles LuaJIT 2.1+ which provides these APIs, so no additional Lua installation is required.
Plug 'julwrites/llm-nvim'
use 'julwrites/llm-nvim'
-- Example lazy.nvim configuration
return {
{
'julwrites/llm-nvim',
-- Optional: Specify dependencies if needed, e.g., for UI components
-- dependencies = { 'nvim-lua/plenary.nvim' },
config = function()
-- Configure the plugin
require('llm').setup({
-- Specify the default LLM model to use
model = 'gpt-4o', -- Or 'claude-3-haiku-20240307', 'llama3', etc.
-- Define a default system prompt (optional)
system_prompt = 'You are a helpful Neovim assistant.',
-- Disable default key mappings if you prefer to set your own
-- no_mappings = true,
-- Enable debug logging (optional)
-- debug = true,
-- Enable or disable automatic updates for the underlying `llm` CLI tool.
-- Defaults to `false`.
-- auto_update_cli = false,
-- Set the interval in days for checking for `llm` CLI updates.
-- Defaults to `7`.
-- auto_update_interval_days = 7,
})
-- Example custom key mappings (if no_mappings = true or for overrides)
-- vim.keymap.set('n', '<leader>lp', '<Plug>(llm-prompt)', { desc = "LLM Prompt" })
-- vim.keymap.set('v', '<leader>ls', '<Plug>(llm-selection)', { desc = "LLM Selection" })
-- vim.keymap.set('n', '<leader>lt', '<Plug>(llm-toggle)', { desc = "LLM Toggle Manager" })
end
}
}
-- Setup with configuration options
require('llm').setup({
model = 'gpt-4o', -- Default model to use
system_prompt = 'You are a helpful assistant.', -- Default system prompt
no_mappings = false, -- Set to true to disable default mappings
debug = false, -- Set to true to enable debug output
auto_update_cli = false, -- Enable/disable CLI auto-updates (default: false)
auto_update_interval_days = 7, -- Interval in days for CLI update checks (default: 7)
})
-- Custom mappings
vim.keymap.set('n', '<leader>lp', '<Plug>(llm-prompt)')
vim.keymap.set('v', '<leader>ls', '<Plug>(llm-selection)')
vim.keymap.set('n', '<leader>le', '<Plug>(llm-explain)')
vim.keymap.set('n', '<leader>lm', '<Plug>(llm-models)') -- Note: <Plug>(llm-select-model) is deprecated
The plugin includes a feature to automatically check for updates to the llm command-line tool upon startup.
auto_update_cli = true setting, the plugin will check if the configured auto_update_interval_days has passed since the last check.llm CLI tool. The update mechanism tries common upgrade methods including uv tool upgrade llm, pipx upgrade llm, pip install --upgrade llm (and python -m pip install --upgrade llm), and brew upgrade llm to keep the tool current.This helps ensure your llm tool stays up-to-date with the latest features and fixes.
:LLM {prompt} - Send prompt to LLM:LLM file [{prompt}] - Send current file's content with optional prompt :LLM selection [{prompt}] - Send visual selection with optional prompt:LLM explain - Explain current buffer's code:LLM fragments - Interactive prompt with fragment selection:LLM update - Manually trigger an update check for the underlying llm CLI tool.:LLMConfig [view] - Open unified manager windowmodels, plugins, keys, fragments:LLMConfig models - Open Models view:LLMConfig plugins - Open Plugins view:LLMConfig keys - Open API Keys view:LLMConfig fragments - Open Fragments view:LLM Write a short poem about Neovim and press Enter.:LLMWithSelection Refactor this code for clarity and press Enter.:LLMExplain and press Enter.:LLMConfig or press <leader>ll (default mapping).P to switch to the Plugins view.K to switch to the API Keys view.j and k.s in the Models view to set a default model).q or <Esc> to close the manager.The plugin provides default key mappings that can be disabled with no_mappings = true. Here are the default mappings and some suggested alternatives:
-- Toggle unified manager
vim.keymap.set('n', '<leader>ll', '<Cmd>LLMConfig<CR>', { desc = "Toggle LLM Manager" })
-- Basic prompt
vim.keymap.set('n', '<leader>lp', '<Cmd>LLM<Space>', { desc = "LLM Prompt" })
-- Explain current buffer
vim.keymap.set('n', '<leader>le', '<Cmd>LLM explain<CR>', { desc = "Explain Code" })
-- Prompt with visual selection
vim.keymap.set('v', '<leader>ls', '<Cmd>LLM selection<CR>', { desc = "LLM Selection" })
-- Interactive fragments
vim.keymap.set('n', '<leader>lf', '<Cmd>LLM fragments<CR>', { desc = "LLM with Fragments" })
The plugin includes a test suite using busted. To run the tests, you first need to install the test dependencies:
sudo luarocks install busted
sudo luarocks install luassert
Then, you can run the tests:
# Run all tests
make test
# Run a specific test file
make test file=init_spec.lua
Tests cover:
This project enforces a minimum code coverage of 70%. The CI/CD pipeline will fail if the coverage drops below this threshold. To run the coverage check locally, you first need to install the coverage dependencies:
sudo luarocks install luacov
sudo luarocks install luacov-console
Then, you can run the coverage check:
make coverage
This will run the tests with Luacov and print a coverage report to the console.
If you encounter errors like "attempt to call a nil value (global 'unpack')":
:lua print(_VERSION) in NeovimThe plugin requires Lua 5.2+ APIs which are provided by Neovim's bundled LuaJIT 2.1+.
Apache 2.0