A Neovim plugin for integrating with Simon Willison's llm CLI tool.
llm-nvim-models-plugins-keys.mov
llm-nvim-schemas.mov
llm-nvim-fragments.mov
llm-nvim-templates.mov
- Unified LLM command interface (
:LLM
) - Interactive prompting with fragments support
- Process selected text or entire files with LLMs
- Explain code in current buffer
- Support for custom models and system prompts
- API key management for multiple providers
- Fragment management (files, URLs, GitHub repos)
- Template creation and execution
- Schema management and execution
- Unified manager window (
:LLMToggle
) with views for:- Models
- Plugins
- API Keys
- Fragments
- Templates
- Schemas
- Markdown-formatted responses with syntax highlighting
- Asynchronous command execution
- Neovim 0.7.0 or later
- llm CLI tool installed (
pip install llm
orbrew install llm
)
Using vim-plug
Plug 'julwrites/llm-nvim'
Using packer.nvim
use 'julwrites/llm-nvim'
Using lazy.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.
- When enabled via the
auto_update_cli = true
setting, the plugin will check if the configuredauto_update_interval_days
has passed since the last check. - If an update check is due, it will attempt to update the
llm
CLI tool. The update mechanism tries common upgrade methods includinguv tool upgrade llm
,pipx upgrade llm
,pip install --upgrade llm
(andpython -m pip install --upgrade llm
), andbrew upgrade llm
to keep the tool current. - This check runs asynchronously in the background to avoid impacting Neovim's startup time.
- You will receive a notification about the outcome of the update attempt (success or failure).
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 schema
- Select and run schema:LLM template
- Select and run template:LLM update
- Manually trigger an update check for the underlyingllm
CLI tool.
:LLMToggle [view]
- Toggle unified manager window- Optional views:
models
,plugins
,keys
,fragments
,templates
,schemas
- Optional views:
:LLMToggle models
- Open Models view:LLMToggle plugins
- Open Plugins view:LLMToggle keys
- Open API Keys view:LLMToggle fragments
- Open Fragments view:LLMToggle templates
- Open Templates view:LLMToggle schemas
- Open Schemas view
- Type
:LLM Write a short poem about Neovim
and press Enter. - A new buffer will open with the LLM's response.
- Visually select a block of code.
- Type
:LLMWithSelection Refactor this code for clarity
and press Enter. - The selected code and your prompt will be sent to the LLM.
- Open a code file.
- Type
:LLMExplain
and press Enter. - The LLM will explain the code in the current buffer.
- Type
:LLMToggle
or press<leader>ll
(default mapping). - The manager window opens, likely showing the Models view first.
- Press
P
to switch to the Plugins view. - Press
K
to switch to the API Keys view. - Navigate the list using
j
andk
. - Follow the instructions in the header for actions (e.g., press
s
in the Models view to set a default model). - Press
q
or<Esc>
to close the manager.
The plugin doesn't set any default key mappings. Here are some suggested mappings you might want to set up:
-- Toggle unified manager
vim.keymap.set('n', '<leader>ll', '<Cmd>LLMToggle<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:
- Core functionality (prompts, code explanation)
- Model management
- Plugin management
- API key management
- Fragment management
Apache 2.0