# fish — the user-friendly shell with autosuggestions

> Practical guide to fish — variables, functions, abbreviations and universal variables in the user-friendly, non-POSIX command-line shell.

Source: https://www.jpkc.com/db/en/cheatsheets/shell-system/fish/

<!-- PROSE:intro -->
fish – the Friendly Interactive Shell – favours comfort over convention: autosuggestions, syntax highlighting and smart tab completion all work straight away, with no configuration required. Its main stumbling block is the deliberately non-POSIX syntax – instead of `export` you use `set -x`, and instead of `&&`/`||` you write `and`/`or`. This guide walks you through the variables, functions, abbreviations and string tools you actually reach for day to day.
<!-- PROSE:intro:end -->

## Basics

`fish` — Start a Fish shell session.

```bash
fish
```

`fish -c '<command>'` — Execute a command string and exit.

```bash
fish -c 'echo Hello World'
```

`fish -l` — Start as a login shell.

```bash
fish -l
```

`fish -n <script>` — Check syntax without executing (no-execute mode).

```bash
fish -n myscript.fish
```

`fish_config` — Open the web-based configuration UI in a browser.

```bash
fish_config
```

`fish_config theme choose <name>` — Set a color theme from the command line.

```bash
fish_config theme choose 'Dracula'
```

`fish --version` — Show the installed Fish version.

```bash
fish --version
```

## Variables & Environment

`set <var> <value>` — Set a local variable (current scope only).

```bash
set name 'World'
```

`set -x <var> <value>` — Set and export a variable (available to child processes).

```bash
set -x EDITOR vim
```

`set -U <var> <value>` — Set a universal variable (persists across sessions and restarts).

```bash
set -U fish_greeting 'Welcome back!'
```

`set -e <var>` — Erase (unset) a variable.

```bash
set -e TEMP_VAR
```

`set -S <var>` — Show detailed info about a variable (scope, export status).

```bash
set -S PATH
```

`set -l <var> <value>` — Set a local variable (only in current block).

```bash
set -l tmp_file /tmp/output.txt
```

`fish_add_path <dir>` — Permanently add a directory to PATH (universal).

```bash
fish_add_path ~/.local/bin
```

## Abbreviations & Aliases

`abbr -a <name> <expansion>` — Add an abbreviation (expands inline when typed).

```bash
abbr -a gco 'git checkout'
```

`abbr -a --position command <name> <expansion>` — Add abbreviation that only triggers in command position.

```bash
abbr -a --position command l 'ls -la'
```

`abbr -e <name>` — Erase an abbreviation.

```bash
abbr -e gco
```

`abbr -l` — List all abbreviation names.

```bash
abbr -l
```

`abbr --show` — Show all abbreviations with their expansions.

```bash
abbr --show
```

`alias <name> '<command>'` — Create a function alias (wrapper around function).

```bash
alias ll 'ls -la'
```

`funcsave <name>` — Save a function/alias permanently to disk.

```bash
funcsave ll
```

## Functions

`function <name>; ...; end` — Define a function.

```bash
function greet; echo "Hello, $argv[1]"; end
```

`function <name> -a <args>; ...; end` — Define a function with named arguments.

```bash
function greet -a name; echo "Hello, $name"; end
```

`function <name> -d '<desc>'` — Define a function with a description.

```bash
function serve -d 'Start dev server'; python3 -m http.server; end
```

`functions <name>` — Show the definition of a function.

```bash
functions greet
```

`functions -e <name>` — Erase a function.

```bash
functions -e greet
```

`funcsave <name>` — Save function to ~/.config/fish/functions/<name>.fish.

```bash
funcsave greet
```

`functions -n` — List all defined function names.

```bash
functions -n
```

## Control Flow

`if <condition>; ...; else; ...; end` — Conditional execution.

```bash
if test -f config.yaml; echo 'Found'; else; echo 'Missing'; end
```

`switch <value>; case <pattern>; ...; end` — Pattern matching (like case/switch).

```bash
switch $os; case Linux; echo 'Linux'; case Darwin; echo 'Mac'; end
```

`for <var> in <list>; ...; end` — Loop over a list of values.

```bash
for f in *.txt; echo $f; end
```

`while <condition>; ...; end` — Loop while a condition is true.

```bash
while test $count -lt 10; set count (math $count + 1); end
```

`begin; ...; end` — Group commands in a block (for redirection or scoping).

```bash
begin; echo stdout; echo stderr >&2; end 2>/dev/null
```

`and <command>` — Execute command only if the previous succeeded.

```bash
make build; and make test
```

`or <command>` — Execute command only if the previous failed.

```bash
test -f .env; or echo '.env not found'
```

## String & Math

`string match '<pattern>' <string>` — Match strings against a glob or regex pattern.

```bash
string match '*.txt' readme.txt
```

`string replace '<old>' '<new>' <string>` — Replace first occurrence in a string.

```bash
string replace 'foo' 'bar' 'foobar'
```

`string split '<sep>' <string>` — Split a string by a delimiter.

```bash
string split ',' 'a,b,c'
```

`string trim <string>` — Remove leading and trailing whitespace.

```bash
string trim '  hello  '
```

`string length <string>` — Return the length of a string.

```bash
string length 'hello'
```

`string sub -s <start> -l <len> <string>` — Extract a substring.

```bash
string sub -s 1 -l 5 'Hello World'
```

`math '<expression>'` — Evaluate a math expression.

```bash
math '2 ^ 10'
```

## Completions & History

`complete -c <cmd> -s <short> -l <long> -d '<desc>'` — Add a tab completion for a command.

```bash
complete -c myapp -s v -l verbose -d 'Enable verbose output'
```

`complete -c <cmd> -a '<args>'` — Add argument completions for a command.

```bash
complete -c myapp -a 'start stop restart'
```

`history search <term>` — Search command history.

```bash
history search git
```

`history delete --exact '<cmd>'` — Delete a specific entry from history.

```bash
history delete --exact 'rm -rf /tmp/test'
```

`history clear` — Clear all command history.

```bash
history clear
```

`history merge` — Merge history from other Fish sessions.

```bash
history merge
```

<!-- PROSE:outro -->
## Conclusion

fish takes a lot of typing off your hands: autosuggestions, syntax highlighting and completions are available with zero setup, and with `set -U`, `funcsave` and `fish_config` you can build a persistent environment of your own. The biggest stumbling block remains the non-POSIX syntax: snippets from bash/zsh or Stack Overflow often won't run unchanged – you have to translate `export`, `&&`/`||` and command substitution into `set -x`, `and`/`or` and fish's `(…)` parentheses. For portable scripts that must run everywhere, a `#!/bin/sh` shebang stays the safe choice; as a comfortable interactive everyday shell, however, fish really shines.

## Further Reading

- [fish documentation](https://fishshell.com/docs/current/) – the official reference and complete tutorial
- [fish tutorial](https://fishshell.com/docs/current/tutorial.html) – hands-on introduction to the Friendly Interactive Shell
<!-- PROSE:outro:end -->

## Related Commands

- [bash](https://www.jpkc.com/db/en/cheatsheets/shell-system/bash/) – the ubiquitous POSIX shell and default on most Linux systems
- [zsh](https://www.jpkc.com/db/en/cheatsheets/shell-system/zsh/) – a powerful POSIX-compatible shell with extensive enhancements
- [env](https://www.jpkc.com/db/en/cheatsheets/shell-system/env/) – show environment variables and run commands in a modified environment

