Skip to main content
โšก Calmops

Fish Shell 4.0: The Modern CLI Shell Built with Rust

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:

  1. Memory Safety: Buffer overflows, null pointer dereferences
  2. Thread Safety: Data races, deadlock risks
  3. Toolchain: Complex build systems, poor cross-platform support
  4. 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.
# 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

  1. Slow startup: Check for expensive commands in config.fish
  2. Missing completions: Install package-specific completions
  3. Script errors: Use fish -n script.fish to debug
  4. Performance: Run fish --profile /tmp/profile.log to 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


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