What variant of Codex are you using?
CLI (codex-tui).
What feature would you like to see?
Add a Vim normal-mode C binding to the composer. In Vim, C is equivalent to c$: delete from the cursor to the end of the line, then enter insert mode. Codex already implements the parallel D (delete to end of line) and Y (yank line) shortcuts; C is the natural missing piece for users with Vim muscle memory.
Additional information
I can't open a PR directly (outside collaborators are restricted on this repo), so the branch and commit live on my fork:
Happy to rework the change if a maintainer wants to pick it up; treat the linked branch as a reference implementation.
Implementation summary
Mirrors the existing delete_to_line_end (D) wiring across the configurable keymap stack:
codex-rs/config/src/tui_keymap.rs — adds change_to_line_end: Option<KeybindingsSpec> to TuiVimNormalKeymap.
codex-rs/tui/src/keymap.rs — adds the runtime field, the resolve_local! line, default bindings [shift-c, plain('C')], and a validate_unique entry.
codex-rs/tui/src/bottom_pane/textarea.rs — adds the handler in handle_vim_normal (calls kill_to_end_of_line() then switches to VimMode::Insert) and two unit tests covering both default bindings.
codex-rs/tui/src/keymap_setup/actions.rs — exposes the action in the keymap picker (catalog entry, binding_slot, bindings_for_action).
codex-rs/core/config.schema.json — regenerated via just write-config-schema.
- 5 insta snapshots — picker action counts (93→94 total, 34→35 Vim).
Total diff: 10 files, +63 / -6.
Default bindings
shift-c and plain C, matching the cross-terminal shift-reporting pattern used by D, Y, A, I, and O in this codebase (see commit eb2275a feat(tui): support shift-letter vim bindings across terminal variants).
Validation
cargo test -p codex-tui --lib -- vim — all 43 vim tests pass, including the two new ones (vim_shift_c_changes_to_line_end_and_enters_insert_mode and vim_uppercase_c_changes_to_line_end_with_shift_only_binding).
cargo test -p codex-tui --lib -- keymap_setup — 157 keymap/picker tests pass after snapshot refresh.
just write-config-schema produces no further diff (manual edits matched the generator).
just fmt and just fix -p codex-tui clean.
Behavior note
This implementation reuses the existing kill_to_end_of_line() helper, which deletes the trailing newline when the cursor is already at EOL. The D binding already inherits this quirk; C now matches D for parity. Real Vim's C at EOL is a no-op (just enters insert mode), so if D's EOL behavior is ever aligned with upstream Vim, C should be aligned in lockstep.
Not in scope
A full c operator (so cw, cc, c$, etc. all work) is a separate change — it would also need a VimOperator::Change variant alongside the existing Delete and Yank operators. Happy to follow up on that if there's interest.
What variant of Codex are you using?
CLI (
codex-tui).What feature would you like to see?
Add a Vim normal-mode
Cbinding to the composer. In Vim,Cis equivalent toc$: delete from the cursor to the end of the line, then enter insert mode. Codex already implements the parallelD(delete to end of line) andY(yank line) shortcuts;Cis the natural missing piece for users with Vim muscle memory.Additional information
I can't open a PR directly (outside collaborators are restricted on this repo), so the branch and commit live on my fork:
Happy to rework the change if a maintainer wants to pick it up; treat the linked branch as a reference implementation.
Implementation summary
Mirrors the existing
delete_to_line_end(D) wiring across the configurable keymap stack:codex-rs/config/src/tui_keymap.rs— addschange_to_line_end: Option<KeybindingsSpec>toTuiVimNormalKeymap.codex-rs/tui/src/keymap.rs— adds the runtime field, theresolve_local!line, default bindings[shift-c, plain('C')], and avalidate_uniqueentry.codex-rs/tui/src/bottom_pane/textarea.rs— adds the handler inhandle_vim_normal(callskill_to_end_of_line()then switches toVimMode::Insert) and two unit tests covering both default bindings.codex-rs/tui/src/keymap_setup/actions.rs— exposes the action in the keymap picker (catalog entry,binding_slot,bindings_for_action).codex-rs/core/config.schema.json— regenerated viajust write-config-schema.Total diff: 10 files, +63 / -6.
Default bindings
shift-cand plainC, matching the cross-terminal shift-reporting pattern used byD,Y,A,I, andOin this codebase (see commit eb2275afeat(tui): support shift-letter vim bindings across terminal variants).Validation
cargo test -p codex-tui --lib -- vim— all 43 vim tests pass, including the two new ones (vim_shift_c_changes_to_line_end_and_enters_insert_modeandvim_uppercase_c_changes_to_line_end_with_shift_only_binding).cargo test -p codex-tui --lib -- keymap_setup— 157 keymap/picker tests pass after snapshot refresh.just write-config-schemaproduces no further diff (manual edits matched the generator).just fmtandjust fix -p codex-tuiclean.Behavior note
This implementation reuses the existing
kill_to_end_of_line()helper, which deletes the trailing newline when the cursor is already at EOL. TheDbinding already inherits this quirk;Cnow matchesDfor parity. Real Vim'sCat EOL is a no-op (just enters insert mode), so ifD's EOL behavior is ever aligned with upstream Vim,Cshould be aligned in lockstep.Not in scope
A full
coperator (socw,cc,c$, etc. all work) is a separate change — it would also need aVimOperator::Changevariant alongside the existingDeleteandYankoperators. Happy to follow up on that if there's interest.