fish-shell-config

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Fish 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
    ,
    [[ ]]
    ,
    export
    , heredocs) in Fish contexts
  • Variables Are Lists: Treat every Fish variable as a list; never use colon-separated PATH strings
  • No Word Splitting:
    $var
    and
    "$var"
    are identical in Fish; do not add defensive quotes for word-splitting
  • test
    Over Brackets
    : Use
    test
    builtin, never
    [[ ]]
    or
    [ ]
  • set
    Over Assignment
    : Variable assignment is always
    set VAR value
    , never
    VAR=value
  • Filename = Function Name: Autoloaded function files must match:
    functions/foo.fish
    contains
    function foo
  • 仅使用 Fish 语法:在 Fish 场景中绝不输出 Bash 语法(如
    VAR=value
    [[ ]]
    export
    、here文档)
  • 变量为列表类型:将所有 Fish 变量视为列表;绝不使用冒号分隔的 PATH 字符串
  • 无单词拆分:Fish 中
    $var
    "$var"
    完全相同;无需为避免单词拆分添加防御性引号
  • 使用
    test
    而非括号
    :使用内置的
    test
    ,绝不使用
    [[ ]]
    [ ]
  • 使用
    set
    而非赋值语法
    :变量赋值必须使用
    set VAR value
    ,绝不使用
    VAR=value
  • 文件名与函数名一致:自动加载的函数文件必须匹配:
    functions/foo.fish
    中包含
    function foo

Default Behaviors (ON unless disabled)

默认行为(默认开启,可关闭)

  • Modular Config: Place config in
    conf.d/
    files, keep
    config.fish
    minimal
  • fish_add_path
    : Use for PATH manipulation instead of manual
    set PATH
  • Interactive Guards: Wrap abbreviations and key bindings in
    if status is-interactive
  • type -q
    Checks
    : Guard tool integrations with existence checks
  • Numeric Prefixes: Use
    00-
    ,
    10-
    ,
    20-
    prefixes in
    conf.d/
    for ordering
  • 模块化配置:将配置放在
    conf.d/
    目录的文件中,保持
    config.fish
    精简
  • 使用
    fish_add_path
    :用其管理 PATH,而非手动使用
    set PATH
  • 交互式防护:将缩写和按键绑定包裹在
    if status is-interactive
    语句中
  • type -q
    检查
    :通过存在性检查来集成工具
  • 数字前缀:在
    conf.d/
    目录中使用
    00-
    10-
    20-
    前缀来控制加载顺序

Optional Behaviors (OFF unless enabled)

可选行为(默认关闭,可开启)

  • Universal Variables: Use
    -U
    flag for cross-session persistence
  • 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
    ~/.config/fish/
    with proper modular layout
  • 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
  • $SHELL
    contains
    fish
    , or
  • Target file has
    .fish
    extension, or
  • 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.fish
Decision tree:
What you're writingWhere it goes
PATH additions
conf.d/00-path.fish
Environment variables
conf.d/10-env.fish
Abbreviations
conf.d/20-abbreviations.fish
Tool integrations
conf.d/30-tools.fish
Named function
functions/<name>.fish
Custom prompt
functions/fish_prompt.fish
Completions
completions/<command>.fish
One-time interactive init
config.fish
(inside
status is-interactive
)
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 添加
conf.d/00-path.fish
环境变量
conf.d/10-env.fish
缩写
conf.d/20-abbreviations.fish
工具集成
conf.d/30-tools.fish
命名函数
functions/<name>.fish
自定义提示符
functions/fish_prompt.fish
补全规则
completions/<command>.fish
一次性交互式初始化
config.fish
(放在
status is-interactive
语句中)
准入条件:选择了正确的文件存放位置,仅当满足条件时才可继续。

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
undefined

CORRECT: 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
end
Step 4: Abbreviations vs Functions vs Aliases
Use CaseMechanismWhy
Simple shortcut
abbr -a g git
Expands in-place, visible in history
Needs arguments/logic
function
in
functions/
Full programming, works in scripts
Wrapping a command
alias ll "ls -la"
Convenience; creates function internally
Abbreviations are interactive-only — they do not work in scripts.
fish
undefined
function 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:缩写、函数与别名的对比
使用场景实现方式原因
简单快捷方式
abbr -a g git
原地展开,历史记录中可见完整命令
需要参数/逻辑
function
放在
functions/
目录
具备完整编程能力,可在脚本中使用
命令包装
alias ll "ls -la"
便捷,内部会自动创建函数
缩写仅适用于交互式场景——无法在脚本中使用。
fish
undefined

