Neovim plugin for running the Codex CLI in an embedded terminal.
- Neovim >= 0.11.0
codexavailable on yourPATH(or configurelaunch.cmd)
Caution
You are reading the main branch README. Install and configuration details
may differ from tagged releases. The current latest release tag is
v0.5.0. For
version-accurate instructions, read the README for your target tag from
Codeberg releases.
{
url = "https://codeberg.org/yaadata/codex.nvim.git",
version = "0.5.0",
cmd = {
"Codex",
"CodexFocus",
"CodexClose",
"CodexClearInput",
"CodexSend",
"CodexAddBuffer",
"CodexMentionFile",
"CodexMentionDirectory",
"CodexResume",
"CodexModel",
"CodexStatus",
"CodexPermissions",
"CodexCompact",
"CodexReview",
"CodexDiff",
},
opts = {},
config = function(_, opts)
require("codex").setup(opts)
end,
}Use this table as your lazy.nvim plugin opts value:
Show default opts table
opts = {
launch = {
cmd = "codex",
args = {},
env = {},
auto_start = true,
cwd = nil,
},
log = {
level = "warn",
verbose = false,
},
terminal = {
provider = "auto", -- auto | snacks | native
provider_opts = {
native = {
window = "vsplit", -- vsplit | hsplit | float
vsplit = {
side = "right", -- left | right
size_pct = 40, -- 10-90
},
hsplit = {
side = "bottom", -- top | bottom
size_pct = 30, -- 10-90
},
float = {
width_pct = 80, -- 10-100
height_pct = 80, -- 10-100
border = "rounded",
title = " Codex ",
title_pos = "center", -- left | center | right
},
},
snacks = {
-- pass-through for snacks.terminal(..., opts)
},
},
auto_close = true, -- close terminal buffer automatically when process exits
startup = {
timeout_ms = 2000, -- max time to wait for startup readiness before dropping queued sends
retry_interval_ms = 50, -- retry interval while waiting for startup readiness
grace_ms = 800, -- minimum delay after terminal open before first send
},
keymaps = {}, -- terminal-local keymaps are opt-in; no defaults are registered
},
}:Codextoggles the Codex terminal:Codex!force-opens and focuses the Codex terminal:CodexFocusfocuses the terminal (opens it if needed):CodexClosecloses the active Codex terminal session:CodexClearInputclears the active Codex terminal input line:CodexSendsends selected lines with path and range context.:CodexAddBuffersends current buffer path as ACP file reference (@path).:CodexMentionFile [path]sends/mentionfor a file path, normalized to cwd-relative.:CodexMentionDirectory [path]sends/mentionfor a directory path, normalized to cwd-relative and forced to end with a path separator.:CodexResume[!]resumes in-process or launchescodex resume(!uses--lastwhen launching).:CodexModelsends/model:CodexStatussends/status:CodexPermissionssends/permissions:CodexCompactsends/compact:CodexReview [instructions]sends/review.:CodexDiffsends/diff
For detailed command behavior and component interactions, see
docs/command-interactions.md.
When using lazy.nvim with cmd + opts, prefer wiring setup explicitly in
config and passing lazy's resolved opts through:
config = function(_, opts)
require("codex").setup(opts)
endThe cmd list still ensures first-use lazy loading when a :Codex* command is
run.
codex.nvim does not register global keymaps in setup(). Define global mappings
in your lazy.nvim plugin spec keys:
Show lazy keys table
{
url = "https://codeberg.org/yaadata/codex.nvim.git",
version = "0.5.0",
main = "codex",
cmd = {
"Codex",
"CodexFocus",
"CodexClose",
"CodexClearInput",
"CodexSend",
"CodexAddBuffer",
"CodexMentionFile",
"CodexMentionDirectory",
"CodexResume",
"CodexModel",
"CodexStatus",
"CodexPermissions",
"CodexCompact",
"CodexReview",
"CodexDiff",
},
opts = {},
config = function(_, opts)
require("codex").setup(opts)
end,
keys = {
{
"<leader>ot",
function()
require("codex").toggle()
end,
desc = "Codex: Toggle terminal",
mode = { "n", "v" },
},
{
"<leader>os",
function()
require("codex").send_buffer()
end,
desc = "Codex: Add current buffer",
mode = "n",
},
{
"<leader>os",
function()
require("codex").send_selection()
end,
desc = "Codex: Send selection",
mode = "x",
},
{
"<leader>om",
function()
require("codex").mention_file()
end,
desc = "Codex: Mention current file",
mode = { "n", "v" },
},
{
"<leader>oM",
function()
require("codex").mention_directory()
end,
desc = "Codex: Mention current directory",
mode = { "n", "v" },
},
{
"<leader>or",
function()
require("codex").resume()
end,
desc = "Codex: Resume session",
mode = { "n", "v" },
},
{
"<leader>oi",
function()
require("codex").show_status()
end,
desc = "Codex: Show status",
mode = { "n", "v" },
},
{
"<leader>op",
function()
require("codex").show_permissions()
end,
desc = "Codex: Permissions",
mode = { "n", "v" },
},
{
"<leader>oc",
function()
require("codex").compact()
end,
desc = "Codex: Compact context",
mode = { "n", "v" },
},
{
"<leader>oR",
function()
require("codex").review()
end,
desc = "Codex: Review changes",
mode = { "n", "v" },
},
{
"<leader>od",
function()
require("codex").show_diff()
end,
desc = "Codex: Show diff",
mode = { "n", "v" },
},
},
}Set vim.g.mapleader before plugin setup so <leader> expands as expected.
Terminal-local keymaps inside the Codex terminal buffer are configured
separately via terminal.keymaps:
local km = require("codex.keymaps").builtins
require("codex").setup({
log = {
level = "warn",
verbose = false,
},
terminal = {
keymaps = {
["<C-c>"] = { mode = { "t", "n" }, action = km.toggle },
["<M-BS>"] = { mode = { "t", "n" }, action = km.clear_input },
["<C-x>"] = { mode = { "t", "n" }, action = km.close },
["<A-h>"] = { mode = { "t", "n" }, action = km.nav_left },
["<A-j>"] = { mode = { "t", "n" }, action = km.nav_down },
["<A-k>"] = { mode = { "t", "n" }, action = km.nav_up },
["<A-l>"] = { mode = { "t", "n" }, action = km.nav_right },
},
},
})Each entry uses { mode, action, desc? }, where:
modeis a string or list of modes accepted byvim.keymap.set.actionis a function (for builtins, userequire("codex.keymaps").builtins).descis optional for builtin actions (auto-filled), required for custom actions.
terminal.auto_close controls whether provider windows auto-close only after
the terminal process exits.
The authoritative Lua API reference lives in
docs/api.md.
For :Codex* command behavior and component interaction details, see
docs/command-interactions.md.
auto (default) prefers snacks when available, falls back to native. See
docs/architecture.md for the full provider interface and
implementation details.
See docs/contributing.md for setup, testing, formatting, linting, and code style guidelines.
See docs/troubleshooting.md for logging-focused debugging steps and issue report guidance.