FIM completion extension for Neovim with pluggable providers.
Provider-agnostic Fill-In-Middle (FIM) completion plugin for Neovim with inline ghost text.
Note: This plugin was entirely vibe-coded as an experiment to explore Mistral’s Codestral FIM API. It’s a playground for testing inline completion capabilities and the provider-agnostic architecture.
{
'aliou/nvim-fim',
config = function()
require('fim').setup({
provider = 'codestral',
codestral = {
api_key_provider = function()
return os.getenv("CODESTRAL_API_KEY")
end,
},
})
end
}
Full configuration with defaults:
require('fim').setup({
-- Provider selection (required)
provider = 'codestral',
-- Provider-specific configuration
codestral = {
api_key_provider = function()
return os.getenv("CODESTRAL_API_KEY")
end,
-- Free tier endpoint (requires phone-verified API key)
endpoint = "https://codestral.mistral.ai/v1/fim/completions",
-- Or use paid endpoint: "https://api.mistral.ai/v1/fim/completions"
model = "codestral-latest",
max_tokens = 256,
stop = nil,
},
-- Universal settings (apply to all providers)
context = {
prefix_lines = 100,
suffix_lines = 30,
max_prefix_chars = 4000,
max_suffix_chars = 1000,
},
debounce_ms = 50,
highlight = "Comment",
keymaps = {
accept = "<Tab>",
accept_word = "<C-Right>",
accept_line = "<C-e>",
dismiss = "<C-]>",
trigger = "<C-Space>",
},
disabled_filetypes = {},
})
Free API Key: Get a free Codestral API key at console.mistral.ai. The free tier (codestral.mistral.ai endpoint) is designed for individual users and plugin developers. Phone verification is required.
For more details, see the Codestral FIM documentation.
:FimLogin command (easiest):FimLogin
This saves your key to ~/.local/share/nvim/fim/codestral/api_key (the default location).
export CODESTRAL_API_KEY="your-key-here"
codestral = {
api_key_provider = function()
return os.getenv("CODESTRAL_API_KEY")
end,
}
codestral = {
api_key_provider = function()
return vim.fn.readfile(vim.fn.expand("~/.secrets/codestral"))[1]
end,
}
By default, if you don’t specify api_key_provider, it reads from:
~/.local/share/nvim/fim/codestral/api_key
Just create this file with your key, or use :FimLogin to set it up.
<Tab>: Accept full suggestion<C-Right>: Accept next word<C-e>: Accept to end of line<C-]>: Dismiss suggestion<C-Space>: Trigger completion manuallyType in insert mode
↓
Debounced trigger (50ms)
↓
Extract context (prefix/suffix around cursor)
↓
Request completion from active provider
↓
Render ghost text via extmarks
↓
Accept (Tab), partial accept (C-Right/C-e), or dismiss (C-])
Run tests with:
nix-shell --run "busted"
CI runs automatically on push/PR.
Provider-agnostic core engine with pluggable providers:
lua/fim/
├── init.lua # Entry point, setup(), autocommands
├── config.lua # Configuration management
├── context.lua # Buffer context extraction
├── suggestion.lua # State management
├── render.lua # Ghost text rendering
├── keymaps.lua # Keybindings
└── providers/ # Provider implementations
├── init.lua # Provider interface/registry
└── codestral.lua # Mistral Codestral implementation
Future providers (OpenAI, Anthropic, DeepSeek, etc.) can be added by implementing the provider interface.
Inspired by:
MIT