Fish 3.2 adds undo to the command-line editor
Undo and redo make command editing recoverable in fish 3.2. The release also gives path configuration an explicit helper and removes input buffering that delayed useful pipeline output.
A command line is an editing buffer before it becomes a process. Completion and history search make that buffer easier to construct, but an accidental edit still needs a way back. Fish 3.2.0, released on March 1, adds undo and redo to the command-line editor and the completion pager's search field.
The default bindings are Control+Z for undo and Alt+/ for redo. The change addresses an editing operation, not an executed command's effects. Recovering text before execution is a different capability from reversing what a program has already done. The distinction matters in a shell because both activities can otherwise be described loosely as undoing a command.
I am drawn to fish's emphasis on a usable interactive environment without extensive configuration. Undo fits that preference directly. A shell that helps construct a command should also support correcting the construction process, especially when completion or an editing command changes more text than intended.
Undo joins the editor's existing operations
The binding reference shipped with 3.2 lists undo and redo as special input functions. These functions revert or repeat recent command-line edits. They belong to the same binding system used for cursor movement, history search, completion, and other editor operations.
That placement makes the capability configurable without requiring a shell script to reconstruct old text. bind can invoke a special input function directly. The documentation distinguishes those functions from ordinary shell commands and says a binding must use one category or the other, rather than combining them in a single command sequence.
The binding system also has modes. Each binding applies to a mode, with default as the ordinary mode. Vi-style editing uses this mechanism to interpret keys differently according to the current mode. Introducing undo as an input function gives it a place in that existing editor model instead of making it a separate executable.
User bindings take precedence over preset bindings, according to the same reference. A user can therefore adapt the key choices without rewriting the complete preset set. The release's default shortcuts describe the out-of-the-box interface, while the editor operation remains available through the binding mechanism.
Terminal encoding still constrains which shortcuts can be distinguished. The binding documentation explains that some control-key combinations are identical to other characters at the terminal interface, and that Alt commonly produces an escape sequence. These are properties of the input environment, not evidence that fish can observe every physical key combination independently.
The practical improvement is recovery within the editor's own information model. History search retrieves previous commands. Undo instead concerns edits to the current input. The two operations support different tasks even when the line being edited originated in command history.
Path configuration gets an operation with defined repetition behavior
The same release introduces fish_add_path. Its versioned documentation explains that it normally adds directories to fish_user_paths, which contributes to command lookup through PATH. It can also modify PATH directly when given --path.
The helper addresses a concrete configuration problem. Startup configuration runs repeatedly across shell sessions. A naive command that prepends a directory every time can accumulate duplicates. fish_add_path checks for an existing component and leaves it where it is by default, so repeating the same request does not repeatedly insert it.
For an existing directory, the basic request names the directory to add. The helper applies its default duplicate and ordering rules, so the same request remains meaningful when repeated. This example uses the conventional local binary directory, assuming it exists.
fish_add_path ~/.local/bin
The documentation permits using this in config.fish or calling it interactively. Its default use of universal variables, when the variable does not already exist, can preserve the path for future shells. That means an interactive invocation can establish persistent configuration without requiring the same command to be added to a startup file as well.
Normalization has defined limits. The helper removes irrelevant trailing slashes and makes relative paths absolute, but it does not resolve symbolic links. A nonexistent directory is ignored. These rules make the command more specific than a general-purpose variable prepend, and they explain why its result depends on the filesystem at the time of invocation.
The helper also avoids resetting the variable when no component is new. The documentation points out that this avoids triggering variable handlers unnecessarily. Repeated configuration therefore concerns more than duplicate display text. Reassigning a variable can cause other shell behavior, so a no-change operation has an observable benefit.
Order remains part of path policy
Duplicate avoidance does not automatically mean an existing directory moves to the front. The default preserves its position. The --move option explicitly requests relocation to the position where the helper would otherwise insert it. That distinction preserves an established lookup order unless the caller asks to change it.
Appending also has two meanings depending on the target variable. --append with fish_user_paths appends within that variable, but those entries still precede system paths. Appending directly to the complete PATH requires --path as well. The documentation gives a fallback-directory example using the combined -aP options.
These details matter because command lookup is ordered. Adding a directory that contains a command already available elsewhere can change which program executes. A helper that states whether it prepends, appends, or moves an entry lets configuration express that choice. Deduplication alone would leave the precedence question unanswered.
I prefer this kind of helper to accumulating small variations of path-editing code. It gives a common configuration task a documented contract, including repeated invocation and existing-entry behavior. The value is in those semantics, rather than the number of characters saved in a startup file.
Streaming builtins remove an unrelated source of waiting
Fish 3.2 also changes builtin buffering so output can appear before all input has been consumed. The release notes use string processing in a pipeline as the example. Previously, a builtin could wait for the upstream command to finish before producing any output, which is a poor fit for a command that intentionally keeps running.
The documented example places a string filter after a continuing source of messages. Quoting the match pattern passes it to the string builtin without asking the shell to expand it as a filename pattern first.
dmesg -w | string match '*usb*'
Here the upstream command follows kernel messages instead of producing a finite file and exiting immediately. A filter that requires end-of-input before emitting matches cannot provide a useful live view. Allowing builtin output while input is still arriving makes the filter usable in that streaming arrangement.
This is a separate mechanism from speeding up a finite computation. A pipeline can spend little CPU time and still appear unresponsive if a stage waits for an end-of-file that will not arrive during normal use. The release changes when output becomes available, which is the relevant property for an interactive stream.
Other interface changes address terminal geometry. Overwide prompts now truncate instead of being replaced by a generic prompt, and ambiguous completions can appear after one Tab even when candidates share a common prefix. Both changes retain useful information during ordinary interaction. A prompt can also inspect COLUMNS if it needs a more deliberate response to terminal width.
Interactive convenience remains distinct from shell compatibility
The release adds a guide for Bash users that states fish's intentional lack of POSIX compatibility. Its examples explain command substitutions with parentheses, variables managed through set, and the absence of automatic word splitting on variable expansion. The guide describes a different scripting model rather than presenting every difference as a shortcut.
That is relevant to adopting the new conveniences. Using fish interactively does not make a Bash script valid fish code. The path helper belongs in fish configuration, and its universal-variable behavior belongs to fish's environment model. Treating it as a spelling change for a POSIX export would miss the persistence and duplicate-handling rules.
The release also changes fish --no-execute so it no longer complains about unknown commands or unmatched wildcards that may be valid only at runtime. This makes it a more useful static syntax check. Syntax checking and execution-time command availability are different questions, just as undoing input and undoing a program's effects are different operations. Fish 3.2 gives the editor recovery while retaining those boundaries in the scripting and configuration tools around it.