[FEATURE] Reposition built-in vim mode indicator while preserving instant rendering

Resolved 💬 1 comment Opened Apr 27, 2026 by g-i-o-r-g-i-o Closed May 30, 2026

Preflight Checklist

  • [x] I have searched existing requests. Open #53556 / #47345 and closed #18917 / #19185 all propose the opposite: hide the native indicator and keep only the custom-statusLine replica. This issue is their inverse.
  • [x] This is a single feature request (not multiple features)

Problem Statement

editorMode: "vim" renders the mode indicator (-- INSERT -- / -- NORMAL --) natively and instantly on a dedicated TUI row above the prompt input. That responsiveness is core to vim's UX: the indicator is the only confirmation that a mode-change keypress (i, Esc, v, …) actually took effect, and any perceptible delay breaks muscle memory.

Since v2.1.119, vim.mode is also exposed in the statusLine stdin JSON. Mirroring it from a custom statusLine script, however, introduces:

  1. A 300 ms debounce.
  2. A subprocess spawn of the user's statusLine script.
  3. A JSON parse / jq / printf round-trip.

The combined latency is clearly perceptible during normal iEsc cycling. A script that re-renders vim.mode always visibly lags the native indicator.

Today the only configurations available are:

  • Keep both. Layout is fixed at [custom statusLine] / [native vim row] / [input] — vim mode necessarily appears below whatever the user puts in their statusLine, and is not configurable.
  • Hide the native row (per #53556 / #47345) and accept the laggy custom replica. This sacrifices the instant feedback that makes vim mode usable.

There is no way to have both instant vim feedback and a custom statusLine sitting above or beside it.

Proposed Solution

Three concrete shapes, in increasing implementation cost:

A — invert the row order (smallest change). A boolean setting such as vimModeIndicatorAboveStatusLine: true that swaps the two rows:

…transcript…
-- INSERT --                                    ← native vim, instant
5h 23% · resets in 1h47m │ session 41.4k tok    ← custom statusLine
> _

No change to either render path; only relative order is configurable. The native indicator stays instant; the statusLine keeps its existing debounced/event-driven refresh.

B — render native vim mode inline on the statusLine row. The core reserves a leading slot on the statusLine row that it renders directly with the live vim mode (instant, no subprocess). The user's statusLine script output is appended to the right. Same row, same height; the user's script is never re-run for vim toggles, and refreshInterval still controls only the user-script side.

C — combine with #49939 (multi-position statusLine). If statusLine-on-top lands, allow the statusLine to render at the top while the native vim row stays where it is: [top statusLine] / …transcript… / [native vim] / [input]. Same property: instant vim feedback + custom statusLine, no duplication.

Why this matters — efficiency angle

Beyond UX, mirroring vim mode through the statusLine is also wasteful: every i / Esc keypress triggers a debounced subprocess execution of the user's script (JSON parse, jq, formatting, printf) only to re-derive a piece of state the core already has and is already rendering natively a few rows below. For users whose statusLine script does non-trivial work (git status, network calls, anything cached), this is real overhead per keypress, generating traffic for nothing. The native indicator already does the right thing instantly and for free; the request is to keep that path and just let the user position it differently.

Alternative Solutions

  • Status quo: native row below statusLine (acceptable but not configurable).
  • hideVimModeIndicator per #53556 / #47345 — sacrifices instant feedback, unacceptable for actual vim users.

Priority

Medium - Would be very helpful (necessary for users who rely on vim muscle memory)

Feature Category

Interactive mode (TUI)

Use Case Example

  1. editorMode: "vim" + a custom statusLine that shows 5-hour quota and session token usage.
  2. Today the layout is [my statusLine] / [-- INSERT --] / [prompt]. I want my statusLine to render above -- INSERT --, so the vim indicator (which I scan with peripheral vision while typing) sits just above the prompt where it belongs.
  3. With option A: vimModeIndicatorAboveStatusLine: true in settings.json swaps the order. My script is unchanged. Vim feedback stays instant. My token info is still glanceable, just one row up.

Additional Context

  • Inverse of #53556, #47345, #18917, #19185 — those propose hiding the native row to keep only the (slower) custom replica. This issue argues the native row should be preserved and repositionable.
  • Related: #49939 (multi-position statusLine), #16788 (the vim.mode JSON exposure that made the laggy replica possible).

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