zledit

February 21, 2026 · View on GitHub

Zsh Line Editor toolkit - fuzzy navigation and in-place editing for your command line.

Mentioned in Awesome Load Parse Leak

Jump to any word on the current command line via fuzzy picker.

Long commands are tedious to navigate. Instead of holding arrow keys or Ctrl+Left repeatedly, fuzzy-search any word and jump straight to it.

$ kubectl get pods -n kube-system --output wide

              [Alt+/]

 [a]kubectl [s]get [d]pods [f]-n [g]kube-system [h]--output [j]wide   ← overlay
┌─────────────────────────────────────┬────────────────────────────────────────┐
 jump> kubectl controls the Kubernetes...
 ^S:wrap | ^E:var | ^R:replace | ^M:m|
│─────────────────────────────────────│
> 1: kubectl Basic Commands (Beginner):             │
  2: get   create    Create a resource
  3: pods   expose    Expose a resource
  4: -n   run       Run a particular image
  5: kube-system   set       Set specific features
  6: --output
  7: wide Basic Commands (Intermediate):         │
└─────────────────────────────────────┴────────────────────────────────────────┘

The overlay shows letter hints ([a]kubectl [s]get [d]pods) for instant jump. The picker has numbered items for fuzzy search, with --help preview on the right.

Press ; to enter instant mode: press a letter key (a, s, d...) to jump directly to that word.

Features

  • Multiple picker support: fzf, fzf-tmux, sk (skim), peco, percol
  • Auto-detection: Prefers fzf-tmux when in tmux, falls back to available picker
  • Overlay hints: EasyMotion-style [a] [s] [d] labels on command line for instant jump
  • Instant jump: Press ; then a letter to jump without fuzzy searching
  • Configurable: Custom keybindings, picker options via zstyle
  • Fast: ~0.2ms load time (see Metrics)
  • Wrap/Surround: Wrap tokens in quotes, brackets, or command substitution
  • Move/Swap: Swap token positions via secondary picker
  • Variable extraction: Convert tokens to shell variables
  • Batch-apply: Actions apply to all identical tokens at once
  • Smart preview: Command help (--help/tldr/man), file contents, directory listings

Requirements

DependencyMinimum VersionCheck
zsh5.3+zsh --version
fzf0.53.0+fzf --version

Alternative pickers (instead of fzf): sk/skim, peco, percol

Note: System package managers often ship outdated fzf (e.g., Ubuntu/Debian ships 0.29). Install from GitHub releases or via git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf && ~/.fzf/install

Installation

Pick your plugin manager, then verify with Alt+/ on any command.

zinit
# Add to .zshrc
zinit light Piotr1215/zledit
antigen
# Add to .zshrc
antigen bundle Piotr1215/zledit
oh-my-zsh
# 1. Clone to oh-my-zsh custom plugins
git clone https://github.com/Piotr1215/zledit \
    ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zledit

# 2. Add to plugins array in ~/.zshrc
plugins=(... zledit)

# 3. Restart shell or run: source ~/.zshrc

Verify oh-my-zsh path: echo ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}

sheldon
# Add to ~/.config/sheldon/plugins.toml
[plugins.zledit]
github = "Piotr1215/zledit"
zplug
# Add to .zshrc
zplug "Piotr1215/zledit"
Manual
# Clone anywhere
git clone https://github.com/Piotr1215/zledit ~/.zledit

# Add to .zshrc
source ~/.zledit/zledit.plugin.zsh

Usage

Press Alt+/ (default) on a command line with multiple words. Select a word to jump cursor there.

FZF Actions (inside picker)

With FZF, additional actions available via key combos (shown in header):

KeyAction
EnterJump to selected token
Ctrl+SWrap token in "...", '...', $(...), etc.
Ctrl+EExtract token to UPPERCASE variable (uses push-line)
Ctrl+RReplace token (prompts with tab completion, batch-applies)
Ctrl+MMove/swap token with another position
Alt+1Single mode: apply next action to selected token only (skip batch)
;Enter instant mode (then press a-z to jump)

Tip: Ctrl+R removes the token and drops you into in-context editing with full zsh tab completion. Press Enter to apply the replacement to all identical tokens. Press Ctrl-G to cancel.

Instant mode: Press ; while in the picker, then press a hint letter (a, s, d, f...) to jump directly to that word. The overlay on your command line shows which letter maps to which word.

Variable extraction converts my-gpu to MY_GPU="my-gpu" and "$MY_GPU" in the command. Special characters become underscores.