Always 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**

```fish
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

**步骤 5:条件判断与控制流**

```fish

Conditionals — 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`:
```fish
switch $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 —
fish -n <file>
(parse without executing)
Step 2: For functions — verify filename matches function name
Step 3: For conf.d — verify
status is-interactive
guards on interactive-only code
Step 4: Test in clean environment —
fish --no-config
then
source <file>
Gate: All verification steps pass. Configuration is complete.

目标:确认配置可正常运行且结构正确。
步骤 1:语法检查 —
fish -n <file>
(仅解析,不执行)
步骤 2:对于函数 — 验证文件名与函数名一致
步骤 3:对于 conf.d 目录中的文件 — 验证交互式代码已被
status is-interactive
语句包裹
步骤 4:在干净环境中测试 —
fish --no-config
后执行
source <file>
准入条件:所有验证步骤通过,配置完成。

Examples

示例

Example 1: Setting Up a New Fish Config

示例 1:新建 Fish 配置

User says: "Set up my Fish shell config" Actions:
  1. Detect Fish context (DETECT)
  2. Create modular structure in
    ~/.config/fish/
    (STRUCTURE)
  3. Write
    conf.d/00-path.fish
    ,
    conf.d/10-env.fish
    ,
    conf.d/20-abbreviations.fish
    (WRITE)
  4. Syntax-check all files (VERIFY) Result: Clean modular Fish configuration
用户需求:"设置我的 Fish Shell 配置" 操作步骤:
  1. 检测 Fish 环境(检测阶段)
  2. ~/.config/fish/
    目录创建模块化结构(结构化阶段)
  3. 编写
    conf.d/00-path.fish
    conf.d/10-env.fish
    conf.d/20-abbreviations.fish
    (编写阶段)
  4. 对所有文件进行语法检查(验证阶段) 结果:得到精简的模块化 Fish 配置

Example 2: Migrating a Bash Alias File

示例 2:迁移 Bash 别名文件

User says: "Convert my .bash_aliases to Fish" Actions:
  1. Read
    .bash_aliases
    , confirm Fish target (DETECT)
  2. Determine which become abbreviations vs functions (STRUCTURE)
  3. Write abbreviations to
    conf.d/
    , functions to
    functions/
    (WRITE)
  4. Syntax-check, test in clean shell (VERIFY) Result: Bash aliases converted to idiomatic Fish

用户需求:"将我的 .bash_aliases 转换为 Fish 格式" 操作步骤:
  1. 读取
    .bash_aliases
    ,确认目标为 Fish(检测阶段)
  2. 确定哪些内容转为缩写,哪些转为函数(结构化阶段)
  3. 将缩写写入
    conf.d/
    目录,函数写入
    functions/
    目录(编写阶段)
  4. 语法检查,并在干净 Shell 中测试(验证阶段) 结果:Bash 别名被转换为符合 Fish 惯用写法的配置

Error Handling

错误处理

Error: "Unknown command" for new function

错误:新函数提示「未知命令」

Cause: Filename does not match function name Solution: Ensure
functions/foo.fish
contains exactly
function foo
. Check for typos in both the filename and the function declaration.
原因:文件名与函数名不匹配 解决方案:确保
functions/foo.fish
中包含的函数名为
function foo
,检查文件名和函数声明中的拼写错误。

Error: PATH changes not persisting across sessions

错误:PATH 修改无法跨会话持久化

Cause: Used
set -gx PATH
(session-only) instead of
fish_add_path
(writes to universal
fish_user_paths
) Solution: Use
fish_add_path /new/path
which persists by default, or use
set -U fish_user_paths /path $fish_user_paths
explicitly.
原因:使用了
set -gx PATH
(仅当前会话有效)而非
fish_add_path
(会写入全局持久化变量
fish_user_paths
) 解决方案:默认使用
fish_add_path /new/path
来实现持久化,或显式使用
set -U fish_user_paths /path $fish_user_paths

Error: Abbreviations not expanding in scripts

错误:缩写在脚本中无法展开

Cause: Abbreviations are interactive-only by design Solution: Use a function instead. Move the logic from
abbr
to a file in
functions/
.
原因:缩写设计为仅适用于交互式场景 解决方案:改用函数实现,将
abbr
的逻辑移至
functions/
目录下的文件中。

Error: Variable not visible to child process

错误:变量对子进程不可见

Cause: Missing
-x
(export) flag on
set
Solution: Use
set -gx VAR value
to make variable visible to subprocesses. Check with
set --show VAR
to inspect current scope and export status.

