Fish Shell 4.9.0 Drops a Konsole Bug, Plus 18 New Committers
The September 3 release tackles a scrolling regression, cleans up old regressions, and quietly improves the scripting engine.
Fish 4.9.0 is live, and it finally stops breaking terminal scrolling in KDE Konsole. Lead maintainer Johannes Altmanninger pushed the new stable release on Wednesday, closing out a two-month development cycle. It is a solid, if narrowly provoked, update.
The whole release really kicks off from a single user report on the bug tracker. Back in late August, [@pfactum] documented that Shift+PageUp and friends just stopped responding while fish waited for input. Turned out Konsole's new implementation of the kitty keyboard protocol was leaking escape sequences straight into fish's stdin. The shell wasn't intercepting them, but Konsole wasn't handling them either. You were stuck.
The Konsole Problem (and the Escape Hatch)
"The reporter traced this with strace and found fish reading escape sequences like \33[5;2~ from its file descriptor," Altmanninger noted in the release notes. Konsole's buggy protocol handling was essentially gaslighting the shell.
Fish 4.9.0 resolves the mess by detecting Konsole and skipping the kitty keyboard protocol request entirely. No more conflicting escape sequences. If you are a power user who really wants the protocol on Konsole despite the regression, there is a new escape hatch.
set --global fish_feature_flags omit-term-workarounds
It is a pragmatic move, though it highlights how messy terminal emulator compatibility has become. The long-running war between kitty's protocol extensions and legacy terminal behaviors is something shell developers probably wish they did not have to mediate. The opt-in flag approach respects both sides without forcing a hard break.
More Interactive Tweaks and Parser Cleanup
There is a handful of other usability improvements stacked on top of the Konsole fix. On terminals that support it, Shift+Space and plain Space can now be mapped independently, which finally untangles a long-standing keybinding headache. Tab completion also gets a speed boost in directories littered with slow-resolving symlinks, a common complaint among people juggling NFS or SMB mounts.
Vi mode commands like cF and cT are restored after a couple of regressions, and abbr definitions now show descriptions in the completion pager. If you have built up a long list of custom abbreviations, you will actually remember what they do without digging through your config.
On the scripting side, the parser got some long-overdue surgery. Nested list indexing like $foo[$bar[1] 2] now actually works. Escaped square brackets will no longer be misinterpreted as slicing operators, and variables containing closing brackets will not prematurely truncate array slices. The builtin help system also finally respects user overrides of man, which feels like it should have been fixed three releases ago.
Maybe the most quietly important change is that commands like status=123 echo $status now throw an error instead of silently swallowing a variable that conflicts with a protected name. It is the kind of breaking change that prevents nasty bugs in production scripts. Not exactly intuitive, but absolutely necessary.
The release also knocks out three regressions that had been lingering since the Rust rewrite. Chinese and Japanese C library error messages are fixed, the shell correctly blocks erasing read-only variables again, and the fg builtin finally works on NetBSD after being broken since version 4.0. Fish is now twenty-one years old, and the parser cleanup shows the Rust transition is still paying dividends.
If you are tracking the release schedule, 4.9.0 slots right into the typical two-month cadence. It follows the bugfix-only 4.8.1 and uses the same feature-flag system introduced in earlier 4.x releases. Translation work now uses Fluent for the Rust core, though scripts still rely on gettext.
Head here to download the release from GitHub.