Batch mode: When identical tokens appear multiple times, actions apply to all occurrences automatically. The picker shows duplicate counts like (x2) next to repeated tokens. Press Alt+1 to apply to only the selected occurrence.

Complex edits: For heavy multiline editing, Ctrl+X Ctrl+E (edit in $EDITOR) still shines. zledit is for quick navigation and token manipulation.

Preview Panel (FZF only)

The preview panel shows contextual information:

  • Commands: --help output (with bat syntax highlighting), fallback to tldr, then man
  • Files: Content preview via bat (or head)
  • Directories: ls -la listing

Scroll preview with Ctrl+D / Ctrl+U. See Configuration for options.

Multiline Commands

Multiline commands with backslash are also supported, for example:

$ docker run -d \
    --name my-container \
    --network host \
    nginx:latest

Words are split on whitespace (spaces, tabs, newlines). Line continuation backslashes are filtered out, so you see only actual command tokens in the picker.

Configuration

All options use zstyle. Set in .zshrc before loading the plugin.

# Picker: fzf (default), fzf-tmux, sk, peco, percol
zstyle ':zledit:' picker fzf
zstyle ':zledit:' picker-opts '--height=50% --reverse --border'

# Keybinding (default: Alt+/)
zstyle ':zledit:' binding '^X^J'        # Ctrl+X Ctrl+J
zstyle ':zledit:' disable-bindings yes  # manual binding only

# Cursor position after jump: start (default), middle, end
zstyle ':zledit:' cursor end

# Overlay hints on command line
zstyle ':zledit:' overlay off           # disable [a] [s] [d] hints

# Preview panel
zstyle ':zledit:' preview off           # disable
zstyle ':zledit:' preview-window 'bottom:40%'

# FZF action keys (if defaults conflict with your setup)
zstyle ':zledit:' fzf-wrap-key 'ctrl-s'
zstyle ':zledit:' fzf-var-key 'ctrl-e'
zstyle ':zledit:' fzf-replace-key 'ctrl-r'
zstyle ':zledit:' fzf-move-key 'ctrl-m'
zstyle ':zledit:' fzf-instant-key ';'
zstyle ':zledit:' fzf-single-key 'alt-1'  # single-mode key (skip batch)

# Batch-apply: actions apply to all identical tokens (default: on)
zstyle ':zledit:' batch-apply off          # disable batch mode

# Vi mode: bind to both insert and command modes
zstyle ':zledit:' disable-bindings yes
bindkey -M viins '^[/' zledit-widget
bindkey -M vicmd '^[/' zledit-widget

Inspect config: zledit-list shows registered paths, actions, previewers.

Picker priority: explicit picker setting → fzf-tmux (in tmux) → fzf → sk → peco → percol

Architecture

Core logic is pure zsh - external pickers (fzf/skim/peco) only handle UI.

tokenizer (pure)  →  actions (pure)  →  picker (external)
     ↓                    ↓
 _ze_words[]        jump/wrap/var
 _ze_positions[]    (O(1) lookup)

The single-pass tokenizer records word positions during parsing. Actions access _ze_positions[$idx] directly for O(1) lookup.

See docs/design.md for engineering details.

Metrics

CI measures and enforces thresholds on every commit:

MetricWhat it measuresThreshold
LoadTime to source the plugin< 200ms
ParseTokenize a 10-word command 100×< 150ms
LeakMemory delta after 10 load/unload cycles< 400KB

Leak checks for memory that isn't freed on zledit-unload. A 5-cycle warmup runs first (zsh internals allocate once), then 10 more cycles. Growth beyond 400KB fails CI.

Extensibility (Advanced)

The plugin works out of the box with built-in actions. For power users who want custom behavior, extensibility is opt-in via TOML config:

zstyle ':zledit:' config ~/.config/zledit/config.toml
# Custom previewer for URLs
[[previewers]]
pattern = '^https?://'
description = 'URL preview'
script = '~/.config/zledit/scripts/url-preview.sh'

# Custom action bound to Ctrl+U
[[actions]]
binding = 'ctrl-u'
description = 'upper'
script = '~/.config/zledit/scripts/uppercase.sh'

User-defined actions override built-in defaults when bindings collide.

See docs/extensibility-guide.md for writing custom scripts.

Testing

zsh tests/test_plugin.zsh

Credits

The EasyMotion-style overlay hints feature was inspired by @DehanLUO's thoughtful feature suggestion and their zsh-easymotion implementation.

License

MIT