FISH-RELEASENOTES(1)

🐟💖 FISH-RELEASENOTES(1) 💖🐟

okay so bestie, this is the release-notes page for fish-shell — that's the manual name, FISH-RELEASENOTES(1), and it's literally the entire receipts file of every fish drop, newest first. Every fix, every flag, every "we broke it in 4.3.2 and we're so sorry" is in here. no cap, it's a lot, so hydrate first 🥤


🎀 FISH 4.9.3 (RELEASED SEPTEMBER 08, 2026)

another macOS moment, bestie 😭 this one fixes a thing where dead keys were acting up — like, for example, the two-key sequence ",space on the US International keyboard layout would incorrectly insert space (#12979 <https://github.com/fish-shell/fish-shell/issues/12979>).


🦋 FISH 4.9.2 (RELEASED SEPTEMBER 05, 2026)

this one just corrects the fix for macOS terminals from 4.9.1 (#12973 <https://github.com/fish-shell/fish-shell/issues/12973>)


🌸 FISH 4.9.1 (RELEASED SEPTEMBER 04, 2026)

so fish 4.9.0 had some problems and this release fixes the following ones, periodt:


✨ FISH 4.9.0 (RELEASED SEPTEMBER 03, 2026) ✨

🔥 Interactive improvements 🔥

🧚 Scripting improvements 🧚

💀 Regression fixes: 💀


🌈 FISH 4.8.1 (RELEASED JULY 14, 2026) 🌈

🔥 Interactive improvements 🔥

💀 Regression fixes: 💀


👑 FISH 4.8.0 (RELEASED JUNE 24, 2026) 👑

⭐ Notable improvements and fixes ⭐

🚫 Deprecations and removed features 🚫

  • Builtin complete's <> --command and --path options no longer unescape their argument.

🔥 Interactive improvements 🔥

🧚 Scripting improvements 🧚

🍓 Other improvements 🍓

  • fish no longer creates the __fish_initialized universal variable on startup. if you don't expect to need to downgrade to earlier versions, you can remove it with set --erase __fish_initialized. this means that fish now only creates universal variables if instructed by the user. main character energy: no unsolicited variables 💅

🧑‍💻 For distributors and developers 🧑‍💻

  • With the exception of the $CMAKE_INSTALL_PREFIX/share/fish/man directory, fish no longer installs files to $CMAKE_INSTALL_PREFIX/share/fish. in particular, this means that both $CMAKE_INSTALL_PREFIX/share/fish/completions and $CMAKE_INSTALL_PREFIX/share/fish/functions should no longer exist. these directories have been ignored since fish 4.2. if another package installs fish scripts there, they should be corrected to install to extra_completionsdir (typically $CMAKE_INSTALL_PREFIX/share/fish/vendor_completions.d), extra_functionsdir (typically $CMAKE_INSTALL_PREFIX/share/fish/vendor_functions.d) or extra_confdir (typically $CMAKE_INSTALL_PREFIX/share/fish/vendor_functions.d) instead. see also the output of:
for var in completions functions conf; pkgconf fish --variable="$var"dir; end.

💀 Regression fixes: 💀


🫶 FISH 4.7.1 (RELEASED MAY 08, 2026) 🫶

this release fixes a regression in 4.7.0 that caused the web config (fish_config) to fail to start (#12717 <https://github.com/fish-shell/fish-shell/issues/12717>). the vibes are restored 💖

🦋 FISH 4.7.0 (RELEASED MAY 05, 2026)

💅 Deprecations and removed features

  • The default theme — like, all the fish_color_* variables — is no longer set in non-interactive shells. Bestie. It's gone. Non-interactive only, okay? Don't panic if your prompt still slays.

✨ Interactive improvements

  • prompt_pwd now strips control characters. Clean. Fresh. Iconic.
  • Repaint events (the ones triggered by changes to color variables, or by event handlers running commandline -f repaint) no longer reset the completion pager and other transient UI states (#12683). The pager finally keeps its main character energy. 👑
  • fish_color_valid_path now respects background and underline colors (#12622). Yes queen, layer those styles.
  • funced will no longer lose your work if there are parse errors multiple times without new changes to the file. Your six-paragraph function is safe, bestie 😭
  • Fixed a case where directory completions were sorted in a genuinely surprising order (#12695). Weird order = fixed. Slay.
  • When you're at the command token, the alt-o binding will now open read-only files too (#12671). Read-only files, your time has come.
  • Private mode in-memory history (set fish_history) is no longer shared with the builtin read (#12662). Secrets stay secret, periodt. 🙈

🫶 Other improvements

  • History is no longer corrupted with NUL bytes when fish receives SIGTERM or SIGHUP (#10300). Bye bye weird little ghost bytes 💀
  • fish_update_completions now handles groff \X'...' device control escapes, which fixes completion generation for man pages produced by help2man 1.50 and later (such as coreutils 9.10). Niche? Yes. Gorgeous? Also yes.
  • Removing history entries via the web-based config is more intuitive now. Genuinely less of a scavenger hunt.
  • If XDG_DATA_DIRS is empty, the default value is assumed — which means fish will now also use configuration from paths like $PREFIX/share/fish/vendor_completions.d (#11349). Free completions, no cap.
  • Some internal file descriptors were moved to number 10 or higher, so there's less risk of them clashing with the ones you use in your own scripts. Personal space: respected ✨
  • The wording of error messages has been made consistent, especially for builtin subcommands (#12556). One voice, one vibe.

🧚 For distributors and developers

  • When the default global config directory ($PREFIX/etc/fish) exists but has been overridden via -DCMAKE_INSTALL_SYSCONFDIR, fish will now respect that override (#10748). Respect the override, always.
  • build_tools/update_translations.fish has been replaced by cargo xtask gettext {check,new,update} (#12676). Out with the old script, in with the cargo.
  • New: cargo xtask shellcheck to lint shell-scripts. Lint your scripts, bestie, your future self will thank you.

😭 Regression fixes:

  • (from 4.6) Vi mode dl (#12461).
  • (from 4.6) Backspace after newline (#12583).
  • (from 4.3.3) Long options were spuriously completed after typing short options (85e76ba3561).
  • (from 3.2) nosuchcommand || echo hello executes the right hand side again (#12654). The right hand side said "not me being skipped" and honestly, fair.

🌈 FISH 4.6.0 (RELEASED MARCH 28, 2026)

👑 Notable improvements and fixes

  • New Spanish translations (#12489). ¡Vamos! 🎉
  • New Japanese translations (#12499). やった!🎉

💅 Deprecations and removed features

  • The default width for emoji is switched from 1 to 2, which improves life for people connecting to old systems from modern desktops. If you're on an old desktop and notice lines containing emoji are misaligned, you can set $fish_emoji_width back to 1 (#12562). The emoji got wider. That's the whole thing. 💖

✨ Interactive improvements

  • The tab completion pager now left-justifies the description of each column (#12546). Alignment? Immaculate.
  • fish now supports the SHELL_PROMPT_PREFIX, SHELL_PROMPT_SUFFIX, and SHELL_WELCOME environment variables. The prefix and suffix are automatically prepended and appended to the left prompt, and the welcome message is displayed on startup after the greeting. These variables are set by systemd's run0 for example (#10924). Systemd said "let me customize your prompt" and fish said "bet".

🔥 Improved terminal support

  • set_color is able to turn off italics, reverse mode, strikethrough and underline individually (e.g. --italics=off). Granular control, we love to see it.
  • set_color learned the foreground (--foreground or -f) and reset (--reset) options. New options just dropped.
  • An error caused by slow terminal responses at macOS startup has been addressed (#12571). macOS startup said "sorry for the delay" and fish said "not anymore".

🫶 Other improvements

  • Signals like SIGWINCH (as sent on terminal resize) no longer interrupt builtin output (#12496). Resize your window in peace.
  • For compatibility with Bash, fish now accepts |& as an alternate spelling of &|, for piping both standard output and standard error (#11516). Two spellings, same slay.
  • fish_indent now preserves comments and newlines immediately preceding a brace block ({ }) (#12505). Your comments survived. Victory.
  • A crash when suspending certain pipelines with Ctrl+Z has been fixed (#12301).

🧚 For distributors and developers

  • cargo xtask subcommands no longer panic on test failures. They're handling their emotions now.

😭 Regression fixes:

  • (from 4.5.0) Intermediate ⏎ artifact when redrawing prompt (#12476).
  • (from 4.4.0) history honors explicitly specified --color= again (#12512).
  • (from 4.4.0) Vi mode dl and dh (#12461).
  • (from 4.3.0) Error completing of commands starting with - (#12522).

🌸 FISH 4.5.0 (RELEASED FEBRUARY 17, 2026)

This is mostly a patch release for Vi mode regressions in 4.4.0, but other minor behavior changes are included as well. Lowkey a glow-up patch. 💅

✨ Interactive improvements

  • Ctrl+L no longer cancels history search (#12436). Clear the screen, keep the search.
  • History search cursor positioning now works correctly with characters of arbitrary width. Wide characters deserved better and now they have it.

💅 Deprecations and removed features

  • fish no longer reads the terminfo database to alter behaviour based on the TERM environment variable, and does not depend on ncurses or terminfo. The ignore-terminfo feature flag, introduced and enabled by default in fish 4.1, is now permanently enabled. fish may no longer work correctly on Data General Dasher D220 and Wyse WY-350 terminals, but should continue to work on all known terminal emulators released in the 21st century. If your terminal predates the 21st century, bestie, I'm so sorry 🫶 terminfo is gone-gone.

😭 Regression fixes:

  • (from 4.4.0) Vi mode d,f key binding did not work (#12417).
  • (from 4.4.0) Vi mode c,w key binding wrongly deleted trailing spaces (#12443).
  • (from 4.4.0) Vi mode crash on c,i,w after accepting autosuggestion (#12430).
  • (from 4.4.0) fish_vi_key_bindings called with a mode argument produced an error (#12413).
  • (from 4.0.0) Build on Illumos (#12410).

🦋 FISH 4.4.0 (RELEASED FEBRUARY 03, 2026)

💅 Deprecations and removed features

  • The default fossil prompt has been disabled (#12342). It's not you, fossil prompt, it's the vibes.

✨ Interactive improvements

  • The bind builtin lists mappings from all modes if --mode is not provided (#12214). No more "where are my other bindings" moments.
  • Line-wise autosuggestions that don't start a command are no longer shown (739b82c34db, 58e7a50de8a). If it's not a command, it's not invited.
  • Builtin history now assumes that PAGER supports ANSI color sequences. Color is the default assumption now, periodt.
  • fish now clears the terminal's FLUSHO flag when acquiring control of the terminal, which fixes an issue caused by pressing Ctrl+O on macOS (#12304). macOS found a bug, fish handled it 💅

👑 New or improved bindings

  • Vi mode word movements (w, W, e, and E) are now largely in line with Vim. The only exception is that underscores are treated as word separators (#12269). Mostly Vim, slightly fish. Iykyk.
  • New special input functions to support these movements: forward-word-vi, kill-word-vi, forward-bigword-vi, kill-bigword-vi, forward-word-end, backward-word-end, forward-bigword-end, backward-bigword-end, kill-a-word, kill-inner-word, kill-a-bigword, and kill-inner-bigword. That's twelve functions and every one of them ate. 🔥
  • Vi mode key bindings now support counts for movement and deletion commands (e.g. d3w or 3l), via a new operator mode (#2192). Counts! In my Vi mode! Finally.
  • New catppuccin-* color themes. The themes are here and they are gorgeous 🎀

🔥 Improved terminal support

  • set_color learned the strikethrough (--strikethrough or -s) modifier. Strike through your text with style.

🧚 For distributors and developers

  • The CMake option WITH_GETTEXT has been renamed to WITH_MESSAGE_LOCALIZATION, to reflect that it toggles localization independently of the backend used in the implementation. New name, same job, clearer energy.
  • New cargo xtask commands can replace some CMake workflows.

😭 Regression fixes:

  • (from 4.1.0) Crash when autosuggesting Unicode characters with nontrivial lowercase mapping (#12326, 78f4541116e).
  • (from 4.3.0) Glitch on read --prompt-str "" (#12296). An empty prompt should just be empty, bestie. Empty. Not glitchy.

💅 FISH 4.3.3 (RELEASED JANUARY 07, 2026) 💅

Okay so this one is a little cleanup arc bestie — it patches up the following problems that were identified in fish 4.3.0:

  • So rude: selecting a completion could insert only part of the token (#12249). Fixed ✨
  • A glitch moment with soft-wrapped autosuggestions and fish_right_prompt (#12255) — fixed.
  • Spurious echo in tmux when you're typing a command really fast (#12261) — fixed, you can be fast again.
  • The tomorrow theme was always using the light variant (#12266) — fixed 🌞
  • fish_config theme choose sometimes wasn't shadowing themes set by e.g. webconfig (#12278) — fixed.
  • The sample prompts and themes are correctly installed now (#12241) 🎀
  • Last line of command output could be hidden when missing a newline (#12246) — fixed, no more sneaky disappearing lines.

Other improvements include:

  • The abbr, bind, complete, functions, history and type commands now support a --color option to control syntax highlighting in their output. Valid values are auto (default), always, or never. Slay, options for days.
  • Existing file paths in redirection targets such as > file.txt are now highlighted using fish_color_valid_path, which is basically fish tapping you on the shoulder like "bestie that file is gonna get clobbered" (#12260). Iconic behavior honestly.

🌸 FISH 4.3.2 (RELEASED DECEMBER 30, 2025) 🌸

This release fixes the following problems identified in 4.3.0:

  • Pre-built macOS packages failed to start due to a Malformed Mach-O file error (#12224). Rough. Fixed.
  • extra_functionsdir (usually vendor_functions.d) and friends were not being used (#12226) — now they are, as intended.
  • The sample config file ~/.config/fish/config.fish/ and config directories ~/.config/fish/conf.d/, ~/.config/fish/completions/ and ~/.config/fish/functions/ were being recreated on every startup instead of only the first time fish runs on a system (#12230). Fixed — one and done now.
  • Spurious echo of ^[[I in some scenarios (#12232) — fixed, thank goodness.
  • Infinite prompt redraw loop on some prompts (#12233) — fixed, the loop has been cancelled 🔁💀
  • So the removal of pre-built HTML docs from tarballs revealed that cross compilation is broken, because we use ${CMAKE_BINARY_DIR}/fish_indent for building HTML docs. As a workaround, the new CMake build option FISH_INDENT_FOR_BUILDING_DOCS can be set to the path of a runnable fish_indent binary. Very "it's giving workaround" of us but it works.

🦋 FISH 4.3.1 (RELEASED DECEMBER 28, 2025) 🦋

This release fixes the following problem identified in 4.3.0:

  • Possible crash after expanding an abbreviation (#12223). Yikes! Fixed, no cap.

👑 FISH 4.3.0 (RELEASED DECEMBER 28, 2025) 👑

🎀 Deprecations and removed features 🎀

  • fish no longer sets user-facing universal variables by default, which makes the configuration easier to understand. Specifically, the fish_color_*, fish_pager_color_* and fish_key_bindings variables are now set in the global scope by default. After upgrading to 4.3.0, fish will (once and never again) migrate these universals to globals set at startup in the ~/.config/fish/conf.d/fish_frozen_theme.fish and ~/.config/fish/conf.d/fish_frozen_key_bindings.fish files. We suggest that you delete those files and set your theme in ~/.config/fish/config.fish. The way that's the cleaner setup… obsessed.
    • You can still configure fish to propagate theme changes instantly; there's an example in the docs (see syntax-highlighting-instant-update).
    • You can still opt into storing color variables in the universal scope via fish_config theme save — though unlike fish_config theme choose, it does not support dynamic theme switching based on the terminal's color theme (more on that below).
  • In addition to setting the variables which are explicitly defined in the given theme, fish_config theme choose now clears only color variables that were set by earlier invocations of a fish_config theme choose command (which is how fish's default theme is set).

⭐ Scripting improvements ⭐

  • New status language command lets you show and modify language settings for fish messages without having to modify environment variables. iykyk, that's so much nicer.
  • When using a noninteractive fish instance to compute completions, commandline --cursor works as expected instead of throwing an error (#11993) 🫶
  • fish_trace can now be set to all to also trace execution of key bindings, event handlers as well as prompt and title functions.

🌈 Interactive improvements 🌈

  • When typing immediately after starting fish, the first prompt is now rendered correctly. No more "why is my prompt weird for 0.2 seconds" era.
  • Completion accuracy was improved for file paths containing = or : (#5363) 🔥
  • Prefix-matching completions are now shown even if they don't match the case typed by the user (#7944).
  • On Cygwin/MSYS, command name completion will favor the non-exe name (foo) unless the user started typing the extension.
  • When using the exe name (foo.exe), fish will use the description and completions for foo if there are none for foo.exe.
  • Autosuggestions now also show soft-wrapped portions (#12045) — no more mysterious missing ghost text 💀

💜 New or improved bindings 💜

  • Ctrl+W (backward-kill-path-component) also deletes escaped spaces now (#2016).
  • New special input functions backward-path-component, forward-path-component and kill-path-component (#12127). Path navigation is having a moment.

🧚 Improved terminal support 🧚

  • Themes can now be made color-theme-aware by including both [light] and [dark] sections in the theme file. Some default themes have been made color-theme-aware, meaning they dynamically adjust as your terminal's background color switches between light and dark colors (#11580). It's giving adaptive 💅
  • The working directory is now reported on every fresh prompt (via OSC 7), fixing scenarios where a child process (like ssh) left behind a stale working directory (#12191).
  • OSC 133 prompt markers now also mark the prompt end, which improves shell integration with terminals like iTerm2 (#11837).
  • Operating-system-specific key bindings are now decided based on the terminal's host OS (status terminal-os).
  • New feature flag omit-term-workarounds can be turned on to prevent fish from trying to work around some incompatible terminals.

🍓 For distributors and developers 🍓

  • Tarballs no longer contain prebuilt documentation, so building and installing documentation requires Sphinx. To avoid users accidentally losing docs, the BUILD_DOCS and INSTALL_DOCS configuration options have been replaced with a new WITH_DOCS option.
  • fish_key_reader and fish_indent are now installed as hardlinks to fish, to save some space. Frugal queen behavior 💖

🙈 Regression fixes: 🙈

  • (from 4.1.0) Crash on incorrectly-set color variables (#12078).
  • (from 4.1.0) Crash when autosuggesting Unicode characters with nontrivial lowercase mapping.
  • (from 4.2.0) Incorrect emoji width computation on macOS.
  • (from 4.2.0) Mouse clicks and Ctrl+L edge cases in multiline command lines (#12121).
  • (from 4.2.0) Completions for Git remote names on some non-glibc systems.
  • (from 4.2.0) Expansion of ~$USER.

🎀 FISH 4.2.1 (RELEASED NOVEMBER 13, 2025) 🎀

This release fixes the following problems identified in 4.2.0:

  • When building from a tarball without Sphinx (that is, with -DBUILD_DOCS=OFF or when sphinx-build is not found), builtin man pages and help files were missing, which has been fixed (#12052). Your docs are safe 🫶
  • fish_config's theme selector (the "colors" tab) was broken, which has been fixed (#12053). The colors tab is back and it's thriving 🌈

🌸 FISH 4.2.0 (RELEASED NOVEMBER 10, 2025) 🌸

✨ Notable improvements and fixes ✨

  • History-based autosuggestions now include multi-line commands. Bestie, your messy three-line pipelines are finally getting remembered properly 💖
  • A transient prompt containing more lines than the final prompt will now be cleared properly (#11875). No more ghost lines haunting your scrollback ✨
  • Taiwanese Chinese translations have been added 🎀
  • French translations have been supplemented (#11842) 🥖

💀 Deprecations and removed features 💀

  • fish now assumes UTF-8 for character encoding even if the system does not have a UTF-8 locale. Input bytes which are not valid UTF-8 are still round-tripped correctly. So like, file paths using legacy encodings can still be used, but may be rendered differently on the command line. Not broken, just dressed different 💅
  • On systems where no multi-byte locale is available, fish will no longer fall back to using ASCII replacements for Unicode characters such as "…". It's giving "no more fake ... pretending to be …" 🙈

🦋 Interactive improvements 🦋

  • The title of the terminal tab can now be set separately from the window title by defining the fish_tab_title function (#2692). Two titles, two vibes, zero conflict 👑
  • fish now hides the portion of a multiline prompt that is scrolled out of view due to a huge command line. This prevents duplicate lines after repainting with a partially visible prompt (#11911). Main character prompt energy, no doppelgängers 🌈
  • fish_config prompt's choose and save subcommands have been taught to reset fish_mode_prompt in addition to the other prompt functions (#11937). It learned a new trick, we're obsessed ✨
  • fish no longer force-disables mouse capture (DECSET/DECRST 1000), so you can use those commands to let mouse clicks move the cursor or select completion items (#4918). Mouse girlies, this one's for you 🫶
  • The alt-p binding no longer adds a redundant space to the command line. Tiny fix, huge relief 😭
  • When run as a login shell on macOS, fish now sets MANPATH correctly when that variable was already present in the environment (#10684) 🍓
  • A Windows-specific case of the web-based config failing to launch has been fixed (#11805) 💜
  • A MSYS2-specific workaround for Konsole and WezTerm has been added, to prevent them from using the wrong working directory when opening new tabs (#11981) 🧚

🔥 For distributors and developers 🔥

  • Release tags and source code tarballs are GPG-signed again (#11996). Signatures are back, we love a security glow-up 💅
  • Documentation in release tarballs is now built with the latest version of Sphinx, which means that pre-built man pages include OSC 8 hyperlinks ✨ (clickable links in your terminal, iykyk)
  • The Sphinx dependency is now specified in pyproject.toml, which allows you to use uv to provide Sphinx for building documentation (e.g. uv run cargo install --path .) 🌸
  • The minimum supported Rust version (MSRV) has been updated to 1.85 🦀
  • The standalone build mode has been made the default. This means that the files in $CMAKE_INSTALL_PREFIX/share/fish will not be used anymore, except for HTML docs. As a result, future upgrades will no longer break running shells if one of fish's internal helper functions has been changed in the updated version. For now, the data files are still installed redundantly, to prevent upgrades from breaking already-running shells (#11921). To reverse this change (which should not be necessary), patch out the embed-data feature from cmake/Rust.cmake. This option will be removed in future.
Ok so, that reversal thing? "should not be necessary" is doing a lot of heavy lifting there. Consider it a last resort, bestie 🙈
  • OpenBSD 7.8 revealed an issue with fish's approach for displaying builtin man pages, which has been fixed 🐡

🎀 Regression fixes 🎀

  • (from 4.1.0) Fix the web-based config for Python 3.9 and older (#12039).
  • (from 4.1.0) Correct wrong terminal modes set by fish -c 'read; cat (#12024).
  • (from 4.1.0) On VTE-based terminals, stop redrawing the prompt on resize again, to avoid glitches.
  • (from 4.1.0) On MSYS2, fix saving/loading of universal variables (#11948).
  • (from 4.1.0) Fix error using man for the commands ! . : [ { (#11955).
  • (from 4.1.0) Fix build issues on illumos systems (#11982).
  • (from 4.1.0) Fix crash on invalid function command (#11912).
  • (from 4.0.0) Fix build on SPARC and MIPS Linux by disabling SIGSTKFLT.
  • (from 4.0.0) Fix crash when passing negative PIDs to builtin wait (#11929).
  • (from 4.0.0) On Linux, fix status fish-path output when fish has been reinstalled since it was started.

💖 FISH 4.1.2 (RELEASED OCTOBER 7, 2025) 💖

This release fixes the following regressions identified in 4.1.0:

  • Fixed spurious error output when completing remote file paths for scp (#11860).
  • Fixed the alt-l binding not formatting ls output correctly (one entry per line, no colors) (#11888).
  • Fixed an issue where focus events (currently only enabled in tmux) would cause multiline prompts to be redrawn in the wrong line (#11870).
  • Stopped printing output that would cause a glitch on old versions of Midnight Commander (#11869).
  • Added a fix for some configurations of Zellij where escape key processing was delayed (#11868).
  • Fixed a case where the web-based configuration tool would generate invalid configuration (#11861).
  • Fixed a case where pasting into fish -c read would fail with a noisy error (#11836).
  • Fixed a case where upgrading fish would break old versions of fish that were still running.

In general, fish still needs to be restarted after it is upgraded, except for standalone builds.

Just restart fish, bestie. It's the "have you tried turning it off and on again" of shells 💀

🦋 FISH 4.1.1 (RELEASED SEPTEMBER 30, 2025) 🦋

This release fixes the following regressions identified in 4.1.0:

  • Many of our new Chinese translations were more confusing than helpful; they have been fixed or removed (#11833).

Note that you can work around this type of issue by configuring fish's message localization: if your environment contains something like LANG=zh_CN.UTF-8, you can use set -g LC_MESSAGES en to use English messages inside fish. This will not affect fish's child processes unless LC_MESSAGES was already exported.

  • Some fish_config subcommands for showing prompts and themes had been broken in standalone Linux builds (those using the embed-data cargo feature), which has been fixed (#11832).
  • On Windows Terminal, we observed an issue where fish would fail to read the terminal's response to our new startup queries, causing noticeable lags and a misleading error message. A workaround has been added (#11841).
  • A WezTerm issue breaking shifted key input has resurfaced on some versions of WezTerm; our workaround has been extended to cover all versions for now (#11204). WezTerm said "not today" and fish said "bet" 😤
  • Fixed a crash in the web-based configuration tool when using the new underline styles (#11840).

👑 FISH 4.1.0 (RELEASED SEPTEMBER 27, 2025) 👑

✨ Notable improvements and fixes ✨

  • Compound commands (begin; echo 1; echo 2; end) can now be written using braces ({ echo1; echo 2 }), like in other shells. We're so back 🎀
  • fish now supports transient prompts: if fish_transient_prompt is set to 1, fish will reexecute prompt functions with the --final-rendering argument before running a commandline (#11153).
  • Tab completion results are truncated up to the common directory path, instead of somewhere inside that path. E.g. if you complete "share/functions", and it includes the files "foo.fish" and "bar.fish", the completion pager will now show "…/foo.fish" and "…/bar.fish" (#11250). Cleaner, prettier, less chaotic 💅
  • Self-installing builds as created by e.g. cargo install no longer install other files, see below.
  • Our gettext-based message-localization has been reworked, adding translations to self-installing builds; see below.

💀 Deprecations and removed features 💀

  • set_color --background=COLOR no longer implicitly activates bold mode. If your theme is stored in universal variables (the historical default), some bold formatting might be lost. To fix this, we suggest updating to the latest version of our theme, to explicitly activate bold mode, for example use fish_config theme save "fish default".
Ngl this one can sneak up on you — your theme suddenly goes lowkey flat and you're like "who did this" 😭 It's the bold-mode thing. Go re-save your theme.
  • {echo,echo} or { echo, echo } are no longer interpreted as brace expansion tokens but as compound commands. Different meaning, same punctuation, keep up bestie ✨
  • Terminfo-style key names (bind -k nul) are no longer supported. They had been superseded by fish's own key names since 4.0 (#11342).
  • fish no longer reads the terminfo database, so its behavior is generally no longer affected by the TERM environment variable (#11344). For the time being, this change can be reversed via the ignore-terminfo feature flag. To do so, run the following once and restart fish:
set -Ua fish_features no-ignore-terminfo
  • The --install option when fish is built as self-installing is removed, see below.
  • set_color ff0000 now spits out real 24-bit RGB true-color, even when COLORTERM isn't set. Not the vibe? Flip fish_term24bit to 0 and it'll chill (#11372).
  • fish now requires the terminal to answer queries for the Primary Device Attribute. For now you can undo that with a feature flag — run set -Ua fish_features no-query-term once and restart fish.
  • GNU screen users 💀 may hit minor glitches when starting fish. Sorry bestie.

🧚 Scripting improvements 🧚

  • The argparse builtin got a glow-up and a half — there's a whole section about it below, iykyk.
  • string pad now has a -C/--center option. Centered text era 💅
  • psub now lets you combine --suffix with --fifo (#11729).
  • read learned the --tokenize-raw option, which tokenizes without quote removal (#11084).

✨ Interactive improvements ✨

  • Autosuggestions now show up in multi-line command lines too 🎀. Just like ctrl+r, they only operate on the current line.
  • Autosuggestions used to skip multi-line command lines from history entirely — now they include the individual lines from multi-line command lines. Obsessed.
  • The history pager search now preserves ordering between ctrl+s forward searches and ctrl+r backward searches.
  • Instead of highlighting stuff by flashing all the text to the left of the cursor, fish now flashes the thing that's actually relevant:
    • a failing history token search (alt+.) flashes the associated token
    • failing tab-completion flashes the to-be-completed token (#11050)
    • deleting an autosuggestion (shift+delete) flashes the suggestion
    • every other scenario flashes the full command line
  • Pasted commands now get stripped of any $ command prefixes, which makes pasting code snippets so much easier 🫶
  • Builtin help options (like abbr --help) now call man directly, which means variables like MANWIDTH are actually respected (#11786).
  • funced now edits copied functions directly, instead of editing the file where function --copy was invoked (#11614).
  • Added a simple fish_jj_prompt that cuts down visual noise in the prompt inside Jujutsu repositories that are colocated with Git. Clean prompt, clear mind ✨

🌈 New or improved bindings 🌈

  • On non-macOS systems, alt+left, alt+right, alt+backspace and alt+delete no longer operate on punctuation-delimited words — they operate on whole arguments, which can include special characters like / and quoted spaces. On macOS, the corresponding ctrl-prefixed keys do the whole-argument thing. Word operations are still there via the other respective modifier, just like in most web browsers. Best of both, fr.
  • ctrl+z (undo) after executing a command now restores the previous cursor position instead of yeeting the cursor to the end of the command line.
  • The alt+s binding will now also use run0 if it's available.
  • Mouse support got a little something something 🐭: the OSC 133 prompt marking feature has learned about kitty's click_events=1 flag, which means you can move fish's cursor by clicking in the command line and select pager items (#10932).
  • Before clearing the screen and redrawing, ctrl+l now pushes all the text above the prompt into the terminal's scrollback, via a brand-new special input function scrollback-push. For compatibility with terminals that don't implement ECMA-48's SCROLL UP command, this function is only used if the terminal advertises support for it via XTGETTCAP. No cap, scrollback preservation is iconic.
  • Vi mode learned ctrl+a (increment) and ctrl+x (decrement) (#11570). Main character energy 🔥

🦋 Completions 🦋

  • git completions now show the remote URL as the description when completing remotes. Chef's kiss.
  • systemctl completions no longer print escape codes if SYSTEMD_COLORS happens to be set (#11465). Thank god.
  • Added and improved many completion scripts, notably tmux.

💜 Improved terminal support 💜

  • Support for double, curly, dotted and dashed underlines, usable in fish_color_* variables and the set_color builtin (#10957). Underline aesthetics have been upgraded, periodt.
  • Underlines can now be colored independently of the text (#7619). Yes, really.
  • New documentation page Terminal Compatibility (also reachable via man fish-terminal-compatibility) lists the terminal control sequences fish uses.

🍓 Other improvements 🍓

  • Updated the Chinese and German translations 💖
  • fish_indent --dump-parse-tree now emits simple metrics about the tree, including its memory consumption.
  • We added some tools to improve development workflows, for example build_tools/{check,update_translations,release}.sh and tests/test_driver.py. In conjunction with cargo, these enable almost all day-to-day development tasks without using CMake. Slay.

👑 For distributors 👑

  • Builtin commands that support the --help option now require the man program. The direct dependency on mandoc and nroff has been removed.
  • fish no longer uses gettext MO files — see below. If you've got use cases that are incompatible with our new approach, please let us know.
  • The fish_indent and fish_key_reader programs are now also available as builtins. If fish is invoked via e.g. a symlink with one of these names, it'll act like the given tool (i.e. it's a multi-call binary). This allows truly distributing fish as a single file (#10876). One file to rule them all 😭
  • The CMake build configuration has been simplified and no longer second-guesses rustup. It'll run rustc and cargo via PATH or in ~/.cargo/bin/. If that doesn't match your setup, set the Rust_COMPILER and Rust_CARGO CMake variables (#11328).
  • Cygwin support has been reintroduced, since Rust gained a Cygwin target (#11238).
  • CMake 3.15 is now required.

🎀 Changes to self-installing builds 🎀

The self-installing build type that was introduced in fish 4.0 has been changed (#11143). So now, when fish is built with embedded data, it just reads the data straight from its own binary — or writes it out to temporary files when necessary — instead of needing an installation step on start. Which means you can now build fish as a single file and copy it to any system with a compatible CPU architecture, including as a different user, without extracting any files at all. Like before, this is the default when building via cargo, and disabled when building via CMake. For packagers, we still recommend CMake.

Note bestie: when fish is built like this, the __fish_data_dir variable will be empty, because that directory no longer has any meaning. You generally shouldn't need these files. For example, if you want to make sure completions for "foo" are loaded, use complete -C"foo " >/dev/null instead. The raw files are still exposed via status subcommands, mainly for fish's internal use — but you can also use them as a last resort.

Remaining benefits of a full installation (as currently done by CMake) are:

  • man pages like fish(1) in standard locations, easily accessible from outside fish.
  • a local copy of the HTML documentation, typically accessed via the help function. In builds with embedded data, help will redirect to e.g. https://fishshell.com/docs/current/
  • fish_indent and fish_key_reader as separate files, making them easily accessible outside fish
  • an (empty) /etc/fish/config.fish as well as empty directories /etc/fish/{functions,completions,conf.d}
  • $PREFIX/share/pkgconfig/fish.pc, which defines directories for configuration-snippets, like vendor_completions.d

💅 Changes to gettext localization 💅

We replaced several parts of the gettext functionality with custom implementations (#11726). Most notably, message extraction — which should now work reliably — and the runtime implementation, where we no longer dynamically link to gettext but instead use our own implementation, whose behavior is similar to GNU gettext, with some minor deviations. Our implementation now fully respects fish variables, so locale variables don't have to be exported for fish localizations to work. They still have to be exported to inform other programs about language preferences, though. The LANGUAGE environment variable is now treated as a path variable, meaning it's an implicitly colon-separated list. While we no longer have any runtime dependency on gettext, we still need gettext tools for building — most notably msgfmt. When building without msgfmt available, localization will not work with the resulting executable. Localization data is no longer sourced at runtime from MO files on the file system, but instead built into the executable. This is always done, independently of the other data embedding, so all fish executables will have access to all message catalogs, regardless of the state of the file system. Disabling our new localize-messages cargo feature will cause fish to be built without localization support. CMake builds can continue to use the WITH_GETTEXT option, with the same semantics as the localize-messages feature. The current implementation doesn't provide any configuration options for controlling which language catalogs get built into the executable (other than disabling them all). As a workaround, you can delete files in the po directory before building to exclude unwanted languages.

🌸 Changes to the argparse builtin 🌸

  • argparse now saves recognised options, including option-arguments, in argv_opts, which lets them be forwarded to other commands (#6466). Game changer.
  • argparse options can now be marked to be deleted from argv_opts (by adding a & at the end of the option spec, before a ! if present). There's now also a corresponding -d / --delete option to fish_opt.
  • argparse --ignore-unknown now yeets the known short options that come before the unknown ones in a group — so when you parse -abc and a is known but b isn't, argv gets -bc in it. Cleanup icon behavior ✨
  • argparse now has a -u / --move-unknown option, which is basically --ignore-unknown's chill cousin: it keeps the unknown options sitting in argv instead of tossing them 💖
  • argparse now has a -S / --strict-longopts option that forbids abbreviating long options or passing them with a single dash (so like, if there's a long option called foo, then --fo and --foo won't match it). No more sneaky shortcuts, bestie 🚫
  • argparse now has a -U / --unknown-arguments option so you can specify how to parse the arguments that belong to unknown options 👑
  • argparse now lets you specify options that take multiple optional values by using =* in the option spec (#8432). And fish_opt got updated to support those too, by using --multiple-vals together with -o / --optional-val — and -m is now acceptable as an abbreviation for --multiple-vals 🎀
  • fish_opt no longer makes you give a short flag name when you're defining options, as long as you give it a long flag name with more than one character. Short-flag-free era fr fr 🦋
  • argparse option specifiers for long-only options can now start with /, which means you can define long options that are just a single letter. Because of that, the --long-only option to fish_opt is now no longer necessary and is deprecated (iykyk, it's giving legacy) 🙈
  • fish_opt now has a -v / --validate option, where you hand it a fish script to validate the values of the option. Validation slay 💅

🧚 FISH 4.0.9 (RELEASED SEPTEMBER 27, 2025) 🧚

This release fixes:

  • a regression in 4.0.6 that was making shifted keys not get inserted on some terminals (#11813). not the shifted keys 😭
  • a regression in 4.0.6 that made the build fail on systems where char is unsigned (#11804). build girlies, we're so back 🫶
  • a regression in 4.0.0 causing a crash on an invalid bg invocation. no more crashing on nonsense, periodt 💀

🌸 FISH 4.0.8 (RELEASED SEPTEMBER 18, 2025) 🌸

This release fixes a regression in 4.0.6 that caused user bindings to be shadowed by either fish's or a plugin's bindings (#11803). your bindings are YOUR bindings, no cap ✨


🎀 FISH 4.0.6 (RELEASED SEPTEMBER 12, 2025) 🎀

This release of fish fixes a number of issues identified in fish 4.0.2:

  • fish now properly inherits $PATH under Windows WSL2 (#11354). WSL2 besties, you're seen 💖
  • Remote filesystems are detected properly again on non-Linux systems. detection queen 👑
  • the printf builtin no longer miscalculates width of multi-byte characters (#11412). multi-byte characters are getting the respect they deserve 🦋
  • For many years, fish has been "relocatable" — it was possible to move the entire CMAKE_INSTALL_PREFIX and fish would use paths relative to its binary. Only gettext locale paths were still determined purely at compile time, which has been fixed. relocatable icon behavior, finally complete 🎀
  • the commandline builtin failed to print the commandline set by a commandline -C invocation, which broke some completion scripts. This has been corrected (#11423). completion scripts were suffering fr fr 😭
  • To work around terminals that fail to parse Operating System Command (OSC) sequences, a temporary feature flag has been added. It allows you to disable prompt marking (OSC 133) by running (once) set -Ua fish_features no-mark-prompt and restarting fish (#11749). temporary workaround era, note the word temporary 💅
  • The routines to save history and universal variables have seen some robustness improvements. history and universal variables said "we're stronger now" ⭐
  • builtin status current-command no longer prints a trailing blank line. no more stray blank line, we cheered 🌈
  • A crash displaying multi-line quoted command substitutions has been fixed (#11444). multi-line quoted command substitutions are safe now 🫶
  • Commands like set fish_complete_path ... accidentally disabled completion autoloading, which has been corrected. autoloading, you're back on your feet bestie 💜
  • nmcli completions have been fixed to query network information dynamically instead of only when completing the first time. dynamic querying is the moment 🔥
  • Git completions no longer print an error when no git-foo executable is in PATH. silence is golden 🧚
  • Custom completions like complete foo -l long -xa ... that use the output of commandline -t. on a command-line like foo --long= have been invalidated by a change in 4.0; the completion scripts have been adjusted accordingly (#11508). adjusted, validated, slayed ✨
  • Some completions were misinterpreted, which caused garbage to be displayed in the completion list. This has been fixed. no more garbage in the completion list, we love to see it 🙈
  • fish no longer interprets invalid control sequences from the terminal as if they were alt-[ or alt-o key strokes. invalid sequences stay invalid 💀
  • bind has been taught about the printscreen and menu keys. new keys, new knowledge 🎀
  • alt-delete now deletes the word right of the cursor. rightward word deletion is so real 🌸
  • ctrl-alt-h erases the last word again (#11548). it's giving "back by popular demand" 👑
  • alt-left alt-right were misinterpreted because they send unexpected sequences on some terminals; a workaround has been added. (#11479). terminals were being weird, workaround said "I gotchu" 🫶
  • Key bindings like bind shift-A are no longer accepted; use bind shift-a or bind A. lowercase era, the shift-A girlies must adapt 💅
  • Key bindings like bind shift-a take precedence over bind A when the key event included the shift modifier. precedence hierarchy, very main character ⭐
  • Bindings using shift with non-ASCII letters (such as ctrl-shift-ä) are now supported. non-ASCII girlies rise 🌈
  • Bindings with modifiers such as bind ctrl-w work again on non-Latin keyboard layouts such as a Russian one. This is implemented by allowing key events such as ctrl-ц to match bindings of the corresponding Latin key, using the kitty keyboard protocol's base layout key (#11520). international keyboard slay 🦋
  • Vi mode: The cursor position after pasting via p has been corrected. cursor said "my placement is accurate now" ✨
  • Vi mode: Trying to replace the last character via r no longer replaces the last-but-one character (#11484). it replaces the right one, as it should 💖

🦋 FISH 4.0.2 (RELEASED APRIL 20, 2025) 🦋

This release of fish fixes a number of issues identified in fish 4.0.1:

  • Completions are quoted, rather than backslash-escaped, only if the completion is unambiguous. Continuing to edit the token is therefore easier (#11271). This changes the behavior introduced in 4.0.0 where all completions were quoted. so much easier to keep typing, thank u 🫶
  • The warning when the terminfo database can't be found has been downgraded to a log message. fish will act as if the terminal behaves like xterm-256color, which is correct for the vast majority of cases (#11277, #11290). less yelling, more logging 🧚
  • Key combinations using the super (Windows/command) key can now (actually) be bound using the super- prefix (#11217). This was listed in the release notes for 4.0.1 but did not work correctly. it actually works this time, we promise 😭
  • function is stricter about argument parsing, rather than allowing additional parameters to be silently ignored (#11295). no more silent ignoring, we're being honest 💅
  • Using parentheses in the test builtin works correctly, following a regression in 4.0.0 where they were not recognized (#11387). parentheses are back, iconic ✨
  • delete in Vi mode when Num Lock is active will work correctly (#11303). Num Lock girlies, this one's for you 👑
  • Abbreviations cannot alter the command-line contents, preventing a crash (#11324). abbreviations knew too much, now they don't 💀
  • Improvements to various completions, including new completions for wl-randr (#11301), performance improvements for cargo completions by avoiding network requests (#11347), and other improvements for btrfs (#11320), cryptsetup (#11315), git (#11319, #11322, #11323), jj (#11046), and systemd-analyze (#11314). completion glow-up era 🔥
  • The Mercurial (hg) prompt can handle working directories that contain an embedded newline, rather than producing errors (#11348). newlines in dirs, handled 🌸
  • A number of crashes have been fixed. Triggers include prompts containing backspace characters (#11280), history pager search (#11355), invalid UTF-8 in read (#11383), and the kill-selection binding (#11367). crash-free era, fingers crossed 🫶
  • A race condition in the test suite has been fixed (#11254), and a test for fish versioning relaxed to support downstream distributors' modifications (#11173). test suite said "no more racing" ⭐
  • Small improvements to the documentation (#11264, #11329, #11361). docs got a little glow-up too 💖

💖 FISH 4.0.1 (RELEASED MARCH 12, 2025) 💖

okay bestie, this release of fish includes the following improvements compared to fish 4.0.0, and it’s lowkey a little cleanup era ✨

set -g fish_color_search_match --reverse

🦋 FISH 4.0.0 (RELEASED FEBRUARY 27, 2025) 🦋

bestie. this is the big one. fish's core code has been ported from C++ to Rust (#9512, https://github.com/fish-shell/fish-shell/issues/9512). This means a large change in dependencies and how to build fish. However, there should be no direct impact on users. Packagers should see the For Distributors section at the end. iconic rewrite behavior, honestly 👑

✨ Notable backwards-incompatible changes ✨

  • new bind notation — As part of a larger binding rework, bind gained a new key notation. In most cases the old notation should keep working, but in rare cases you may have to change a bind invocation to use the new notation. See below for details.
  • ctrl-c behavior — ctrl-c now calls a new bind function called clear-commandline. The old behavior, which leaves a "^C" marker, is available as cancel-commandline (#10935, https://github.com/fish-shell/fish-shell/issues/10935).
  • random values — random will produce different values from previous versions of fish when used with the same seed, and will work more sensibly with small seed numbers. The seed was never guaranteed to give the same result across systems, so we do not expect this to have a large impact (#9593, https://github.com/fish-shell/fish-shell/issues/9593).
  • command-position variables — Variables in command position that expand to a subcommand keyword are now forbidden to fix a likely user error. For example, set editor command emacs; $editor is no longer allowed (#10249, https://github.com/fish-shell/fish-shell/issues/10249).
  • functions --handlers order — functions --handlers will now list handlers in a different order. Now it is definition order, first to last, where before it was last to first. This was never specifically defined, and we recommend not relying on a specific order (#9944, https://github.com/fish-shell/fish-shell/issues/9944).
  • qmark-noglob on by default — The qmark-noglob feature, introduced in fish 3.0, is enabled by default. That means ? will no longer act as a single-character glob. You can, for the time being, turn it back on by adding no-qmark-noglob to fish_features and restarting fish:
set -Ua fish_features no-qmark-noglob

The flag will eventually be made read-only, making it impossible to turn off. so enjoy the toggle while it lasts 🎀

  • garbage on weird terminals — Terminals that fail to ignore unrecognized OSC or CSI sequences may display garbage. We know cool-retro-term and emacs' ansi-term are affected, but most mainstream terminals are not.
  • Windows $PATH behavior — fish no longer searches directories from the Windows system/user $PATH environment variable for Linux executables. To execute Linux binaries by name (i.e. not with a relative or absolute path) from a Windows folder, make sure the /mnt/c/... path is explicitly added to $fish_user_paths and not just automatically appended to $PATH by wsl.exe (#10506, https://github.com/fish-shell/fish-shell/issues/10506).
  • WSL 1 background jobs — Under Microsoft Windows Subsystem for Linux 1 (not WSL 2), backgrounded jobs that have not been disowned and do not terminate on their own after a SIGHUP + SIGCONT sequence will be explicitly killed by fish on exit (after the usual prompt to close or disown them) to work around a WSL 1 deficiency that sees backgrounded processes that run into SIGTTOU remain in a suspended state indefinitely (#5263, https://github.com/fish-shell/fish-shell/issues/5263). The workaround is to explicitly disown processes you wish to outlive the shell session.
bestie this one is very “read the whole sentence before you panic” energy, but the details matter fr fr 🫶

🌸 Notable improvements and fixes 🌸

Additionally, bind now supports a human-readable syntax in addition to byte sequences. This includes modifier names, and names for keys like enter and backspace. For example

  • bind up 'do something' binds the up-arrow key instead of a two-key sequence ("u" and then "p")
  • bind ctrl-x,alt-c 'do something' binds a sequence of two keys.

Any key argument that starts with an ASCII control character (like \e or \cX) or is up to 3 characters long, not a named key, and does not contain , or - will be interpreted in the old syntax to keep compatibility for the majority of bindings.

Keyboard protocols can be turned off by disabling the "keyboard-protocols" feature flag:

set -Ua fish_features no-keyboard-protocols

This is a temporary measure to work around buggy terminals (#11056, https://github.com/fish-shell/fish-shell/issues/11056), which appear to be relatively rare. Use this if something like "=0" or "=5u" appears in your commandline mysteriously.

  • self-installing binary — fish can now be built as a self-installing binary (#10367, https://github.com/fish-shell/fish-shell/issues/10367). That means it can be easily built on one system and copied to another, where it can extract supporting files. To do this, run:
cargo install --path . # in a clone of the fish repository
# or `cargo build --release` and copy target/release/fish{,_indent,_key_reader} wherever you want

The first time it runs interactively, it will extract all the data files to ~/.local/share/fish/install/. A specific path can be used for the data files with fish --install=PATH To uninstall, remove the fish binaries and that directory.

This build system is experimental; the main build system, using cmake, remains the recommended approach for packaging and installation to a prefix. experimental but cute, yk?

abbr --add --command git back 'reset --hard HEAD^'

…will expand "back" to reset --hard HEAD^, but only when the command is git (issue #9411). iykyk 💅


🚫 Deprecations and removed features 🚫

  • commandline --tokenize (short option -o) is deprecated bestie, it's been replaced by commandline --tokens-expanded (short option -x) which expands variables and other shell syntax — so you literally don't need to reach for eval <> in your completion scripts anymore (issue #10212). slay.
  • Two brand-new feature flags, ok so listen:
    • remove-percent-self (peep it via status features) disables PID expansion of %self, which has been supplanted by $fish_pid (issue #10262).
    • test-require-arg disables test's one-argument mode. That means test -n without an additional argument will return false, test -z will keep returning true. Any other option without an argument, anything that is not an option and no argument will be an error. This also goes for [, test's alternate name. This is a frequent source of confusion and so we are breaking with POSIX explicitly in this regard. In addition to the feature flag, there is a debug category "deprecated-test". Running fish with fish -d deprecated-test will show warnings whenever a test invocation that would change is used (issue #10365).

These can be enabled with:

set -Ua fish_features remove-percent-self test-require-arg

We intend to enable them by default in future, and after that eventually make them read-only. 👑

  • Specifying key names as terminfo names (using the bind -k syntax) is deprecated and may be removed in a future version. heads up 🫶
  • When a terminal pastes text into fish using bracketed paste, fish used to switch to a special paste bind mode. This bind mode has been removed. The behavior on paste is no longer configurable. periodt.
  • When an interactive fish is stopped or terminated by a signal that cannot be caught (SIGSTOP or SIGKILL), it may leave the terminal in a state where keypresses with modifiers are sent as CSI u sequences, instead of traditional control characters or escape sequences that are recognized by Readline and compatible programs, such as bash and python. If this happens, you can use the reset command from ncurses to restore the terminal state. no cap, go hit that. 😭
  • fish_key_reader --verbose no longer shows timing information.
  • Terminal information is no longer read from hashed terminfo databases, or termcap databases (issue #10269). The vast majority of systems use a non-hashed terminfo database, which is still supported. so like, you're probably fine bestie.
  • source returns an error if used without a filename or pipe/redirection (issue #10774).

✨ Scripting improvements ✨

  • for loops will no longer remember local variables from the previous iteration (issue #10525). fresh start every loop, we love that for us 🦋
  • A new history append subcommand appends a command to the history, without executing it (issue #4506). iconic.
  • A new redirection: <? /path/to/file will try opening the file as input, and if it doesn't succeed silently uses /dev/null instead. This can help with checks like test -f /path/to/file; and string replace foo bar < /path/to/file (issue #10387). lowkey genius.
  • A new option commandline --tokens-raw prints a list of tokens without any unescaping (issue #10212).
  • A new option commandline --showing-suggestion tests whether an autosuggestion is currently displayed (issue #10586).
  • functions and type now show that a function was copied and its source, rather than solely Defined interactively (issue #6575). transparency era 💖
  • Stack trace now shows line numbers for copied functions (issue #6575).
  • foo & && bar is now a syntax error, like in other shells (issue #9911). bestie you can't do both, pick a lane 💅
  • if -e foo; end now prints a more accurate error (issue #10000).
  • cd into a directory that is not readable but accessible (permissions --x) is now possible (issue #10432).
  • An integer overflow in string repeat leading to a near-infinite loop has been fixed (issue #9899). genuinely terrifying, glad that's over 🙈
  • string shorten behaves better in the presence of non-printable characters, including fixing an integer overflow that shortened strings more than intended (issue #9854).
  • string pad no longer allows non-printable characters as padding (issue #9854).
  • string repeat now allows omission of -n when the first argument is an integer (issue #10282).
  • string match and replace have a new --max-matches option to return as soon as the specified number of matches have been identified, which can improve performance in scripts (issue #10587). speed queen ⭐
  • functions --handlers-type caller-exit once again lists functions defined as function --on-job-exit caller, rather than them being listed by functions --handlers-type process-exit.
  • A new set --no-event option sets or erases variables without triggering a variable event. This can be useful to change a variable in an event handler (issue #10480). sneaky but make it valid 🧚
  • Commas in command substitution output are no longer used as separators in brace expansion, preventing a surprising expansion in some cases (issue #5048).
  • Universal variables can now store strings containing invalid UTF-8 (issue #10313).
  • A new path basename -E option that causes it to return the basename ("filename" with the directory prefix removed) with the final extension (if any) also removed. This is a shorter version of path change-extension "" (path basename $foo) (issue #10521).
  • A new math --scale-mode option to select truncate, round, floor, ceiling as you wish; the default value is truncate. (issue #9117).
  • random is now less strict about its arguments, allowing a start larger or equal to the end. (issue #10879) it's giving chill vibes.
  • function --argument-names now produces an error if a read-only variable name is used, rather than simply ignoring it (issue #10842). we love an honest error 💀
  • Tilde expansion in braces (that is, {~,}) works correctly (issue #10610).

🎀 Interactive improvements 🎀

  • Autosuggestions were sometimes not shown after recalling a line from history, which has been fixed (issue #10287).
  • Up-arrow search matches — which are highlighted in reverse colors — are no longer syntax-highlighted, to fix bad contrast with the search match highlighting. aesthetic fix fr.
  • Command abbreviations (those with --position command or without a --position) now also expand after decorators like command (issue #10396).
  • Abbreviations now expand after process separators like ; and |. This fixes a regression in version 3.6 (issue #9730). we're so back 🔥
  • When exporting interactively defined functions (using type, functions or funcsave) the function body is now indented, to match the interactive command line editor (issue #8603). pretty AND functional 🌸
  • Ctrl+x (fish_clipboard_copy) on multiline commands now includes indentation (issue #10437).
  • Ctrl+v (fish_clipboard_paste) now strips ASCII control characters from the pasted text. This is consistent with normal keyboard input (issue #5274).
  • When a command like fg %2 fails to find the given job, it no longer behaves as if no job spec was given (issue #9835).
  • Redirection in command position like >echo is now highlighted as error (issue #8877). bestie that's not a thing, and fish will tell you 💀
  • fish_vi_cursor now works properly inside the prompt created by builtin read (issue #10088).
  • fish no longer fails to open a FIFO if interrupted by a terminal resize signal (issue #10250).
  • read --help and friends no longer ignore redirections. This fixes a regression in version 3.1 (issue #10274).
  • Measuring a command with time now considers the time taken for command substitution (issue #9100). accurate timing, we stan ⏱️
  • fish_add_path now automatically enables verbose mode when used interactively (in the command line), in an effort to be clearer about what it does (issue #10532).
  • fish no longer adopts TTY modes of failed commands (issue #10603).
  • complete -e cmd now prevents autoloading completions for cmd (issue #6716).
  • fish's default color scheme no longer uses the color "blue", as it has bad contrast against the background in a few terminal's default palettes (issues #10758, #10786). The color scheme will not be upgraded for existing installs. If you want, you should select it again via fish_config. like, go pick it again manually bestie, sorry 🫶
  • Command lines which are larger than the terminal are now displayed correctly, instead of multiple blank lines being displayed (issue #7296). no more mysterious void 🙈
  • Prompts using external commands won't spiral into an infinite loop anymore if that command crashes — no more runaway prompt of doom, bestie (#9796 — https://github.com/fish-shell/fish-shell/issues/9796). 🌀
  • The output of jobs shows - for jobs that share the same process group ID as the fish process, instead of -2 (#10833 — https://github.com/fish-shell/fish-shell/issues/10833). Lowkey a tiny detail but it matters 💅
  • Job expansion (that's the %1 syntax, iykyk) works properly for jobs that are a mixture of external commands and functions (#10832 — https://github.com/fish-shell/fish-shell/issues/10832). 🫶
  • Command lines that have more lines than the terminal can hold are now displayed and edited correctly — no more visual chaos (#10827 — https://github.com/fish-shell/fish-shell/issues/10827). ✨
  • Functions that have been erased are no longer highlighted as valid commands (#10866 — https://github.com/fish-shell/fish-shell/issues/10866). Bye ghost commands 👋
  • not, time, and variable assignments — that is, not time a=b env — are correctly recognized as valid syntax (#10890 — https://github.com/fish-shell/fish-shell/issues/10890). It's giving "grammar police but make it syntax highlighting" 🎀
  • The Web-based configuration removes old right-hand-side prompts again, fixing a regression in fish 3.4.0 (#10675 — https://github.com/fish-shell/fish-shell/issues/10675). We love a comeback 💖
  • Further protection against programs which crash and leave the terminal in an inconsistent state (#10834 — https://github.com/fish-shell/fish-shell/issues/10834, #11038 — https://github.com/fish-shell/fish-shell/issues/11038). Your terminal stays cute even when things go wrong 🧚
  • A workaround for git being very slow on macOS has been applied, improving performance after a fresh boot (#10535 — https://github.com/fish-shell/fish-shell/issues/10535). Git said "let me take my time" and fish said absolutely not ⚡

✨ New or improved bindings ✨

  • When the cursor is on a command that resolves to an executable script, alt+o will now open that script in your editor (#10266 — https://github.com/fish-shell/fish-shell/issues/10266). Main character energy: jump straight into the source 🔥
  • During up-arrow history search, shift+delete deletes the current search item and moves to the next older item. Previously this was only supported in the history pager. 🗑️
  • shift+delete will also remove the currently-displayed autosuggestion from history, and remove it as a suggestion. Double duty, periodt 💅
  • Ctrl+Z (also known as Ctrl+shift+z) is now bound to redo. Undo's sibling finally got a key 🎀
  • Some improvements to the alt+e binding, the one that edits the command line in an external editor:
    • The editor's cursor position is copied back to fish. This is currently supported for Vim and Kakoune. 🎯
    • Cursor position synchronization is only supported for a set of known editors, which are now also detected in aliases which use complete --wraps. For example, use complete --wraps my-vim vim to synchronize cursors when EDITOR=my-vim. iykyk 🪄
    • Multiline commands are indented before being sent to the editor, which matches how they are displayed in fish. Consistent vibes only 📐
  • The ...-path-component bindings, like backward-kill-path-component, now treat # as part of a path component (#10271 — https://github.com/fish-shell/fish-shell/issues/10271). # is a path girlie now 🦋
  • Bindings like alt+l that print output in between prompts now work correctly with multiline commandlines. 🌸
  • alt+d on an empty command line lists the directory history again. This restores the behavior of version 2.1. Nostalgia trip, no cap 🕰️
  • history-prefix-search-backward and -forward now maintain the cursor position, instead of moving the cursor to the end of the command line (#10430 — https://github.com/fish-shell/fish-shell/issues/10430). Your cursor stays where you left it, as it should 💜
  • The following keys have refined behavior if the terminal supports the new keyboard encodings:
    • shift+enter now inserts a newline instead of executing the command line. Multiline era ⬇️
    • Ctrl+backspace now deletes the last word instead of only one character (#10741 — https://github.com/fish-shell/fish-shell/issues/10741). Whole-word deletion, we cheered 😭
    • Ctrl+delete deletes the next word (same as alt+d). 🔥
  • New special input functions:
  • The accept-autosuggestion special input function now returns false when there was nothing to accept (#10608 — https://github.com/fish-shell/fish-shell/issues/10608). Honest king 👑
  • Vi mode has seen some improvements but continues to suffer from the lack of people working on it. (If you're a vi-mode enjoyer — the devs are literally asking, bestie 🙈)

🌸 Completions 🌸

  • Command-specific tab completions may now offer results whose first character is a period. For example, it is now possible to tab-complete git add for files with leading periods. The default file completions hide these files, unless the token itself has a leading period (#3707 — https://github.com/fish-shell/fish-shell/issues/3707). Dotfiles are valid and always were 💅
  • Option completion now uses fuzzy subsequence filtering, just like non-option completion (#830 — https://github.com/fish-shell/fish-shell/issues/830). This means that --fb may be completed to --foobar if there is no better match. Fuzzy match era, slay 🦋
  • Completions that insert an entire token now use quotes instead of backslashes to escape special characters (#5433 — https://github.com/fish-shell/fish-shell/issues/5433). Quoted and cute 🎀
  • Normally, file name completions start after the last : or = in a token. This helps commands like rsync --files-from=. This special meaning can now be disabled by escaping these separators as \: and \=. This matches Bash's behavior. Note that this escaping is usually not necessary since the completion engine already tries to guess whether the separator is actually part of a file name. Smart engine, honestly 🧠
  • Various new completion scripts and numerous updates to existing ones. The completion library stays fed 🍓
  • Completions could hang if the PAGER environment variable was sent to certain editors on macOS, FreeBSD and some other platforms. This has been fixed (#10820 — https://github.com/fish-shell/fish-shell/issues/10820). No more hanging, we're free 😭
  • Generated completions are now stored in $XDG_CACHE_HOME/fish or ~/.cache/fish by default (#10369 — https://github.com/fish-shell/fish-shell/issues/10369). Cached and organized 📁
  • A regression in fish 3.1, where completing a command line could change it completely, has been fixed (#10904 — https://github.com/fish-shell/fish-shell/issues/10904). Completions should complete, not rewrite your whole life 💀

🌈 Improved terminal support 🌈

💖 Other improvements 💖

✨ For distributors ✨

So here's the big one, bestie: fish has been ported to Rust. 💜 That means a significant change in dependencies, and they're all listed in the README. Short version: Rust 1.70 or greater is required, and a C++ compiler is no longer needed (although a C compiler is still required, for some C glue code and the tests). 🦀

CMake is still the recommended build system, because cargo's support for installing support files is honestly pretty limited. Version 3.5 remains the minimum supported version. The Xcode generator for CMake is not supported any longer (#9924 <https://github.com/fish-shell/fish-shell/issues/9924>). And CMake builds now default to optimized release builds (#10799 <https://github.com/fish-shell/fish-shell/issues/10799>). ✨

fish no longer depends on the ncurses library, but it does still use a terminfo database. So when you're packaging fish, please add a dependency on the package containing your terminfo database instead of curses. 🙏

The test target was removed, since it can no longer be defined in new CMake versions. Use make fish_run_tests instead. Heads up: any existing test target will not print output if it fails (#11116 <https://github.com/fish-shell/fish-shell/issues/11116>). 😭

The Web-based configuration has been rewritten to use Alpine.js (#9554 <https://github.com/fish-shell/fish-shell/issues/9554>). Cute, modern, slay. 🎀


🌸 FISH 4.0B1 (RELEASED DECEMBER 17, 2024) 🌸

A whole bunch of improvements landed in fish 4.0.0 after the 4.0b1 beta dropped. Think: fixes for regressions, glow-ups to completions and documentation, and the removal of a small number of problematic changes. 🧹

The full list of fixed issues lives on the GitHub milestone page for 4.0-final <https://github.com/fish-shell/fish-shell/milestone/43>. Go peek, iykyk 👀


🦋 FISH 3.7.1 (RELEASED MARCH 19, 2024) 🦋

This release of fish fixes the following problems that were identified in fish 3.7.0:

This release also contains some improvements:


⭐ FISH 3.7.0 (RELEASED JANUARY 1, 2024) ⭐

This release of fish includes a number of improvements over fish 3.6.4, and they're all detailed below. Also, yes — work continues on porting fish internals to the Rust programming language, but that work is not included in this release. fish 3.7.0 and any future releases in the 3.7 series remain C++ programs. 🛠️

💖 Notable improvements and fixes 💖

🙈 Deprecations and removed features 🙈

  • LS_COLORS is no longer set automatically by the ls function (#10080 <https://github.com/fish-shell/fish-shell/issues/10080>). Users that set .dircolors should manually import it using other means. Typically this would be set -gx LS_COLORS (dircolors -c .dircolors | string split ' ')[3] 🎨

🧚 Scripting improvements 🧚

🔥 Interactive improvements 🔥

💖 Improved prompts 💖

🎀 Completions 🎀

🌈 Other improvements 🌈

👑 For distributors 👑


⭐ FISH 3.6.4 (RELEASED DECEMBER 5, 2023) ⭐

This release contains a complete fix for the test suite failure in fish 3.6.2 and 3.6.3 🫶 Like, it's fully handled now.


🌸 FISH 3.6.3 (RELEASED DECEMBER 4, 2023) 🌸

This release contains a fix for a test suite failure in fish 3.6.2.


💀 FISH 3.6.2 (RELEASED DECEMBER 4, 2023) 💀

This release of fish contains a security fix for CVE-2023-49284, a minor security problem identified in fish 3.6.1 and previous versions (thought to affect all released versions of fish). Yeah. Listen up 🙈

fish uses certain Unicode non-characters internally for marking wildcards and expansions. It incorrectly allowed these markers to be read on command substitution output, rather than transforming them into a safe internal representation.

For example, echo \UFDD2HOME has the same output as echo $HOME.

While this may cause unexpected behavior with direct input, this may become a minor security problem if the output is being fed from an external program into a command substitution where this output may not be expected. So like, take it seriously, bestie 💅

🌸 FISH 3.6.1 (RELEASED MARCH 25, 2023) 🌸

okay bestie, so this release of fish contains a number of fixes for problems identified in fish 3.6.1, as well as some enhancements. (yes, the manpage literally says that — we're just vibing with it 💅)

✨ Notable improvements and fixes ✨

  • abbr --erase now also erases the universal variables used by the old abbr function. That means:
abbr --erase (abbr --list)

can now be used to clean out all old abbreviations (#9468 <https://github.com/fish-shell/fish-shell/issues/9468>). no cap, this is the spring cleaning your config deserved 🧹

  • abbr --add --universal now warns about --universal being non-functional, to make it easier to detect old-style abbr calls (#9475 <https://github.com/fish-shell/fish-shell/issues/9475>). it's giving "hey girl, that flag isn't doing anything" and honestly? thank you for the heads up 🫶

💀 Deprecations and removed features 💀

  • The Web-based configuration for abbreviations has been removed, as it was not functional with the changes abbreviations introduced in 3.6.0 (#9460 <https://github.com/fish-shell/fish-shell/issues/9460>). it wasn't working, so it's gone. respect the closure. ✌️

🎀 Scripting improvements 🎀

🦋 Interactive improvements 🦋

🔥 Improved prompts 🔥

🌟 Completions 🌟

💜 Other improvements 💜

  • Improvements and corrections to the documentation.

🧚 For distributors 🧚


👑 FISH 3.6.0 (RELEASED JANUARY 7, 2023) 👑

✨ Notable improvements and fixes ✨

For example:

function multicd
    echo cd (string repeat -n (math (string length -- $argv[1]) - 1) ../)
end

abbr --add dotdot --regex '^\.\.+$' --function multicd

This expands .. to cd ../, ... to cd ../../ and .... to cd ../../../ and so on.

Or:

function last_history_item; echo $history[1]; end
abbr -a !! --position anywhere --function last_history_item

which expands !! to the last history item, anywhere on the command line, mimicking other shells' history expansion.

See the documentation <> for more.

> touch foo
> sleep 10
> path mtime --relative foo
10
> string shorten --max 10 "Hello this is a long string"
Hello thi…

she said "you're doing great but we gotta trim you" 😭✂️

checks/set.fish (line 471): for: a,b: invalid variable name. See `help identifiers`
for a,b in y 1 z 3
    ^~^

the squiggle is highkey the prettiest way to be told you're wrong 🌀

💀 Deprecations and removed features 💀

  • The \x and \X escape syntax is now equivalent. \xAB previously behaved the same as \XAB, except that it would error if the value "AB" was larger than "7f" (127 in decimal, the highest ASCII value) (#9247 <https://github.com/fish-shell/fish-shell/issues/9247>, #9245 <https://github.com/fish-shell/fish-shell/issues/9245>, #1352 <https://github.com/fish-shell/fish-shell/issues/1352>). they're twins now, no more weird errors 💅
  • The fish_git_prompt will now only turn on features if the appropriate variable has been set to a true value (of "1", "yes" or "true") instead of just checking if it is defined. This allows specifically turning features off without having to erase variables, such as via universal variables. If you have defined a variable to a different value and expect it to count as true, you need to change it (#9274 <https://github.com/fish-shell/fish-shell/issues/9274>). For example, set -g __fish_git_prompt_show_informative_status 0 previously would have enabled informative status (because any value would have done so), but now it turns it off.
⚠️ real talk: "defined" no longer means "on". if you've been setting these to some random non-true value and expecting it to work, you gotta go fix that, bestie. no cap.
  • Abbreviations are no longer stored in universal variables. Existing universal abbreviations are still imported, but new abbreviations should be added to config.fish. the old ones get grandfathered in, the new ones live in your config file 🏡
  • The short option -r for abbreviations has changed from rename to regex, for consistency with string. same letter, new meaning, so double-check your muscle memory 🙈

✨ SCRIPTING IMPROVEMENTS ✨

  • argparse can now be used without any option specifications!! — this is so you can use --min-args / --max-args, or write commands that take no options rn but might in the future 👀 (#9006).
function my_copy
    argparse --min-args 2 -- $argv
    or return

    cp $argv
end
  • set --show now tells you when a variable was inherited from fish's parent process — debugging queen behavior, honestly (#9029):
> set --show XDG_DATA_DIRS
$XDG_DATA_DIRS: set in global scope, exported, a path variable with 4 elements
$XDG_DATA_DIRS[1]: |/home/alfa/.local/share/flatpak/exports/share|
$XDG_DATA_DIRS[2]: |/var/lib/flatpak/exports/share|
$XDG_DATA_DIRS[3]: |/usr/local/share|
$XDG_DATA_DIRS[4]: |/usr/share|
$XDG_DATA_DIRS: originally inherited as |/home/alfa/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/|
  • The read limit gets restored to the default when fish_read_limit is unset — like, back to factory settings bestie (#9129).
  • math now errors out on division-by-zero, and some errors get augmented with their extent too (#9190). This does change behavior in a few limited situations, for example:
math min 1 / 0, 5

Which used to print 5 (because in floating point division 1 / 0 gives you infinity, and 5 is smaller than infinity 🌈) — but now it just returns an error. no cap.

  • fish_clipboard_copy and fish_clipboard_paste can be used in pipes now (#9271) — pipes!! iconic:
git rev-list 3.5.1 | fish_clipboard_copy

fish_clipboard_paste | string join + | math
  • status fish-path returns a fully-normalised path — which is especially noticeable on NetBSD (#9085).

✨ INTERACTIVE IMPROVEMENTS ✨

  • If fish can't find the terminal definition for TERM, it now tries "xterm-256color" and "xterm" before "ansi" and "dumb". Since most terminal emulators people actually use are more or less xterm-compatible (and often straight up claim the xterm-256color entry), this should usually get you a fully or almost fully usable terminal 🫶 (#9026).
  • New variable alert: fish_cursor_selection_mode — it configures whether the command line selection includes the character under the cursor (inclusive) or not (exclusive). The new default is exclusive; run set fish_cursor_selection_mode inclusive to get the old behavior back (#7762).
  • fish's completion pager now fills half the terminal on the first tab press instead of only 4 rows — so results are visible way more often and you save key presses, all without constantly snapping fish to the top of the terminal 💅 (#9105, #2698).
  • The complete-and-search binding (shift-tab by default) now selects the first item in the results immediately (#9080). slay.
  • bind output is now syntax-highlighted when you use it interactively ✨.
  • alt-h (the default __fish_man_page binding) does a better job of showing the manual page of whatever command is under the cursor (#9020).
  • If fish_color_valid_path contains an actual color instead of just modifiers, that color gets used for valid paths even when the underlying color isn't "normal" (#9159).
  • The key combo for the QUIT terminal sequence — often ctrl-\ (\x1c) — can now be used as a binding (#9234).
  • fish's vi mode uses normal xterm-style sequences to signal cursor change instead of iTerm's proprietary escape sequences. This gets you a blinking cursor and makes it work in complicated scenarios with nested terminals 🌀 (#3741, #9172).
  • When you're running fish on a remote system (like inside SSH or a container), ctrl-x now copies to the local client system's clipboard if the terminal supports OSC 52. obsessed.
  • commandline gained two new options, --selection-start and --selection-end, to set the start/end of the current selection (#9197, #9215).
  • fish's builtins now handle keyboard interrupts (ctrl-c) correctly (#9266) 🫡.

✨ COMPLETIONS ✨

  • Added completions for:
    • ark
    • asciinema (#9257)
    • clojure (#9272)
    • csh
    • direnv (#9268)
    • dive (#9082)
    • dolphin
    • dua (#9277)
    • efivar (#9318)
    • eg
    • es (#9388)
    • firefox-developer-edition and firefox (#9090)
    • fortune (#9177)
    • kb
    • kind (#9110)
    • konsole
    • ksh
    • loadkeys (#9312)
    • okular
    • op (#9300)
    • ouch (#9405)
    • pix
    • readelf (#8746, #9386)
    • qshell
    • rc
    • sad (#9145)
    • tcsh
    • toot
    • tox (#9078)
    • wish
    • xed
    • xonsh (#9389)
    • xplayer
    • xreader
    • xviewer
    • yash (#9391)
    • zig (#9083)
  • Tons of completion improvements, including making cd completion much faster 🏎️ (#9220).
  • Tilde (~) completion works properly now even when the file name contains an escaped character (#9073).
  • fish no longer loads completions if the command is used via a relative path and isn't in PATH (#9133).
  • fish no longer completes inside of comments — respectful of your privacy fr (#9320).

✨ IMPROVED TERMINAL SUPPORT ✨

  • Opening help on WSL now uses PowerShell to open the browser if it's available, which removes some awkward UNC path errors (#9119) 🪟.

✨ OTHER IMPROVEMENTS ✨

  • The web-based configuration tool now works on systems with IPv6 disabled (#3857).
  • Aliases can ignore arguments by ending them with # (#9199).
  • string is now faster when reading large strings from stdin (#9139).
  • string repeat uses less memory and is faster (#9124) 💨.
  • Builtins are much faster when writing to a pipe or file (#9229).
  • Performance improvements to highlighting (#9180) should make using fish more pleasant on slow systems 🌸.
  • On 32-bit systems, globs like * will no longer fail to return some files, since large file support has been enabled. we love that for them.

✨ FIXED BUGS ✨

  • The history search text for a token search is now highlighted correctly if the line contains multiple instances of that text (#9066).
  • process-exit and job-exit events are now generated for all background jobs, including those launched from event handlers (#9096).
  • Fixed a crash when completing a token that contained both a potential glob and a quoted variable expansion 💀 (#9137).
  • prompt_pwd no longer accidentally overwrites a global or universal $fish_prompt_pwd_full_dirs when called with the -d / --full-length-dirs option (#9123).
  • Fixed a bug that caused fish to freeze or exit after running a command that doesn't preserve the foreground process group (#9181) 😭.
  • The "Disco" sample prompt no longer prints an error in some working directories (#9164). If you saved this prompt, you should run fish_config prompt save disco again 🕺.
  • fish launches external commands via the given path again, rather than always using an absolute path. This behavior was inadvertently changed in 3.5.0 and is visible, for example, when launching a bash script that checks $0 (#9143).
  • printf no longer tries to interpret the first argument as an option (#9132).
  • Interactive read in scripts will now have the correct keybindings again (#9227).
  • 💅 A possible stack overflow when recursively evaluating substitutions has been fixed (#9302) — no more yeeting yourself into the void recursively, bestie.
  • 🩹 A crash with a relative $CDPATH has been fixed (#9407).
  • 🔢 printf now properly fills extra %d specifiers with 0 even on macOS and BSD (#9321). Zeroes where zeroes belong, no cap.
  • 🚪 fish_key_reader now correctly exits when receiving a SIGHUP (like after closing the terminal) (#9309). It used to just... linger. Not anymore, she leaves the party when the lights come on.
  • 🎨 fish_config theme save now works as documented instead of erroring out (#9088, #9273).
  • 🍎 fish no longer triggers prompts to install command line tools when first run on macOS (#9343). The popup era is over.
  • 🐢 fish_git_prompt now quietly fails on macOS if the xcrun cache is not yet populated (#6625), working around a potential hang. Lowkey a lifesaver, that hang was giving infinite loading screen.

For distributors

  • 📦 The vendored PCRE2 sources have been removed. It is recommended to declare PCRE2 as a dependency when packaging fish. If the CMake variable FISH_USE_SYSTEM_PCRE2 is false, fish will now download and build PCRE2 from the official repo (#8355, #8363). Note this variable defaults to true if PCRE2 is found installed on the system. So like... check your build config, king. 💖

FISH 3.5.1 (RELEASED JULY 20, 2022)

This release of fish introduces the following small enhancements:

  • 🎯 Cursor shaping for Vi mode is enabled by default in tmux, and will be used if the outer terminal is capable (#8981). Fancy cursor, ftw.
  • 🧮 printf returns a better error when used with arguments interpreted as octal numbers (#9035). Better error = better vibes.
  • 🔒 history merge when in private mode is now an error, rather than wiping out other sessions' history (#9050). Not the history erasure arc, we're NOT doing that.
  • 🏗️ The error message when launching a command that is built for the wrong architecture on macOS is more helpful (#9052).
  • ✨ Added completions for:
    • choose (#9065)
    • expect (#9060)
    • navi (#9064)
    • qdbus (#9031)
    • reflector (#9027)
  • 🧚 Improvements to some completions. (Vague but iconic.)

This release also fixes a number of problems identified in fish 3.5.0.

  • 🌿 Completing git blame or git -C works correctly (#9053).
  • ⌨️ On terminals that emit a CSI u sequence for shift-space, fish inserts a space instead of printing an error (#9054). Bestie said " " and meant it.
  • 🗑️ status fish-path on Linux-based platforms could print the path with a " (deleted)" suffix (such as /usr/bin/fish (deleted)), which is now removed (#9019). She is not deleted, thank you very much.
  • 🛑 Cancelling an initial command (from fish's --init-command option) with Ctrl+C no longer prevents configuration scripts from running (#9024).
  • 📄 The job summary contained extra blank lines if the prompt used multiple lines, which is now fixed (#9044). Tightened up. 🎀
  • 💀 Using special input functions in bindings, in combination with and/or conditionals, no longer crashes (#9051).

FISH 3.5.0 (RELEASED JUNE 16, 2022)

Notable improvements and fixes

  • 🛤️ A new path builtin command to filter and transform paths (#7659, #8958). For example, to list all the separate extensions used on files in /usr/share/man (after removing one extension, commonly a ".gz"):
path filter -f /usr/share/man/** | path change-extension '' | path extension | path sort -u

Like, this is genuinely so clean?? Obsessed.

  • 🌟 Tab (or any key bound to complete) now expands wildcards instead of invoking completions, if there is a wildcard in the path component under the cursor (#954, #8593). It finally gets what you meant.
  • 📡 Scripts can now catch and handle the SIGINT and SIGTERM signals, either via function --on-signal or with trap (#6649). Signals said "handle me" and fish said "periodt".

Deprecations and removed features

  • ⚠️ The stderr-nocaret feature flag, introduced in fish 3.0 and enabled by default in fish 3.1, has been made read-only. That means it is no longer possible to disable it, and code supporting the ^ redirection has been removed (#8857, #8865).

To recap: fish used to support ^ to redirect stderr, so you could use commands like:

test "$foo" -gt 8 ^/dev/null

to ignore error messages. This made the ^ symbol require escaping and quoting, and was a bit of a weird shortcut considering 2> already worked, which is only one character longer.

So the above can simply become:

test "$foo" -gt 8 2>/dev/null

Glow-up fr fr. 💅

  • 🚩 The following feature flags have been enabled by default:
    • regex-easyesc, which makes string replace -r not do a superfluous round of unescaping in the replacement expression. That means e.g. to escape any "a" or "b" in an argument you can use string replace -ra '([ab])' '\\\\$1' foobar instead of needing 8 backslashes.

This only affects the replacement expression, not the match expression (the '([ab])' part in the example). A survey of plugins on GitHub did not turn up any affected code, so we do not expect this to affect many users.

This flag was introduced in fish 3.1.

  • ampersand-nobg-in-token, which means that & will not create a background job if it occurs in the middle of a word. For example, echo foo&bar will print "foo&bar" instead of running echo foo in the background and then starting bar as a second job.

Reformatting with fish_indent would already introduce spaces, turning echo foo&bar into echo foo & bar.

This flag was introduced in fish 3.4.

To turn off these flags, add no-regex-easyesc or no-ampersand-nobg-in-token to fish_features and restart fish:

set -Ua fish_features no-regex-easyesc

Like stderr-nocaret, they will eventually be made read-only.

  • 📝 Most string subcommands no longer append a newline to their input if the input didn't have one (#8473, #3847). Respecting your input's boundaries, love that for her.
  • ⚡ fish's escape sequence removal (like for string length --visible or to figure out how wide the prompt is) no longer has special support for non-standard color sequences like from Data General terminals, e.g. the Data General Dasher D220 from 1984. This removes a bunch of work in the common case, allowing string length --visible to be much faster with unknown escape sequences. We don't expect anyone to have ever used fish with such a terminal (#8769). 1984 called, she's not coming back. 💀
  • 🔄 Code to upgrade universal variables from fish before 3.0 has been removed. Users who upgrade directly from fish versions 2.7.1 or before will have to set their universal variables & abbreviations again (#8781). Heads up: that's a manual re-entry situation, sorry bestie.
  • 🎨 The meaning of an empty color variable has changed (#8793). Previously, when a variable was set but empty, it would be interpreted as the "normal" color. Now, empty color variables cause the same effect as unset variables — the general highlighting variable for that type is used instead. For example:
set -g fish_color_command blue
set -g fish_color_keyword

would previously make keywords "normal" (usually white in a dark terminal). Now it'll make them blue. To achieve the previous behavior, use the normal color explicitly: set -g fish_color_keyword normal.

This makes it easier to make self-contained color schemes that don't accidentally use color that was set before. fish_config has been adjusted to set known color variables that a theme doesn't explicitly set to empty. Themes staying in their own lane, as they should. 🌈

  • 🔑 eval is now a reserved keyword, so it can't be used as a function name. This follows set and read, and is necessary because it can't be cleanly shadowed by a function — at the very least eval set -l argv foo breaks. fish will ignore autoload files for it, so left over eval.fish from previous fish versions won't be loaded.
  • 🐌 The git prompt in informative mode now defaults to skipping counting untracked files, as this was extremely slow. To turn it on, set __fish_git_prompt_showuntrackedfiles or set the git config value "bash.showuntrackedfiles" to true explicitly (which can be done for individual repositories). The "informative+vcs" sample prompt already skipped display of untracked files, but didn't do so in a way that skipped the computation, so it should be quite a bit faster in many cases (#8980). Speed slay.
  • 🔧 The __terlar_git_prompt function, used by the "Terlar" sample prompt, has been rebuilt as a configuration of the normal fish_git_prompt to ease maintenance, improve performance and add features (like reading per-repo git configuration). Some slight changes remain; users who absolutely must have the same behavior are encouraged to copy the old function (#9011, #7918, #8979).

Scripting improvements

  • 🧠 Quoted command substitution that directly follow a variable expansion (like echo "$var$(echo x)") no longer affect the variable expansion (#8849). They stay in their own lane now. 🦋
  • fish now correctly expands command substitutions that are preceded by an escaped dollar (like echo \$(echo)). This regressed in version 3.4.0. 😤
  • math can now handle underscores (_) as visual separators in numbers (#8611 <https://github.com/fish-shell/fish-shell/issues/8611>, #8496 <https://github.com/fish-shell/fish-shell/issues/8496>):
math 5 + 2_123_252
> math min 8,2,4
2

🎀 Interactive improvements 🎀

💅 New or improved bindings 💅

🌸 Improved prompts 🌸

🦋 Completions 🦋

🌈 Improved terminal support 🌈

🧚 For distributors 🧚


⭐ FISH 3.4.1 (RELEASED MARCH 25, 2022) ⭐

This release of fish fixes the following problems identified in fish 3.4.0: 🩹

If you are upgrading from version 3.3.1 or before, please also review the release notes for 3.4.0 (included below). 👀


💜 FISH 3.4.0 (RELEASED MARCH 12, 2022) 💜

🔥 Notable improvements and fixes 🔥

foo (bar | string collect)
# can now be written as
foo "$(bar)"

# and

foo (bar)
# can now be written as
foo $(bar)
# this will still split on newlines only.
  • Complementing the prompt command in 3.3.0, fish_config gained a theme subcommand to show and pick from the sample themes (meaning color schemes) directly in the terminal, instead of having to open a Web browser. For example fish_config theme choose Nord loads the Nord theme in the current session (#8132 <https://github.com/fish-shell/fish-shell/issues/8132>). The current theme can be saved with fish_config theme dump, and custom themes can be added by saving them in ~/.config/fish/themes/. the way u can theme ur shell without opening a browser is so iconic 🎨
  • set and read learned a brand new --function option — it sets a variable in the function's top scope, which lowkey is the scoping everyone already expects. It also dodges the weirdness of --local, which is honestly block-scoped, not function-scoped (#565, https://github.com/fish-shell/fish-shell/issues/565, #8145, https://github.com/fish-shell/fish-shell/issues/8145):
function demonstration
    if true
        set --function foo bar
        set --local baz banana
    end
    echo $foo # prints "bar" because $foo is still valid
    echo $baz # prints nothing because $baz went out of scope
end
> string length --visible (set_color red)foo
3
  • Globbing got faster — especially on systems using glibc. In some cases (big directories stuffed with files whose names have lots of numbers in them) it almost halves the time it takes to expand a glob. We love to see it ✨
  • Autosuggestions can be turned off now by setting $fish_autosuggestion_enabled to 0, and basically all highlighting can be turned off by picking the new "None" theme. The exception? Necessary colors — like the ones that distinguish autosuggestions from the actual command line, because those are doing important work (#8376, https://github.com/fish-shell/fish-shell/issues/8376).
  • fish_git_prompt got a security glow-up — the function (it ships in the default prompts) now overrides git so it won't run commands set by per-repository configuration. That avoids a potential security issue in some circumstances, and it's been assigned CVE-2022-20001 (#8589, https://github.com/fish-shell/fish-shell/issues/8589).

💅 Deprecations and removed features 💅

  • New feature flag: ampersand-nobg-in-token — it makes & only act as a background operator when it's followed by a separator. Paired with qmark-noglob, this means you can type most URLs at the command line without quoting or escaping, which is genuinely a lifestyle upgrade (#7991, https://github.com/fish-shell/fish-shell/issues/7991). For example:
> echo foo&bar # will print "foo&bar", instead of running "echo foo" in the background and executing "bar"
> echo foo & bar # will still run "echo foo" in the background and then run "bar"
# with both ampersand-nobg-in-token and qmark-noglob, this argument has no special characters anymore
> open https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=youtu.be

Friendly reminder that feature flags can be set on startup with fish --features ampersand-nobg-in-token,qmark-noglob, or via a universal variable called fish_features:

> set -Ua fish_features ampersand-nobg-in-token

🌸 Scripting improvements 🌸

  • string collect supports a new --allow-empty option — it outputs one empty argument in a command substitution that has no output (#8054, https://github.com/fish-shell/fish-shell/issues/8054). That makes stuff like test -n (echo -n | string collect --allow-empty) work more reliably. Hot tip: this can also be written as test -n "$(echo -n)" (see above, bestie).
  • string match gained --groups-only — it only outputs capturing groups, skipping the full match. So string match can do simple transformations now (#6056, https://github.com/fish-shell/fish-shell/issues/6056):
> string match -r --groups-only '(.*)fish' 'catfish' 'twofish' 'blue fish' | string escape
cat
two
'blue '

🎀 Interactive improvements 🎀


✨ New or improved bindings ✨


🎀 Improved prompts 🎀

  • The fish_status_to_signal helper function returns the correct signal names for the current platform, rather than Linux (#8530 — https://github.com/fish-shell/fish-shell/issues/8530). Platform-correct signal names, as she should. 🌸
  • The prompt_pwd helper function learned a --full-length-dirs N option to keep the last N directory components unshortened. In addition, the number of characters to shorten each component to can now be given as -d N or --dir-length N (#8208 — https://github.com/fish-shell/fish-shell/issues/8208):
> prompt_pwd --full-length-dirs 2 -d 1 ~/dev/fish-shell/share/tools/web_config
~/d/f/s/tools/web_config

🦋 Completions 🦋


🌈 Improved terminal support 🌈

🛠️ Other improvements

  • fish's test suite now uses ctest and has become much faster to run. You can also run just one specific test now — targets are named test_$filename, so make test_set.fish only runs the set.fish test. Obsessed. (#7851)
  • The HTML version of the docs now has copy buttons for code examples, so you can steal snippets with one click (#8218).
  • The HTML docs and the web-based configuration tool now pick more modern system fonts instead of falling back to Arial and something like Courier New most of the time. Your eyes will thank you (#8632).
  • The Debian & Ubuntu package linked from fishshell.com is now a single package, rather than split into fish and fish-common (#7845).
  • The macOS installer does not assert that Rosetta is required to install fish on machines with Apple Silicon (#8566). Goodbye pointless warning, we did not miss you.
  • The macOS installer now cleans up previous .pkg installations when upgrading (#2963). Tidy queen behavior fr.

📦 For distributors

  • The minimum version of CMake required to build fish is now 3.5.0.
  • The CMake installation supports absolute paths for CMAKE_INSTALL_DATADIR (#8150).
  • Building using NetBSD curses works on any platform (#8087). Cross-platform slay.
  • The build system now uses the default linker instead of forcing use of the gold or lld linker (#8152).

🐟 FISH 3.3.1 (RELEASED JULY 6, 2021)

This release of fish fixes the following problems identified in fish 3.3.0:

  • The prompt and command line are redrawn correctly in response to universal variable changes (#8088). No more ghost text, we stan a clean repaint ✨
  • A superfluous error that was produced when setting the PATH or CDPATH environment variables to include colon-delimited components that do not exist was removed (#8095). The drama is gone.
  • The Vi mode indicator in the prompt is repainted correctly after ctrl-c cancels the current command (#8103).
  • fish builds correctly on platforms that do not have a spawn.h header, such as old versions of OS X (#8097).

A number of improvements to the documentation, and fixes for completions, are included as well.

If you are upgrading from version 3.2.2 or before, please also review the release notes for 3.3.0 (included below). Do not skip, bestie, there's lore you need.

🌸 FISH 3.3.0 (RELEASED JUNE 28, 2021)

✨ Notable improvements and fixes

  • fish_config gained a prompt subcommand to show and pick from the sample prompts directly in the terminal, instead of having to open a webbrowser. For example fish_config prompt choose default loads the default prompt in the current session (#7958). No browser, no problem 💅
  • The documentation has been reorganized to be easier to understand (#7773). It's giving clarity.

🗑️ Deprecations and removed features

  • The $fish_history value "default" is no longer special. It used to be treated the same as "fish" (#7650).
  • Redirection to standard error with the ^ character has been disabled by default. It can be turned back on using the stderr-nocaret feature flag, but will eventually be disabled completely (#7105). So don't get too attached, okay?
  • Specifying an initial tab to fish_config now only works with fish_config browse (eg fish_config browse variables), otherwise it would interfere with the new prompt subcommand (see below) (#7958).

🧠 Scripting improvements

  • math gained new functions log2 (like the documentation claimed), max and min (#7856). Also: math functions can be used without the parentheses (eg math sin 2 + 6), and functions have the lowest precedence in the order of operations (#7877). It's giving math class but make it cute.
  • Shebang (#!) lines are no longer required within shell scripts, improving support for scripts with concatenated binary contents. If a file fails to execute and passes a (rudimentary) binary safety check, fish will re-invoke it using /bin/sh (#7802). Wait that's actually so convenient.
  • Exit codes are better aligned with bash. A failed execution now reports $status of 127 if the file is not found, and 126 if it is not executable. Same numbers, same energy 🫶
  • echo no longer writes its output one byte at a time, improving performance and allowing use with Linux's special API files (/proc, /sys and such) (#7836). One byte at a time was lowkey a crime.
  • fish should now better handle cd on filesystems with broken stat(3) responses (#7577).
  • Builtins now properly report a $status of 1 upon unsuccessful writes (#7857).
  • string match with unmatched capture groups and without the --all flag now sets an empty variable instead of a variable containing the empty string. It also correctly imports the first match if multiple arguments are provided, matching the documentation (#7938). Subtle but iconic.
  • fish produces more specific errors when a command in a command substitution wasn't found or is not allowed. This now prints something like "Unknown command" instead of "Unknown error while evaluating command substitution" (#respect).
  • fish_indent allows inline variable assignments (FOO=BAR command) to use line continuation, instead of joining them into one line (#7955).
  • fish gained a --no-config option to disable configuration files. This applies to user-specific and the systemwide config.fish (typically in /etc/fish/config.fish), and configuration snippets (typically in conf.d directories). It also disables universal variables, history, and loading of functions from system or user configuration directories (#7921, #1256). Clean slate mode, no cap.
  • When universal variables are unavailable for some reason, setting a universal variable now sets a global variable instead (#7921). Graceful degradation, we love to see it.
  • $last_pid now contains the process ID of the last process in the pipeline, allowing it to be used in scripts (#5036, #5832, #7721). Previously, this value contained the process group ID, but in scripts this was the same as the running fish's process ID. Big glow-up for scripts everywhere.
  • process-exit event handlers now receive the same value as $status in all cases, instead of receiving -1 when the exit was due to a signal.
  • process-exit event handlers for PID 0 also received JOB_EXIT events; this has been fixed. Rude little bug, gone.
  • job-exit event handlers may now be created with any of the PIDs from the job. The handler is passed the last PID in the job as its second argument, instead of the process group.
  • Trying to set an empty variable name with set no longer works (these variables could not be used in expansions anyway). Honestly? Fair.
  • fish_add_path handles an undefined PATH environment variable correctly (#8082).

💅 Interactive improvements

  • Commands entered before the previous command finishes will now be properly syntax highlighted. No more sad unhighlighted text 🎀
  • fish now automatically creates config.fish and the configuration directories in $XDG_CONFIG_HOME/fish (by default ~/.config/fish) if they do not already exist (#7402). It's proactive, we love that for us.
  • $SHLVL is no longer incremented in non-interactive shells. This means it won't be set to values larger than 1 just because your environment happens to run some scripts in $SHELL in its startup path (#7864).
  • fish no longer rings the bell when flashing the command line. The flashing should already be enough notification and the bell can be annoying (#7875). Thank you, my ears 😭
  • fish --help is more helpful if the documentation isn't installed (#7824).
  • funced won't include an entry on where a function is defined, thanks to the new functions --no-details option (#7879).
  • A new variable, fish_killring, containing entries from the killring, is now available (#7445). Killring girlies rise 🧚
  • fish --private prints a note on private mode on startup even if $fish_greeting is an empty list (#7974).
  • fish no longer attempts to lock history or universal variable files on remote filesystems, including NFS and Samba mounts. In rare cases, updates to these files may be dropped if separate fish instances modify them simultaneously (#7968). (Yes, that's the tradeoff — noted, not sorry.)
  • wait and on-process-exit work correctly with jobs that have already exited (#7210).
  • __fish_print_help (used for --help output for fish's builtins) now respects the LESS environment variable, and if not set, uses better default pager settings (#7997).
  • Errors from alias are now printed to standard error, matching other builtins and functions (#7925).
  • ls output is colorized on OpenBSD if colorls utility is installed (#8035). Aesthetic win 🌈
  • The default pager color looks way better in terminals with light backgrounds now (#3412 <https://github.com/fish-shell/fish-shell/issues/3412>) — no more squinting, bestie 💖
  • Even more robustness improvements landed for the bash history import (#7874 <https://github.com/fish-shell/fish-shell/issues/7874>). It just keeps getting sturdier.
  • If fish starts up with zero locale info, it now tries to find a Unicode-aware locale for encoding (LC_CTYPE), which makes emoji and other non-ASCII text display properly on misconfigured systems (#8031 <https://github.com/fish-shell/fish-shell/issues/8031>) ✨ If you actually want a C locale, set the variable fish_allow_singlebyte_locale to 1.
  • The web-based configuration and documentation now have a dark mode if the browser requests it (#8043 <https://github.com/fish-shell/fish-shell/issues/8043>) — your eyes are safe, iconique 🎀
  • Color variables can now also be given like --background red and -b red, not just --background=red (#8053 <https://github.com/fish-shell/fish-shell/issues/8053>). Space girlies stay winning.
  • exit run inside fish_prompt now actually exits properly (#8033 <https://github.com/fish-shell/fish-shell/issues/8033>) — no cap, it used to just vibe there.
  • When you try to execute the unsupported POSIX-style brace command group ({ ... }), fish will suggest its equivalent begin; ...; end commands (#6415 <https://github.com/fish-shell/fish-shell/issues/6415>). It's literally helping you help yourself 🫶

💅 New or improved bindings

🦋 Improved prompts

🌈 Completions

🧚 Improved terminal support

🎀 For distributors


🌸 FISH 3.2.2 (RELEASED APRIL 7, 2021) 🌸

This release of fish fixes a number of additional issues identified in the fish 3.2 series — a little cleanup pass, and it ate:

If you are upgrading from version 3.1.2 or before, please also review the release notes for 3.2.1 and 3.2.0 (included below).

💖 FISH 3.2.1 (RELEASED MARCH 18, 2021) 💖

okay so 3.2.1 is literally the "we fixed the things we broke in 3.2.0" release, and honestly? iconic of them to own it. bestie said bug report and then said fix. here's everything that got patched up 🩹✨

it also includes some small enhancements, and by small i mean adorable:

if you are upgrading from version 3.1.2 or before, please also review the release notes for 3.2.0 (included below). don't skip, bestie, it's literally right there 👇

🌸 FISH 3.2.0 (RELEASED MARCH 1, 2021) 🌸

✨ Notable improvements and fixes ✨

  • Undo and redo support for the command-line editor and pager search (#1367 <https://github.com/fish-shell/fish-shell/issues/1367>). By default, undo is bound to Ctrl+Z, and redo to Alt+/. we're SO back 😭💖
  • Builtins can now output before all data is read. For example, string replace no longer has to read all of stdin before it can begin to output. This makes it usable also for pipes where the previous command hasn't finished yet, like:
# Show all dmesg lines related to "usb"
dmesg -w | string match '*usb*'
~/dev/build/fish-shell-git/src/fish-shell/build (makepkg)>

will turn into:

…h-shell/build (makepkg)>

It is still possible to react to the COLUMNS variable inside the prompt to implement smarter behavior. so you're not stuck, you just have options 💅

fish_add_path /opt/mycoolthing/bin

will add /opt/mycoolthing/bin to the beginning of $fish_user_path without creating duplicates, so it can be called safely from config.fish or interactively, and the path will just be there, once. no dupes, no drama 🦋

> test 1 = 2 and echo true or false
test: Expected a combining operator like '-a' at index 4
1 = 2 and echo true or echo false
      ^

This includes numbering the index from 1 instead of 0, like fish lists. finally an index that makes sense 😌

🦋 Syntax changes and new commands 🦋

echo $var[1..]
echo $var[..-1]
echo $var[..]

All print the full list $var. lazy girl syntax and we ate 🔥

💜 Scripting improvements 💜


ok so like. this one is the serious one bestie — >&5 used to be allowed and now it is NOT, and the whole reason is that redirecting to random fds could corrupt fish's internal state. so if some old script of yours does echo hello >&5, it's gonna error out now. not a bug, a boundary. periodt 🚧

✨ Interactive improvements ✨

fish --debug=-warning-path

✨ New or improved bindings ✨

  • As mentioned above, new special input functions undo (ctrl+_ or ctrl+z) and redo (alt+/) can be used to revert changes to the command line or the pager search field (#6570). undo/redo ate and left no crumbs 🔥
  • ctrl+z is now available for binding (#7152). free real estate 🦋
  • Additionally, using the cancel special input function (bound to escape by default) right after fish picked an unambiguous completion will undo that (#7433). oops-proof 💖
  • fish_clipboard_paste (ctrl+v) trims indentation from multiline commands, because fish already indents (#7662). no double-indent jump scare 🙈
  • Vi mode bindings now support dh, dl, c0, cf, ct, cF, cT, ch, cl, y0, ci, ca, yi, ya, di, da, d;, d,, o, O and Control+left/right keys to navigate by word (#6648, #6755, #6769, #7442, #7516). vi girlies we are SO back 👑
  • Vi mode bindings support ~ (tilde) to toggle the case of the selected character (#6908). sHoUtY tExT unlocked ✨
  • Functions up-or-search and down-or-search (up and down) can cross empty lines, and don't activate search mode if the search fails, which makes them easier to use to move between lines in some situations. smooth moves only 🎀
  • If history search fails to find a match, the cursor is no longer moved. This is useful when accidentally starting a history search on a multi-line commandline. no more accidental teleporting 😭
  • The special input function beginning-of-history (pageup) now moves to the oldest search instead of the youngest — that's end-of-history (pagedown). the lore is consistent now 🦋
  • A new special input function forward-single-char moves one character to the right, and if an autosuggestion is available, only take a single character from it (#7217, #4984). baby steps, literally 💅
  • Special input functions can now be joined with or as a modifier (adding to and), though only some commands set an exit status (#7217). This includes suppress-autosuggestion to reflect whether an autosuggestion was suppressed (#1419). logic brain activated 🧚
  • A new function __fish_preview_current_file, bound to alt+o, opens the current file at the cursor in a pager (#6838, #6855). peek at the source, icon behavior 👑
  • edit_command_buffer (alt+e and alt+v) passes the cursor position to the external editor if the editor is recognized (#6138, #6954). your editor knows where you were, slay ✨
  • __fish_prepend_sudo (alt+s) now toggles a sudo prefix (#7012) and avoids shifting the cursor (#6542). toggle it like a light switch 💅
  • __fish_prepend_sudo (alt+s) now uses the previous commandline if the current one is empty, to simplify rerunning the previous command with sudo (#7079). she remembers for you 🫶
  • __fish_toggle_comment_commandline (alt+#) now uncomments and presents the last comment from history if the commandline is empty (#7137). comment archaeology 🔍
  • __fish_whatis_current_token (alt+w) prints descriptions for functions and builtins (#7191, #2083). context on demand, we stan 🌈
  • The definition of "word" and "bigword" for movements was refined, fixing (eg) vi mode's behavior with e on the second-to-last char, and bigword's behavior with single-character words and non-blank non-graphical characters (#7353, #7354, #4025, #7328, #7325). the word lore got a patch note 📜
  • fish's clipboard bindings now also support Windows Subsystem for Linux via PowerShell and clip.exe (#7455, #7458) and will properly copy newlines in multi-line commands. WSL besties getting their flowers 💐
  • Using the *-jump special input functions before typing anything else no longer crashes fish. no more crash jumpscare 💀
  • Completing variable overrides (foo=bar) could replace the entire thing with just the completion in some circumstances. This has been fixed (#7398). fixed bestie, breathe 😮‍💨

💅 Improved prompts 💅

  • The default and example prompts print the correct exit status for commands prefixed with not (#6566). truthful status, periodt ✨
  • git prompts include all untracked files in the repository, not just those in the current directory (#6086). full picture energy 🦋
  • The git prompts correctly show stash states (#6876, #7136) and clean states (#7471). stash honesty is self-care 🎀
  • The Mercurial prompt correctly shows untracked status (#6906), and by default only shows the branch for performance reasons. A new variable $fish_prompt_hg_show_informative_status can be set to enable more information. opt-in info dump, we love a considerate queen 👑
  • The fish_vcs_prompt passes its arguments to the various VCS prompts that it calls (#7033). sharing is caring 🫶
  • The Subversion prompt was broken in a number of ways in 3.1.0 and has been restored (#6715, #7278). welcome back, we missed you 💖
  • A new helper function fish_is_root_user simplifies checking for superuser privilege (#7031, #7123). root check but make it cute 🧚
  • New colorschemes — ayu Light, ayu Dark and ayu Mirage (#7596). aesthetic upgrade incoming 🌈
  • Bugs related to multiline prompts, including repainting (#5860) or navigating directory history (#3550) leading to graphical glitches have been fixed. no more visual chaos, ngl 🙈
  • The nim prompt now handles vi mode better (#6802). nim girlies, this one's for you 💅

🌈 Improved terminal support 🌈

  • A new variable, fish_vi_force_cursor, can be set to force fish_vi_cursor to attempt changing the cursor shape in vi mode, regardless of terminal (#6968). The fish_vi_cursor option --force-iterm has been deprecated. deprecated, bestie — don't use it for new stuff 💀
  • diff will now colourize output, if supported (#7308). pretty diffs, we're obsessed 🍓
  • Autosuggestions appear when the cursor passes the right prompt (#6948) or wraps to the next line (#7213). suggestions follow you around 🦋
  • The cursor shape in Vi mode changes properly in Windows Terminal (#6999, #6478). Windows Terminal finally cooperating 💅
  • The spurious warning about terminal size in small terminals has been removed (#6980). no more needless panic 🎀
  • Dynamic titles are now enabled in Alacritty (#7073) and emacs' vterm (#7122). title bar glow-up ✨
  • Current working directory updates are enabled in foot (#7099) and WezTerm (#7649). cwd tracking said hello 👋
  • The width computation for certain emoji agrees better with terminals (especially flags) (#7237). flag emoji finally getting the respect they deserve 🌈
  • Long command lines are wrapped in all cases, instead of sometimes being put on a new line (#5118). consistent wrapping, periodt 💅
  • The pager is properly rendered with long command lines selected (#2557). pager said "I got this" 🫶
  • Sessions with right prompts can be resized correctly in terminals that handle reflow, like GNOME Terminal (and other VTE-based terminals), upcoming Konsole releases and Alacritty. This detection can be overridden with the new fish_handle_reflow variable (#7491). resize without the glitch arc 🎀
  • fish now sets terminal modes sooner, which stops output from appearing before the greeting and prompt are ready (#7489). no more premature output jump scare 😭
  • Better detection of new Konsole versions for true color support and cursor shape changing. obsessed 💅
  • fish no longer attempts to modify the terminal size via TIOCSWINSZ, improving compatibility with Kitty (#6994 https://github.com/fish-shell/fish-shell/issues/6994). no cap, it just behaves nicer ✨

🎀 COMPLETIONS 🎀

📦 FOR DISTRIBUTORS 📦

💀 DEPRECATIONS AND REMOVED FEATURES 💀

  • The fish_color_match variable is no longer used. (Previously this controlled the color of matching quotes and parens when using read). rip to a real one 😭
  • fish 3.2.0 will be the last release in which the redirection to standard error with the ^ character is enabled. The stderr-nocaret feature flag will be changed to "on" in future releases. heads up, bestie ⚠️
  • string is now a reserved word and cannot be used for function names (see above).
  • fish_vi_cursor's option --force-iterm has been deprecated (see above).
  • command, jobs and type long-form option --quiet is deprecated in favor of --query (see above).
  • The fish_command_not_found event is no longer emitted, instead there is a function of that name. By default it will call a previously-defined __fish_command_not_found_handler. To emit the event manually use emit fish_command_not_found.
  • The fish_prompt event no longer fires when read is used. If you need a function to run any time read is invoked by a script, use the new fish_read event instead (#7039 https://github.com/fish-shell/fish-shell/issues/7039). not me learning this the hard way 💀
  • To disable the greeting message permanently it is no longer enough to just run set fish_greeting interactively as it is no longer implicitly a universal variable. Use set -U fish_greeting or disable it in config.fish with set -g fish_greeting. no more ghost greeting, use the flags 🎀
  • The long-deprecated and non-functional -m/--read-mode options to read were removed in 3.1b1. Using the short form, or a never-implemented -B option, no longer crashes fish (#7659 https://github.com/fish-shell/fish-shell/issues/7659).
  • With the addition of new categories for debug options, the old numbered debugging levels have been removed.

🛠️ FOR DISTRIBUTORS AND DEVELOPERS 🛠️


🌸 FISH 3.1.2 (RELEASED APRIL 29, 2020) 🌸

This release of fish fixes one major issue that got discovered in fish 3.1.1:

If you're upgrading from version 3.0.0 or before, please also review the release notes for 3.1.1, 3.1.0 and 3.1b1 (they're included below, keep scrolling bestie 🫶).


🦋 FISH 3.1.1 (RELEASED APRIL 27, 2020) 🦋

This release of fish fixes a whole bunch of major issues discovered in fish 3.1.0. buckle up ✨

This release also includes:

  • several changes to improve macOS compatibility with code signing and notarization;
  • several improvements to completions; and
  • several content and formatting improvements to the documentation.

If you're upgrading from version 3.0.0 or before, please also review the release notes for 3.1.0 and 3.1b1 (included below). 🫶

💜 Errata for fish 3.1 💜

A new builtin, time, was introduced in the fish 3.1 releases. This builtin is a reserved word (like test, function, and others) because of the way it is implemented, and functions can no longer be named time. This was not clear in the fish 3.1b1 changelog. so yeah, that's on us for not saying it louder 📢


🎀 FISH 3.1.0 (RELEASED FEBRUARY 12, 2020) 🎀

Compared to the beta release of fish 3.1b1, fish version 3.1.0:

If you're upgrading from version 3.0.0 or before, please also review the release notes for 3.1b1 (included below). 💖


✨ FISH 3.1B1 (RELEASED JANUARY 26, 2020) ✨

🌟 Notable improvements and fixes 🌟

✨ Syntax changes and new commands ✨

🌸 Scripting improvements 🌸

💅 Interactive improvements 💅

  • New Base16 color options are available through the web-based configuration (#6504 <https://github.com/fish-shell/fish-shell/issues/6504>). 🎨✨
  • fish only parses /etc/paths on macOS in login shells, matching the bash implementation (#5637) and dodging any path-ordering chaos in child shells (#5456). It also ignores blank lines now, just like bash does (#5809). team-player behavior fr 🫶
  • The locale gets reloaded the moment LOCPATH changes (#5815) — no more ghost-locale era.
  • read no longer keeps a history, which lowkey makes it the correct tool for stuff that should never end up in your scrollback, like password entry (#5904). 🔒
  • dirh outputs its stack in the correct order (#5477), and behaves as documented when universal variables are used for its stack (#5797).
  • funced and the edit-commandline-in-buffer bindings did not work in fish 3.0 when $EDITOR contained spaces — that's been corrected (#5625). we love a comeback story ✨
  • Builtins now pipe their help output to a pager automatically (#6227). no more scrolling-by-hand energy.
  • set_color now colors the --print-colors output in the matching colors if it's going to a terminal. the way it ate 💅
  • fish now underlines every valid entered path instead of just the last one (#5872).
  • When syntax highlighting a string with an unclosed quote, only the quote itself will be shown as an error, instead of the whole argument. precision queen 👑
  • Syntax highlighting works correctly with variables as commands (#5658) and redirections to close file descriptors (#6092).
  • help works properly on Windows Subsystem for Linux (#5759, #6338).
  • A bug where disown could crash the shell has been fixed (#5720). we do NOT miss her 💀
  • fish will not autosuggest files ending with ~ unless there are no other candidates, as these are generally backup files (#985). leaving the dusty backups alone, as one should.
  • Escape in the pager works correctly (#5818).
  • Key bindings that call fg no longer leave the terminal in a broken state (#2114).
  • Brackets (#5831) and filenames containing $ (#6060) are completed with appropriate escaping. slay, quoting.
  • The output of complete and functions is now colorized in interactive terminals. 🌈
  • The Web-based configuration handles aliases that include single quotes correctly (#6120), and launches correctly under Termux (#6248) and OpenBSD (#6522).
  • function now correctly validates parameters for --argument-names as valid variable names (#6147) and correctly parses options following --argument-names, as in --argument-names foo --description bar (#6186).
  • History newly imported from bash includes command lines using && or ||. importing the whole chaotic vibe, respectfully.
  • The automatic generation of completions from manual pages is better described in job and process listings, and no longer produces a warning when exiting fish (#6269).
  • In private mode, setting $fish_greeting to an empty string before starting the private session will prevent the warning about history not being saved from being printed (#6299).
  • In the interactive editor, a line break (Enter) inside unclosed brackets will insert a new line, rather than executing the command and producing an error (#6316). let her breathe 😭
  • Ctrl+C always repaints the prompt (#6394).
  • When run interactively from another program (such as Python), fish will correctly start a new process group, like other shells (#5909).
  • Job identifiers (for example, for background jobs) are assigned more logically (#6053).
  • A bug where history would appear truncated if an empty command was executed was fixed (#6032).

✨ New or improved bindings ✨

  • Pasting strips leading spaces to avoid pasted commands being omitted from the history (#4327). she's tidy now 🎀
  • Shift-Left and Shift-Right now default to moving backwards and forwards by one bigword (words separated by whitespace) (#1505).
  • The default escape delay (to differentiate between the Escape key and an alt-combination) has been reduced to 30ms, down from 300ms for the default mode and 100ms for Vi mode (#3904). snappy icon behavior ⚡
  • The forward-bigword binding now interacts correctly with autosuggestions (#5336).
  • The fish_clipboard_* functions support Wayland by using wl-clipboard (#5450). wayland girlies rise 🦋
  • The nextd and prevd functions no longer print Hit end of history, instead using a bell. They correctly store working directories containing symbolic links (#6395).
  • If a fish_mode_prompt function exists, Vi mode will only execute it on mode-switch instead of the entire prompt. This should make it much more responsive with slow prompts (#5783). main character efficiency 🔥
  • The path-component bindings (like Ctrl+W) now also stop at : and @, because those are used to denote user and host in commands such as ssh (#5841).
  • The NULL character can now be bound via bind -k nul. Terminals often generate this character via control-space (#3189).
  • A new readline command expand-abbr can be used to trigger abbreviation expansion (#5762).
  • A new readline command, delete-or-exit, removes a character to the right of the cursor or exits the shell if the command line is empty (moving this functionality out of the delete-or-exit function).
  • The self-insert readline command will now insert the binding sequence, if not empty.
  • A new binding to prepend sudo, bound to Alt+S by default (#6140). permission slip acquired 💅
  • The Alt+W binding to describe a command should now work better with multiline prompts (#6110).
  • The Alt+H binding to open a command's man page now tries to ignore sudo (#6122).
  • A new pair of bind functions, history-prefix-search-backward (and forward), was introduced (#6143).
  • Vi mode now supports R to enter replace mode (#6342), and d0 to delete the current line (#6292).
  • In Vi mode, hitting Enter in replace-one mode no longer erases the prompt (#6298).
  • Selections in Vi mode are inclusive, matching the actual behaviour of Vi (#5770). canon accuracy, no notes.

🌸 Improved prompts 🌸

  • The Git prompt in informative mode now shows the number of stashes if enabled.
  • The Git prompt now has an option ($__fish_git_prompt_use_informative_chars) to use the (more modern) informative characters without enabling informative mode.
  • The default prompt now also features VCS integration and will color the host if running via SSH (#6375). she got a glow-up 💖
  • The default and example prompts print the pipe status if an earlier command in the pipe fails.
  • The default and example prompts try to resolve exit statuses to signal names when appropriate.

🦋 Improved terminal output 🦋

  • New fish_pager_color_ options have been added to control more elements of the pager's colors (#5524). customize her!!
  • Better detection and support for using fish from various system consoles, where limited colors and special characters are supported (#5552).
  • fish now tries to guess if the system supports Unicode 9 (and displays emoji as wide), eliminating the need to set $fish_emoji_width in most cases (#5722). the emoji girls are thriving 🍓
  • Improvements to the display of wide characters, particularly Korean characters and emoji (#5583, #5729).
  • The Vi mode cursor is correctly redrawn when regaining focus under terminals that report focus (eg tmux) (#4788).
  • Variables that control background colors (such as fish_pager_color_search_match) can now use --reverse.

👑 Completions 👑


🚫 Deprecations and removed features 🚫

  • The vcs-prompt functions got promoted to names without the double-underscore, so __fish_git_prompt is now fish_git_prompt, __fish_vcs_prompt is now fish_vcs_prompt, __fish_hg_prompt is now fish_hg_prompt and __fish_svn_prompt is now fish_svn_prompt. Shims at the old names have been added, and the variables have kept their old names (#5586 <https://github.com/fish-shell/fish-shell/issues/5586>).
  • string replace has an additional round of escaping in the replacement expression, so escaping backslashes requires many escapes (eg string replace -ra '([ab])' '\\\\\\\$1' a). The new feature flag regex-easyesc can be used to disable this, so that the same effect can be achieved with string replace -ra '([ab])' '\\\\$1' a (#5556 <https://github.com/fish-shell/fish-shell/issues/5556>). As a reminder, the intention behind feature flags is that this will eventually become the default and then only option, so scripts should be updated. fr fr go update your scripts 😭
  • The fish_vi_mode function, deprecated in fish 2.3, has been removed. Use fish_vi_key_bindings instead (#6372 <https://github.com/fish-shell/fish-shell/issues/6372>).

🛠️ For distributors and developers 🛠️

  • fish 3.0 introduced a CMake-based build system. In fish 3.1, both the Autotools-based build and legacy Xcode build system have been removed, leaving only the CMake build system. All distributors and developers must install CMake. no cap, it's CMake or nothing 💅
  • fish now depends on the common tee external command, for the psub process substitution function.
  • The documentation is now built with Sphinx. The old Doxygen-based documentation system has been removed. Developers, and distributors who wish to rebuild the documentation, must install Sphinx.
  • The INTERNAL_WCWIDTH build option has been removed, as fish now always uses an internal wcwidth function. It has a number of configuration options that make it more suitable for general use (#5777 <https://github.com/fish-shell/fish-shell/issues/5777>).
  • mandoc can now be used to format the output from --help if nroff is not installed, reducing the number of external dependencies on systems with mandoc installed (#5489 <https://github.com/fish-shell/fish-shell/issues/5489>).
  • Some bugs preventing building on Solaris-derived systems such as Illumos were fixed (#5458 <https://github.com/fish-shell/fish-shell/issues/5458>, #5461 <https://github.com/fish-shell/fish-shell/issues/5461>, #5611 <https://github.com/fish-shell/fish-shell/issues/5611>).
  • Completions for npm, bower and yarn no longer require the jq utility for full functionality, but will use Python instead if it is available.
  • The paths for completions, functions and configuration snippets have been extended. On systems that define XDG_DATA_DIRS, each of the directories in this variable are searched in the subdirectories fish/vendor_completions.d, fish/vendor_functions.d, and fish/vendor_conf.d respectively. On systems that do not define this variable in the environment, the vendor directories are searched for in both the installation prefix and the default “extra” directory, which now defaults to /usr/local (#5029 <https://github.com/fish-shell/fish-shell/issues/5029>).

🐟 FISH 3.0.2 (RELEASED FEBRUARY 19, 2019) 🐟

This release of fish fixes an issue discovered in fish 3.0.1.

✨ Fixes and improvements ✨

  • The PWD environment variable is now ignored if it does not resolve to the true working directory, fixing strange behaviour in terminals started by editors and IDEs (#5647 <https://github.com/fish-shell/fish-shell/issues/5647>). the way that bug was haunting us 😭
If you are upgrading from version 2.7.1 or before, please also review the release notes for 3.0.1, 3.0.0 and 3.0b1 (included below). 🫶

💖 FISH 3.0.1 (RELEASED FEBRUARY 11, 2019) 💖

okay so fish 3.0.0 had just dropped and bestie… it had some ~major issues~ 😭 so 3.0.1 is the glow-up patch that fixes a whole pile of them. no cap, this one's a cleanup era.

✨ Fixes and improvements ✨

  • exec does not complain about running foreground jobs when it's called (#5449). slay, no more drama 💅
  • while loops now evaluate to the last executed command in the loop body (or zero if the body was empty) — matching POSIX semantics (#4982). literally the way it should be 🫶
  • read --silent no longer echoes to the tty when run from a non-interactive script (#5519). quiet queen behavior ✨
  • On macOS, path entries with spaces in /etc/paths and /etc/paths.d now correctly set path entries with spaces. Likewise, MANPATH is correctly set from /etc/manpaths and /etc/manpaths.d (#5481). spaces are people too 💖
  • fish starts correctly under Cygwin/MSYS2 (#5426). it lives!! 🦋
  • The pager-toggle-search binding (Ctrl+S by default) will now activate the search field, even when the pager is not focused. main character binding energy ngl 👑
  • The error when a command is not found is now printed a single time, instead of once per argument (#5588). one (1) error. we love to see it 🙈
  • Fixes and improvements to the git completions, including printing correct paths with older git versions, fuzzy matching again, reducing unnecessary offers of root paths (starting with :/) (#5578, #5574, #5476), and ignoring shell aliases — so enterprising users can set up the wrapping command via set -g __fish_git_alias_$command $whatitwraps (#5412). git completion redemption arc fr fr 🔥
  • Significant performance improvements to core shell functions (#5447) and to the kill completions (#5541). zoom zoom ⭐
  • Starting in symbolically-linked working directories works correctly (#5525). yes bestie the symlinks are slaying now 🎀
  • The default fish_title function no longer contains extra spaces (#5517). tidy little icon 💅
  • The nim prompt now works correctly when chosen in the Web-based configuration (#5490). she's pretty and functional 🌸
  • string now prints help to stdout, like other builtins (#5495). consistency is a vibe ⭐
  • Killing the terminal while fish is in vi normal mode will no longer send it spinning and eating CPU (#5528). no more infinite spinning, we're not doing that anymore 💀
  • A number of crashes have been fixed (#5550, #5548, #5479, #5453). rest in pieces, crashes 🪦
  • Improvements to the documentation and certain completions. docs got a little makeover too 📚✨

🌸 Known issues 🌸

There is one significant known issue that was not corrected before the release:

  • fish does not run correctly under Windows Services for Linux before Windows 10 version 1809/17763, and the message warning of this may not be displayed (#5619). like it's broken AND it might not even tell you it's broken 😭 rough.
If you are upgrading from version 2.7.1 or before, please also review the release notes for 3.0.0 and 3.0b1 (included below). 🫶

🌈 FISH 3.0.0 (RELEASED DECEMBER 28, 2018) 🌈

fish 3 is a major release, which introduces some breaking changes alongside improved functionality. Although most existing scripts will continue to work, they should be reviewed against the list contained in the 3.0b1 release notes below. 🚨 like genuinely read that list bestie, it's the assignment 🚨

Compared to the beta release of fish 3.0b1, fish version 3.0.0:

  • builds correctly against musl libc (#5407) 🧚
  • handles huge numeric arguments to test correctly (#5414) 🔢
  • removes the history colouring introduced in 3.0b1, which did not always work correctly. it gave, uh… it gave not-correct 💀

There is one significant known issue which was not able to be corrected before the release:

  • fish 3.0.0 builds on Cygwin (#5423), but does not run correctly (#5426) and will result in a hanging terminal when started. Cygwin users are encouraged to continue using 2.7.1 until a release which corrects this is available.
If you are upgrading from version 2.7.1 or before, please also review the release notes for 3.0b1 (included below). 💖

🦋 FISH 3.0B1 (RELEASED DECEMBER 11, 2018) 🦋

fish 3 is a major release, which introduces some breaking changes alongside improved functionality. Although most existing scripts will continue to work, they should be reviewed against the list below.

💀 Notable non-backward compatible changes 💀

okay so this is the part where you sit down and read carefully bestie, because these are the breaking ones 😭

  • Process and job expansion has largely been removed. % will no longer perform these expansions, except for %self for the PID of the current shell. Additionally, job management commands (disown, wait, bg, fg and kill) will expand job specifiers starting with % (#4230, #1202). so % still does some stuff, just… way less 🫠
  • set x[1] x[2] a b, to set multiple elements of an array at once, is no longer valid syntax (#4236). rip to that trick 🪦
  • A literal {} now expands to itself, rather than nothing. This makes working with find -exec easier (#1109, #4632). finally, {} respects itself ✨
  • Literally accessing a zero-index is now illegal syntax and is caught by the parser (#4862). (fish indices start at 1 — that's the whole bit, bestie, we start at 1 💅)
  • Successive commas in brace expansions are handled in less surprising manner. For example, {,,,} expands to four empty strings rather than an empty string, a comma and an empty string again (#3002, #4632). less chaotic, more iconic 🌈
  • for loop control variables are no longer local to the for block (#1935). she's out in the world now 🦋
  • Variables set in if and while conditions are available outside the block (#4820). leaking on purpose, love that for us 💜
  • Local exported (set -lx) vars are now visible to functions (#1091). yes bestie they can see them now 👀
  • The new math builtin (see below) does not support logical expressions; test should be used instead (#4777). math is for math, not for logic, know the difference 😤
  • Range expansion will now behave sensibly when given a single positive and negative index ($foo[5..-1] or $foo[-1..5]), clamping to the last valid index without changing direction if the list has fewer elements than expected. sensible ranges, we love a glow-up ⭐
  • read now uses -s as short for --silent (à la bash); --shell's abbreviation (formerly -s) is now -S instead (#4490). note the case, it MATTERS 🙈
  • cd no longer resolves symlinks. fish now maintains a virtual path, matching other shells (#3350). virtual path era 👑
  • source now requires an explicit - as the filename to read from the terminal (#2633). no more ambiguity, bestie 🎀
  • Arguments to end are now errors, instead of being silently ignored. she's calling you out now, respectfully 💅
  • The names argparse, read, set, status, test and [ are now reserved and not allowed as function names. This prevents users unintentionally breaking stuff (#3000). protective, and honestly fair 🫶
  • The fish_user_abbreviations variable is no longer used; abbreviations will be migrated to the new storage format automatically. automatic migration, we love a smooth transition ✨
  • The FISH_READ_BYTE_LIMIT variable is now called fish_byte_limit (#4414). lowercase rebrand 💖
  • Environment variables are no longer split into arrays based on the record separator character on startup. Instead, variables are not split, unless their name ends in PATH, in which case they are split on colons (#436). PATH gets the special treatment, everyone else chill 😌
  • The history builtin's --with-time option has been removed; this has been deprecated in favor of --show-time since 2.7.0 (#4403). out with the old ⭐
  • The internal variables __fish_datadir and __fish_sysconfdir are now known as __fish_data_dir and __fish_sysconf_dir respectively. new name, same energy 🎀

🌸 Deprecations 🌸

With the release of fish 3, a number of features have been marked for removal in the future. All users are encouraged to explore alternatives. A small number of these features are currently behind feature flags, which are turned on at present but may be turned off by default in the future. 👀

A new feature flags mechanism is added for staging deprecations and breaking changes. Feature flags may be specified at launch with fish --features ... or by setting the universal fish_features variable. (#4940) 🚩

  • The use of the IFS variable for read is deprecated; IFS will be ignored in the future (#4156). Use the read --delimiter option instead.
  • The function --on-process-exit switch will be removed in future (#4700). Use the fish_exit event instead: function --on-event fish_exit.
  • $_ is deprecated and will removed in the future (#813). Use status current-command in a command substitution instead.
  • ^ as a redirection is deprecated and will be removed in the future (#4394). Use 2> to redirect stderr. This is controlled by the stderr-nocaret feature flag.
  • ? as a glob (wildcard) is deprecated and will be removed in the future (#4520). This is controlled by the qmark-noglob feature flag.

✨ Notable fixes and improvements ✨

🌈 Syntax changes and new commands

  • fish now supports && (like and), || (like or), and ! (like not), for better migration from POSIX-compliant shells (#4620 <https://github.com/fish-shell/fish-shell/issues/4620>). Bestie, your muscle memory is SAFE now 💅
  • Variables may be used as commands (#154 <https://github.com/fish-shell/fish-shell/issues/154>). Yes literally, a variable can be the main character of your command line 👑
  • fish may be started in private mode via fish --private. Private mode fish sessions do not have access to the history file and any commands evaluated in private mode are not persisted for future sessions. A session variable $fish_private_mode can be queried to detect private mode and adjust the behavior of scripts accordingly to respect the user's wish for privacy 🕵️‍♀️
  • A new wait command for waiting on backgrounded processes (#4498 <https://github.com/fish-shell/fish-shell/issues/4498>). Your background jobs finally get a chaperone 🫶
  • math is now a builtin rather than a wrapper around bc (#3157 <https://github.com/fish-shell/fish-shell/issues/3157>). Floating point computations is now used by default, and can be controlled with the new --scale option (#4478 <https://github.com/fish-shell/fish-shell/issues/4478>). Math class but make it fast ✨
  • Setting $PATH no longer warns on non-existent directories, allowing for a single $PATH to be shared across machines (eg via dotfiles) (#2969 <https://github.com/fish-shell/fish-shell/issues/2969>). No more nagging, we love a chill queen 🎀
  • while sets $status to a non-zero value if the loop is not executed (#4982 <https://github.com/fish-shell/fish-shell/issues/4982>).
  • Command substitution output is now limited to 10 MB by default, controlled by the fish_read_limit variable (#3822 <https://github.com/fish-shell/fish-shell/issues/3822>). Notably, this is larger than most operating systems' argument size limit, so trying to pass argument lists this size to external commands has never worked 😭 (that's not a fish thing, that's a kernel thing, iykyk).
  • The machine hostname, where available, is now exposed as the $hostname reserved variable. This removes the dependency on the hostname executable (#4422 <https://github.com/fish-shell/fish-shell/issues/4422>). One less fork, one more win 🦋
  • Bare bind invocations in config.fish now work. The fish_user_key_bindings function is no longer necessary, but will still be executed if it exists (#5191 <https://github.com/fish-shell/fish-shell/issues/5191>). If you're old-school about it, it still runs, no drama 🫶
  • $fish_pid and $last_pid are available as replacements for %self and %last. Glow-up for the pid girlies 🌸

🧚 New features in commands


🦋 Interactive improvements


🌸 Other fixes and improvements 🌸

  • Significant performance improvements to abbr (#4048), setting variables (#4200, #4341), executing functions, globs (#4579), string reading from standard input (#4610), and slicing history — in particular, $history[1] for the last executed command. Fast fast fast, no cap 🔥
  • fish's internal wcwidth function has been updated to deal with newer Unicode, and the width of some characters can be configured via the fish_ambiguous_width (#5149) and fish_emoji_width (#2652) variables. Alternatively, a new build-time option INTERNAL_WCWIDTH can be used to use the system's wcwidth instead (#4816). Width drama = handled 💅
  • functions correctly supports -d as the short form of --description. (#5105) 🎀
  • /etc/paths is now parsed like macOS' bash path_helper, fixing $PATH order (#4336, #4852) on macOS. Your path is ordered, bestie ✨
  • Using a read-only variable in a for loop produces an error, rather than silently producing incorrect results (#4342). Loud error > silent chaos, always 💀
  • The universal variables filename no longer contains the hostname or MAC address. It is now at the fixed location .config/fish/fish_variables (#1912). Stable address, main character energy 👑
  • Exported variables in the global or universal scope no longer have their exported status affected by local variables (#2611). Boundaries! Set them! 💜
  • Major rework of terminal and job handling to eliminate bugs (#3805, #3952, #4178, #4235, #4238, #4540, #4929, #5210). A whole saga, and it ends in slay 🦋
  • Improvements to the manual page completion generator (#2937, #4313). Yes, the thing that generated the thing you're reading — meta ✨
  • suspend --force now works correctly (#4672). Force it, queen 💅
  • Pressing Ctrl+C while running a script now reliably terminates fish (#5253). FINALLY 😭

🎀 For distributors and developers 🎀

  • fish ships with a new build system based on CMake. CMake 3.2 is the minimum required version. Although the autotools-based Makefile and the Xcode project are still shipped with this release, they will be removed in the near future. All distributors and developers are encouraged to migrate to the CMake build. This is your heads-up, bestie, the autotools era is ending 🫶
  • Build scripts for most platforms no longer require bash, using the standard sh instead. So portable 💖
  • The hostname command is no longer required for fish to operate. One less dependency, we love to see it ✨

🦋 FISH 2.7.1 (RELEASED DECEMBER 23, 2017) 🦋

This release of fish fixes an issue where iTerm 2 on macOS would display a warning about paste bracketing being left on when starting a new fish session (#4521). That weird little warning? Gone. You're welcome 💅

If you are upgrading from version 2.6.0 or before, please also review the release notes for 2.7.0 and 2.7b1 (included below). Don't skip your reading, it's giving responsible user 🌸


👑 FISH 2.7.0 (RELEASED NOVEMBER 23, 2017) 👑

There are no major changes between 2.7b1 and 2.7.0. If you are upgrading from version 2.6.0 or before, please also review the release notes for 2.7b1 (included below). Same homework as above, bestie 🎀

Xcode builds and macOS packages could not be produced with 2.7b1, but this is fixed in 2.7.0. Beta problems, stable-era solutions ✨


🦋 FISH 2.7B1 (RELEASED OCTOBER 31, 2017) 🦋

✨ Notable improvements ✨


🧚 Other significant changes 🧚


🍓 FISH 2.6.0 (RELEASED JUNE 3, 2017) 🍓

So since the beta release of fish 2.6b1, fish version 2.6.0 contains a number of minor fixes, new completions for magneto (#4043 — https://github.com/fish-shell/fish-shell/issues/4043), and improvements to the documentation. Little glow-up era 💅

💀 Known issues 💀

  • Apple macOS Sierra 10.12.5 introduced a problem with launching web browsers from other programs using AppleScript. This affects the fish Web configuration (fish_config) — so if you're on these platforms, you'll need to manually open the address displayed in the terminal, like by copying and pasting it into a browser. Not ideal, ik. This problem will be fixed with macOS 10.12.6.
Heads up, bestie: if you are upgrading from version 2.5.0 or before, please also review the release notes for 2.6b1 (included below). Don't skip them, I'm begging 🫶

🌸 FISH 2.6B1 (released May 14, 2017) 🌸

✨ Notable fixes and improvements ✨

  • Bestie, background jobs can now actually be yeeted off the job list with the brand-new disown builtin, and it behaves exactly like the same command in other shells (#2810). Freedom 💅
  • Command substitutions now get access to the terminal, just like in other shells — so tools like fzf work properly now (#1362, #3922). No more pretending the terminal doesn't exist smh.
  • When the operating system is being unhelpful and won't report the terminal size, the COLUMNS and LINES environment variables are used instead; and if those are unset too, it just assumes a default of 80x24. Iconic fallback behaviour honestly 🫶
  • New French translations (#3772 & #3788) and improved German ones (#3834). Oui oui, ja ja 🇫🇷🇩🇪
  • fish no longer depends on the external which command. It said "not me relying on you" and left 👋

🔥 Other significant changes 🔥

  • Performance improvements in launching processes, including major reductions in signal blocking. Although this has been heavily tested, it may cause problems in some circumstances — if it does, set the FISH_NO_SIGNAL_BLOCK variable to 0 in your fish configuration file to return to the old behaviour (#2007). Consider this your little escape hatch 🚪
  • Performance improvements in prompts and in functions that set lots of colours (#3793). Your prompt is gonna be so fast and so pretty, it's giving main character energy.
  • The Delete key no longer deletes backwards. That was a regression in 2.5.0 and we do NOT talk about it 🙈
  • functions supports a new --details option, which identifies where the function was loaded from (#3295), plus a --details --verbose option that includes the function description (#597). Receipts, and more receipts 💀
  • read will read up to 10 MiB by default, leaving the target variable empty and exiting with status 122 if the line is too long. You can set a different limit with the FISH_READ_BYTE_LIMIT variable.
  • read supports a new --silent option to hide the characters typed (#838), for when you're reading sensitive data from the terminal. Also read now accepts simple strings for the prompt (rather than scripts) with the new -P and --prompt-str options (#802). Secretive AND convenient, we love a multitasker ✨
  • export and setenv now understand colon-separated PATH, CDPATH and MANPATH variables. Slay.
  • setenv is no longer a simple alias for set -gx and will complain, just like the csh version, if you hand it more than one value (#4103). It's got boundaries now 💅
  • bind supports a new --list-modes option (#3872).
  • bg will check all of its arguments before backgrounding any jobs; any invalid arguments cause a failure, but non-existent (eg recently exited) jobs are ignored (#3909). It's thorough, not petty.
  • funced warns if the function you're editing hasn't been modified (#3961). Not me opening the editor and changing nothing 😭
  • printf correctly outputs "long long" integers (#3352). Big numbers, big brain 🧠
  • status supports a new current-function subcommand to print the current function name (#1743).
  • string supports a new repeat subcommand (#3864). string match supports a new --entire option to emit the entire line matched by a pattern (#3957). And string replace supports a new --filter option to only emit lines which underwent a replacement (#3348). The string builtin is literally collecting features like Pokémon rn 🔥
  • test supports the -k option to test for sticky bits (#733). Sticky bits, not sticky vibes.
  • umask understands symbolic modes (#738). Fancy.
  • Empty components in the CDPATH, MANPATH and PATH variables are now converted to "." (#2106, #3914). Tiny change, huge fix, periodt.
  • New versions of ncurses (6.0 and up) wipe terminal scrollback buffers with certain commands; the C-l binding tries to avoid this (#2855). Your scrollback is safe with us 🫶
  • Some systems' su implementations do not set the USER environment variable; it is now reset for root users (#3916).
  • Under terminals which support it, bracketed paste is enabled, escaping problematic characters for security and convenience (#3871). Inside single quotes ('), single quotes and backslashes in pasted text are escaped (#967). The fish_clipboard_paste function (bound to C-v by default) is still the recommended pasting method where possible as it includes this functionality and more. Paste responsibly bestie 🎀
  • Processes in pipelines are no longer signalled as soon as one command in the pipeline has completed (#1926). This behaviour matches other shells more closely. Growth. Maturity. We love to see it ⭐
  • All functions requiring Python work with whichever version of Python is installed (#3970). Python 3 is preferred, but Python 2.6 remains the minimum version required. Equal opportunity Python enjoyer 🐍
  • The colour of the cancellation character can be controlled by the fish_color_cancel variable (#3963). Aesthetic control, as you deserve.

💖 Added completions for: 💖

  • caddy (#4008)
  • castnow (#3744)
  • climate (#3760)
  • flatpak
  • gradle (#3859)
  • gsettings (#4001)
  • helm (#3829)
  • i3-msg (#3787)
  • ipset (#3924)
  • jq (#3804)
  • light (#3752)
  • minikube (#3778)
  • mocha (#3828)
  • mkdosfs (#4017)
  • pv (#3773)
  • setsid (#3791)
  • terraform (#3960)
  • usermod (#3775)
  • xinput
  • yarn (#3816)

🦋 Improved completions for 🦋

adb (#3853), apt (#3771), bzr (#3769), dconf, git (including #3743), grep (#3789), go (#3789), help (#3789), hg (#3975), htop (#3789), killall (#3996), lua, man (#3762), mount (#3764 & #3841), obnam (#3924), perl (#3856), portmaster (#3950), python (#3840), ssh (#3781), scp (#3781), systemctl (#3757) and udisks (#3764). Look at that glow-up, I'm obsessed ✨


🎀 FISH 2.5.0 (released February 3, 2017) 🎀

Ok so there are no major changes between 2.5b1 and 2.5.0. If you're upgrading from version 2.4.0 or before, please also review the release notes for 2.5b1 (included below). Just a lil heads up bestie, no cap 🫶

✨ Notable fixes and improvements ✨

  • The Home, End, Insert, Delete, Page Up and Page Down keys work in Vi-style key bindings (#3731). All six of them, working, as they should. We love a functional keyboard era 💅

🦋 FISH 2.5B1 (RELEASED JANUARY 14, 2017) 🦋

💻 Platform Changes

okay so starting with version 2.5, fish needs a more up-to-date version of C++, specifically C++11 (from 2011). This affects some older platforms:

🐧 Linux

For users building from source, GCC's g++ 4.8 or later, or LLVM's clang 3.3 or later, are known to work. Older platforms may require a newer compiler installed.

Unfortunately, because of the complexity of the toolchain, binary packages are no longer published by the fish-shell developers for the following platforms:

  • Red Hat Enterprise Linux and CentOS 5 & 6 for 64-bit builds
  • Ubuntu 12.04 (EoLTS April 2017)
  • Debian 7 (EoLTS May 2018)

Installing newer version of fish on these systems will require building from source.

🍎 OS X SnowLeopard

Starting with version 2.5, fish requires a C++11 standard library on OS X 10.6 ("SnowLeopard"). If this library is not installed, you will see this error: dyld: Library not loaded: /usr/lib/libc++.1.dylib

MacPorts is the easiest way to obtain this library. After installing the SnowLeopard MacPorts release from the install page, run:

sudo port -v install libcxx

Now fish should launch successfully. (Please open an issue if it does not.)

This is only necessary on 10.6. OS X 10.7 and later include the required library by default.

✨ Other significant changes

🛠️ Notable fixes and improvements


🎀 FISH 2.4.0 (RELEASED NOVEMBER 8, 2016) 🎀

There are no major changes between 2.4b1 and 2.4.0.

🌸 Notable fixes and improvements

  • The documentation is now generated properly and with the correct version identifier.
  • Automatic cursor changes are now only enabled on the subset of XTerm versions known to support them, resolving a problem where older versions printed garbage to the terminal before and after every prompt (#3499 — https://github.com/fish-shell/fish-shell/issues/3499).
  • Improved the title set in Apple Terminal.app.
  • Added completions for defaults and improved completions for diskutil (#3478 — https://github.com/fish-shell/fish-shell/issues/3478).

FISH 2.4B1 (RELEASED OCTOBER 18, 2016)

✨ Significant changes ✨

🎀 Notable fixes and improvements 🎀


FISH 2.3.1 (RELEASED JULY 3, 2016)

Okay so this one is a functionality and bugfix release. Heads up though — this release does not contain all the changes to fish since the last release, but it fixes a number of issues directly affecting users at present and includes a small number of new features. Not a full makeover, more like a targeted touch-up 💅

🌸 Significant changes 🌸

🦋 Notable fixes and improvements 🦋

🎀 FISH 2.3.0 (RELEASED MAY 20, 2016) 🎀

okay so bestie, real talk: there are, like, literally no significant changes between 2.3.0 and 2.3b2. That's it. That's the whole vibe. Moving on. ✨

💅 Other notable fixes and improvements

  • abbr now allows non-letter keys (#2996). yes queen, keys that aren't letters. we love flexibility.
  • Define a few extra colours on first start (#2987). first impressions matter, so we're coming in with a full palette. 🌈
  • Multiple documentation updates. the docs got a glow-up.
  • Added completions for rmmod (#3007). so you can't forget how modules work while you're removing them.
  • Improved completions for git (#2998). git completions keep getting better and honestly? obsessed.

😭 Known issues

  • Interactive commands started from fish configuration files or from the -c option may, under certain circumstances, be started with incorrect terminal modes and fail to behave as expected. A fix is planned but requires further testing (#2619). lowkey a real one — so heads up, this is a genuine known bug, not a vibe, and the fix is still marinating.

🦋 FISH 2.3B2 (RELEASED MAY 5, 2016) 🦋

✨ Significant changes

  • A new fish_realpath builtin and associated function to allow the use of realpath even on those platforms that don't ship an appropriate command (#2932). no realpath on your system? not anymore bestie.
  • Alt+# toggles the current command line between commented and uncommented states, making it easy to save a command in history without executing it. the way that just… saves a command to history without running it? main character energy fr. 👑
  • The fish_vi_mode function is now deprecated in favour of fish_vi_key_bindings. deprecated means move on, babe — use the new name.

💖 Other notable fixes and improvements

  • Fix the build on Cygwin (#2952) and RedHat Enterprise Linux/CentOS 5 (#2955). we build where you build.
  • Avoid confusing the terminal line driver with non-printing characters in fish_title (#2453). the terminal line driver was getting confused and we said no more of that.
  • Improved completions for busctl, git (#2585, #2879, #2984), and netctl. completion sweep, slay. 🧚

🌸 FISH 2.3B1 (RELEASED APRIL 19, 2016) 🌸

🔥 Significant Changes

  • A new string builtin to handle… strings! This builtin will measure, split, search and replace text strings, including using regular expressions. It can also be used to turn lists into plain strings using join. string can be used in place of sed, grep, tr, cut, and awk in many situations. (#2296) — okay this is THE moment. it's giving builtin that eats the classic tools' lunch. iconic. 💅
  • Allow using escape as the Meta modifier key, by waiting after seeing an escape character wait up to 300ms for an additional character. This is consistent with readline (e.g. bash) and can be configured via the fish_escape_delay_ms variable. This allows using escape as the Meta modifier. (#1356) — note the number, 300ms, and the variable name fish_escape_delay_ms, bestie, they're all doing work here.
  • Add new directories for vendor functions and configuration snippets (#2500). vendor stuff gets its own lil home.
  • A new fish_realpath builtin and associated realpath function should allow scripts to resolve path names via realpath regardless of whether there is an external command of that name; albeit with some limitations. See the associated documentation. limitations are mentioned, so go read the docs, i'm not making things up.

💀 Backward-incompatible changes

bestie, this whole list is stuff that WILL break your old setup. read it. absorb it. i'm serious. 😭
  • Unmatched globs will now cause an error, except when used with for, set or count (#2719).
  • and and or will now bind to the closest if or while, allowing compound conditions without begin and end (#1428).
  • set -ql now searches up to function scope for variables (#2502).
  • status -f will now behave the same when run as the main script or using source (#2643).
  • source no longer puts the file name in $argv if no arguments are given (#139).
  • History files are stored under the XDG_DATA_HOME hierarchy (by default, in ~/.local/share), and existing history will be moved on first use (#744). your history is moving house and honestly it'll be happier there.

🍓 Other notable fixes and improvements

  • fish no longer silences errors in config.fish (#2702). if something's wrong in there, you'll hear about it now. no more secrets.
  • Directory autosuggestions will now descend as far as possible if there is only one child directory (#2531). it just keeps going down. as far as possible. one child at a time.
  • Add support for bright colors (#1464). brights are in, we're glowing. ✨
  • Allow Ctrl+J (\cj) to be bound separately from Ctrl+M (\cm) (#217). they were previously the same party and now they get their own.
  • psub now has a -s/-suffix option to name the temporary file with that suffix. yes the quotes in the original are curly, the flag is -s and the long one is -suffix, that's the whole deal.
  • Enable 24-bit colors on select terminals (#2495). 24-BIT COLOR. on select terminals, so don't come for me if yours isn't one.
  • Support for SVN status in the prompt (#2582).
  • Mercurial and SVN support have been added to the Classic + Git (now Classic + VCS) prompt (via the new __fish_vcs_prompt function) (#2592). it's not just git anymore, it's a whole VCS situation.
  • export now handles variables with a = in the value (#2403). yes, the value. the = inside the value. handled.
  • New completions for:
    • alsactl
    • Archlinux's asp, makepkg
    • Atom's apm (#2390)
    • entr - the "Event Notify Test Runner" (#2265)
    • Fedora's dnf (#2638)
    • OSX diskutil (#2738)
    • pkgng (#2395)
    • pulseaudio's pacmd and pactl
    • rust's rustc and cargo (#2409)
    • sysctl (#2214)
    • systemd's machinectl (#2158), busctl (#2144), systemd-nspawn, systemd-analyze, localectl, timedatectl
    • and more
  • fish no longer has a function called sgrep, freeing it for user customization (#2245). it's yours now. name your child sgrep if you want.
  • A rewrite of the completions for cd, fixing a few bugs (#2299, #2300, #562). the cd completions got a full makeover and honestly she's serving.
  • Linux VTs now run in a simplified mode to avoid issues (#2311).
  • The vi-bindings now inherit from the emacs bindings.
  • fish will also execute fish_user_key_bindings when in vi-mode. yes, even in vi-mode. equal treatment. 🫶
  • funced will now also check $VISUAL (#2268).
  • A new suspend function (#2269).
  • Subcommand completion now works better with split /usr (#2141).
  • The command-not-found-handler can now be overridden by defining a function called __fish_command_not_found_handler in config.fish (#2332). your handler, your rules.
  • A few fixes to the Sorin theme. a lil touch-up, she's fine.
  • PWD shortening in the prompt can now be configured via the fish_prompt_pwd_dir_length variable, set to the length per path component (#2473).
  • fish no longer requires /etc/fish/config.fish to correctly start, and now ships a skeleton file that only contains some documentation (#2799). it boots without it bestie, the skeleton file is just vibes and docs.

🌸 FISH 2.2.0 (RELEASED JULY 12, 2015) 🌸

✨ Significant changes ✨

  • Abbreviations, bestie!! The brand-new abbr command gives you interactively-expanded abbreviations, so your most-used commands are literally right there at your fingertips (#731 — https://github.com/fish-shell/fish-shell/issues/731). Obsessed.
  • Vi mode is here 🎀 — run fish_vi_mode and fish switches into the key bindings and the prompt that Vi editor girlies already know and love (#65 — https://github.com/fish-shell/fish-shell/issues/65).
  • A brand-new inline and interactive pager that the zsh crowd will feel right at home with (#291 — https://github.com/fish-shell/fish-shell/issues/291). Iconic.
  • Underlying architectural changes, and this one's the big one 👑 — the fishd universal variable server has been removed, because it was a whole source of many bugs and security problems. Heads up though: old fish sessions will not be able to communicate universal variable changes with new fish sessions. For best results, restart all running instances of fish. No cap.
  • The web-based configuration tool got a glow-up 💅 — it's been redesigned, and it features a prompt theme chooser plus other improvements.
  • New translations in German, Brazilian Portuguese, and Chinese 🌈.

💀 Backward-incompatible changes 💀

These are kept to a minimum, but they either change undocumented features or are just too hard to use in their existing forms. Ngl, these changes may break existing scripts.


🔥 Other notable fixes and improvements 🔥


🦋 FISH 2.1.2 (RELEASED FEB 24, 2015) 🦋

fish 2.1.2 contains a workaround for a filesystem bug in Mac OS X Yosemite 💀. #1859 — https://github.com/fish-shell/fish-shell/issues/1859

Specifically, after installing fish 2.1.1 and then rebooting, "Verify Disk" in Disk Utility will report "Invalid number of hard links." We don't have any reports of data loss or other adverse consequences, okay? Breathe. fish 2.1.2 avoids triggering the bug, but it does not repair an already affected filesystem. To repair the filesystem, you can boot into Recovery Mode and use Repair Disk from Disk Utility. Linux and versions of OS X prior to Yosemite are believed to be unaffected 🫶.

There are no other changes in this release.

💖 FISH 2.1.1 (RELEASED SEPTEMBER 26, 2014) 💖

Important: bestie if you're upgrading, stop all running instances of fishd as soon as possible after installing this release — it'll restart itself automatically, don't worry. On most systems there's literally nothing else you need to do. But heads up: some environments (the ones where XDG_RUNTIME_DIR is set), like Fedora 20, will need you to restart all running fish processes before universal variables work the way they're supposed to. 😭

Distributors, please — you're highly encouraged to call killall fishd, pkill fishd or something similar in your installation scripts, or at least warn your users to do it themselves. 🫶


🔒 Security fixes

  • The fish_config web interface now uses an authentication token to protect requests, and it only responds to requests from the local machine that carry this token — which prevents a remote code execution attack. (closing CVE-2014-2914). #1438
  • psub and funced are no longer vulnerable to attacks which allow local privilege escalation and data tampering (closing CVE-2014-2906 and CVE-2014-3856). #1437
  • fishd uses a secure path for its socket, which prevents a local privilege escalation attack (closing CVE-2014-2905). #1436
  • __fish_print_packages is no longer vulnerable to attacks which would allow local privilege escalation and data tampering (closing CVE-2014-3219). #1440

✨ Other fixes

  • fishd now ignores SIGPIPE, which fixes crashes when using tools like GNU Parallel — crashes that happened more often as a result of the other fishd changes, ngl. #1084 & #1690

🦋 FISH 2.1.0 🦋

🌟 Significant Changes

  • Tab completions will fuzzy-match files. #568

Okay so when you tab-complete a file, fish first tries prefix matches (foo matches foobar), then substring matches (ooba matches foobar), and lastly subsequence matches (fbr matches foobar). Example time: in a directory with files foo1.txt, foo2.txt, foo3.txt…, you can type just the numeric part and hit tab to fill in the rest. obsessed.

This feature is implemented for files and executables. It is not yet implemented for options (like --foobar), and not yet implemented across path components (like /u/l/b to match /usr/local/bin).

  • Redirections now work better across pipelines. #110, #877

In particular, you can pipe stderr and stdout together — for example with cmd ^&1 | tee log.txt, or the more familiar cmd 2>&1 | tee log.txt.

  • A single % now expands to the last job backgrounded. #1008

Before this, a single % would pid-expand to either all backgrounded jobs, or all jobs owned by your user. Now it expands to the last job backgrounded. And if no job is in the background, it'll just fail to expand. So in particular, fg % can be used to put the most recent background job in the foreground. 💅


🔥 Other Notable Fixes

  • alt+U and alt+C now uppercase and capitalize words, respectively. #995
  • VTE based terminals should now know the working directory. #906
  • The autotools build now works on Mavericks. #968
  • The end-of-line binding (ctrl+E) now accepts autosuggestions. #932
  • Directories in /etc/paths (used on OS X) are now prepended instead of appended, similar to other shells. #927
  • Option-right-arrow (used for partial autosuggestion completion) now works on iTerm2. #920
  • Tab completions now work properly within nested subcommands. #913
  • printf supports \e, the escape character. #910
  • fish_config history no longer shows duplicate items. #900
  • $fish_user_paths is now prepended to $PATH instead of appended. #888
  • Jobs complete when all processes complete. #876

For example, in previous versions of fish, sleep 10 | echo Done returns control immediately, because echo does not read from stdin. Now it does not complete until sleep exits (presumably after 10 seconds). character development tbh

  • Better error reporting for square brackets. #875
  • fish no longer tries to add /bin to $PATH unless PATH is totally empty. #852
  • History token substitution (alt+up) now works correctly inside subshells. #833
  • Flow control is now disabled, freeing up ctrl+S and ctrl+Q for other uses. #814
  • sh-style variable setting like foo=bar now produces better error messages. #809
  • Commands with wildcards no longer produce autosuggestions. #785
  • funced no longer freaks out when supplied with no arguments. #780
  • fish.app now works correctly in a directory containing spaces. #774
  • Tab completion cycling no longer occasionally fails to repaint. #765
  • Comments now work in eval'd strings. #684
  • History search (up-arrow) now shows the item matching the autosuggestion, if that autosuggestion was truncated. #650
  • Ctrl+T now transposes characters, as in other shells. #128

<h2>🌸 Other Notable Fixes 🌸</h2>


🦋 FISHFISH BETA R2 🦋

<h2>🐛 Bug Fixes 🐛</h2>

  • Implicit cd is back — for paths that start with one or two dots, a slash, or a tilde 💖
  • overrides of default functions should be fixed. The "internalized scripts" feature is disabled for now.
  • disabled delayed suspend. That's a strange job-control feature of BSD systems, OS X included. Disabling it frees up Control+Y for other stuff — specifically for yank, which now works on OS X.
  • fish_indent is fixed. Especially, funced and funcsave work again.
  • a SIGTERM ends the whole execution stack again now (resolving #13 — https://github.com/fish-shell/fish-shell/issues/13).
  • bumped the __fish_config_interactive version number so the default fish_color_autosuggestion actually kicks in.
  • fish_config handles combined term256 and classic colors better — like "555 yellow".

<h2>🌻 New Features 🌻</h2>

  • A history builtin, plus an associated interactive function that lets you delete history items. Example usage:
    • print all history items beginning with echo: history --prefix echo
    • print all history items containing foo: history --contains foo
    • interactively delete some items containing foo: history --delete --contains foo

Credit to @siteshwar for implementation. Thanks @siteshwar! 🫶


👑 FISHFISH BETA R1 👑

🧚 Scripting

  • No changes! Like, literally zero 💅 Every single fish script, config file, completion, etc. from trunk should keep on working like nothing happened. Bestie behavior only.

✨ New Features ✨

  • Autosuggestions 🩷 Think, like, the URL field in your browser. When you type a command, fish will suggest the rest of it after the cursor, in a muted gray when possible. You can accept that suggestion with the right arrow key or Ctrl+F. Where do the suggestions come from? Command history, completions, and some custom code for cd — and there's a lot of potential for improvement here. The suggestions are computed on a background pthread, so they never slow down your typing. The autosuggestion feature is incredible. The author misses it dearly every time they use anything else 😭🔥
  • term256 support where available, specifically modern xterms and OS X Lion 🌈 You can specify colors the old way (set_color cyan) or by specifying RGB hex values (set_color FF3333); fish will pick the closest supported color. Some xterms do not advertise term256 support either in the $TERM or terminfo max_colors field, but nevertheless support it. For that reason, fish will default into using it on any xterm (but it can be disabled with an environment variable) 👀
  • Web-based configuration page 🎀 There's a new function, fish_config. It spins up a simple Python web server and opens a browser window to it. From this web page you can set your shell colors and view your functions, variables, and history — and all changes apply immediately to all running shells. Eventually all configuration ought to be supported via this mechanism (but in addition to, not instead of, command line mechanisms). Both vibes, no rivalry 💖
  • Man page completions 🦋 There's a new function, fish_update_completions. It reads all the man1 files from your manpath, removes the roff formatting, parses them to find the commands and options, and outputs fish completions into ~/.config/fish/completions. It won't overwrite existing completion files (except ones that it generated itself). Respectful queen behavior 👑

🛠️ Programmatic Changes

  • fish is now entirely in C++ 💀 The author has no particular love for C++, but it provides a ready memory-model to replace halloc. They've made an effort to keep it to a sane and portable subset (no C++11, no boost, no going crazy with templates or smart pointers), but they do use the STL and a little tr1.
  • halloc is entirely gone, replaced by normal C++ ownership semantics. If you don't know what halloc is, well, now you have two reasons to be happy 😌
  • All the crufty C data structures are entirely gone 🧹 array_list_t, priority_queue_t, hash_table_t, string_buffer_t have been removed and replaced by STL equivalents like std::vector, std::map, and std::wstring. A lot of the string handling now uses std::wstring instead of wchar_t *.
  • fish now spawns pthreads for tasks like syntax highlighting that require blocking I/O 🧵
  • History has been completely rewritten 📜 History files now use an extensible YAML-style syntax. History "merging" (multiple shells writing to the same history file) now works better. There is now a maximum history length of about 250k items (256 * 1024).
  • The parser has been "instanced," so you can now create more than one 👯‍♀️
  • Total #LoC has shrunk slightly even with the new features. Less code, more slay, that's the dream 🍓

⚡ Performance

  • fish now runs syntax highlighting in a background thread, so typing commands is always responsive even on slow filesystems 🏃‍♀️💨
  • echo, test, and pwd are now builtins, which eliminates many forks 🔥
  • The files in share/functions and share/completions now get 'internalized' into C strings that get compiled in with fish. This substantially reduces the number of files touched at startup. A consequence is that you cannot change these functions without recompiling — but often other functions depend on these "standard" functions, so changing them is perhaps not a good idea anyways 🙈
Here are some system call counts for launching and then exiting fish with the default configuration, on OS X. The first column is fish trunk, the next column is with our changes, and the last column is bash for comparison. This data was collected via dtrace.
  • open — before: 9, after: 4, bash: 5
  • fork — before: 28, after: 14, bash: 0
  • stat — before: 131, after: 85, bash: 11
  • lstat — before: 670, after: 0, bash: 0
  • read — before: 332, after: 80, bash: 4
  • write — before: 172, after: 149, bash: 0

The large number of forks relative to bash are due to fish's insanely expensive default prompt, which is unchanged in my version. If we switch to a prompt comparable to bash's (lame) default, the forks drop to 16 with trunk, 4 after our changes 👀

The large reduction in lstat() numbers is due to fish no longer needing to call ttyname() on OS X 🎉

We've got some work to do to be as lean as bash, but we're on the right track 💪


🌸 Author

fish-shell developers

fish-shell developers


And that's a wrap on the whole page, bestie 🎬💖 This one was rendered under version 4.9, dated Sep 08, 2026, and it's the FISH-RELEASENOTES(1) manual page — go forth and flex your history knowledge, ilysm 🌈👑✨

📦 where this page comes from
  • arch rolling: fish 4.9.3-1 · GPL-2.0-only AND BSD-3-Clause AND ISC AND MIT AND PSF-2.0
  • 💖 girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms