Skip to content

Repository files navigation

OpenCode Vim Plugin

npm versionWebsite

Adds Vim editing to the OpenCode prompt, including motions, operators, text objects, registers, visual mode, counts, undo/redo, and dot repeat.

Installation

Install globally:

opencode plugin @leohenon/opencode-vim-plugin --global

Important

Requires OpenCode 1.17.10 or newer.

Usage

Toggle via command palette > Toggle vim mode or slash command /vim.

Prompt controls

Unicode word boundaries are not yet supported.

CategoryKeys
Character / wordh, j, k, l, w, b, e, W, B, E
Line / buffer0, ^, _, $, gg, G
Display linegj, gk, g<Down>, g<Up>, g0, g^, g$
Matching / paragraph%, {, }
Find / tillf, F, t, T, ;, ,
ScrollCtrl+e, Ctrl+y, Ctrl+d, Ctrl+u, Ctrl+f, Ctrl+b
Insert / replacei, I, a, A, o, O, R
Character / line editr, x, ~, s, S, J, C, D, dd, cc
Word changescw, cb, ce, cW, cE, ciw, caw, ciW, caW
Word deletesdw, db, de, dW, dE, diw, daw, diW, daW
Quote changesci", ca", ci', ca', ci` , ca`
Quote deletesdi", da", di', da', di` , da`
Bracket changesci(, ca(, ci[, ca[, ci{, ca{, ci<, ca<
Bracket deletesdi(, da(, di[, da[, di{, da{, di<, da<
Find / till operatorscf, cF, ct, cT, df, dF, dt, dT
Matching / paragraph operatorsc%, d%, c}, c{, d}, d{
Line boundary operatorsc0, c^, c$, d0, d^, d$, y0, y^, y$
Display line operatorscgj, cgk, cg0, cg^, cg$, dgj, dgk, dg0, dg^, dg$, ygj, ygk, yg0, yg^, yg$
Line / word yanksyy, yw, ye, yW, yE, yiw, yaw, yiW, yaW
Quote yanksyi", ya", yi', ya', yi` , ya`
Bracket yanksyi(, ya(, yi[, ya[, yi{, ya{, yi<, ya<
Matching / paragraph yanksy%, y}, y{
Put / undo / repeatp, P, u, Ctrl+r, .
Visual selectionv, V
Commands::q

Numeric count prefixes are supported for motions and common operators.

Note

gg and G move within the prompt when the prompt has text. On an empty prompt, they dispatch OpenCode's session.first and session.last commands.

Configuration

Configure the plugin in tui.json:

{
"plugin": [
[
"@leohenon/opencode-vim-plugin",
{
"enabled": true,
"toggle_key": "ctrl+shift+v",
"indicator": true,
"vim_enter_submit": false,
"vim_insert_after_submit": false,
"vim_system_clipboard_register": false
}
]
]
}

Options

For options beginning with vim_, the prefix may be omitted in plugin configuration.

OptionPurpose
enabledStart with Vim mode enabled
vim_initial_modeStart in insert (default) or normal mode
toggle_keyKeybind for Toggle vim mode
indicatorShow the prompt Vim indicator
vim_enter_submitSubmit with Enter from insert mode
vim_insert_after_submitReturn to insert mode after submit
vim_system_clipboard_registerUse the system clipboard as Vim register
vim_langmapMap non-English keys or simple aliases
vim_normal_leaderLeader key for normal keybinds
normal_keybindsExtra keybinds active only in Vim normal mode
keybinds["vim.normal"]Nested normal-mode keybind configuration
vim_escape_sequenceUse a two-key escape sequence like jk

Note

Unsupported OCV options: vim_line_motions

Initial mode

Vim mode starts in insert mode by default. To start in normal mode instead, use:

{
"plugin": [
[
"@leohenon/opencode-vim-plugin",
{
"enabled": true,
"vim_initial_mode": "normal"
}
]
]
}

Mode-scoped keybinds

Bind existing OpenCode commands only in Vim normal mode:

{
"plugin": [
[
"@leohenon/opencode-vim-plugin",
{
"vim_normal_leader": "space",
"normal_keybinds": {
"<leader>s": "session.list",
"j": "session.line.down",
"k": "session.line.up"
}
}
]
]
}

normal_keybinds values can be command strings or objects:

{
"normal_keybinds": {
"j": {
"command": "session.line.down",
"desc": "Scroll down",
"preventDefault": false
}
}
}

Nested normal-mode keybind configuration is also accepted inside the plugin options:

{
"plugin": [
[
"@leohenon/opencode-vim-plugin",
{
"keybinds": {
"vim.normal": {
"leader": "space",
"session_list": "<leader>s",
"messages_line_up": "<leader>k",
"messages_line_down": "<leader>j"
}
}
}
]
]
}

Submit behavior

By default, insert mode uses Enter for newlines and normal mode uses Enter to submit.

To submit from insert mode too:

{
"plugin": [
[
"@leohenon/opencode-vim-plugin",
{
"vim_enter_submit": true
}
]
]
}

To always default to insert mode after a prompt submission:

{
"plugin": [
[
"@leohenon/opencode-vim-plugin",
{
"vim_insert_after_submit": true
}
]
]
}

To keep newline available when vim_enter_submit is enabled, configure OpenCode's top-level input_newline keybind:

{
"keybinds": {
"input_newline": "alt+return"
}
}

Or configure a separate OpenCode submit key:

{
"keybinds": {
"prompt_submit": "alt+return"
}
}

input_newline and prompt_submit are OpenCode keybinds, not plugin options.

System clipboard register

Use the system clipboard as Vim's register:

{
"plugin": [
[
"@leohenon/opencode-vim-plugin",
{
"vim_system_clipboard_register": true
}
]
]
}

Yank and delete operations sync to the system clipboard, p / P paste from it.

Note

Clipboard sync uses pbcopy / pbpaste on macOS, PowerShell clipboard commands on Windows, and wl-copy / wl-paste, xclip, or xsel on Linux.

Vim langmap

Map non-English keyboard layout characters to Vim command keys.

Keys and values should be single characters.

{
"plugin": [
[
"@leohenon/opencode-vim-plugin",
{
"vim_langmap": {
"р": "h",
"о": "j",
"л": "k",
"д": "l"
}
}
]
]
}

Or for simple aliases:

{
"plugin": [
[
"@leohenon/opencode-vim-plugin",
{
"vim_langmap": {
"H": "^",
"L": "$"
}
}
]
]
}

Vim escape sequence

Set a two-character sequence to leave insert mode without pressing Escape:

{
"plugin": [
[
"@leohenon/opencode-vim-plugin",
{
"vim_escape_sequence": "jk"
}
]
]
}

Want more?

This plugin covers the prompt only. For Vim controls across the whole TUI — copy mode, session navigation — see OpenCode Vim, a fork of OpenCode that this plugin shares its Vim core with.

Local development

bun install
bun run check

Launch a local installed OpenCode test workspace:

./script/test-installed.sh

About

Vim controls for the OpenCode TUI

Topics

Resources

Stars

15 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages