Introduction
The command line is getting a major upgrade. Fish Shell 4.0, released in early 2025, represents the most significant rewrite of this popular shell since its inception. The entire core has been rewritten in Rust, bringing modern memory safety, improved performance, and better cross-platform support.
In this guide, we’ll explore everything about Fish Shell 4.0, from its technical foundations to practical migration strategies.
What is Fish Shell?
Fish (Friendly Interactive Shell) is a smart command line shell for Linux, macOS, and other Unix systems. Unlike Bash or Zsh, Fish is designed from the ground up to be user-friendly with:
- Smart suggestions: Based on history and completions
- Syntax highlighting: Colorized commands as you type
- Out-of-the-box: No configuration needed
- Web-based configuration: Easy setup via browser
Why Fish Matters
Fish has always been different:
| Feature | Bash/Zsh | Fish |
|---|---|---|
| Configuration | Text files | Web UI |
| Completions | Manual | Automatic |
| Syntax | Legacy | Modern |
| Defaults | Minimal | Feature-rich |
Why Rust? The Big Rewrite
Problems with C++
The original Fish Shell was written in C++, which presented several challenges:
- Memory Safety: Buffer overflows, null pointer dereferences
- Thread Safety: Data races, deadlock risks
- Toolchain: Complex build systems, poor cross-platform support
- Contributions: High barrier to entry for new developers
Why Rust Solves These Issues
// Memory safety: Rust prevents these at compile time
// - Buffer overflows
// - Null pointer dereferences
// - Use-after-free
// - Data races
fn process_command(input: &str) -> Result<Command, Error> {
// Compiler ensures safety
let parsed = parse(input)?;
Ok(Command::new(parsed))
}
Benefits of the Rewrite
| Aspect | C++ (Pre-4.0) | Rust (4.0) |
|---|---|---|
| Memory Safety | Manual | Compile-time enforced |
| Performance | Good | Better |
| Thread Safety | Complex | Built-in |
| Cross-platform | Variable | Excellent |
| Maintenance | Difficult | Sustainable |
New Features in Fish 4.0
1. Improved Performance
The Rust rewrite brings significant speed improvements:
- Faster startup: < 10ms cold start
- Responsive completions: Near-instant suggestions
- Reduced memory: Lower RAM footprint
- Better scaling: Handles large histories efficiently
2. Enhanced Completions
# Fish 4.0 completions are smarter
git commit -m "fix: resolve" # Suggests conventional commit types
docker run -p # Suggests common port mappings
npm install # Shows available packages
3. Better Scripting
# Modern Fish scripting
function deploy --description "Deploy application"
set -l stage $argv[1]
# Pattern matching
switch $stage
case production
echo "Deploying to production..."
case staging
echo "Deploying to staging..."
case '*'
echo "Unknown stage: $stage"
return 1
end
# Parallel execution
if type -q parallel
echo "Running tasks in parallel..."
end
end
4. Improved Async Support
# Background operations
background --name my-task "long-running-command"
jobs # List background tasks
fg my-task # Bring to foreground
Installation
macOS
# Using Homebrew
brew install fish-shell
# Add to shells
echo "/usr/local/bin/fish" | sudo tee -a /etc/shells
# Set as default
chsh -s /usr/local/bin/fish
Linux
# Ubuntu/Debian
sudo apt install fish
# Fedora
sudo dnf install fish
# Arch
sudo pacman -S fish
From Source
# Install Rust first
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Clone and build
git clone https://github.com/fish-shell/fish-shell.git
cd fish-shell
cargo build --release
sudo ./target/release/fish --version
Configuration
Web-Based Setup
# Open configuration in browser
fish_config
This opens a web interface for:
- Theme selection
- Key bindings
- Functions
- History
- Completions
Configuration File
# ~/.config/fish/config.fish
# Set environment variables
set -gx EDITOR vim
set -gx VISUAL vim
# Aliases
alias ll 'ls -la'
alias gs 'git status'
alias gco 'git checkout'
# Functions
function fish_greeting
echo "Welcome to Fish 4.0!"
end
# Prompt
starship init fish | source
Migrating from Bash
Key Differences
| Bash | Fish |
|---|---|
if [ $x = "y" ] |
if test "$x" = "y" |
$(command) |
(command) |
$var |
$var (same) |
${var} |
$var (same) |
export VAR=value |
set -gx VAR value |
Converting Scripts
Before (Bash)
#!/bin/bash
for file in *.txt; do
echo "Processing $file"
cat "$file" | wc -l
done
After (Fish)
#!/usr/bin/fish
for file in *.txt
echo "Processing $file"
cat "$file" | wc -l
end
Bash Compatibility Mode
Fish can run many Bash scripts:
# Enable bash compatibility
source /usr/share/fish/functions/bass.fish
bass 'bash_script.sh'
Essential Fish Features
1. Syntax Highlighting
Fish highlights commands as you type:
- Red: Invalid commands
- Blue: Variables
- Green: Executables
- Yellow: Comments
2. Autosuggestions
# Type partial command
git chec
# Fish suggests:
git checkout <branch>
# Press โ to accept
3. Tab Completion
# Press Tab for completions
git commit -<Tab>
# Shows: -a, --amend, --message, etc.
docker run -<Tab>
# Shows: -d, -p, -v, --name, etc.
4. History Search
# Press Ctrl+R to search
# Type to filter
# Press Enter to execute
Customization
Using Oh My Fish
# Install Oh My Fish
curl -L https://get.oh-my.fish | fish
# Install theme
omf install bobthefish
# Install plugins
omf install fzf
Starship Prompt
# Install starship
curl -sS https://starship.rs/install.sh | sh
# Add to config.fish
starship init fish | source
Functions
# Create a function
function mkcd
mkdir -p $argv[1]
cd $argv[1]
end
# Save to functions directory
functions save mkcd
Performance Comparison
Startup Time
| Shell | Cold Start | Warm Start |
|---|---|---|
| Fish 4.0 | 8ms | 2ms |
| Fish 3.x | 45ms | 10ms |
| Bash | 50ms | 5ms |
| Zsh | 80ms | 15ms |
Memory Usage
| Shell | RSS |
|---|---|
| Fish 4.0 | 18MB |
| Fish 3.x | 28MB |
| Bash | 22MB |
| Zsh | 35MB |
Best Practices
1. Use Abbreviations
# Instead of typing full commands
abbr --add g git
abbr --add gs git status
abbr --add ga git add
abbr --add gc git commit
2. Leverage Universal Variables
# Set once, available everywhere
set -U EDITOR vim
3. Use Fish-Specific Tools
# fisher - package manager
fisher install jorgebucaran/fisher
# fzf - fuzzy finder
fisher install PatrickF1/fzf.fish
4. Write Functions, Not Scripts
# Better: function
function backup
tar -czf backup.tar.gz .
end
# Use: backup
Troubleshooting
Common Issues
- Slow startup: Check for expensive commands in config.fish
- Missing completions: Install package-specific completions
- Script errors: Use
fish -n script.fishto debug - Performance: Run
fish --profile /tmp/profile.logto analyze
Getting Help
# Built-in help
help
help function
# Manual pages
man fish
# Official docs
# https://fishshell.com/docs/current/
Tools and Resources
Official Resources
Related Tools
Related Articles
Conclusion
Fish Shell 4.0 represents a major step forward for this friendly shell. The Rust rewrite brings:
- Better performance: Faster startup and execution
- Memory safety: No more buffer overflows
- Modern development: Sustainable codebase
- Cross-platform: Consistent everywhere
Whether you’re new to Fish or a longtime user, version 4.0 offers compelling reasons to upgrade. The out-of-the-box experience is better than ever, and the performance improvements are noticeable in daily use.
Key takeaways:
- Rust rewrite improves safety and performance
- Better completions boost productivity
- Easy migration from Bash
- Active development ensures future improvements
Comments