Vim Mode
Circuitry has Vim keybindings in two places: code editors, where you get full modal editing, and terminals — including the ones running CLI coding agents like Claude Code — where you get modal navigation. Same grammar, different jobs.
| Code editors | Terminals & CLI agents | |
|---|---|---|
| What it's for | Editing text | Reading, searching, copying — and editing what you're typing |
| Turn it on | Settings → Code Editing → Vim Mode, or ⌘⇧V | Settings → Terminal → Vim keys, or the terminal's own menu |
| Editing keys | d c x u . : — but no file commands | d c x r on the line you're typing. No u, no . |
| Motions | Everything, including f t % { } | h j k l w W b B e E 0 ^ $ gg G |
| Copy & paste | Full registers, marks | One register: y and p |
New to Vim, or want to be taught rather than handed a table? Start with Learn Vim — a nine-part tutorial that builds up from modes to text objects to lifting things out of terminal output with a thumb. This page is the reference you come back to afterwards.
If you already know Vim and only want one section, make it the sequences worth memorising.
Vim in code editors
Modal editing for developers who never want to leave the home row. Off by default; turn it on once and every code editor in the app becomes a Vim editor.
Turning it on
- Settings → Code Editing → Vim Mode — the master switch.
- ⌘⇧V (Mac) / Ctrl⇧V (Windows / Linux) — toggle from anywhere, even while typing. A small confirmation appears so you know which state you're in. Reconfigurable in Settings → Keyboard Shortcuts. (Inside a terminal the same combination keeps its terminal meaning — pasting images — so toggle from an editor or Settings instead.)
When Vim mode is on, a slim status bar appears at the bottom of each editor showing the current mode (--INSERT--, --VISUAL--) and echoing commands as you type them.
Where it works
Everywhere you edit code or structured text:
- Code files — from your projects, local folders, or remote storage
- Workflow nodes — Code, Agent (prompt editing), Data Viz, Code File, Params, Database (SQL), and Web nodes
- Side panels — the docked editors that open next to a workflow
- CodeBook — code cells and the console input
- Designer & web pages — the page-source editors
- 3D scenes — the scene code editor
New to Vim? The ten-minute version
Vim has modes. In normal mode (where you start) keys are commands, not text. In insert mode, typing works like any other editor.
- Click into a code editor. You're in normal mode — the status bar is empty.
- Press
ito insert text at the cursor. The status bar shows--INSERT--. Type normally. - Press
Escto go back to normal mode. - Move around:
hjkl= left, down, up, right.wjumps a word forward,ba word back,0start of line,$end of line,ggtop of file,Gbottom. - Delete a line with
dd. Undo withu. Redo withCtrl+R. - Copy ("yank") a line with
yy, paste withp. - Search with
/somethingthen Enter;njumps to the next match. - Combine counts and motions:
3jmoves down three lines,d3wdeletes three words.
That's the whole trick — everything else is more vocabulary for the same grammar: (count) (operator) (motion).
Supported commands
| Category | Keys |
|---|---|
| Modes | i a I A o O insert · v visual · V visual line · Esc back to normal |
| Motions | h j k l · w b e words · 0 ^ $ line · gg G file · { } paragraphs · f/t + char · % matching bracket |
| Operators | d delete · c change · y yank · > < indent — all combine with motions (dw, ci(, y$) |
| Line ops | dd cc yy · J join · ~ toggle case |
| Counts & repeat | 3w, 2dd, 5j · . repeats the last change |
| Undo / redo | u · Ctrl+R |
| Search | / forward · ? backward · n / N next / previous · * word under cursor |
| Registers & marks | "a–"z named registers · m + letter to set a mark, backtick + letter to jump to it |
| Macros | q + letter to record, q to stop, @ + letter to replay |
| Visual block | CtrlV |
| Command line | :%s/old/new/g substitute · :42 jump to line · :sort · :g / :v global · :noh clear highlight · :reg · :set · :map and friends |
There are no file commands
:w, :q, :wq and :e do not work — :q and friends report "Not an editor command", and :w is accepted but does nothing at all, which is the more surprising of the two.
This is not an oversight to be fixed: an editor here is a pane in a workspace, not a window over a file handle, so there is nothing for "quit" to mean and no separate save step to perform. Files auto-save, and ⌘S / CtrlS forces one immediately. Close a pane the way you close any other tab.
The ' + letter form of a mark jump is also absent; use the backtick form.
Esc in workflow nodes
In a workflow node, Esc normally hands focus back to the canvas. With Vim mode on it's mode-aware:
- In insert or visual mode,
Escreturns you to normal mode — you stay in the editor. - In normal mode,
Escexits the editor and returns focus to the node.
So a reflexive extra Esc never costs more than a click back in.
Works alongside Inline AI
Vim mode and Inline AI coexist: ghost-text suggestions appear while you type in insert mode (Tab still accepts), and the Cmd+K inline prompt opens from any mode.
Vim in terminals and CLI coding agents
The same modal idea, aimed at a different problem: getting things out of terminal output. A URL twenty lines up, an error message worth quoting, a filename you want to paste back into a prompt. On a phone or tablet the key row already gives you cursor keys, Home and End — but they move one character at a time, so this is the difference between forty taps and one.
It works in every terminal: standalone terminals, Terminal nodes, and the panes running CLI coding agents.
Turning on Vim keys in a terminal
- The terminal's own menu — right-click, or long-press with a finger or Apple Pencil. Vim keys is the last item. This affects that terminal only.
- Settings → Terminal → Vim keys — the default for new terminals.
It's off by default because it changes what Esc does, which isn't a surprise to spring on anyone who didn't ask for it.
Modes, and how to get out
You start in insert mode, which is the ordinary terminal — every key goes to the program exactly as before.
Press Esc and you're in normal mode: a blue block appears on the cursor, a badge appears in the corner showing NORMAL, and keys become commands. Output arriving while you're navigating won't yank the screen back to the bottom.
To get back to typing: press i, or tap the badge. The badge is the escape hatch — it always returns you to typing, without needing to know which mode you're stuck in.
In visual mode i starts a text object rather than returning to typing — that's what viw means — so pressing it once looks like nothing happened. Press it twice: ii always gets you back to typing, because an i followed by anything that isn't an object means you wanted out.
The Esc ladder
Because Esc is now a mode key, sending a real Esc to the program — to interrupt Claude Code, or leave a menu in a TUI — takes a second press:
Escfrom insert mode → normal mode. Nothing is sent.Escagain from normal mode → a realEscgoes to the program. You stay in normal mode.
On a phone the key row's esc does the same job in one tap, whichever page it is showing.
Vim in Claude Code and other CLI agents
An agent's input box is not a shell prompt, and three things follow from that.
Editing pauses while the agent is working. Mid-turn, the screen is being repainted and is not a reliable picture of your input line, so the editing keys send nothing until the turn ends. Navigation, selection and copying keep working throughout — reading back what an agent just said is exactly what you want to do while it thinks.
Edits arrive as arrow keys and backspaces. A CLI agent's input is usually an Ink component rather than readline, so the readline verbs (⌥D, CtrlW) are a bet on what that particular program binds. Sending plain cursor keys is understood by all of them, and the whole edit rides in one burst, so ciw costs one round trip.
Esc Esc interrupts the agent — the first press is the mode key, the second sends a real Esc. See the Esc ladder above.
Pasting is bracketed whenever the program asks for it, which every current CLI agent does — so a multi-line yank arrives as text in the input box and waits for you to press Enter, rather than firing off a line at a time.
An agent's reply is a block of non-blank rows, which makes yip the key for "copy what it just told me".
Editing the command you're typing
Vim's editing keys work on the line you are currently typing — the shell prompt, or a CLI agent's input box:
x X D C s r, and d / c over any motion or word object: dw de db d$ diw diW daw ciw cw dd cc.
Or select it first. v plus a motion selects a run of the line — vw, ve, v$ — and then d deletes it, c replaces it, x and s doing the same as those two. o swaps which end of the selection you're extending, which saves starting again when you overshoot. V selects the whole line, so Vd clears it. This works only where any editing works — on the line the program is reading. Drag a selection up into the output and d sends nothing at all, deliberately: the rows above are a picture of what already happened, not a buffer we can change.
So a mistyped command is: Esc, b to the word, ciw, type the correction. Or Esc diW to remove a whole pasted URL in three keys.
Behind the scenes each edit is sent as ordinary cursor keys and backspaces, in a single burst, so it works in any shell and any TUI rather than depending on what that particular program binds. A ten-character deletion costs no more than a one-character one.
The rest of the screen is not editable
Everything above the input line is output that has already happened — a picture painted by a program, often on another machine. Circuitry has the pixels, not the buffer, so a dw up there would be a lie the next redraw undoes. With the cursor in the scrollback, the editing keys do nothing; navigation, selection and copying all still work.
Editing also pauses while the program is working — while an agent is thinking, or a command is running — because mid-render the screen isn't a reliable picture of the input line. Navigation keeps working throughout.
No undo
There's no u. Undo isn't something a program can portably be asked for, and reconstructing it by retyping what we think was there would mean acting on a guess. Your shell's own undo still works — Ctrl_ in bash and zsh — once you're back in insert mode.
. repeats a deletion, not a retyping
. repeats the last change: daw then . . removes three words, and 3x then . removes three more characters. Counts and visual selections are part of what's remembered, so vwd repeats too.
3. does it three times. Vim's own rule is subtly different — there a count on . replaces the one in the original change, so 3x then 2. means 2x. Here it repeats what you did, the number of times you asked. The two agree whenever the original change had no count of its own, which is nearly always.
A change that ended in typing is not remembered. After ciw, . does nothing. Insert mode passes every keystroke straight to the program — that's what makes turning Vim keys on safe — so the replacement text you typed was never seen here, and a . that repeated only the deletion would do half of what you asked without saying so. It refuses instead.
What each key does
| Category | Keys |
|---|---|
| Modes | Esc normal · i a I A back to typing · v visual · V visual line |
| Also back to typing | o O — accepted, but there is no line to open in a prompt, so they simply return you to the input |
| Edit (input line only) | x X delete a character · r replace one · s substitute · D C to end of line · dd cc the whole line |
| Edit a selection | Select with v and a motion, then d or x to delete it, c or s to replace it. o swaps which end you are extending. Only on the line you're typing — a selection reaching into the output above sends nothing |
| Edit + motion | dw de db d$ · cw ce c$ · diw diW daw · ciw ciW |
| Motions | h j k l · 0 ^ $ line · gg G scrollback top / bottom · Ctrl+U Ctrl+D half page · Ctrl+B Ctrl+F full page |
| Words | w b e — runs of letters and digits |
| WORDs | W B E — runs of non-space. A URL is one W, but seven ws |
| Objects | viw viW select · yiw yiW yank without selecting · yaw includes the trailing space |
| Paragraphs | { } move between blocks of output, landing ON the block rather than in the gap — so } yip needs no j · yip yanks the block you're in · yap includes the blank line after it · vip selects it |
| Quotes & brackets | yi" ci' yi` · yi( da[ ci{ vi< — either half of a pair names it, and vim's b (parens) / B (braces) aliases work |
| Character search | f F t T + a character · ; , repeat it forwards / back · combines: dt/ yf. |
| Brackets | % jumps to the matching one |
| Yank | y takes the selection (or the search match) · yy a whole line · yw y$ ye over a motion |
| Yanking across rows | A yank that crosses a row — y} over a block — comes out linewise, whole lines at a time. d and c refuse to cross a row at all |
| Paste | p sends what you yanked to the program · P does the same (there is no "before the cursor" in a line you don't own) · 3p sends it three times |
| Paste over a selection | Select on the line you're typing, then p replaces it |
| Registers | "a before a yank stores it: "ayiw · "ap pastes that one back. Letters and digits, and it applies to the next command only |
| Search | / forward · ? backward · n N next / previous · * # search for the word already under the cursor |
| Screen | H M L top / middle / bottom of what's visible · 3H three lines in from the top |
| Move the view | zt zz zb put the cursor's line at the top / middle / bottom without moving the cursor |
| Marks | m + a letter drops one · backtick + that letter returns to it · ' + the letter returns to the start of its line |
| Links | gx or Enter opens a URL — the one under the cursor, or failing that the next one on the line, so landing on the right line is enough |
| Counts | 5j, 3W, 2yy |
| Repeat | . repeats the last deletion — not a change that ended in typing |
| Case | ~ flips the character under the cursor (5~ for five) · select, then u U ~ for lower / upper / flip · gUiw guiw g~e over a motion or object · gUU the whole line |
A bare y copies what is selected, but only a selection you just made — visual mode, or the search that just landed. A terminal can be holding a selection nobody asked for (a stray drag, an earlier Select All), and that no longer counts, so yiw yanks the word under the cursor rather than spending the y on the leftover highlight.
Copying puts text on the system clipboard as well as in Vim's register, so a yank here can be pasted anywhere on your device.
Pasting with p sends the text at the program's own cursor. Where the program supports bracketed paste — every modern shell does — a multi-line paste arrives as text, and waits for you to press Enter rather than running each line as it arrives.
The sequences worth memorising
Nine errands that cover almost everything anyone actually does in terminal output.
| To do this | Press |
|---|---|
| Copy a URL from the output | Esc → move to it → yiW |
| Copy the last word you typed | Esc → b → yiw — no need to select first |
| Find something | Esc → / → type it → Enter → n for the next match |
| Copy what you just searched for | / → type → Enter → y |
| Copy a whole line | Esc → yy |
| Copy a whole block of output | Esc → move into it → yip |
Lift a path out of cannot open "src/x.ts" | Esc → move onto the line → yi" |
| Copy several lines | Esc → 3yy |
| Collect three things off one screen | Esc → "ayiw → "byiw → "cyiw, then "ap "bp "cp |
| Paste it back into your prompt | p |
| Open a link | Esc → move to its line → gx |
| Fix a word in what you're typing | Esc → b to it → ciw → type the correction |
| Delete a phrase you're typing | Esc → v → motion to the end of it → d |
| Delete several words | Esc → daw → . . |
| Delete a pasted URL you don't want | Esc → move onto it → diW |
| Clear the whole command | Esc → dd |
| Interrupt the agent (send a real Esc) | Esc Esc |
| Jump to the top / bottom of the scrollback | gg / G |
| Find every other mention of a word you can see | Esc → move onto it → * → n |
| Keep your place while you look further up | Esc → ma → go and read → backtick a |
| Get a line out of the bottom two rows | Esc → move to it → zz |
| Get back to typing | i, or tap the mode badge |
These are ordinary Vim sequences, read the same way: an operator (y yank, d delete, c change, or v to select), then either a motion (yw to the next word, y} to the end of the block) or a text object — i for "inner" and a for "around", then what kind: w word, W WORD, p paragraph, or a delimiter — " ' ` ( [ { <. So yiw is yank inner word, daW is delete around WORD, vip is select inner paragraph, yi" is yank inner quotes. Learn the three parts and the combinations come free.
The one worth committing to memory first is W rather than w. w steps between runs of letters, so https://example.com/docs is seven stops; W steps between runs of non-space, so it's one. Every URL errand gets shorter.
And the one to know about i: it doesn't just switch modes, it takes the program's cursor to where you are. Navigate to a typo in the command you're typing, press i, and you're editing at that spot — not back at the end of the line. c does the same thing implicitly: ciw leaves you typing exactly where the old word was.
On a phone
While a terminal is in normal mode, the key row above the keyboard swaps to the Vim set, because most of its usual contents are dead weight there — tab and the modifiers do nothing, and ← → just duplicate h and l.
The Numbers page moves up to sit one swipe behind the Vim set, because a count is digits — 3j, 2yy, or 3. to repeat a change three times.
Every page is a whole set, not a slice of a list. Each one is esc, abc, four or five characters, ctrl, and the repeating ↑ ↓.
esc,abcandctrlare on every page, deliberately duplicated.escsends a real Esc — in normal mode the press goes through to the program, which is how you interrupt an agent, so it is not the way back to typing;abcbeside it is, from any mode.ctrlis what CtrlU CtrlD CtrlF CtrlB need, and a phone has no ctrl key. Being three swipes from any of them would defeat the point.- First page —
/0$^*to begin with - One swipe —
?{}"' - Two — the backtick,
#()· three —[]<>· four —%;,~
A pair never straddles a swipe: { and } are the block motions and get used together, and the bracket pairs stay together too (though either half names the object, so yi( and yi) are the same command).
The row learns. Those are the starting positions; after that the keys you actually reach for move to the front page, and the ones you never touch drift back a swipe. You don't have to do anything — it counts what you press.
Two things it deliberately won't do. It carries only what the keyboard hides: characters behind 123, or behind #+= after that. No letters, in either case — h j k l w b are one tap on the layer already in front of you, and G N W I A are that same layer plus a shift, so a slot spent on any of them would buy almost nothing. The delimiters get those slots instead, which is what makes yi" and ci' and da( practical with a thumb.
And it won't rearrange itself while you're using it: the order is settled when you enter normal mode and then held, so nothing moves under your thumb. Trying a key once won't shuffle the front page either — it takes real, repeated use to promote one.
esc never moves from the first slot, every page ends with the repeating arrows, and the page you were on comes back when you return to typing.