@thazhemadam/pi-vim

Vim-style modal editing integration for Pi.

Packages

Package details

extension

Install @thazhemadam/pi-vim from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@thazhemadam/pi-vim
Package
@thazhemadam/pi-vim
Version
0.1.2
Published
Aug 30, 2026
Downloads
225/mo · 151/wk
Author
thazhemadam
License
LGPL-3.0-only
Types
extension
Size
82.4 KB
Dependencies
2 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./dist/index.js"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

@thazhemadam/pi-vim

npm License: LGPL-3.0-only

A Pi extension for Vim-style modal editing in the prompt editor.

The extension provides colored mode labels, mode-specific cursor shapes, Visual selections, registers, and linear undo history. It uses @thazhemadam/vim-state for host-neutral editing behavior.

Requirements

  • Node.js 22.19.0 or later
  • Pi 0.79.8 or later

Install

Install the extension from npm:

pi install npm:@thazhemadam/pi-vim

To install a specific Git revision instead:

pi install git:github.com/thazhemadam/vim-state@<commit>

Then start or restart Pi. The prompt starts in Insert mode.

Run this Pi command to verify that the extension loaded:

/pi-vim-status

Use pi config to enable or disable the extension after installation. To remove an npm installation:

pi remove npm:@thazhemadam/pi-vim

First steps

  1. Type a prompt in Insert mode.
  2. Press Escape to enter Normal mode.
  3. Use Vim commands to edit the prompt.
  4. Press i to return to Insert mode.
  5. Press Enter in Normal mode to submit the prompt.

If autocomplete is open, the first Escape closes autocomplete. Press Escape again to enter Normal mode.

The label at the lower-right edge shows the active parser state:

  • INSERT
  • NORMAL
  • OPERATOR
  • VISUAL
  • VISUAL LINE
  • REPLACE

The terminal cursor also changes by mode. Insert mode uses a bar. Normal and Visual modes use a block. Replace and operator states use an underline.

Command reference

Only the commands listed below are supported. Host keys that pass through to Pi are described under Pi behavior.

Modes and insert entry

Key Action
Escape Leave Insert, Replace, Visual, or operator-pending mode.
i Insert before the cursor.
a Insert after the cursor.
I Insert before the first non-blank character.
A Insert at the end of the line.
o Open a line below and enter Insert mode.
O Open a line above and enter Insert mode.
r{char} Replace one character.
R Enter Replace mode.
v Enter character-wise Visual mode.
V Enter line-wise Visual mode.

Motions

Key Action
h, j, k, l Move left, down, up, or right.
0 Move to the start of the line.
^, _ Move to the first non-blank character.
$ Move to the end of the line.
w, b, e Move by Vim-style words.
W, B, E Move by whitespace-delimited WORDS.
f{char}, F{char} Find a character forward or backward on the line.
t{char}, T{char} Move just before a forward target or just after a backward target.
gg Move to the first line.
G Move to the last line.
{count}gg, {count}G Move to the specified one-based line number.

A word contains ASCII letters, digits, or _. Adjacent punctuation is a separate word. A WORD is any non-whitespace run.

Operators, edits, and registers

Key Action
d{motion} Delete the motion range.
c{motion} Change the motion range and enter Insert mode.
y{motion} Yank the motion range.
dd, cc, yy Delete, change, or yank whole lines.
iw, aw Select an inner word or a word with surrounding whitespace after an operator.
x, X Delete the character under or before the cursor.
D, C Delete or change through the end of the line.
p, P Put the unnamed register after or before the cursor.
J Join lines.
~ Toggle character case.
u Undo one pi-vim edit.
Ctrl-R Redo one pi-vim edit.

Operators support h, j, k, l, 0, $, ^, _, w, b, e, W, B, E, f, F, t, and T. They also support iw and aw.

Counts work with:

  • h, j, k, l, w, b, e, W, B, E, f, F, t, T, gg, and G
  • d, c, and y with those motions except gg and G, with $, or as dd, cc, and yy
  • x, X, D, C, p, P, J, and ~

Counts do not apply to 0, ^, _, iw, or aw.

The editor stores at most 100 undo snapshots. One Insert or Replace session is one undo step. A new edit after undo clears the redo path.

Visual mode

Use h, j, k, l, 0, $, ^, _, w, b, e, W, B, E, or G to extend a Visual selection. Counts work with h, j, k, l, w, b, e, W, B, E, and G.

Then use one of these keys:

Key Action
o, O Swap the selection anchor and active end.
y Yank the selection.
d, x Delete the selection.
c Change the selection and enter Insert mode.
p, P Replace the selection with the unnamed register.
~ Toggle the case of the selection.
u, U Convert the selection to lowercase or uppercase.
J Join the selected lines.

Clipboard and registers

Delete, change, yank, and Visual replacement commands write to the internal unnamed register. By default, the extension also copies these writes to the system clipboard.

Start Pi with this flag to keep register writes local:

pi --pi-vim-local-registers

This flag stops outgoing clipboard copies. The extension does not read clipboard text into the unnamed register.

Pi behavior

The adapter keeps these Pi editor behaviors:

  • Enter submits a prompt in Insert, Normal, or Visual mode.
  • Pi retains its normal Up and Down prompt-history behavior in Insert and Normal modes.
  • Pi clear, suspend, and exit shortcuts continue to work in Insert and Normal modes.
  • In Normal mode, Escape runs the Pi interrupt action.
  • Pi autocomplete receives Escape before Vim leaves Insert or Replace mode.
  • Programmatic text insertion creates one undoable edit.

Limitations

This package implements a Vim subset, not a Vim runtime. It does not support these features:

  • Command-line mode and : commands
  • / and ? search
  • Named registers
  • Marks, macros, and key mappings
  • The repeat command (.)
  • Most text objects
  • Plugins or a vimrc

Positions use UTF-16 string columns, so some multi-code-point graphemes behave differently than they do in Vim.

If Pi's wrapped editor layout becomes incompatible, Visual commands still work, but pi-vim omits selection highlighting.

Local development

From the repository root:

npm ci
npm run dev:pi

The development command builds both packages and starts Pi with only the extensions in this checkout. It also inserts a multi-line sample prompt.

Run the package tests directly with:

npm test --workspace @thazhemadam/pi-vim

Run all repository checks before you submit a change:

npm run check
npm test
npm run check:packages

The package check verifies the tarball contents, production installation, and Pi loading. CI also builds a clean Git package without development dependencies.

Programmatic exports

The package default export is the Pi extension factory. It also exports these integration helpers:

  • VimPiEditor
  • normalizePiKey
  • piInputToVimEvent
  • isPrintablePiInput

It re-exports the public API from @thazhemadam/vim-state.

License

This package uses the GNU Lesser General Public License v3.0 only. The package also includes the corresponding GNU GPL v3 text.