macos-programmer
macOS-specific development patterns, platform APIs, and decision frameworks. Use when developing Mac apps, macOS applications,…
Fish shell scripting judgment frameworks and critical idioms. Use when writing Fish scripts or shell automation. Focuses on when to use Fish vs bash, macOS/Fedora compatibility requirements, and Fish-specific patterns that prevent bugs (universal variable anti-patterns, wrapper
Claude Code
$ npx -y skills add Pyroxin/opinionated-claude-skills --skill fish-shell-scripting --agent claude-code
Codex
$ npx skills add Pyroxin/opinionated-claude-skills --skill fish-shell-scripting -a codex -y
Cursor
$ npx skills add Pyroxin/opinionated-claude-skills --skill fish-shell-scripting -a cursor -y
Gemini CLI
$ npx skills add Pyroxin/opinionated-claude-skills --skill fish-shell-scripting -a gemini-cli -y
GitHub Copilot
$ npx skills add Pyroxin/opinionated-claude-skills --skill fish-shell-scripting -a github-copilot -y
OpenCode
$ npx skills add Pyroxin/opinionated-claude-skills --skill fish-shell-scripting -a opencode -y
Windsurf
$ npx skills add Pyroxin/opinionated-claude-skills --skill fish-shell-scripting -a windsurf -y
name: fish-shell-scripting description: Fish shell scripting judgment frameworks and critical idioms. Use when writing Fish scripts or shell automation. Focuses on when to use Fish vs bash, macOS/Fedora compatibility requirements, and Fish-specific patterns that prevent bugs (universal variable anti-patterns, wrapper functions, interactive guards).
**Related skills:**
<core_philosophy> **Fish is a user-friendly shell that prioritizes correctness over POSIX compatibility.** Its lists-not-strings semantics eliminates entire classes of bugs common in bash/zsh. The limitation is portability, not capability.
**Key insight**: Fish handles sophisticated automation well. Choose Fish when you control the environment; choose bash when you don't. </core_philosophy>
<platform_requirements> **Compatibility**: All Fish scripts MUST work on both macOS and Fedora Linux. Handle platform differences via `uname` detection.
**Quote paths with spaces**: Always quote file paths even though Fish has no word splitting. Fish doesn't need quotes technically (no word splitting), but quoting anyway: (1) makes intent explicit for readability, (2) builds consistent habits when switching between shells, (3) ensures compatibility when passing to external commands that may interpret spaces.
**Shebang**: Use `#!/usr/bin/env fish` for portability across installation locations. </platform_requirements>
<fish_vs_alternatives> **Use Fish for:**
**Use bash for:**
**Use a programming language for:**
</fish_vs_alternatives>
<posix_differences> **No word splitting**: Variables don't split on spaces. `set name "foo bar"; echo $name` is one argument. This eliminates a major source of bugs in bash/zsh.
**All variables are lists**: A "string" is a one-element list. Indexing is 1-based: `$PATH[1]`, `$PATH[-1]`.
**No `VAR=value` syntax**: Use `set` command. `set -gx VAR value` (global exported), `set -lx VAR value` (local exported).
**Command substitution splits on newlines only**: `set lines (cat file)` creates one element per line. For space-splitting: `string split " "`. </posix_differences>
<scoping_decision> **Choosing a scope:**
| Need | Scope | Example Use Case | |------|-------|------------------| | Temporary within function/block | `-l` | Loop variables, intermediate results | | Shared across session | `-g` | Current project settings, temporary overrides | | Available to child processes | `-gx` or `-lx` | PATH, EDITOR, build flags | | Persist across sessions (Fish UI only) | `-U` | fish_color_*, key bindings, prompt config |
**Flag combinations:**
**Example**: `set -gx EDITOR vim` (global + exported), `set -lx DEBUG 1` (local + exported to children).
**CRITICAL**: Environment variables (PATH, EDITOR, etc.) should NEVER be universal. Universal scope is for Fish UI config only. </scoping_decision>
<universal_variable_antipattern> **NEVER use universal variables for PATH or environment variables**. Universal scope is for Fish UI config only (colors, key bindings, prompt).
**Why this matters**: Universal variables persist to disk and are shared across all Fish sessions. If you append to PATH in config.fish using universal variables, it grows indefinitely on every shell start because: 1. config.fish runs on every session 2. Universal variable already contains previous value 3. Append adds duplicate entries 4. This compounds across reboots
# WRONG: Grows PATH indefinitely on every shell start set -U fish_user_paths ~/bin $fish_user_paths # RIGHT: Session-scoped (recalculated fresh each session) set -gx PATH ~/bin $PATH # RIGHT: Use fish_add_path once interactively (idempotent, uses universal internally) fish_add_path ~/bin
**Safe universal variable uses**: `fish_color_*`, `fish_key_bindings`, `fish_prompt`, `fish_greeting`. </universal_variable_antipattern>
<cross_platform> **OS detection**: `switch (uname); case Darwin; ...; case Linux; ...; end`
**Conditional PATH**: `test -d ~/.cargo/bin; and fish_add_path ~/.cargo/bin`
**Platform-specific utilities to watch for**:
</cross_platform>
<critical_idioms> **Wrapper functions require `--wraps` and `$argv`**:
function ls --wraps=ls --description "ls with color"
command ls --color=auto $argv
end**Argument parsing**: Use `argparse` + `fish_opt` for complex CLI tools. Check flags with `set -q _flag_name`.
**Guard interactive code**: Non-in
This project descends from the personal prompts I'd been keeping for Claude Code prior to the release of skills and plugins. Over time it's also evolved into a sandbox where I figure out what makes Claude reliably good at a task, and find prompts that work.
macOS-specific development patterns, platform APIs, and decision frameworks. Use when developing Mac apps, macOS applications,…
Swift-specific idioms, tooling, and philosophy for both application development and command-line scripting. Use when working with…
Java-specific tooling, documentation standards, testing practices, and modern idioms. Use when working with Java code or…
Clojure-specific philosophy, idioms, and judgment frameworks. Use when working with Clojure code. Emphasizes data-oriented…
Racket-specific tooling, libraries, idioms, and language-oriented programming philosophy. Use when working with Racket code.…
SWI-Prolog-specific tooling, standards, and idioms. Use when working with SWI-Prolog code. Emphasizes relational thinking,…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.