Basic vim keybindings are missing, makes vim mode useless

Open 💬 3 comments Opened Jul 15, 2026 by neumannjan
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of Codex CLI is running?

0.144.4

What subscription do you have?

ChatGPT Plus

Which model were you using?

doesn't matter

What platform is your computer?

Darwin 25.5.0 arm64 arm

What terminal emulator and version are you using (if applicable)?

kitty

Codex doctor report

Probably not relevant, but can provide upon request

What issue are you seeing?

IMO mandatory missing ones, i.e. the absolute basics:
  • ^ is missing, even though its opposite equivalent ($) is available??
  • B and E to jump whole words - faster navigation than to have to stop at every punctuation
  • u for undo
  • ctrl+r for redo
  • f, F, t, T - jump to (or right before) the nearest given letter (forwards/backwards) (the keybind is always followed by the given char)
Ones I can live without but also useful:
  • c binds (ce, cb, cB, cE) - even though ciw works??
  • r
  • d<number>d (eg. d2d - delete two lines)

Tl;dr: you have vim mode but clearly no actual vim users in your vicinity, guys

What steps can reproduce the bug?

Enable vim mode, try to use it

What is the expected behavior?

_No response_

Additional information

_No response_

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #32745

Powered by Codex Action

etdev · 1 month ago

I discovered this too and have a branch ready that fixes it. Would love an invitation to send a PR @fcoury-oai

Diff: https://github.com/openai/codex/compare/main...etdev:codex:fix-vim-mode

New functionality I added:

| Key | Does |
| --- | --- |
| W / B / E | Next / previous / end of WORD (whitespace-delimited) |
| ^ | First non-blank character of line |
| gg / G | First / last line |
| c{motion} | Change over any motion (cw, ce, cb, cB, cE, cf{c} …) |
| cc / cj / ck | Change current line / with the one below / above |
| u | Undo, one command per step |
| . | Repeat last change |
| f{c} / F{c} | Forward / backward to next {c} on the line |
| t{c} / T{c} | Forward / backward, stopping beside {c} |
| ; / , | Repeat last find, same / opposite direction |
| r{c} | Replace character under cursor with {c} |
| >> / << | Indent / dedent line |
| 3G / 2gg | Jump to line N |
| dG / dgg / cG / yG | Delete / change from cursor to end / start of buffer |
| P | Paste before cursor |
| J | Join lines, Vim spacing rules |
| 3w 2dd d3w 5x 3p 3J 2>> | Counts, on both motions and operators |
| 3. | Repeat last change, substituting the new count |
| Space | Right, as l |

NOTE Not included: ctrl+r for redo.

Why: Claude Code's vim mode doesn't implement this either. It falls back to the ctrl+r command search functionality. I think it makes sense to maintain parity with them on this, but I'm happy to add ctrl+r if people disagree.

The stack is already there since this adds u.

This would close #32745 (c-operators), #30103 (f/F/t/T) and #31972 (^) too.

~3.4k lines across 14 files, most of it keymap/schema plumbing for the 32 new configurable actions. Tests take their expected values from real Vim (vim -Nu NONE) instead of from the implementation. Where the composer intentionally diverges to stay consistent with existing behavior, the tests say so.

It builds properly and all tests pass (including my new tests). I ensured it works manually as well and didn't find any issues.

I tried to preserve existing behavior except where the fix requires it: c{motion}now acts instead of doing nothing (that's #32745). One existing test changed to match, since c$ is no longer an invalid motion. Every other existing test passes untouched.

@fcoury-oai - you own the Vim composer work (#18595, #24380, #24382).

Per the instructions in CONTRIBUTING, I understand PR submissions are invitation-only, so I'm asking your permission:

Should I send my changes as a PR? Please let me know and I'll do so. I think my changes will make vim mode vastly more useful.

Thanks!

jzila · 14 days ago

There is already a broad Vim expansion branch discussed above. I split the missing u / Ctrl+R behavior—especially the redo support that branch intentionally omits—into a focused, independently mergeable commit:

Behavior covered:

  • u undoes one Vim edit.
  • Ctrl+R redoes one undone edit in Vim Normal mode.
  • A complete Insert-mode session is grouped into one undo step.
  • Normal-mode edits are independently undoable.
  • New edits invalidate redo history.
  • Starting a fresh message clears history, so undo cannot resurrect the previous submission.
  • History is bounded to 100 entries.
  • Snapshots preserve text, cursor position, text elements, pending/large paste payloads, local and remote image attachments, and shell-command mode.
  • Ctrl+R retains its existing history-search behavior when Vim Normal mode does not own the key.

Coverage includes textarea history, composer-level paste and attachment restoration, shell mode, redo invalidation, fresh-buffer isolation, and Ctrl-R routing. All 255 codex-config tests and all 3,530 codex-tui tests passed, along with scoped lint and formatting.

This intentionally does not attempt every missing navigation command from this issue; it is the smallest coherent undo/redo slice. The c operations and count support are separately available in the focused branch discussed on #32745.

Would a maintainer like to adopt this internally, or explicitly invite a PR for this slice?