Claude Code for Fish Shell — Workflow Guide
The Setup
You are running Claude Code in Fish, the user-friendly command line shell with syntax highlighting, autosuggestions, and tab completions out of the box. Fish has a different scripting syntax from bash/zsh, and Claude Code generates bash commands that need translation. The key challenge is getting Claude Code to output Fish-compatible commands.
What Claude Code Gets Wrong By Default
-
Generates bash variable syntax. Claude writes
export VAR=valueand$()subshells. Fish usesset -x VAR valuefor exports and(command)for command substitution — no dollar-sign parentheses. -
Uses bash conditional syntax. Claude writes
if [ -f file ]; then ... fi. Fish usesif test -f file; ...; end— no square brackets, nothen, and blocks end withendnotfi. -
Creates
.bashrcconfigurations. Claude adds config to.bashrcor.zshrc. Fish config goes in~/.config/fish/config.fishwith different syntax. -
Uses
&&and||for command chaining. Claude writescmd1 && cmd2. Fish usesand/orkeywords or the semicolon:cmd1; and cmd2. Recent Fish versions support&&but the traditional approach differs.
The CLAUDE.md Configuration
# Fish Shell Development Environment
## Shell
- Shell: Fish (user-friendly, NOT bash/zsh)
- Config: ~/.config/fish/config.fish
- Functions: ~/.config/fish/functions/ (one file per function)
- Variables: set, set -x (export), set -U (universal)
## Fish Rules
- Variables: set name value (NOT export name=value)
- Export: set -x NAME value
- Command sub: (command) NOT $(command)
- Conditionals: if test condition; ...; end
- Loops: for item in list; ...; end
- Functions: function name; ...; end
- No source .bashrc — Fish has its own syntax
- Path: fish_add_path /new/path (NOT export PATH=...)
## Conventions
- Claude Code runs fine in Fish — output is universal
- Shell commands from Claude Code may need bash-to-fish translation
- Use fish_add_path for PATH modifications
- Abbreviations instead of aliases: abbr -a gs git status
- Functions auto-loaded from config/fish/functions/name.fish
- Universal variables persist across sessions: set -U VAR value
- Use string command for text processing (Fish built-in)
Workflow Example
You want to set up Fish for a new development project. Prompt Claude Code:
“Set up my Fish shell for this Node.js project. Add the project’s bin directory to PATH, create abbreviations for common npm scripts, and set environment variables for the dev database.”
Claude Code should use fish_add_path ./node_modules/.bin, abbr -a nr 'npm run', abbr -a nd 'npm run dev', and set -x DATABASE_URL 'postgresql://...' in config.fish — all in Fish syntax, not bash.
Common Pitfalls
-
Sourcing bash scripts in Fish. Claude writes
source .envexpecting bash env file parsing. Fish cannot source bash-format env files. Usebass source .env(via bass plugin) or convert to Fish syntax:set -x VAR valueper line. -
Using
exportkeyword. Claude writesexport PATH="$PATH:/new". Fish does not have anexportkeyword (recent versions add it for compatibility, butset -xis idiomatic). Useset -x VAR valuefor exported variables. -
Wildcard and glob differences. Claude uses
**/*.tsin commands. Fish handles globs differently from bash —**recursive glob works but some edge cases differ. Test glob patterns in Fish before relying on them in scripts.