fish-shell-config
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFish Shell Configuration Skill
Fish Shell 配置技能
Operator Context
操作场景
This skill operates as an operator for Fish shell configuration tasks, configuring Claude's behavior for correct Fish syntax and idioms. It implements Domain Intelligence — Fish-specific patterns that differ fundamentally from Bash/POSIX — ensuring generated shell code actually works in Fish.
本技能用于处理 Fish Shell 配置任务,配置 Claude 的行为以生成正确的 Fish 语法和惯用写法。它实现了领域智能——Fish 特有的、与 Bash/POSIX 本质不同的模式——确保生成的 Shell 代码能在 Fish 中正常运行。
Hardcoded Behaviors (Always Apply)
硬编码行为(始终适用)
- Fish Syntax Only: Never emit Bash syntax (,
VAR=value,[[ ]], heredocs) in Fish contextsexport - Variables Are Lists: Treat every Fish variable as a list; never use colon-separated PATH strings
- No Word Splitting: and
$varare identical in Fish; do not add defensive quotes for word-splitting"$var" - Over Brackets: Use
testbuiltin, nevertestor[[ ]][ ] - Over Assignment: Variable assignment is always
set, neverset VAR valueVAR=value - Filename = Function Name: Autoloaded function files must match: contains
functions/foo.fishfunction foo
- 仅使用 Fish 语法:在 Fish 场景中绝不输出 Bash 语法(如 、
VAR=value、[[ ]]、here文档)export - 变量为列表类型:将所有 Fish 变量视为列表;绝不使用冒号分隔的 PATH 字符串
- 无单词拆分:Fish 中 和
$var完全相同;无需为避免单词拆分添加防御性引号"$var" - 使用 而非括号:使用内置的
test,绝不使用test或[[ ]][ ] - 使用 而非赋值语法:变量赋值必须使用
set,绝不使用set VAR valueVAR=value - 文件名与函数名一致:自动加载的函数文件必须匹配:中包含
functions/foo.fishfunction foo
Default Behaviors (ON unless disabled)
默认行为(默认开启,可关闭)
- Modular Config: Place config in files, keep
conf.d/minimalconfig.fish - : Use for PATH manipulation instead of manual
fish_add_pathset PATH - Interactive Guards: Wrap abbreviations and key bindings in
if status is-interactive - Checks: Guard tool integrations with existence checks
type -q - Numeric Prefixes: Use ,
00-,10-prefixes in20-for orderingconf.d/
- 模块化配置:将配置放在 目录的文件中,保持
conf.d/精简config.fish - 使用 :用其管理 PATH,而非手动使用
fish_add_pathset PATH - 交互式防护:将缩写和按键绑定包裹在 语句中
if status is-interactive - 检查:通过存在性检查来集成工具
type -q - 数字前缀:在 目录中使用
conf.d/、00-、10-前缀来控制加载顺序20-
Optional Behaviors (OFF unless enabled)
可选行为(默认关闭,可开启)
- Universal Variables: Use flag for cross-session persistence
-U - Bash Migration: Convert Bash scripts to Fish syntax (see )
references/bash-migration.md - Completion Authoring: Write custom Fish completions
- 全局变量:使用 标志实现跨会话持久化
-U - Bash 迁移:将 Bash 脚本转换为 Fish 语法(详见 )
references/bash-migration.md - 补全规则编写:编写自定义 Fish 补全规则
What This Skill CAN Do
本技能可完成的任务
- Write syntactically correct Fish functions, config, and abbreviations
- Structure with proper modular layout
~/.config/fish/ - Manage variable scoping (local, function, global, universal, export)
- Integrate tools (Starship, direnv, fzf, Homebrew, Nix) with Fish
- Migrate Bash patterns to Fish equivalents
- 编写语法正确的 Fish 函数、配置和缩写
- 合理规划 目录的模块化结构
~/.config/fish/ - 管理变量作用域(局部、函数、全局、全局持久化、导出)
- 将工具(Starship、direnv、fzf、Homebrew、Nix)与 Fish 集成
- 将 Bash 模式迁移为对应的 Fish 写法
What This Skill CANNOT Do
本技能无法完成的任务
- Write POSIX-compatible scripts (Fish is not POSIX)
- Fix Bash/Zsh configurations (use appropriate shell skill)
- Manage Fish plugin frameworks (Fisher, Oh My Fish) beyond basic guidance
- Debug Fish shell internals or C/Rust source code
- 编写兼容 POSIX 的脚本(Fish 不兼容 POSIX)
- 修复 Bash/Zsh 配置(请使用对应 Shell 的技能)
- 深度管理 Fish 插件框架(Fisher、Oh My Fish),仅提供基础指导
- 调试 Fish Shell 内部逻辑或 C/Rust 源代码
Instructions
操作步骤
Phase 1: DETECT
阶段 1:检测
Goal: Confirm Fish shell context before writing any shell code.
Step 1: Check shell environment
- contains
$SHELL, orfish - Target file has extension, or
.fish - Target directory is
~/.config/fish/
Step 2: Identify Fish version constraints
- All patterns target Fish 3.0+ (supports ,
$(),&&)|| - Fish 4.0 (Rust rewrite) has no syntax changes
Gate: Confirmed Fish context. Proceed only when gate passes.
目标:在编写任何 Shell 代码前,确认当前为 Fish Shell 环境。
步骤 1:检查 Shell 环境
- 包含
$SHELL,或fish - 目标文件扩展名为 ,或
.fish - 目标目录为
~/.config/fish/
步骤 2:确定 Fish 版本限制
- 所有模式均针对 Fish 3.0+(支持 、
$()、&&)|| - Fish 4.0(Rust 重写版本)无语法变更
准入条件:确认当前为 Fish 环境,仅当满足条件时才可继续。
Phase 2: STRUCTURE
阶段 2:结构化
Goal: Place configuration in the correct location.
Directory layout:
~/.config/fish/
├── config.fish # Minimal — interactive-only init
├── fish_variables # Auto-managed by Fish (never edit)
├── conf.d/ # Auto-sourced in alphabetical order
│ ├── 00-path.fish
│ ├── 10-env.fish
│ └── 20-abbreviations.fish
├── functions/ # Autoloaded functions (one per file)
│ ├── fish_prompt.fish
│ └── mkcd.fish
└── completions/ # Custom completions
└── mycommand.fishDecision tree:
| What you're writing | Where it goes |
|---|---|
| PATH additions | |
| Environment variables | |
| Abbreviations | |
| Tool integrations | |
| Named function | |
| Custom prompt | |
| Completions | |
| One-time interactive init | |
Gate: Correct file location chosen. Proceed only when gate passes.
目标:将配置放在正确的位置。
目录结构:
~/.config/fish/
├── config.fish # 精简内容 — 仅包含交互式初始化代码
├── fish_variables # 由 Fish 自动管理(请勿编辑)
├── conf.d/ # 自动按字母顺序加载
│ ├── 00-path.fish
│ ├── 10-env.fish
│ └── 20-abbreviations.fish
├── functions/ # 自动加载的函数(每个函数对应一个文件)
│ ├── fish_prompt.fish
│ └── mkcd.fish
└── completions/ # 自定义补全规则
└── mycommand.fish决策树:
| 编写内容 | 存放位置 |
|---|---|
| PATH 添加 | |
| 环境变量 | |
| 缩写 | |
| 工具集成 | |
| 命名函数 | |
| 自定义提示符 | |
| 补全规则 | |
| 一次性交互式初始化 | |
准入条件:选择了正确的文件存放位置,仅当满足条件时才可继续。
Phase 3: WRITE
阶段 3:编写
Goal: Generate syntactically correct Fish code.
Step 1: Variables
fish
set -l VAR value # Local — current block only
set -f VAR value # Function — entire function scope
set -g VAR value # Global — current session
set -U VAR value # Universal — persists across sessions
set -x VAR value # Export — visible to child processes
set -gx VAR value # Global + Export (typical for env vars)
set -e VAR # Erase variable
set -q VAR # Test if set (silent, for conditionals)Step 2: PATH management
fish
undefined目标:生成语法正确的 Fish 代码。
步骤 1:变量操作
fish
set -l VAR value # Local — current block only
set -f VAR value # Function — entire function scope
set -g VAR value # Global — current session
set -U VAR value # Universal — persists across sessions
set -x VAR value # Export — visible to child processes
set -gx VAR value # Global + Export (typical for env vars)
set -e VAR # Erase variable
set -q VAR # Test if set (silent, for conditionals)步骤 2:PATH 管理
fish
undefinedCORRECT: fish_add_path handles deduplication and persistence
CORRECT: fish_add_path handles deduplication and persistence
fish_add_path ~/.local/bin
fish_add_path ~/.cargo/bin
fish_add_path -P ~/go/bin # -P = session only, no persist
fish_add_path ~/.local/bin
fish_add_path ~/.cargo/bin
fish_add_path -P ~/go/bin # -P = session only, no persist
CORRECT: Direct manipulation when needed (session only)
CORRECT: Direct manipulation when needed (session only)
set -gx PATH ~/custom/bin $PATH
set -gx PATH ~/custom/bin $PATH
WRONG: Colon-separated string — Fish PATH is a list
WRONG: Colon-separated string — Fish PATH is a list
set PATH "$PATH:/new/path"
set PATH "$PATH:/new/path"
**Step 3: Functions**
```fish
**步骤 3:函数编写**
```fish~/.config/fish/functions/mkcd.fish
~/.config/fish/functions/mkcd.fish
function mkcd --description "Create directory and cd into it"
mkdir -p $argv[1]
and cd $argv[1]
end
Functions with argument parsing:
```fish
function backup --description "Create timestamped backup"
argparse 'd/dest=' 'h/help' -- $argv
or return
if set -q _flag_help
echo "Usage: backup [-d destination] file..."
return 0
end
set -l dest (set -q _flag_dest; and echo $_flag_dest; or echo ".")
for file in $argv
set -l ts (date +%Y%m%d_%H%M%S)
cp $file $dest/(basename $file).$ts.bak
end
endStep 4: Abbreviations vs Functions vs Aliases
| Use Case | Mechanism | Why |
|---|---|---|
| Simple shortcut | | Expands in-place, visible in history |
| Needs arguments/logic | | Full programming, works in scripts |
| Wrapping a command | | Convenience; creates function internally |
Abbreviations are interactive-only — they do not work in scripts.
fish
undefinedfunction mkcd --description "Create directory and cd into it"
mkdir -p $argv[1]
and cd $argv[1]
end
带参数解析的函数:
```fish
function backup --description "Create timestamped backup"
argparse 'd/dest=' 'h/help' -- $argv
or return
if set -q _flag_help
echo "Usage: backup [-d destination] file..."
return 0
end
set -l dest (set -q _flag_dest; and echo $_flag_dest; or echo ".")
for file in $argv
set -l ts (date +%Y%m%d_%H%M%S)
cp $file $dest/(basename $file).$ts.bak
end
end步骤 4:缩写、函数与别名的对比
| 使用场景 | 实现方式 | 原因 |
|---|---|---|
| 简单快捷方式 | | 原地展开,历史记录中可见完整命令 |
| 需要参数/逻辑 | | 具备完整编程能力,可在脚本中使用 |
| 命令包装 | | 便捷,内部会自动创建函数 |
缩写仅适用于交互式场景——无法在脚本中使用。
fish
undefinedAlways guard abbreviations
Always guard abbreviations
if status is-interactive
abbr -a g git
abbr -a ga "git add"
abbr -a gc "git commit"
abbr -a gst "git status"
abbr -a dc "docker compose"
end
**Step 5: Conditionals and control flow**
```fishif status is-interactive
abbr -a g git
abbr -a ga "git add"
abbr -a gc "git commit"
abbr -a gst "git status"
abbr -a dc "docker compose"
end
**步骤 5:条件判断与控制流**
```fishConditionals — use 'test', not [[ ]]
Conditionals — use 'test', not [[ ]]
if test -f config.json
echo "exists"
else if test -d config
echo "is directory"
end
if test -f config.json
echo "exists"
else if test -d config
echo "is directory"
end
Command chaining (both styles work in Fish 3.0+)
Command chaining (both styles work in Fish 3.0+)
mkdir build && cd build && cmake ..
mkdir build; and cd build; and cmake ..
mkdir build && cd build && cmake ..
mkdir build; and cd build; and cmake ..
Loops
Loops
for file in *.fish
echo "Processing $file"
end
for file in *.fish
echo "Processing $file"
end
Switch
Switch
switch $argv[1]
case start
echo "Starting..."
case stop
echo "Stopping..."
case "*"
echo "Unknown: $argv[1]"
return 1
end
**Step 6: Tool integrations**
Always guard with `type -q`:
```fishswitch $argv[1]
case start
echo "Starting..."
case stop
echo "Stopping..."
case "*"
echo "Unknown: $argv[1]"
return 1
end
**步骤 6:工具集成**
始终使用 `type -q` 进行检查:
```fish~/.config/fish/conf.d/30-tools.fish
~/.config/fish/conf.d/30-tools.fish
if type -q starship
starship init fish | source
end
if type -q direnv
direnv hook fish | source
end
if type -q fzf
fzf --fish | source
end
if type -q starship
starship init fish | source
end
if type -q direnv
direnv hook fish | source
end
if type -q fzf
fzf --fish | source
end
Homebrew (macOS)
Homebrew (macOS)
if test -x /opt/homebrew/bin/brew
eval (/opt/homebrew/bin/brew shellenv)
end
if test -x /opt/homebrew/bin/brew
eval (/opt/homebrew/bin/brew shellenv)
end
Nix
Nix
if test -e /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.fish
source /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.fish
end
**Gate**: Code uses correct Fish syntax. No Bash-isms present. Proceed only when gate passes.if test -e /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.fish
source /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.fish
end
**准入条件**:代码使用正确的 Fish 语法,无 Bash 写法,仅当满足条件时才可继续。Phase 4: VERIFY
阶段 4:验证
Goal: Confirm configuration works and is correctly structured.
Step 1: Syntax check — (parse without executing)
fish -n <file>Step 2: For functions — verify filename matches function name
Step 3: For conf.d — verify guards on interactive-only code
status is-interactiveStep 4: Test in clean environment — then
fish --no-configsource <file>Gate: All verification steps pass. Configuration is complete.
目标:确认配置可正常运行且结构正确。
步骤 1:语法检查 — (仅解析,不执行)
fish -n <file>步骤 2:对于函数 — 验证文件名与函数名一致
步骤 3:对于 conf.d 目录中的文件 — 验证交互式代码已被 语句包裹
status is-interactive步骤 4:在干净环境中测试 — 后执行
fish --no-configsource <file>准入条件:所有验证步骤通过,配置完成。
Examples
示例
Example 1: Setting Up a New Fish Config
示例 1:新建 Fish 配置
User says: "Set up my Fish shell config"
Actions:
- Detect Fish context (DETECT)
- Create modular structure in (STRUCTURE)
~/.config/fish/ - Write ,
conf.d/00-path.fish,conf.d/10-env.fish(WRITE)conf.d/20-abbreviations.fish - Syntax-check all files (VERIFY) Result: Clean modular Fish configuration
用户需求:"设置我的 Fish Shell 配置"
操作步骤:
- 检测 Fish 环境(检测阶段)
- 在 目录创建模块化结构(结构化阶段)
~/.config/fish/ - 编写 、
conf.d/00-path.fish、conf.d/10-env.fish(编写阶段)conf.d/20-abbreviations.fish - 对所有文件进行语法检查(验证阶段) 结果:得到精简的模块化 Fish 配置
Example 2: Migrating a Bash Alias File
示例 2:迁移 Bash 别名文件
User says: "Convert my .bash_aliases to Fish"
Actions:
- Read , confirm Fish target (DETECT)
.bash_aliases - Determine which become abbreviations vs functions (STRUCTURE)
- Write abbreviations to , functions to
conf.d/(WRITE)functions/ - Syntax-check, test in clean shell (VERIFY) Result: Bash aliases converted to idiomatic Fish
用户需求:"将我的 .bash_aliases 转换为 Fish 格式"
操作步骤:
- 读取 ,确认目标为 Fish(检测阶段)
.bash_aliases - 确定哪些内容转为缩写,哪些转为函数(结构化阶段)
- 将缩写写入 目录,函数写入
conf.d/目录(编写阶段)functions/ - 语法检查,并在干净 Shell 中测试(验证阶段) 结果:Bash 别名被转换为符合 Fish 惯用写法的配置
Error Handling
错误处理
Error: "Unknown command" for new function
错误:新函数提示「未知命令」
Cause: Filename does not match function name
Solution: Ensure contains exactly . Check for typos in both the filename and the function declaration.
functions/foo.fishfunction foo原因:文件名与函数名不匹配
解决方案:确保 中包含的函数名为 ,检查文件名和函数声明中的拼写错误。
functions/foo.fishfunction fooError: PATH changes not persisting across sessions
错误:PATH 修改无法跨会话持久化
Cause: Used (session-only) instead of (writes to universal )
Solution: Use which persists by default, or use explicitly.
set -gx PATHfish_add_pathfish_user_pathsfish_add_path /new/pathset -U fish_user_paths /path $fish_user_paths原因:使用了 (仅当前会话有效)而非 (会写入全局持久化变量 )
解决方案:默认使用 来实现持久化,或显式使用 。
set -gx PATHfish_add_pathfish_user_pathsfish_add_path /new/pathset -U fish_user_paths /path $fish_user_pathsError: Abbreviations not expanding in scripts
错误:缩写在脚本中无法展开
Cause: Abbreviations are interactive-only by design
Solution: Use a function instead. Move the logic from to a file in .
abbrfunctions/原因:缩写设计为仅适用于交互式场景
解决方案:改用函数实现,将 的逻辑移至 目录下的文件中。
abbrfunctions/Error: Variable not visible to child process
错误:变量对子进程不可见
Cause: Missing (export) flag on
Solution: Use to make variable visible to subprocesses. Check with to inspect current scope and export status.
-xsetset -gx VAR valueset --show VAR原因: 命令缺少 (导出)标志
解决方案:使用 使变量对子进程可见,可通过 查看当前变量的作用域和导出状态。
set-xset -gx VAR valueset --show VARAnti-Patterns
反模式
Anti-Pattern 1: Bash Assignment Syntax
反模式 1:Bash 赋值语法
What it looks like: or in a file
Why wrong: Syntax error in Fish. Fish has no inline assignment.
Do instead: or
VAR=valueexport VAR=value.fishset VAR valueset -gx VAR value表现:在 文件中使用 或
错误原因:Fish 中该语法非法,Fish 不支持内联赋值
正确做法:使用 或
.fishVAR=valueexport VAR=valueset VAR valueset -gx VAR valueAnti-Pattern 2: Colon-Separated PATH
反模式 2:冒号分隔的 PATH
What it looks like:
Why wrong: Fish PATH is a list, not a colon-delimited string. Creates a single malformed element.
Do instead: or
set PATH "$PATH:/new/path"fish_add_path /new/pathset PATH $PATH /new/path表现:
错误原因:Fish 的 PATH 是列表类型,而非冒号分隔的字符串,此写法会创建一个格式错误的列表元素
正确做法:使用 或
set PATH "$PATH:/new/path"fish_add_path /new/pathset PATH $PATH /new/pathAnti-Pattern 3: Monolithic config.fish
反模式 3:单一大文件 config.fish
What it looks like: Hundreds of lines in — PATH, env, aliases, functions, integrations
Why wrong: Slow to load, hard to maintain, impossible to selectively disable.
Do instead: Split into modules and autoload files.
config.fishconf.d/functions/表现: 文件包含数百行内容——PATH 配置、环境变量、别名、函数、工具集成
错误原因:加载缓慢,难以维护,无法选择性禁用部分配置
正确做法:拆分为 模块和 自动加载文件
config.fishconf.d/functions/Anti-Pattern 4: Bracket Conditionals
反模式 4:括号条件判断
What it looks like: or
Why wrong: is a syntax error. calls external , slower than builtin.
Do instead: — uses Fish's fast builtin.
if [[ -f file ]]if [ -f file ][[ ]][ ]/bin/[if test -f file表现: 或
错误原因: 是语法错误, 会调用外部 命令,比内置命令慢
正确做法:使用 ——Fish 内置的快速命令
if [[ -f file ]]if [ -f file ][[ ]][ ]/bin/[if test -f fileAnti-Pattern 5: Word-Split Defensive Quoting
反模式 5:为避免单词拆分添加多余引号
What it looks like: Always quoting out of Bash habit
Why wrong: Not harmful, but misleading. Fish never word-splits; and are identical.
Do instead: Quote only when you need to prevent list expansion or preserve empty strings.
"$var"$var"$var"表现:出于 Bash 使用习惯,总是对 添加引号
错误原因:虽无危害,但会造成误解。Fish 不会进行单词拆分, 和 完全等价
正确做法:仅在需要阻止列表展开或保留空字符串时添加引号
"$var"$var"$var"References
参考资料
This skill uses these shared patterns:
- Anti-Rationalization - Prevents shortcut rationalizations
- Verification Checklist - Pre-completion checks
本技能使用以下通用模式:
- Anti-Rationalization - 避免不合理的简化写法
- Verification Checklist - 完成前的验证清单
Domain-Specific Anti-Rationalization
领域特定的反模式说明
| Rationalization | Why It's Wrong | Required Action |
|---|---|---|
| "Quotes won't hurt in Fish" | Masks misunderstanding of Fish semantics | Learn Fish variable expansion rules |
| "Just put it all in config.fish" | Monolithic config is an anti-pattern | Use conf.d/ and functions/ |
| "Bash syntax is close enough" | Fish is not POSIX; Bash-isms cause errors | Use Fish-native syntax only |
| "I'll use [ ] since it works" | Calls external binary, slower than test | Use |
| 不合理简化 | 错误原因 | 正确操作 |
|---|---|---|
| "在 Fish 中加引号也没关系" | 掩盖了对 Fish 语义的误解 | 学习 Fish 变量展开规则 |
| "把所有内容都放在 config.fish 里" | 单一大文件是反模式 | 使用 conf.d/ 和 functions/ 目录 |
| "Bash 语法差不多能用" | Fish 不兼容 POSIX,Bash 写法会导致错误 | 仅使用 Fish 原生语法 |
| "我用 [ ] 也能工作" | 调用外部二进制文件,比内置 test 命令慢 | 始终使用 |
Reference Files
参考文件
- : Complete Bash-to-Fish syntax translation table
${CLAUDE_SKILL_DIR}/references/bash-migration.md - : Variable scoping, special variables, and command cheatsheet
${CLAUDE_SKILL_DIR}/references/fish-quick-reference.md
- :完整的 Bash 到 Fish 语法对照表
${CLAUDE_SKILL_DIR}/references/bash-migration.md - :变量作用域、特殊变量和命令速查表
${CLAUDE_SKILL_DIR}/references/fish-quick-reference.md