Alright team, let's talk about getting AI assistance into your editor without blowing up your existing LSP setup. I've helped clients shove enough square-peg tools into round holes to know that "simple" integrations often come with hidden configuration debt. I've seen entire dev teams revolt over a clunky editor plugin that broke their flow.
I just finished a personal project to integrate Codeium into my Neovim setup, aiming for a seamless experience alongside my existing LSP (like `tsserver` or `pyright`). The goal was to have Codeium's suggestions appear inline without disabling or interfering with my core language intelligence. Here's the step-by-step that worked for me, after a few frustrating dead ends.
**My Starting Point & Philosophy**
I'm using Neovim v0.9+ with `nvim-lspconfig` and `nvim-cmp` for my completion engine. The key was to treat Codeium as a complementary LSP source, not a replacement. You don't want it hijacking your completions, just augmenting them.
**The Process**
1. **Get Your Codeium Auth Sorted:** This is the foundational step. Sign up at Codeium, then generate your API token from the dashboard. I set mine as an environment variable (`CODIEUM_API_KEY`) rather than hardcoding it, because I've learned the hard way that config files get committed.
2. **Install the Plugin:** I used `wbthomason/packer.nvim`, but your favorite plugin manager will work.
```lua
use {
'Exafunction/codeium.vim',
config = function()
vim.g.codeium_disable_bindings = 1
end
}
```
I disabled the default bindings immediately—I want to control how and when it triggers.
3. **Critical: Integrate with nvim-cmp:** This was the make-or-break. You need the `nvim-cmp` source plugin. After installing it, configure your `cmp` setup to include Codeium, but order it *after* your LSP source.
```lua
sources = {
{ name = 'nvim_lsp' },
{ name = 'codeium' }, -- Comes after LSP
{ name = 'buffer' },
{ name = 'path' }
}
```
This priority means your LSP's precise, context-aware completions show first, and Codeium's broader suggestions follow.
4. **Keybindings & Behavior:** I mapped `` to manually trigger Codeium suggestions, and `` to cycle through them when the menu is open. This keeps it non-intrusive. I also set `vim.g.codeium_manual = true` in most filetypes, so it only offers suggestions when I explicitly ask. This prevents the "ghost text" distraction that can derail a deep workflow.
**The Battle Scars & Why This Works**
My first attempt used the default bindings and auto-trigger. It was a disaster—constant visual noise, conflicts with my LSP snippets, and degraded performance on large files. The "manual-first, LSP-priority" approach mirrors a change management principle I use in CRM migrations: augment the existing system, don't force a disruptive replacement. This setup gives my team (or just me) the power to call in the AI artillery when we're stuck on boilerplate or need an alternative approach, without it chattering at us during every keystroke.
The result? A clean, controlled augmentation. My LSP still handles all the linting, go-to-definition, and error checking. Codeium sits quietly on the bench until I need a creative jump-start for a comment, a test case, or a repetitive block. It's about making the tool serve your workflow, not the other way around.
Implementation is 80% process, 20% tool.
Nice! Setting the API key as an env var is a solid move, makes your config portable across machines. I went the lazy route and just dropped my token straight into my `init.lua` for testing, but I should really move it out for security.
One thing I'd watch out for: make sure your Codeium source in `nvim-cmp` is ordered *after* your LSP source. That way you get your accurate type completions first, and Codeium's suggestions pop in as a nice bonus instead of taking over.
Keep deploying!