A pure Vim9 plugin for Vim on macOS/Linux that talks to codex app-server over stdio.
:CodexShow {prompt}: send the current range to Codex and append the reply to a preview window.:CodexShowTool {prompt}: like:CodexShow, but for that turn Codex may call the restrictedvim_normaltool to make one Normal-mode edit in the visible source buffer.:CodexApply {prompt}: replace the current range with the reply.:CodexApply! {prompt}: insert instead of replace. By default the bang inserts after the range; setg:codex_vim.bang_apply_mode = 'before'to insert before.:CodexPreviewToggle: hide/show the Codex preview window.- Sends structured JSON context containing:
- buffer metadata
- cursor and selection positions/text
- line-array context before and after the selection
- same-line prefix/suffix around the selection for local precision
- Uses ephemeral Codex threads by default, so Vim sessions do not create persistent named threads in your normal Codex thread list.
- Optional debug logging.
:CodexShowkeeps prior preview output and appends each turn as quotedUser:/Assistant:sections.
The simplest plugin-manager-free install is Vim's native package layout:
mkdir -p ~/.vim/pack/plugins/start
git clone https://github.com/AnswerDotAI/codex-vim9.git ~/.vim/pack/plugins/start/codex-vim9Vim will load anything under pack/*/start/* automatically on startup. This is the most idiomatic built-in install path for Vim users and does not require a plugin manager.
To view the help:
:h codex_vim- Vim 9.1+
codexinstalled and authenticated- macOS or Linux
:'<,'>CodexShow explain this code
:CodexShowTool add punctuation using the vim tool if needed
:'<,'>CodexApply rewrite this more clearly
:'<,'>CodexApply! add a short comment block after this selection
:%CodexShow summarize this file
:10,30CodexApply refactor this section
:CodexPreviewTogglennoremap <leader>cs :<C-u>CodexShow
xnoremap <leader>cs :CodexShow
nnoremap <leader>ct :<C-u>CodexShowTool
xnoremap <leader>ct :CodexShowTool
nnoremap <leader>ca :<C-u>CodexApply
xnoremap <leader>ca :CodexApply
nnoremap <leader>ci :<C-u>CodexApply!
xnoremap <leader>ci :CodexApply!
nnoremap <leader>cp :CodexPreviewToggle<CR>
nnoremap <leader>cr :CodexReload<CR>
nnoremap <leader>cx :CodexResetThread<CR>Set g:codex_vim as a dictionary. All keys are optional.
By default the plugin leaves Codex runtime defaults alone: it does not force a model, effort level, approval policy, sandbox policy, personality, or network mode unless you set them explicitly. It also uses ephemeral threads by default, so conversation state is kept only for the current Vim session unless you explicitly turn persistence back on.
let g:codex_vim = {
\ 'codex_bin': 'codex',
\ 'context_lines': 12,
\ 'preview_height': 14,
\ 'preview_width': 80,
\ 'preview_split': 'horizontal',
\ 'ephemeral': v:true,
\ 'thread_scope': 'project',
\ 'cwd_mode': 'project',
\ 'bang_apply_mode': 'after',
\ 'strip_markdown_fences': v:true,
\ 'model': '',
\ 'effort': '',
\ 'summary': '',
\ 'personality': '',
\ 'approval_policy': '',
\ 'sandbox_policy': '',
\ 'network_access': v:false,
\ 'system_prompt': 'You are Codex inside Vim...',
\ 'ask_preamble': 'The JSON below is editor context...',
\ 'apply_preamble': 'Return only the text to insert...',
\ 'prompt_suffix': '',
\ 'service_name': 'vim_codex_context',
\ 'state_dir': '',
\ 'debug_log': '',
\ }model: set this if you want a specific model, e.g.'gpt-5.3-codex-spark'. Leave it empty to use your normal Codex default.context_lines: full lines of surrounding context on each side.model,effort,summary,personality,approval_policy,sandbox_policy: only sent when explicitly set.preview_split:'horizontal'or'vertical'. Horizontal usespreview_height; vertical usespreview_width.ephemeral: defaults tov:true. Setv:falseif you want persisted threads resumed across Vim restarts.thread_scope:'project','cwd','buffer', or'global'.cwd_mode:'project','cwd', or'buffer'.bang_apply_mode:'after'or'before'.network_access: only used whensandbox_policyis'workspaceWrite'.state_dir: where persisted thread ids are stored. Defaults to$XDG_STATE_HOME/vim/codex-vimor~/.vim/codex-vim.debug_log: if non-empty, append a trace log there.
Example model override:
let g:codex_vim = {
\ 'model': 'gpt-5.3-codex-spark',
\ }Example vertical preview:
let g:codex_vim = {
\ 'preview_split': 'vertical',
\ 'preview_width': 90,
\ }Example persisted-thread opt-in:
let g:codex_vim = {
\ 'ephemeral': v:false,
\ }- The plugin uses visual marks when the command is invoked from a visual selection, otherwise it uses the supplied line range.
- With no visual selection and no explicit Ex range, the selection is empty at the cursor position and only surrounding context is sent.
:CodexShowToolenables thevim_normaltool only for that turn. Regular:CodexShowturns reject tool calls and tell Codex to ask for:CodexShowToolinstead.- New threads always register the
vim_normaltool with Codex, and the plugin enforces whether it may be used on a given turn. - By default, threads are ephemeral and are not resumed across Vim restarts. Set
g:codex_vim.ephemeral = v:falseto opt back into on-disk thread persistence. - For linewise/range insertion,
:CodexApply!inserts as a block before/after the selected lines. - For charwise selections, insertion is exact at the selection boundary.
:CodexResetThreadforgets the persisted thread for the current scope.