---
title: "Fish Shell Autocomplete & Suggestions Guide"
description: "How Fish Shell's autosuggestions and tab completions work, how to configure them, and how to write your own custom completions."
date: 2026-02-22
categories: ["vps"]
tags: ["fish-shell"]
---

import Notice from "@components/widgets/Notice.astro";

The first thing people notice when they open Fish is the autosuggestions. You start typing and gray text appears after your cursor, predicting what you want. It feels like the shell can read your mind. Compared to [Bash or Zsh](/fish-shell-vs-bash-vs-zsh/), where you need plugins for anything like this, Fish just does it from a fresh install.

This guide covers how both systems work — autosuggestions (the gray inline predictions) and tab completions (the menu that appears when you press Tab) — and how to configure and extend them.

## Autosuggestions

Autosuggestions are the grayed-out text that appears as you type. Fish pulls these from two sources: your command history and available completions (file paths, command names, etc.). History matches take priority, so the more you use a command, the faster it appears as a suggestion.

### How to accept suggestions

- **Right arrow** — accept the entire suggestion
- **Alt+Right arrow** (or `Alt+F`) — accept one word at a time
- **Ctrl+F** — same as right arrow, accept the full suggestion
- Keep typing — ignore the suggestion entirely

Accepting word by word is useful when the suggestion is close but not exactly what you want. If Fish suggests `git commit -m "fix auth bug"` and you want `git commit -m "fix login flow"`, press `Alt+Right` three times to accept `git commit -m` and then type your own message.

### How Fish ranks suggestions

Fish picks suggestions based on:

1. Commands from your history that match what you've typed so far, most recent first
2. File paths and completions that match the current context

If you've run `docker compose up -d` twenty times this week, typing `do` will almost certainly suggest that full command.

### Disabling autosuggestions

Some people find them distracting. Turn them off:

```fish
set -g fish_autosuggestion_enabled 0
```

Add that to `~/.config/fish/config.fish` to make it permanent.

## Tab completions

Press Tab and Fish shows possible completions in a pager-style menu below your command line. Each completion comes with a description, so you're not guessing what `-v` does for a particular command.

### How to navigate the completion menu

- **Tab** — open completions, or cycle forward through them
- **Shift+Tab** — cycle backward
- **Arrow keys** — navigate the completion list
- **Enter** — select the highlighted completion
- **Ctrl+S** — open a search prompt within the completion menu (useful when there are many results)

### Where completions come from

Fish pulls completions from several sources:

**Man pages.** Fish parses man pages in the background and generates completions for command flags and options. This is why `rsync --` followed by Tab shows you every `rsync` flag with descriptions, right out of the box.

**Built-in completions.** Fish ships with hand-written completion scripts for hundreds of commands: `git`, `docker`, `ssh`, `systemctl`, `apt`, `brew`, `npm`, and many more. These are stored in Fish's data directory (usually `/usr/share/fish/completions/`).

**Custom completions.** You can write your own. More on this below.

**File paths.** Fish completes file and directory names by default when no other completions match.

### Forcing file completion

Sometimes Fish's smart completions hide file paths. Press `Alt+E` (or `Alt+O` on some systems) to explicitly complete a file path, bypassing the programmed completions.

## Writing custom completions

This is where Fish's completion system gets interesting. You can add completions for your own scripts, internal tools, or commands that don't have good completions yet.

Completion files go in `~/.config/fish/completions/` and are named after the command: `mycommand.fish` for the command `mycommand`.

### Basic example

Say you have a script called `deploy` that takes subcommands `staging`, `production`, and `rollback`:

```fish
# ~/.config/fish/completions/deploy.fish

# Disable file completions (deploy doesn't take filenames)
complete -c deploy -f

# Add subcommands
complete -c deploy -a "staging production rollback" -d "Deployment target"

# Add flags
complete -c deploy -s v -l verbose -d "Verbose output"
complete -c deploy -s d -l dry-run -d "Show what would happen without doing it"
```

Now `deploy` followed by Tab shows your three subcommands, and `deploy --` shows the two flags.

### Context-aware completions

Completions can be conditional. Use `-n` (condition) to show certain completions only in certain contexts:

```fish
# Only show these when no subcommand has been given yet
complete -c deploy -n "not __fish_seen_subcommand_from staging production rollback" \
    -a "staging production rollback"

# Only show branch names after "deploy staging"
complete -c deploy -n "__fish_seen_subcommand_from staging" \
    -a "(git branch --format='%(refname:short)')" -d "Git branch"
```

The `__fish_seen_subcommand_from` helper function checks whether any of the given words have appeared in the command line. Fish ships with several helper functions like this — look through `/usr/share/fish/completions/git.fish` for a real-world example.

### Completions with dynamic data

The `-a` flag accepts command substitutions:

```fish
# Complete running Docker container names
complete -c myapp -l container \
    -a "(docker ps --format '{{.Names}}')" \
    -d "Container name"

# Complete from a config file
complete -c myapp -l profile \
    -a "(cat ~/.myapp/profiles | string split \\n)" \
    -d "Config profile"
```

The command inside `()` runs every time you press Tab, so the completions stay up to date.

## Tuning completion behavior

### Completion colors

Fish colors the completion pager based on these variables:

```fish
set fish_color_search_match --background=yellow  # highlighted match
set fish_pager_color_completion normal             # regular completion text
set fish_pager_color_description grey              # description text
set fish_pager_color_prefix cyan --underline       # matched prefix
```

You can also set these through `fish_config` in the browser interface.

### Completion performance

Man page parsing happens in the background when Fish starts. If you install new programs and their completions don't appear, run:

```fish
fish_update_completions
```

This regenerates completions from man pages. It takes a few seconds.

### Case sensitivity

Tab completion in Fish is case-insensitive by default. Type `doc` and it matches both `Documents/` and `docker`. If you type an uppercase letter, Fish switches to case-sensitive matching for that completion.

## Autosuggestions vs tab completions

These are two separate features that people sometimes confuse:

| | Autosuggestions | Tab completions |
|---|---|---|
| Trigger | Automatic as you type | Press Tab |
| Display | Gray text after cursor | Menu below command line |
| Source | History + completions | Completions only |
| Accept | Right arrow / Ctrl+F | Enter / Tab |
| Shows options | One suggestion at a time | All matching options |

They work together. Autosuggestions give you quick history recall without stopping. Tab completions give you a browseable list when you need to explore options.

## Comparing with Zsh and Bash

In [Zsh](/fish-shell-vs-zsh/), you get similar autosuggestions with the `zsh-autosuggestions` plugin. Zsh's `compinit` completion system is powerful but needs configuration. Fish's advantage is that all of this works without setup.

Bash has basic tab completion through `readline` and `bash-completion`. It works for simple cases but doesn't generate completions from man pages and shows no descriptions.

If you want to set up Fish from scratch, see my [Ubuntu installation guide](/install-fish-shell-ubuntu/) or the [macOS setup guide](/fish-shell-macos-setup/). For plugins that improve Fish completions further, like fzf.fish for fuzzy searching, check [best Fish Shell plugins](/best-fish-shell-plugins/).