shell-scripting · git:20260920.ac01853 · 2026-09-20 · sha256 c6374e034bcda6d7

shell-scripting git:20260920.ac01853A

Immutable. This exact content is served forever at /api/v1/blob/c6374e034bcda6d7.

---
name: shell-scripting
description: >
  Write and debug Bash, Zsh, POSIX sh, and Fish scripts, commands, quoting, dotfiles, and shell completions.
license: MIT
compatibility: "Use sh, Bash, or Zsh for POSIX examples; Fish and Nushell require their dedicated syntax"
metadata:
  source: iuliandita/skills
  date_added: "2026-03-25"
  effort: medium
  argument_hint: "<task-or-shell>"
---

# Shell Scripting and Configuration

Write commands, scripts, dotfiles, and completions for their actual shell. Detect the target before
writing code, then load the smallest relevant reference instead of borrowing syntax from a similar
shell.

**Version-specific behavior**: read the matching shell reference before relying on release-specific behavior.

## When to use

- Writing shell commands, scripts, or one-liners
- Configuring dotfiles (`.zshrc`, `.bashrc`, `.profile`, `config.fish`)
- Writing completions, shell functions, or aliases
- Porting scripts between shells or debugging quoting, globbing, array, or expansion behavior
- Choosing a target shell for a new script or interactive command

## When NOT to use

- Remote FreeBSD/OPNsense/pfSense commands; use **opnsense-pfsense**
- Ansible shell/command modules; use **ansible**
- CI/CD pipeline design or runner constraints; use **ci-cd**
- General Linux administration that is not a shell-syntax task; do the domain task directly

## AI Self-Check

- [ ] Shebang matches the detected target shell, not an assumed Bash default
- [ ] Error handling matches the declared shell; expected nonzero statuses are handled deliberately
- [ ] Variables are double-quoted unless word splitting is intentional
- [ ] No wrong-shell syntax appears (`[[ ]]` in sh, `BASH_SOURCE` in Zsh, Bash arrays in sh)
- [ ] Array indexing matches the target shell (Bash 0-indexed, Zsh/Fish 1-indexed, no sh arrays)
- [ ] `printf` replaces non-trivial `echo`; globs and temporary files have safe cleanup/empty cases
- [ ] Commands do not expose secrets in history or process arguments
- [ ] Examples were checked with paths containing spaces, empty variables, and glob characters
- [ ] Cross-cutting agent hygiene applied; read `references/agent-hygiene.md` when relevant

## Workflow

### 1. Detect the shell

Read an existing script's shebang first. Otherwise use the file convention, stated deployment
environment, and user context. `$SHELL` normally identifies the login shell, not necessarily the
process running a script.

| Signal | Default route |
|---|---|
| `#!/bin/sh`, minimal Alpine/BusyBox, maximum portability | POSIX sh |
| `#!/usr/bin/env bash`, portable featureful script, common CI/container image | Bash |
| `.zsh`, `.zshrc`, interactive local shell | Zsh |
| `.fish`, `config.fish` | Fish |
| BSD firewall/appliance context | **opnsense-pfsense** |

### 2. Load only the needed reference

- Read `references/bash.md`, `references/zsh.md`, `references/posix-sh.md`, or
  `references/alt-shells.md` for the selected shell; load two only when porting between them.
- Read `references/advanced-patterns.md` for portable redirection/quoting, traps, cleanup, jobs,
  signals, process termination, or a Zsh completion.
- Read `references/ssh-tmux-autostart.md` only for interactive SSH startup that attaches to tmux.

### 3. Write, parse, and exercise the behavior

Use explicit error handling that the selected shell supports. Keep scripts non-interactive unless the
task needs interaction, and use `--` before user-controlled paths for commands that accept it.
Preview destructive expansions before `rm`, `mv`, `chmod`, `chown`, or recursive edits.

Run the parser for the target (`bash -n`, `zsh -n`, or `sh -n`) and ShellCheck for sh/Bash where
available. A completion also needs a real Tab press after `compinit`; parsing alone does not test
discovery. Report commands run and any unavailable checks.

## Verification Checklist

- [ ] The shebang, shell features, indexing, and strict-mode behavior agree
- [ ] Expected failures, pipeline status, cleanup traps, and signal exits were exercised
- [ ] Quoting and empty-glob behavior were exercised with adversarial filenames/values
- [ ] Generated scripts parse in the selected shell; sh/Bash scripts pass ShellCheck when available
- [ ] Completion files load under `compinit` and route at least one real completion request

## Reference Files

- `references/bash.md` - Bash syntax, arrays, parameter expansion, traps, heredocs, and templates
- `references/zsh.md` - Zsh arrays, qualifiers, expansion, completions, hooks, and dotfiles
- `references/posix-sh.md` - portable sh constructs and Bashism avoidance
- `references/alt-shells.md` - Fish, tcsh/csh, Nushell, Elvish, and Oils boundaries
- `references/advanced-patterns.md` - cross-shell comparison, safe portable constructs, traps, jobs,
  and Zsh completion skeletons
- `references/ssh-tmux-autostart.md` - safe interactive SSH-to-tmux startup

## Output Contract

See `references/output-contract.md` for the full contract.

- **Skill name:** SHELL-SCRIPTING
- **Deliverable bucket:** `audits`
- **Mode:** conditional. For an audit or review of existing shell content, apply the reporting rules
  in the local contract and write `docs/local/audits/shell-scripting/<YYYY-MM-DD>-<slug>.md`.
  Writing a script, dotfile, completion, or explanation remains conversational.
- **Severity scale:** `P0 | P1 | P2 | P3 | info`

## Related Skills

- **opnsense-pfsense** - FreeBSD firewall/appliance shell context
- **ansible** - playbook shell and command-module behavior
- **ci-cd** - pipeline design and restricted execution environments
- **networking**, **debian-ubuntu**, and **rhel-fedora** - system/domain administration; this skill
  supplies the shell syntax when those tasks require it

## Rules

1. **Detect the shell first.** Do not assume Bash from a code-looking request.
2. **Load the matching reference.** Similar shell syntax is a source of subtle failures.
3. **Use the declared shell's idioms.** Do not write pseudo-portable mixed Bash/Zsh/sh.
4. **Quote by default and handle errors explicitly.** Treat intentional splitting or ignored failures
   as exceptions that need a reason.
5. **Do not expose secrets or run destructive expansions blindly.** Use secure input paths and preview
   exact targets before a state-changing command.