@burneikis/pi-vim

Vim motions extension for pi – normal, insert, visual, and replace modes with operators, motions, text objects, registers, search, and repeat

Package details

extension

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

$ pi install npm:@burneikis/pi-vim
Package
@burneikis/pi-vim
Version
1.4.0
Published
Mar 31, 2026
Downloads
165/mo · 33/wk
Author
burneikis
License
MIT
Types
extension
Size
129.4 KB
Dependencies
0 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ]
}

Security note

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

README

pi-vim

Vim motions extension for pi-coding-agent. Replaces the default input editor with a vim-modal editor supporting normal, insert, visual, and replace modes.

Install

pi install npm:@burneikis/pi-vim

With Fuzzy File Picker

Install pi-fzfp as a separate pi package alongside pi-vim:

pi install npm:@burneikis/pi-fzfp

That's it. When both are installed, pi-vim detects pi-fzfp at startup and integrates its fuzzy autocomplete automatically. pi-fzfp will not install its own editor — pi-vim handles the editor and wraps its autocomplete provider with fzfp's fuzzy matching.

Requires fd and fzf on your PATH.

Features

Vim Motions

  • Normal, Insert, Visual, and Replace modes
  • Motions (h, j, k, l, w, b, e, 0, $, gg, G, etc.)
  • Operators (d, c, y, p, etc.)
  • Text objects (iw, aw, i", a(, etc.)
  • Search (/, ?, n, N)
  • Registers and yank/paste
  • Dot repeat

Fuzzy File Picker (optional, via pi-fzfp)

  • Replaces @file autocomplete with weighted dual-key fuzzy matching
  • Basename matches scored 2× higher than path matches
  • Suffix alignment bonus for extension-aware matching (@actsabct.ts over abct.scss)
  • Path prefix pre-filtering when query contains /
  • Test file penalty as a tiebreaker

Integration Protocol

pi-vim and pi-fzfp coordinate via pi.events so they work regardless of which extension loads first. Other custom editors can use the same protocol to integrate pi-fzfp.

As an editor extension that wants pi-fzfp integration

Register listeners during your extension factory (before session_start), so they are in place regardless of load order:

import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import type { AutocompleteProvider } from "@mariozechner/pi-tui";

export default function (pi: ExtensionAPI) {
  let wrapAutocomplete: ((provider: AutocompleteProvider) => AutocompleteProvider) | undefined;

  // Tell pi-fzfp not to set its own editor component.
  pi.events.on("pi-fzfp:check-editor", (ack: () => void) => { ack(); });

  // Receive the provider (pi-fzfp emits this from both its factory and
  // session_start to cover both load orderings).
  pi.events.on("pi-fzfp:provider", (fn: (provider: AutocompleteProvider) => AutocompleteProvider) => {
    wrapAutocomplete = fn;
  });

  pi.on("session_start", (_event, ctx) => {
    ctx.ui.setEditorComponent((tui, theme, keybindings) =>
      new MyEditor(tui, theme, keybindings, wrapAutocomplete)
    );
  });
}

Then apply wrapAutocomplete inside your editor's setAutocompleteProvider:

override setAutocompleteProvider(provider: AutocompleteProvider): void {
  super.setAutocompleteProvider(this.wrapAutocomplete ? this.wrapAutocomplete(provider) : provider);
}