原因:
set
命令缺少
-x
(导出)标志 解决方案:使用
set -gx VAR value
使变量对子进程可见,可通过
set --show VAR
查看当前变量的作用域和导出状态。

Anti-Patterns

反模式

Anti-Pattern 1: Bash Assignment Syntax

反模式 1:Bash 赋值语法

What it looks like:
VAR=value
or
export VAR=value
in a
.fish
file Why wrong: Syntax error in Fish. Fish has no inline assignment. Do instead:
set VAR value
or
set -gx VAR value
表现:在
.fish
文件中使用
VAR=value
export VAR=value
错误原因:Fish 中该语法非法,Fish 不支持内联赋值 正确做法:使用
set VAR value
set -gx VAR value

Anti-Pattern 2: Colon-Separated PATH

反模式 2:冒号分隔的 PATH

What it looks like:
set PATH "$PATH:/new/path"
Why wrong: Fish PATH is a list, not a colon-delimited string. Creates a single malformed element. Do instead:
fish_add_path /new/path
or
set PATH $PATH /new/path
表现
set PATH "$PATH:/new/path"
错误原因:Fish 的 PATH 是列表类型,而非冒号分隔的字符串,此写法会创建一个格式错误的列表元素 正确做法:使用
fish_add_path /new/path
set PATH $PATH /new/path

Anti-Pattern 3: Monolithic config.fish

反模式 3:单一大文件 config.fish

What it looks like: Hundreds of lines in
config.fish
— PATH, env, aliases, functions, integrations Why wrong: Slow to load, hard to maintain, impossible to selectively disable. Do instead: Split into
conf.d/
modules and
functions/
autoload files.
表现
config.fish
文件包含数百行内容——PATH 配置、环境变量、别名、函数、工具集成 错误原因:加载缓慢,难以维护,无法选择性禁用部分配置 正确做法:拆分为
conf.d/
模块和
functions/
自动加载文件

Anti-Pattern 4: Bracket Conditionals

反模式 4:括号条件判断

What it looks like:
if [[ -f file ]]
or
if [ -f file ]
Why wrong:
[[ ]]
is a syntax error.
[ ]
calls external
/bin/[
, slower than builtin. Do instead:
if test -f file
— uses Fish's fast builtin.
表现
if [[ -f file ]]
if [ -f file ]
错误原因
[[ ]]
是语法错误,
[ ]
会调用外部
/bin/[
命令,比内置命令慢 正确做法:使用
if test -f file
——Fish 内置的快速命令

Anti-Pattern 5: Word-Split Defensive Quoting

反模式 5:为避免单词拆分添加多余引号

What it looks like: Always quoting
"$var"
out of Bash habit Why wrong: Not harmful, but misleading. Fish never word-splits;
$var
and
"$var"
are identical. Do instead: Quote only when you need to prevent list expansion or preserve empty strings.

表现:出于 Bash 使用习惯,总是对
"$var"
添加引号 错误原因:虽无危害,但会造成误解。Fish 不会进行单词拆分,
$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

领域特定的反模式说明

RationalizationWhy It's WrongRequired Action
"Quotes won't hurt in Fish"Masks misunderstanding of Fish semanticsLearn Fish variable expansion rules
"Just put it all in config.fish"Monolithic config is an anti-patternUse conf.d/ and functions/
"Bash syntax is close enough"Fish is not POSIX; Bash-isms cause errorsUse Fish-native syntax only
"I'll use [ ] since it works"Calls external binary, slower than testUse
test
builtin always
不合理简化错误原因正确操作
"在 Fish 中加引号也没关系"掩盖了对 Fish 语义的误解学习 Fish 变量展开规则
"把所有内容都放在 config.fish 里"单一大文件是反模式使用 conf.d/ 和 functions/ 目录
"Bash 语法差不多能用"Fish 不兼容 POSIX,Bash 写法会导致错误仅使用 Fish 原生语法
"我用 [ ] 也能工作"调用外部二进制文件,比内置 test 命令慢始终使用
test
内置命令

Reference Files

参考文件

  • ${CLAUDE_SKILL_DIR}/references/bash-migration.md
    : Complete Bash-to-Fish syntax translation table
  • ${CLAUDE_SKILL_DIR}/references/fish-quick-reference.md
    : Variable scoping, special variables, and command cheatsheet
  • ${CLAUDE_SKILL_DIR}/references/bash-migration.md
    :完整的 Bash 到 Fish 语法对照表
  • ${CLAUDE_SKILL_DIR}/references/fish-quick-reference.md
    :变量作用域、特殊变量和命令速查表