|
|
||
|---|---|---|
| .github | ||
| lua | ||
| plugin | ||
| .gitignore | ||
| .luarc.json | ||
| .stylua.toml | ||
| LICENSE | ||
| README.md | ||
kodex.nvim
Integrate the Codex AI assistant with Neovim—streamline editor-aware research, reviews, and automation without leaving your buffers.
https://github.com/user-attachments/assets/01e4e2fc-bbfa-427e-b9dc-c1c1badaa90e
✨ Features
- Talk to
codex app-serverdirectly over JSON-RPC. - Prompt with completions, highlights, and normal-mode support.
- Pick prompts from a library or define your own.
- Inject relevant editor context (buffer, cursor, selection, diagnostics, ...).
- Control Codex with commands or map your own shortcuts.
- Auto-reload buffers edited by Codex in real time.
- Approve or reject Codex permission requests from inside Neovim.
- Watch Codex activity via a statusline component and
KodexEventautocmds.
📦 Setup
{
"cau1k/kodex.nvim",
dependencies = {
-- Recommended for `ask()` and `select()`.
-- Required for the default `toggle()` implementation.
{ "folke/snacks.nvim", opts = { input = {}, picker = {}, terminal = {} } },
},
config = function()
---@type kodex.Opts
vim.g.kodex_opts = {
-- Your configuration, if any — see `lua/kodex/config.lua`, or "goto definition".
}
-- Required for `opts.auto_reload`.
vim.o.autoread = true
-- Recommended/example keymaps.
vim.keymap.set({ "n", "x" }, "<C-a>", function() require("kodex").ask("@this: ", { submit = true }) end, { desc = "Ask Kodex" })
vim.keymap.set({ "n", "x" }, "<C-x>", function() require("kodex").select() end, { desc = "Execute Kodex action…" })
vim.keymap.set({ "n", "x" }, "ga", function() require("kodex").prompt("@this") end, { desc = "Add to Codex" })
vim.keymap.set({ "n", "t" }, "<C-.>", function() require("kodex").toggle() end, { desc = "Toggle Codex" })
vim.keymap.set("n", "<S-C-u>", function() require("kodex").command("session.half.page.up") end, { desc = "Codex half page up" })
vim.keymap.set("n", "<S-C-d>", function() require("kodex").command("session.half.page.down") end, { desc = "Codex half page down" })
-- You may want these if you stick with the opinionated "<C-a>" and "<C-x>" above — otherwise consider "<leader>k".
vim.keymap.set('n', '+', '<C-a>', { desc = 'Increment', noremap = true })
vim.keymap.set('n', '-', '<C-x>', { desc = 'Decrement', noremap = true })
end,
}
nixvim
programs.nixvim = {
extraPlugins = [
pkgs.vimPlugins.kodex-nvim
];
};
Tip
Run
:checkhealth kodexafter installation.
⚙️ Configuration
kodex.nvim provides a rich, reliable default experience — see all available options and their defaults in lua/kodex/config.lua.
Provider
By default, kodex.nvim will launch codex app-server via snacks.terminal when it is available:
vim.g.kodex_opts = {
provider = {
enabled = "snacks",
---@type kodex.provider.Snacks
snacks = {
-- Customize `snacks.terminal` to your liking.
}
}
}
Already running Codex yourself? Configure your own provider or disable the built-in one entirely:
vim.g.kodex_opts = {
---@type kodex.Provider
provider = {
toggle = function(self)
-- Called by `require("kodex").toggle()`.
end,
start = function(self)
-- Called when sending a prompt or command to Codex but no process was found.
end,
show = function(self)
-- Called when a prompt or command is sent to Codex,
-- *and* this provider's `toggle` or `start` has previously been called
-- (so as to not interfere when Codex was started externally).
end
}
}
Tip
Pull requests adding additional built-in providers are welcome!
🚀 Usage
✍️ Ask — require("kodex").ask()
Input a prompt to send to Codex.
- Press
<Up>to browse recent asks. - Fetches available subagents from Codex.
- Highlights placeholders.
- Completes placeholders and subagents.
- Press
<Tab>to trigger built-in completion. - When using
blink.cmpandsnacks.input, registersopts.auto_register_cmp_sources.
- Press
📝 Select — require("kodex").select()
Select from all kodex.nvim functionality.
🗣️ Prompt — require("kodex").prompt() | :[range]KodexPrompt
Send a prompt to Codex.
Contexts
Replaces placeholders in the prompt with the corresponding context:
| Placeholder | Context |
|---|---|
@buffer |
Current buffer |
@buffers |
Open buffers |
@cursor |
Cursor position |
@selection |
Visual selection |
@this |
Visual selection if any, else cursor position |
@visible |
Visible text |
@diagnostics |
Current buffer diagnostics |
@quickfix |
Quickfix list |
@diff |
Git diff |
@grapple |
grapple.nvim tags |
Prompts
Reference a prompt by name to review, explain, and improve your code:
| Name | Prompt |
|---|---|
ask |
... |
explain |
Explain @this and its context |
optimize |
Optimize @this for performance and readability |
document |
Add comments documenting @this |
test |
Add tests for @this |
review |
Review @this for correctness and readability |
diagnostics |
Explain @diagnostics |
fix |
Fix @diagnostics |
diff |
Review the following git diff for correctness and readability: @diff |
buffer |
@buffer |
this |
@this |
🧑🏫 Command — require("kodex").command()
Send a command to Codex:
| Command | Description |
|---|---|
session.list |
List sessions |
session.new |
Start a new session |
session.share |
Share the current session |
session.interrupt |
Interrupt the current session |
session.compact |
Compact the current session (reduce context size) |
session.page.up |
Scroll messages up by one page |
session.page.down |
Scroll messages down by one page |
session.half.page.up |
Scroll messages up by half a page |
session.half.page.down |
Scroll messages down by half a page |
session.first |
Jump to the first message in the session |
session.last |
Jump to the last message in the session |
session.undo |
Undo the last action in the current session |
session.redo |
Redo the last undone action in the current session |
prompt.submit |
Submit the TUI input |
prompt.clear |
Clear the TUI input |
agent.cycle |
Cycle the selected agent |
👀 Events
kodex.nvim forwards Codex JSON-RPC notifications as a KodexEvent autocmd:
-- Listen for Codex events
vim.api.nvim_create_autocmd("User", {
pattern = "KodexEvent",
callback = function(args)
-- See the available event payload
vim.notify(vim.inspect(args.data.event))
-- Do something useful
if args.data.event and args.data.event.type == "session.idle" then
vim.notify("Codex finished responding")
end
end,
})
Edits
When Codex edits a file, kodex.nvim automatically reloads the corresponding buffer.
Permissions
When Codex requests a permission, kodex.nvim waits for idle before prompting you to approve, reject, or abort it.
Statusline
require("lualine").setup({
sections = {
lualine_z = {
{
require("kodex").statusline,
},
}
}
})
🙏 Acknowledgments
- Inspired by nvim-aider, neopencode.nvim, and sidekick.nvim.
- Uses Codex's app-server for simplicity — see sudo-tee/opencode.nvim for a Neovim frontend.
- mcp-neovim-server may better suit you, but it lacks customization and tool calls are slow and unreliable.