Zsh plugin for Modern text selection and editing for Zsh command line. Select text with Shift + Arrow keys, type-to-replace, paste-to-replace, mouse selection integration, and clipboard integration for copy/cut/paste like in GUI text editors.
demo.mp4
- Overview
- Features
- Auto Installation
- Manual Installation
- Configuration Wizard
- Terminal Setup
- Wayland Support
- Platform Compatibility
- Performance & Optimization
- Default Key Bindings Reference
- Troubleshooting
- License
- Acknowledgments
- References
Zsh Edit-Select brings familiar text editor behaviors to your Zsh command line:
- ✅ Shift selection — Select text using Shift + Arrow keys
- ✅ Type-to-replace — Type over selected text to replace it
- ✅ Paste-to-replace — Paste clipboard content over selections
- ✅ Mouse integration — Works with text selected by mouse
- ✅ Clipboard integration — Works with X11 and Wayland
- ✅ Standard shortcuts — Ctrl+A (select all), Ctrl+C (copy), Ctrl+X (cut), Ctrl+V (paste), Ctrl+Z (undo), Ctrl+Shift+Z (redo)
Customization: The plugin works after installation with editor-like defaults. Use the command
edit-select configto customize mouse behavior and keybindings.Example Setup: Check out dev-dotfiles to see how this plugin is integrated into a complete real-world environment (Kitty + Zsh + VS Code).
Select text using familiar keyboard shortcuts:
| Shortcut | Action |
|---|---|
| Shift + ←/→ | Select character by character |
| Shift + ↑/↓ | Select line by line |
| Shift + Home/End | Select to line start/end |
| Shift + Ctrl + ←/→ | Select word by word |
| Ctrl + A | Select all text (including multi-line commands) |
The plugin intelligently integrates mouse selections:
When Mouse Replacement is Enabled (default):
- ✅ Copy mouse selections with Ctrl+C
- ✅ Cut mouse selections with Ctrl+X
- ✅ Type to replace mouse selections
- ✅ Delete mouse selections with Backspace/Delete
- ✅ Paste over mouse selections with Ctrl+V
When Mouse Replacement is Disabled:
- ✅ Copy mouse selections with Ctrl+C (still works)
- ✅ Replacement/Deletion work with keyboard selections
Note: Configure mouse behavior with the command
edit-select config→ Option 1
Type or paste while text is selected to replace it automatically.
Works with both keyboard and mouse selections (when mouse replacement is enabled).
⚠️ Mouse Replacement Note (Safeguard Prompt)
If you see the message "Duplicate text: place cursor inside the occurrence you want to modify", the plugin has detected multiple identical occurrences of the selected text in your command buffer.
When does this appear? This message only appears when:
- The selection was made with the mouse, AND
- The exact same text occurs more than once in the buffer, AND
- You try to replace the selected text by either typing or pasting
Why does this happen? This is a protective safeguard for the plugin's mouse-selection workaround. Since mouse replacement is not enabled by default, the implemented workaround cannot automatically distinguish between multiple occurrences of identical text. This prompt prevents accidental edits to the wrong occurrence when using mouse-based selection.
What should you do? When prompted, place the cursor inside the specific occurrence you want to edit, then retry the operation (select it and type or paste to replace).
Note: This safeguard is only for mouse selections. Using Shift+Arrow keys doesn't require caret
replacement and works directly without ambiguity or extra prompting.
Standard editing shortcuts:
- Ctrl + C (or Ctrl+Shift+C): Copy selected text
- Ctrl + X: Cut selected text
- Ctrl + V: Paste (replaces selection if any)
Clipboard Managers Compatibility Note: The plugin is fully compatible with clipboard history managers like CopyQ, GPaste, and others. Since it uses standard X11 and Wayland clipboard protocols, all copied text is automatically captured by your clipboard manager.
Navigate through your command line editing history:
- Ctrl + Z: Undo last edit
- Ctrl + Shift + Z: Redo last undone edit
Note: The Ctrl+Z keybinding works seamlessly alongside the traditional suspend process functionality (Ctrl+Z suspends a running foreground process to background). The plugin intelligently handles undo operations for command line editing while preserving the ability to suspend processes when needed.
Note: The Copy and the Redo keybinding (Ctrl+Shift+Z) requires terminal configuration to send the correct escape sequence. See Terminal Setup for manual configuration instructions, or use the Auto Installation script to configure this automatically.
The plugin uses a high-performance custom C daemon architecture for clipboard operations:
Custom Monitor Daemons: Lightweight C programs handle both selection monitoring and clipboard operations:
| Display Server | Monitor Daemon | Protocol | Performance Gain |
|---|---|---|---|
| X11 | zes-x11-selection-monitor |
XFixes extension + CLIPBOARD atom | 44.6% faster than xclip |
| Wayland | zes-wl-selection-monitor |
zwp_primary_selection_unstable_v1 + wl_data_device |
96.4% faster than wl-copy |
| XWayland | zes-xwayland-monitor |
X11 XFixes through XWayland | Enhance Wayland behaviour |
External Tools (Fallback Only):
| Display Server | Tool | When Used |
|---|---|---|
| X11 | xclip |
Only if custom monitor unavailable |
| Wayland | wl-copy / wl-paste |
Only if custom monitor unavailable |
Performance Achievement: The custom daemon monitors eliminate external tool dependencies entirely. All clipboard operations (copy, paste, clear) are handled by persistent background processes using direct protocol access—delivering faster operations and more control. This achieves better performance, better error handling, zero subprocess overhead.
For more details check the Performance & Optimization section.
The easiest way to install Zsh Edit-Select is using the automated installation script. This intelligent script detects your environment (X11, Wayland, or XWayland), installs necessary dependencies, configures the plugin, and even sets up your terminal emulator.
To install, simply run:
curl -fsSL https://raw.githubusercontent.com/Michael-Matta1/zsh-edit-select/main/assets/auto-install.sh -o install.sh && chmod +x install.sh && bash install.shClick to expand
The installer is designed for reliability and system safety:
- Idempotency: The script checks your configuration files before making changes. It can be run multiple times without creating duplicate entries or corrupting files.
- System Safety: Creates timestamped backups of every file before modification. Implements standard signal trapping (INT, TERM, EXIT) to ensure cleanups even if interrupted.
- optimized Compilation: Builds the monitoring daemons locally using
-O3 -march=native -flto, ensuring the binary is tailored specifically to your CPU architecture for minimum latency. - Universal Compatibility: specific support for 11 different package managers (including
apt,dnf,pacman,zypper,apk, andnix) across X11 and Wayland environments. - Robust Pre-flight Checks: Ensures a smooth installation by validating network connectivity, disk space, and package manager health before starting. It also proactively detects and warns about broken repositories (e.g., problematic apt sources) to prevent install failures.
The script handles the end-to-end setup process:
| Category | Automated Actions |
|---|---|
| Dependencies | - Installs system packages (git, zsh, gcc, make, xclip/wl-clipboard)- Detects your OS (Debian, Fedora, Arch, etc.) and uses the correct package manager ( apt, dnf, pacman) |
| Plugin Manager | - Detects your existing manager (Oh My Zsh, Zinit, Antigen, Sheldon, etc.) - Offers to install Oh My Zsh if you don't have a plugin manager. You can refuse if you prefer manual installation - Note: The installer detects and installs the plugin for other managers such as Zinit or Antigen, but it does not install those managers themselves. If you prefer using them instead of OMZ, make sure they are installed before running the installer. |
| Compilation | - Downloads and compiles the custom C monitor daemons (zes-x11-monitor / zes-wl-monitor)- Optimizes binaries for your specific architecture |
| Terminal Setup | - Configures Kitty, Alacritty, WezTerm, Foot, and VS Code to support keybindings - Backs up existing config files before making changes |
| Safeguards | - Checks for conflicting keybindings in your .zshrc- Verifies the installation with a self-test suite |
When run without arguments, the installer provides an interactive menu with the following options:
- Full Installation (Recommended): The complete setup process. Required for first-time installations.
- Configure Terminals Only: Only detects and configures your terminal emulators.
- Check for Conflicts Only: Scans your configuration files for conflicting keybindings.
- Update Plugin: Pulls the latest changes and rebuilds the monitor daemons.
Advanced Usage & Options
You can customize the installation behavior with command-line flags. To use them, download the script first or pass them to bash:
| Option | Description |
|---|---|
--non-interactive |
Run in headless mode without user prompts (accepts all defaults) |
--skip-deps |
Skip installing system dependencies (useful if you manage packages manually) |
--skip-conflicts |
Skip the configuration conflict detection phase |
--skip-verify |
Skip the post-installation verification tests |
--test-mode |
Allow running as root (for testing only) |
--help |
Show the help message and exit |
Example: Non-interactive installation (CI/CD friendly)
bash auto-install.sh --non-interactiveThe script provides detailed, color-coded feedback for every step:
- ✅ Success: Step completed successfully
⚠️ Warning: Non-critical issue (e.g., optional component missing)- ❌ Error: Critical failure that requires attention
At the end, you'll receive a Summary Report listing all installed components and any manual steps required. A detailed log is also saved to ~/.zsh-edit-select-install.log.
Troubleshooting / Manual Preference: If the automated installation fails or if you prefer to configure everything yourself, you can follow the comprehensive Manual Installation and Terminal Setup guides below.
Tip: The Auto Installation script handles all these steps automatically (dependencies, plugin installation, compiling custom monitor daemons). You only need this section if you prefer full manual control or if the auto-installer fails.
How to check if you're using X11 or Wayland
Run this command in your terminal:
echo $XDG_SESSION_TYPE- If it returns
x11→ You're using X11 - If it returns
wayland→ You're using Wayland
Note: The plugin automatically detects your display server and loads the appropriate implementation.
The plugin automatically compiles native monitor daemons on first use. Install the required build tools and libraries for your platform:
Debian/Ubuntu
The plugin includes a native X11 monitor daemon with full clipboard support. External clipboard tools are optional:
sudo apt install build-essential libx11-dev libxfixes-dev pkg-config xclipNote: The
zes-x11-selection-monitordaemon provides 44.6% faster clipboard operations compared toxclipand does not require external tools for core functionality.
Arch Linux
The plugin includes a native X11 monitor daemon with full clipboard support. External clipboard tools are optional:
sudo pacman -S --needed base-devel libx11 libxfixes pkgconf xclipNote: The
zes-x11-selection-monitordaemon provides 44.6% faster clipboard operations compared toxclipand does not require external tools for core functionality.
Fedora
The plugin includes a native X11 monitor daemon with full clipboard support. External clipboard tools are optional:
sudo dnf install gcc make libX11-devel libXfixes-devel pkgconfig xclipNote: The
zes-x11-selection-monitordaemon provides 44.6% faster clipboard operations compared toxclipand does not require external tools for core functionality.
Debian/Ubuntu
The plugin includes a native Wayland monitor daemon with full PRIMARY selection support. External clipboard tools are optional:
sudo apt install build-essential libwayland-dev wayland-protocols pkg-config wl-clipboardNote: The
zes-wl-selection-monitordaemon uses native Wayland protocols directly and does not require these tools for core functionality.
Arch Linux
The plugin includes a native Wayland monitor daemon with full PRIMARY selection support. External clipboard tools are optional:
sudo pacman -S --needed base-devel wayland wayland-protocols pkgconf wl-clipboardNote: The
zes-wl-selection-monitordaemon uses native Wayland protocols directly and does not require these tools for core functionality.
Fedora
The plugin includes a native Wayland monitor daemon with full PRIMARY selection support. External clipboard tools are optional:
sudo dnf install gcc make wayland-devel wayland-protocols-devel pkgconfig wl-clipboardNote: The
zes-wl-selection-monitordaemon uses native Wayland protocols directly and does not require these tools for core functionality.
If you're running Wayland but need X11 compatibility (XWayland) and enhance the behaviour, install both X11 and Wayland dependencies.
Debian/Ubuntu
sudo apt install build-essential libx11-dev libxfixes-dev libwayland-dev wayland-protocols pkg-configArch Linux
sudo pacman -S --needed base-devel libx11 libxfixes wayland wayland-protocols pkgconfFedora
sudo dnf install gcc make libX11-devel libXfixes-devel wayland-devel wayland-protocols-devel pkgconfigImportant: Before installing, please ensure you have the required Build Dependencies installed.
Tip: The Auto Installation script can perform all of the following installation steps automatically.
Oh My Zsh
Expand your plugin manager:
git clone https://github.com/Michael-Matta1/zsh-edit-select.git \
${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-edit-selectAdd to your .zshrc:
plugins=(... zsh-edit-select)zgenom
zgenom load Michael-Matta1/zsh-edit-selectsheldon
sheldon add zsh-edit-select --github Michael-Matta1/zsh-edit-selectManual Installation
git clone https://github.com/Michael-Matta1/zsh-edit-select.git \
~/.local/share/zsh/plugins/zsh-edit-select
# Add to ~/.zshrc:
source ~/.local/share/zsh/plugins/zsh-edit-select/zsh-edit-select.plugin.zshSome terminals need configuration to support Shift selection. See Terminal Setup for details.
source ~/.zshrcImportant: You may need to fully close and reopen your terminal (not just source ~/.zshrc) for all features to work correctly, especially in some terminal emulators.
You're ready! Try selecting text with Shift + Arrow keys.
The plugin works immediately with sensible defaults, but you can customize:
- Mouse replacement behavior
- Keybindings (Ctrl+A, Ctrl+V, Ctrl+X, Ctrl+Z, Ctrl+Shift+Z)
Run the interactive configuration wizard:
edit-select configLaunch the interactive configuration wizard:
edit-select configThe wizard provides:
- Mouse Replacement — Enable/disable mouse selection integration
- Key Bindings — Customize Ctrl+A, Ctrl+V, Ctrl+X, Ctrl+Z, Ctrl+Shift+Z shortcuts
- View Configuration — See current settings
- Reset to Defaults — Restore factory settings
All changes are saved to ~/.config/zsh-edit-select/config and persist across sessions.
Mouse Replacement Modes
Configure how the plugin handles mouse selections:
Enabled (default):
- Full integration: type, paste, cut, and delete work with mouse selections
- Best for users who want seamless mouse+keyboard workflow
- A lightweight background daemon monitors PRIMARY selection changes for instant mouse selection detection
Disabled:
- Mouse selections can be copied with Ctrl+C
- Typing, pasting, cutting, and deleting only work with keyboard selections
- The background daemon is still running but mouse replacement actions are disabled
- Best for users who prefer strict keyboard-only editing
Change the mode:
edit-select config # → Option 1: Mouse ReplacementKeybinding Customization
Customize the main editing shortcuts:
edit-select config # → Option 2: Key BindingsDefault bindings:
Tip: If you're unsure how keybindings integrate with your shell or terminal, take a look at the dev-dotfiles repository for a working reference implementation.
- Ctrl + A — Select all
- Ctrl + V — Paste
- Ctrl + X — Cut
- Ctrl + Z — Undo
- Ctrl + Shift + Z — Redo
Custom Keybinding Notes (Terminal Configuration)
⚠️ Important: When using custom keybindings (especially with Shift modifiers), you may need to configure your terminal emulator to send the correct escape sequences.
To find the escape sequence for any key combination:
- Run
cat(without arguments) in your terminal - Press the key combination
- The terminal will display the escape sequence
- Use this sequence in your configuration
For example, if you want to use Ctrl + Shift + X for cut add the following to your terminal dotfile:
Kitty
Add to kitty.conf:
map ctrl+shift+x send_text all \x1b[88;6u
WezTerm
Add to wezterm.lua:
return {
keys = {
{
key = 'X',
mods = 'CTRL|SHIFT',
action = wezterm.action.SendString '\x1b[88;6u',
},
},
}Alacritty
Add to alacritty.yml:
key_bindings:
- { key: X, mods: Control|Shift, chars: "\x1b[88;6u" }Or for alacritty.toml:
[[keyboard.bindings]]
key = "X"
mods = "Control|Shift"
chars = "\u001b[88;6u"VS Code Terminal
Add to keybindings.json (usually at ~/.config/Code/User/):
[
{
"key": "ctrl+shift+x",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u001b[88;6u" },
"when": "terminalFocus"
}
]Display Server Override
Note: The plugin automatically uses the correct implementation (X11 or Wayland) based on your system.
# Force a specific implementation (overrides auto-detection)
export ZES_FORCE_IMPL=x11 # Force X11 implementation
export ZES_FORCE_IMPL=wayland # Force Wayland implementationUse case: Force a specific implementation if auto-detection fails or if you want to use a different display server intentionally.
Tip: The Auto Installation script can automatically configure supported terminals (Kitty, WezTerm, Alacritty, Foot, VS Code) for you, saving you from these manual steps.
How to Find Escape Sequences
To find the escape sequence for any key combination:
- Run
cat(without arguments) in your terminal - Press the key combination
- The terminal will display the escape sequence
- Use this sequence in your configuration
⚠️ CRITICAL: Before adding these mappings, you MUST remove or comment out any existingctrl+shift+cmappings in your terminal config (such asmap ctrl+shift+c copy_to_clipboardin Kitty). These will conflict and prevent the plugin from working correctly.
Kitty
To use Ctrl+Shift+C for copying, add the following to kitty.conf:
map ctrl+shift+c send_text all \x1b[67;6u
If you prefer to use Ctrl+C for copying (like in GUI applications) and Ctrl+Shift+C for interrupt:
# Ctrl+C sends the escape sequence for copying
map ctrl+c send_text all \x1b[67;6u
# Ctrl+Shift+C sends interrupt (default behavior)
map ctrl+shift+c send_text all \x03
WezTerm
To use Ctrl+Shift+C for copying, add the following to wezterm.lua:
return {
keys = {
{
key = 'C',
mods = 'CTRL|SHIFT',
action = wezterm.action.SendString '\x1b[67;6u',
},
},
}If you prefer to use Ctrl+C for copying and Ctrl+Shift+C for interrupt:
return {
keys = {
{
-- Ctrl+C sends the escape sequence for copying
key = 'c',
mods = 'CTRL',
action = wezterm.action.SendString '\x1b[67;6u',
},
{
-- Ctrl+Shift+C sends interrupt signal
key = 'C',
mods = 'CTRL|SHIFT',
action = wezterm.action.SendString '\x03',
},
},
}Alacritty
To use Ctrl+Shift+C for copying, add the following to alacritty.yml:
key_bindings:
- { key: C, mods: Control|Shift, chars: "\x1b[67;6u" }Or for alacritty.toml:
[[keyboard.bindings]]
key = "C"
mods = "Control|Shift"
chars = "\u001b[67;6u"If you prefer to use Ctrl+C for copying and Ctrl+Shift+C for interrupt:
For alacritty.yml:
key_bindings:
# Ctrl+C sends the escape sequence for copying
- { key: C, mods: Control, chars: "\x1b[67;6u" }
# Ctrl+Shift+C sends interrupt signal
- { key: C, mods: Control|Shift, chars: "\x03" }For alacritty.toml:
# Ctrl+C sends the escape sequence for copying
[[keyboard.bindings]]
key = "C"
mods = "Control"
chars = "\u001b[67;6u"
# Ctrl+Shift+C sends interrupt signal
[[keyboard.bindings]]
key = "C"
mods = "Control|Shift"
chars = "\u0003"VS Code Terminal
To use Ctrl+Shift+C for copying, add the following to keybindings.json (usually at ~/.config/Code/User/):
[
{
"key": "ctrl+shift+c",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u001b[67;6u" },
"when": "terminalFocus"
}
]If you prefer to use Ctrl+C for copying and Ctrl+Shift+C for interrupt:
[
{
// Ctrl+C sends copy sequence to terminal
"key": "ctrl+c",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u001b[67;6u" },
"when": "terminalFocus"
},
{
// Ctrl+Shift+C sends interrupt signal
"key": "ctrl+shift+c",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u0003" },
"when": "terminalFocus"
}
]Alternative: Without Terminal Remapping
If your terminal doesn't support key remapping, you can add the following to your ~/.zshrc to use Ctrl +
/ for copying:
x-copy-selection () {
if [[ $MARK -ne $CURSOR ]]; then
local start=$(( MARK < CURSOR ? MARK : CURSOR ))
local length=$(( MARK > CURSOR ? MARK - CURSOR : CURSOR - MARK ))
local selected="${BUFFER:$start:$length}"
print -rn "$selected" | xclip -selection clipboard
fi
}
zle -N x-copy-selection
bindkey '^_' x-copy-selectionYou can change the keybinding to any key you prefer. For example, to use Ctrl + K:
bindkey '^K' x-copy-selectionNote: The
^_sequence represents Ctrl + / (Ctrl + Slash), and^Krepresents Ctrl + K. You can find other key sequences by runningcatin your terminal and pressing the desired key combination.
Bonus Feature: If no text is selected, this manual keybinding will copy the entire current line to the clipboard.
Kitty
Add to kitty.conf:
map ctrl+shift+z send_text all \x1b[90;6u
WezTerm
Add to wezterm.lua:
return {
keys = {
{
key = 'Z',
mods = 'CTRL|SHIFT',
action = wezterm.action.SendString '\x1b[90;6u',
},
},
}Alacritty
Add to alacritty.yml:
key_bindings:
- { key: Z, mods: Control|Shift, chars: "\x1b[90;6u" }Or for alacritty.toml:
[[keyboard.bindings]]
key = "Z"
mods = "Control|Shift"
chars = "\u001b[90;6u"VS Code Terminal
Add to keybindings.json (usually at ~/.config/Code/User/):
[
{
"key": "ctrl+z",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u001a" },
"when": "terminalFocus"
},
{
"key": "ctrl+shift+z",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u001b[90;6u" },
"when": "terminalFocus"
}
]Note: The Ctrl+Z keybinding works seamlessly alongside the traditional suspend process functionality (Ctrl+Z suspends a running foreground process to background). The plugin intelligently handles undo operations for command line editing while preserving the ability to suspend processes when needed.
Some terminals intercept Shift key combinations by default. Here's how to configure popular terminals:
Kitty
Add to kitty.conf:
# Enable Shift selection
map ctrl+shift+left no_op
map ctrl+shift+right no_op
map ctrl+shift+home no_op
map ctrl+shift+end no_op
Looking for a reference? The dev-dotfiles repository contains ready-to-use configurations for Kitty (
kitty.conf) and VS Code (keybindings.json) that act as a great starting point for integrating this plugin.
WezTerm
Add to wezterm.lua:
return {
keys = {
{ key = 'LeftArrow', mods = 'CTRL|SHIFT', action = 'DisableDefaultAssignment' },
{ key = 'RightArrow', mods = 'CTRL|SHIFT', action = 'DisableDefaultAssignment' },
},
}VS Code Terminal
Add to keybindings.json (usually at ~/.config/Code/User/):
[
{
"key": "ctrl+shift+left",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u001b[1;6D" },
"when": "terminalFocus"
},
{
"key": "ctrl+shift+right",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u001b[1;6C" },
"when": "terminalFocus"
},
{
"key": "shift+home",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u001b[1;2H" },
"when": "terminalFocus"
},
{
"key": "shift+end",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u001b[1;2F" },
"when": "terminalFocus"
}
]Alacritty
Alacritty doesn't need a tweak to enable Shift/Shift+Ctrl selection, but you will need to configure the copy shortcuts for the clipboard the same as the other terminals.
Tip: The Auto Installation script automatically detects your environment and builds the correct optimized monitor daemon.
Wayland is fully supported with native protocol implementation. The plugin automatically detects your Wayland setup and uses the optimal selection monitor:
Selection Monitor Priority (automatically selected):
-
zes-wl-selection-monitor(Native Wayland) — Custom C daemon with direct Wayland protocol support- Uses
zwp_primary_selection_unstable_v1for PRIMARY selection - Uses
wl_data_devicefor CLIPBOARD operations - Works on all Wayland compositors with protocol support (Sway, Hyprland, KDE Plasma, River, Wayfire)
- Provides full mouse selection replacement feature
- Best performance with zero external tool overhead
- Uses
-
zes-xwayland-monitor(XWayland) — Recommended X11 compatibility layer- Uses XWayland's X11 XFixes extension when available
- Provides seamless support for mixed X11/Wayland environments
- Recommended for maximum compatibility with older applications
Technical Achievement: The native Wayland implementation eliminates reliance on external clipboard tools (
wl-copy/wl-paste). Our custom C daemon connects directly to Wayland protocols, providing instant PRIMARY selection monitoring with zero process-spawn overhead. This architecture delivers superior performance and responsiveness compared to traditional clipboard utility approaches.Architecture: The selection monitor daemons (
zes-wl-selection-monitor,zes-xwayland-monitor,zes-x11-selection-monitor) are lightweight background processes that monitor selection changes via event-driven protocols and write updates to cache files. This zero-fork design ensures instant responsiveness without performance overhead during typing.
Native Wayland Protocol Support (Fully Implemented)
Our zes-wl-selection-monitor daemon provides complete PRIMARY selection support on all Wayland compositors
with protocol implementation:
Supported Compositors:
- ✅ wlroots-based compositors — Sway, Hyprland, River, Wayfire (full PRIMARY support)
- ✅ KDE Plasma Wayland — Full PRIMARY selection via
zwp_primary_selection_unstable_v1 - ✅ GNOME Wayland (Mutter) — Native Wayland implementation provides PRIMARY selection support*
*Note: GNOME's PRIMARY selection support depends on compositor configuration. If unavailable, XWayland bridge provides seamless fallback.
Performance Advantage: Direct Wayland protocol access means:
- No subprocess spawning for clipboard operations
- No
wl-copy/wl-pasteprocess overhead - Native event-driven architecture
- Instant response to selection changes
- Zero typing lag even with frequent selections
XWayland Bridge (Recommended, for Enhanced Compatibility)
The plugin includes a recommended XWayland bridge for environments where native Wayland protocol support is limited. XWayland provides:
- Seamless fallback for hybrid X11/Wayland environments
- Support for legacy applications running under XWayland
- Alternative PRIMARY selection detection when native Wayland protocols unavailable
Enabling XWayland (Recommended)
The recommended selection monitor (zes-xwayland-monitor) requires XWayland. XWayland provides an X11
compatibility layer on top of Wayland, allowing the monitor to use X11's XFixes extension for completely
invisible PRIMARY selection tracking — no windows, no dock entries, no compositor artifacts.
Check if XWayland is already running:
echo $DISPLAYIf this prints something like :0 or :1, XWayland is already available.
If DISPLAY is empty, enable XWayland on your compositor:
GNOME (Mutter)
XWayland is enabled by default on GNOME. If it was disabled:
# Re-enable XWayland (requires logout/login)
gsettings reset org.gnome.mutter experimental-featuresOr add Xwayland to the experimental features if using a custom list. On GNOME 47+, XWayland starts on demand
when any X11 app connects.
KDE Plasma
XWayland is enabled by default. If disabled, re-enable it in:
System Settings → Display and Monitor → Compositor → Allow XWayland applications
Sway
XWayland is enabled by default. If disabled, add to your Sway config:
xwayland enable
Then reload Sway ($mod+Shift+C).
Hyprland
Add to your Hyprland config:
xwayland {
force_zero_scaling = true
}
XWayland is enabled by default in Hyprland.
Without XWayland: The plugin falls back to the pure Wayland monitor (zes-wl-selection-monitor), which
uses zwp_primary_selection_v1. This works on wlroots-based compositors (Sway, Hyprland) and KDE Plasma, but
may show a small surface in the dock/taskbar on GNOME/Mutter.
Mouse Selection Replacement Feature
The Mouse Selection Replacement feature (automatically detecting and replacing mouse-selected text) has comprehensive support across platforms via our custom daemon implementations:
X11 & XWayland:
- X11 - Complete PRIMARY selection support via XFixes extension
- XWayland bridge - Full compatibility layer for mixed environments
Native Wayland (Direct Protocol Implementation):
- wlroots-based compositors — Sway, Hyprland, River, Wayfire with
zwp_primary_selection_unstable_v1 - KDE Plasma Wayland - Full PRIMARY selection support via native protocols
- GNOME Wayland (Mutter) - Native Wayland implementation provides PRIMARY selection support where available
- Other Wayland compositors - Full support for any compositor implementing PRIMARY selection protocols
Our native Wayland implementation (zes-wl-selection-monitor) provides:
- ✅ Direct protocol access (no
wl-copy/wl-pastesubprocess overhead) - ✅ Zero typing lag with instant selection detection
- ✅ Event-driven architecture (no polling)
- ✅ Superior responsiveness compared to standard clipboard tools
- Verify native Wayland or XWayland support is available
- Check that your compositor supports PRIMARY selection protocols
- Disable mouse replacement if needed:
edit-select config→ Option 2 - Report issues with your compositor on GitHub
Testing Coverage
This plugin has been thoroughly and heavily tested on Kitty Terminal and briefly on other popular terminals.
If you encounter issues on other terminals or platforms, please open an issue with your terminal name, OS, and display server.
Core Features (Universal)
These features work universally on X11, Wayland, and XWayland:
- ✅ Shift+Arrow keys for text selection
- ✅ Ctrl+A to select all
- ✅ Ctrl+C to copy
- ✅ Ctrl+X to cut keyboard selection
- ✅ Ctrl+V to paste
- ✅ Ctrl+Z to undo
- ✅ Ctrl+Shift+Z to redo
- ✅ Delete/Backspace to remove keyboard selection
- ✅ Type or paste to replace keyboard selection
- ✅ Mouse selection replacement (where PRIMARY selection available)
Wayland Advantage: Native implementation provides these features with zero subprocess overhead, delivering instant responsiveness and zero typing lag.
This plugin is engineered for maximum performance and responsiveness, ensuring zero lag even during intensive text editing operations. The architecture prioritizes both startup efficiency and runtime speed with careful attention to minimize overhead at every level.
Zero Runtime Overhead:
- ✅ All operations execute instantly without processing delays
- ✅ Near-zero latency response to user interactions
- ✅ No background polling or inefficient loops
One-Time Initialization:
- ✅ Plugin loads once at shell startup with optimized initialization
- ✅ Backend detection happens a single time, not on every operation
- ✅ Subsequent operations have zero initialization cost
Minimized Load Cost:
- ✅ Startup overhead is optimized and amortized across the shell session
- ✅ Plugin files are automatically compiled to
.zwc(Zsh bytecode) on first load for faster execution - ✅ One-time daemon startup eliminates repeated process creation
Minimized Runtime Cost:
- ✅ Operations execute with near-zero latency
- ✅ File-based caching avoids expensive system calls for every operation
- ✅ Direct protocol access eliminates subprocess overhead
Maximized Speed and Responsiveness:
- ✅ Instant feedback for all user interactions
- ✅ No lag between typing and completion
- ✅ Seamless clipboard operations without delays
Startup & Initialization Optimizations
One-Time Backend Detection
- Platform detection runs once at plugin load time
- Environment variables checked:
XDG_SESSION_TYPE,WAYLAND_DISPLAY,DISPLAY - Result cached and reused for entire shell session
- Eliminates decision-making overhead on every operation
Lazy Backend Loading
- Only the relevant implementation (X11 or Wayland) is loaded
- Unnecessary code paths not loaded into memory
- Reduces memory footprint and initialization time
Zsh Bytecode Compilation
- Plugin files automatically compiled to
.zwc(Zsh bytecode) on first load - Bytecode cached and reused on subsequent shell sessions
- Faster parsing and execution compared to raw Zsh scripts
- Compilation happens in background, doesn't block shell startup
One-Time Configuration Loading
- Configuration read once at startup
- No repeated file I/O on every operation
- Settings applied globally and cached
Single Daemon Initialization
- Selection monitor daemon started once when plugin loads
- Remains active for entire shell session
- Eliminates daemon startup overhead on subsequent operations
Runtime Execution Optimizations
File-Based Caching with mtime Detection
- Background daemon writes selection data to cache files
- Shell detects changes via file modification times (mtime)
- Only one
stat()syscall needed, no file content reads - mtime comparisons are instant memory comparisons
- Eliminates expensive clipboard access on every check
Direct State Caching
- Selection state stored in memory variables
- Avoids repeated clipboard queries for unchanged selections
- Early return checks prevent re-detection of active selections
- State invalidation only when actual changes detected
Periodic Health Checks (30-second interval)
- Daemon PID checked only every 30 seconds, not on every operation
- Reduces syscall frequency
- Graceful fallback if daemon dies detected quickly anyway
- Balances responsiveness with minimal overhead
Fast Path Execution
- Optimized code paths for common scenarios
- Mtime-based detection faster than content comparison
- Skips expensive operations when conditions don't apply
- Early returns eliminate unnecessary processing
No Polling Architecture
- Event-driven instead of polling-based
- Wayland: Uses native event loops from Wayland display
- X11: Uses XFixes extension events for instant notifications
- Eliminates busy-waiting and wasted CPU cycles
Custom C Daemon Architecture
Compiled Native Code Performance
- Custom C daemons compiled with aggressive optimization flags (
-O3,-march=native,-flto) - Direct system calls without Zsh interpreter overhead
- No subprocess spawning on clipboard operations
- Minimal dependencies (only system libraries)
Event-Driven Monitoring
- Wayland daemon: Connects to Wayland display server directly
- Uses
zwp_primary_selection_unstable_v1protocol for PRIMARY selection events - Uses
wl_data_deviceprotocol for clipboard events - Listens to server events instead of polling
- Uses
- X11 daemon: Uses XFixes extension for selection change notifications
- Instant event notification on PRIMARY selection changes
- No polling loops or busy-waiting
Efficient Cache Updates
- Daemon writes only when selection actually changes
- File writes ordered: primary content first, then sequence number
- Shell detects only the mtime update of sequence file
- Prevents redundant updates and wasted disk I/O
Non-Blocking I/O with Timeout
- Clipboard reads use non-blocking I/O with poll timeout
- Prevents hanging on unavailable clipboard data -Efficient resource usage during read operations
Daemon Mode Efficiency
- Single daemon supports multiple operation modes:
- Daemon mode: Continuous monitoring with periodic updates
- Oneshot mode: Single selection read without persistence
- Clipboard operations: Direct clipboard access
- Eliminates need for multiple processes
Protocol & System Call Optimizations
Direct Protocol Access (Wayland)
- Connects directly to Wayland server, no subprocess spawning
- Replaces
wl-copy/wl-pastewith direct protocol communication - Native protocol access orders of magnitude faster than subprocess overhead
- Eliminates process creation, IPC, and shell parsing
XFixes Extension (X11)
- Uses native X11 XFixes extension for selection change notifications
- Hardware-level event notification instead of polling
- Instant response to selection changes
- Minimal overhead compared to repeated
xclipinvocations
Single stat() Syscall Pattern
- Uses
zstatto get file mtime - Single filesystem call instead of full file read
- Mtime check happens in memory
- Reduces kernel context switches
Minimal File I/O
- Cache files used only for synchronization signals
- Primary selection data passed directly, not through multiple files
- Reduces disk I/O and buffer cache pressure
Platform-Specific Optimizations
X11-Specific
- Uses
xclipfor copy operations (already optimized) - XFixes extension for instant selection notifications
- No polling loops
- Direct X11 server connection
Wayland-Specific
- Native Wayland event loop for efficient monitoring
- Dual protocol support:
- PRIMARY selection via
zwp_primary_selection_unstable_v1 - Clipboard via
wl_data_devicestandard protocol
- PRIMARY selection via
- XWayland compatibility layer for hybrid environments
- Invisible daemon surface only when needed (Mutter/GNOME)
XWayland Bridge
- Seamless Wayland + XWayland application handling
- Transparent fallback to X11 protocols when needed
- No performance penalty for mixed application environments
What Was Eliminated
Eliminated Process Spawning
- ✅ No subprocess creation on clipboard operations
- ✅ No shell overhead from executing external commands
- ✅ No IPC overhead for inter-process communication
- ✅ No repeated daemon startup cycles
Eliminated Polling Loops
- ✅ Event-driven architecture replaces polling
- ✅ No busy-waiting or CPU spinning
- ✅ No wasted cycles checking conditions repeatedly
- ✅ Instant response to actual changes
Eliminated Repeated System Calls
- ✅ File mtime compared in memory, not repeated stat calls
- ✅ Backend detection happens once, not per-operation decision-making
- ✅ Configuration loaded once, no repeated file reads
- ✅ PID checks throttled to 30-second intervals
Eliminated Unnecessary Overhead
- ✅ No unnecessary selection re-detection with early returns
- ✅ No redundant state checks when conditions unchanged
- ✅ No repeated clipboard queries for same selection
- ✅ No parsing or interpretation overhead in compiled C code
Eliminated Interpreter Overhead
- ✅ Custom C daemons have no scripting language overhead
- ✅ Zsh scripts compiled to bytecode for faster execution
- ✅ Direct system calls without wrapper overhead
- ✅ Minimal dependency chain
Multi-Pane & Multi-Window Resilience
- ✅ Handles multiple panes (splits) within the same terminal window seamlessly
- ✅ Works correctly across multiple terminal windows without conflicts
- ✅ Manages multiple independent terminal instances reliably
- ✅ Maintains independent selection state per pane and window
- ✅ Resilient against edge cases and complex multi-terminal scenarios
Advanced Features & Bug Fixes
Multi-Pane Selection Independence
- Terminal pane isolation: Each pane maintains independent selection state
- PRIMARY selection clearing after operations prevents cross-pane leakage
- State variables invalidated when selection completed
- Early return checks prevent re-detection of stale selections across panes
- Result: Selecting in Pane 1 no longer affects Pane 2
Intelligent Duplicate Occurrence Handling
- Detects when selected text appears multiple times in buffer
- Shows protective prompt: "Duplicate text: place cursor inside the occurrence you want to modify"
- Prevents accidental replacement of wrong occurrence
- Only applies to mouse selections (keyboard selection is unambiguous)
- Result: Safe replacement even with repeated text patterns
Message & Display Integrity
- Proper message clearing prevents persistence between operations
- Display refresh forces correct screen state after state changes
- No message overlap or visual artifacts
- Result: Clean, responsive UI with clear feedback
Configuration Persistence
- Settings saved to
~/.config/zsh-edit-select/config - Configuration loaded once at startup, cached for session
- Changes persist across shell sessions
- Reset option restores factory defaults
- Result: User preferences maintained reliably
Environment Variable Override
ZES_FORCE_IMPLenvironment variable forces specific backend (x11 or wayland)- Overrides automatic detection when needed
- Useful for debugging or forcing compatibility
- Result: Full control over implementation selection
Memory Management & State Efficiency
Minimal Memory Footprint
- ✅ State variables use efficient types (integers for flags, strings for selections)
- ✅ Only active implementation loaded (X11 or Wayland, not both)
- ✅ Lazy daemon initialization (only started when needed)
- ✅ Cache files use temporary directory (XDG_RUNTIME_DIR, typically in RAM on modern systems)
- ✅ No memory leaks from repeated operations
State Variable Efficiency
- ✅ Reused state variables across all operations
- ✅ State validated before use to prevent stale data
- ✅ Efficient string operations for selection detection
- ✅ Integer flags for fast boolean checks (DAEMON_ACTIVE, NEW_SELECTION_EVENT)
- ✅ Floating-point for precise timing (
EPOCHREALTIMEfor selection timestamps)
Caching Strategy
- ✅ mtime-based detection avoids reading full file contents
- ✅ Memory caching of last known selections
- ✅ Invalidation on actual changes only
- ✅ No cache bloat from accumulating old data
Custom C Performance Layer
Unlike standard clipboard utilities, zsh-edit-select uses custom-built C programs specifically optimized for this plugin, providing measurable performance improvements across all platforms.
Architecture Overview:
- Selection Monitoring — Custom C daemons track PRIMARY selection changes using native protocols
- Clipboard Operations — Direct protocol implementation replaces external tools (
xclip,wl-copy,wl-paste) - File-Based Caching — Background monitors cache selection data, eliminating subprocess overhead
- Event-Driven Design — Native event loops replace polling for instant responsiveness
- Zero Typing Lag — All operations execute without process-spawn delays
Custom Daemon Monitors:
| Monitor | Platform | Protocol | Features |
|---|---|---|---|
zes-x11-selection-monitor |
X11 | XFixes extension | PRIMARY monitoring + clipboard operations |
zes-wl-selection-monitor |
Wayland | zwp_primary_selection_unstable_v1 + wl_data_device |
Native Wayland protocols |
zes-xwayland-monitor |
XWayland | X11 via XWayland bridge | Hybrid environment support + clipboard |
Key Performance Features:
- ✅ No External Dependencies — Custom monitors eliminate need for
xcliporwl-copy/wl-paste - ✅ Direct Protocol Access — Native Wayland and X11 communication without subprocess overhead
- ✅ File-Based Synchronization — Cached data read via fast file I/O instead of process spawning
- ✅ Compiled Optimization — C code compiled with aggressive
-O3+ LTO flags for maximum performance - ✅ Event-Driven Architecture — Instant notification of selection changes, zero polling
Clipboard Operation Performance Benchmarks
Our custom clipboard implementations deliver exceptional performance improvements over standard tools, verified through comprehensive benchmarking with real-world measurements.
X11 Performance (Custom Monitor vs xclip):
| Test Scenario | xclip Avg | Custom Avg | Improvement |
|---|---|---|---|
| Small text (50 chars, 100 iterations) | 4.025 ms | 2.258 ms | 43.9% faster |
| Medium text (500 chars, 50 iterations) | 4.307 ms | 2.211 ms | 48.7% faster |
| Large text (5KB, 25 iterations) | 3.949 ms | 2.310 ms | 41.5% faster |
| Very large (50KB, 10 iterations) | 4.451 ms | 2.499 ms | 43.9% faster |
| Rapid consecutive (200 iterations) | 4.206 ms | 2.321 ms | 44.8% faster |
| Overall Average | 4.187 ms | 2.320 ms | 44.6% faster |
Wayland Performance (Custom Monitor vs wl-copy):
| Test Scenario | wl-copy Avg | Custom Avg | Improvement |
|---|---|---|---|
| Small text (50 chars, 100 iterations) | 57.073 ms | 1.966 ms | 96.6% faster |
| Medium text (500 chars, 50 iterations) | 60.382 ms | 2.441 ms | 96.0% faster |
| Large text (5KB, 25 iterations) | 63.020 ms | 1.809 ms | 97.1% faster |
| Very large (50KB, 10 iterations) | 58.343 ms | 2.907 ms | 95.0% faster |
| Rapid consecutive (200 iterations) | 58.860 ms | 1.546 ms | 97.4% faster |
| Overall Average | 59.535 ms | 2.134 ms | 96.4% faster |
Performance Summary:
- X11 Improvement: Custom daemon 44.6% faster than xclip (2.320ms vs 4.187ms)
- Wayland Improvement: Custom daemon 96.4% faster than wl-copy (2.134ms vs 59.535ms)
- Best-case Latency:
- X11: 2.211ms minimum (48.7% better than xclip's 4.307ms)
- Wayland: 1.152ms minimum (97.7% better than wl-copy's 49.066ms)
- Consistency: Performance maintained across all payload sizes (50 bytes to 50KB)
- Memory: Equal or better footprint than external tools
Real-World Impact:
- X11 Operations: Sub-2.5ms average latency means instant clipboard operations
- Wayland Operations: Sub-2.2ms average latency (27x faster than wl-copy)
- Paste Operations: Immediate data retrieval from daemon cache
- Selection Detection: Near-zero latency for mouse selection changes
- High-Frequency Usage: No performance degradation during rapid copy/paste workflows
Why Wayland Shows Exceptional Gains:
- wl-copy's high process spawn overhead (~60ms per operation) makes subprocess-based approaches extremely slow
- Our persistent daemon architecture eliminates all subprocess calls
- Direct Wayland protocol access provides native performance
- Result: 96.4% improvement (27x performance multiplier) on Wayland vs 44.6% improvement on X11
Technical Implementation:
- Custom monitors implement full clipboard protocol support
- Background server maintains clipboard ownership (auto-cleanup after 50 seconds)
- Graceful fallback to standard tools if custom monitors unavailable
- X11 achieves 44.6% performance gains, Wayland achieves 96.4% performance gains
Benchmark Methodology: Tests conducted using high-precision C benchmarking tools with
clock_gettime(CLOCK_MONOTONIC)for nanosecond accuracy. All measurements include real-world overhead (process spawning, IPC, wait time). Results represent actual wall-clock time improvements users experience during interactive use.
Run Benchmarks Yourself: You can verify these performance claims by running the benchmark suite yourself. See the
assets/benchmarks/directory for comprehensive C-based benchmarking tools and detailed instructions. The suite compares our custom implementations against standard tools (xclip,wl-copy/wl-paste) with precise timing and multiple test scenarios.
Selection Detection Optimizations
Eliminated Subprocess Overhead:
Traditional clipboard tools spawn a new process for every selection query. Our architecture eliminates this entirely:
Before (Traditional Approach):
Every mouse selection detection:
1. Fork subprocess for xclip/wl-paste → ~4.3ms overhead
2. Parse output
3. Clean up process
Total: Multiple subprocess calls per operation
After (Custom C Daemon):
One-time daemon startup:
1. Daemon monitors selection changes → 0ms per check
2. Writes updates to cache file
3. Shell reads cached data via file I/O → <0.1ms
Total: Zero subprocess calls during normal operation
Performance Impact:
- Traditional: ~4.3ms per clipboard query (subprocess overhead)
- Custom Daemon: ~0.1ms per check (file mtime comparison)
- Improvement: ~97% reduction in selection detection latency
Additional Optimizations:
- ✅
_zes_sync_selection_state()— Reads daemon cache before selection detection - ✅ Early return checks — Avoids redundant operations when selection unchanged
- ✅ Memory caching — Previous selection cached in memory variables
- ✅ mtime-based detection — Single
stat()call instead of full file reads
Cut Operation Optimization:
Recent optimization reversed operation order in edit-select::cut-region():
- Old: Delete text → Copy to clipboard (perceived as slow)
- New: Copy to clipboard → Delete text (feels instant)
Users perceive the operation complete when data enters clipboard, making the operation feel instant even though total execution time is unchanged.
Platform-Specific Implementation Details
X11 Implementation:
- Monitor:
zes-x11-selection-monitorwith full clipboard support - Protocols: XFixes extension for events, X11 CLIPBOARD atom
- Operations:
--get-clipboard,--copy-clipboard,--clear-primary - Performance: 44.6% faster than
xclipacross all operations - Fallback: Graceful degradation to
xclipif monitor unavailable
Native Wayland Implementation:
- Monitor:
zes-wl-selection-monitorwith native protocol support - Protocols:
- PRIMARY:
zwp_primary_selection_unstable_v1 - Clipboard:
wl_data_devicestandard protocol
- PRIMARY:
- Operations: Direct protocol calls, no external tools needed
- Performance: Zero subprocess overhead, instant responsiveness
- Fallback: Optional
wl-copy/wl-pasteif monitor unavailable
XWayland Implementation:
- Monitor:
zes-xwayland-monitorfor hybrid environments - Protocols: X11 XFixes through XWayland bridge
- Operations: Full clipboard support matching X11 performance
- Performance: Unified architecture with X11-level optimizations
- Compatibility: Seamless support for mixed X11/Wayland applications
Unified Performance:
All platforms now achieve:
- ✅ Zero external tool dependencies for core functionality
- ✅ 44.6% faster on X11, 96.4% faster on Wayland vs standard clipboard tools
- ✅ Consistent sub-2.5ms latency for clipboard operations (X11: 2.3ms avg, Wayland: 2.1ms avg)
- ✅ Event-driven selection monitoring with instant notification
- ✅ X11: 44.6% faster — Custom daemon (2.320ms) vs xclip (4.187ms)
- ✅ Wayland: 96.4% faster — Custom daemon (2.134ms) vs wl-copy (59.535ms)
- ✅ 97% reduction in selection detection latency — Eliminated subprocess overhead
- ✅ Zero typing lag — No process spawning during normal editing operations
- ✅ Sub-2.5ms clipboard latency — Operations complete faster than human perception threshold
- ✅ Consistent performance — Maintained across all payload sizes and platforms
- ✅ Scalable architecture — No degradation during high-frequency usage
- ✅ Minimal startup overhead — One-time initialization, zero per-operation cost
- ✅ Event-driven responsiveness — Instant reaction to selection changes
Technical Excellence: Every component optimized for maximum performance—from compiler flags (
-O3,-march=native,-flto) to protocol selection to operation ordering. The result is a plugin that feels instant and responsive in every interaction, with measurable proof of performance superiority.
| Key Combination | Action |
|---|---|
| Ctrl + ← | Move cursor one word left |
| Ctrl + → | Move cursor one word right |
| Key Combination | Action |
|---|---|
| Shift + ← | Select one character left |
| Shift + → | Select one character right |
| Shift + ↑ | Select one line up |
| Shift + ↓ | Select one line down |
| Shift + Home | Select to line start |
| Shift + End | Select to line end |
| Shift + Ctrl + ← | Select to word start |
| Shift + Ctrl + → | Select to word end |
| Ctrl + A | Select all text |
| Key Combination | Action |
|---|---|
| Ctrl + C | Copy selected text |
| Ctrl + X | Cut selected text |
| Ctrl + V | Paste (replaces selection if any) |
| Ctrl + Z | Undo last edit |
| Ctrl + Shift + Z | Redo last undone edit |
| Delete/Backspace | Delete selected text |
| Any character | Replace selected text if any |
Shift selection doesn't work
Solution: Configure your terminal to pass Shift key sequences. See Terminal Setup.
Verify: Run cat and press Shift+Left. You should see an escape sequence like ^[[1;2D.
Clipboard operations don't work
Solution: Install the required clipboard tool:
- Wayland:
wl-clipboard - X11:
xclip
Verify: Run wl-copy <<< "test" or xclip -i <<< "test" to check if the tool works.
Mouse replacement not working
Solution:
- Check if mouse replacement is enabled:
edit-select config→ View Configuration - Ensure your terminal supports mouse selection (most do)
- Try selecting text with your mouse, then typing—it should replace the selection
If this does not work for you, it is often due to platform limitations or compatibility issues with the PRIMARY selection. See Platform Compatibility for more details.
Ctrl+C doesn't copy
Solution: Configure your terminal to remap Ctrl+C. See Step 1: Configure Copy Shortcut at the Terminal Setup section.
Alternative: Use Ctrl+Shift+C for copying, or configure a custom keybinding with edit-select config, or
use the 'Without Terminal Remapping' method if your terminal doesn't support key remapping.
Configuration wizard doesn't launch
Symptoms: Running edit-select config shows "file not found" error
Solution:
- Check the plugin was installed correctly
- Verify
edit-select-wizard.zshexists in the plugin directory - Ensure the file has read permissions:
chmod +r ~/.oh-my-zsh/custom/plugins/zsh-edit-select/edit-select-wizard.zsh - Try sourcing your
.zshrcagain:source ~/.zshrc - Fully close and reopen your terminal
Delete key not removing mouse-selected text
If the Delete key does not remove mouse-selected text, ensure your ~/.zshrc does not contain a line that
forces the Delete key to the default handler such as:
bindkey '^[[3~' delete-charThat line will override the plugin's binding for the Delete key and prevent zsh-edit-select from handling
mouse selections correctly.
Solution: Remove or comment out that line and reload your shell:
source ~/.zshrcManual Build (Optional)
The plugin compiles monitors automatically on first use. To manually build them:
X11 Monitor:
cd ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-edit-select/impl-x11/backends/x11
makeWayland Monitor:
cd ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-edit-select/impl-wayland/backends/wayland
makeXWayland Monitor:
cd ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-edit-select/impl-wayland/backends/x11
makeTo clean/rebuild:
make clean && makeNote: The plugin will automatically detect your display server and compile the appropriate monitor daemon on first shell startup. The Makefiles require:
- X11 builds:
libX11andlibXfixesdevelopment headers/libraries- Wayland builds:
wayland-clientdevelopment headers,wayland-scanner, andwayland-protocolsIf compilation fails, the plugin will fall back to using external clipboard tools (
xclipfor X11,wl-clipboardfor Wayland).
Build Optimization:
The default Makefiles already compile with aggressive optimization flags for maximum runtime performance:
| Flag | Purpose |
|---|---|
-O3 |
Maximum compiler optimization level |
-march=native |
CPU-specific instruction set (SSE, AVX, etc.) |
-mtune=native |
CPU-specific scheduling optimizations |
-flto |
Link-time optimization across compilation units |
-ffunction-sections -fdata-sections |
Granular dead code elimination |
-Wl,--gc-sections |
Remove unused functions/data at link time |
-fomit-frame-pointer |
Free up a register for better performance |
-fno-plt |
Eliminate PLT indirection for faster library calls |
-s |
Strip symbols for smaller production binaries |
Important:
-march=nativeproduces binaries optimized for the CPU you're building on. These binaries may not run correctly on different CPU architectures. For distributed builds, replace-march=native -mtune=nativewith a portable baseline like-march=x86-64-v2.
This project is licensed under the MIT License.
-
This project Began as a fork (Michael-Matta1/zsh-shift-select) of jirutka/zsh-shift-select
-
The fork was started to add the ability to copy selected text, because the jirutka/zsh-shift-select plugin only supported deleting selected text and did not offer copying by default. This feature was frequently requested by the community, as shown in issue #8 and issue #10.
-
Since then, the project has evolved with its own new features, enhancements, bug fixes, design improvements, and a fully changed codebase, and it now provides a full editor-like experience.
-
-
The primary-selection-unstable-v1.xml protocol definition is Copyright © 2015, 2016 Red Hat.
-
Michael-Matta1/dev-dotfiles — Dotfiles showcasing the plugin with Kitty, VS Code, and Zsh.
-
Zsh ZLE shift selection — StackOverflow — Q&A on Shift-based selection in ZLE.
-
Zsh Line Editor Documentation — Official ZLE widgets and keybindings reference.
