developing-shell-scripts

star 1

Use when writing or reviewing `.sh`, `.bash`, or `.zsh` files, Makefile shell snippets, CI shell commands, or choosing between Zsh, Bash, and POSIX `sh` in this repo.

nisavid By nisavid schedule Updated 6/2/2026

name: developing-shell-scripts description: Use when writing or reviewing .sh, .bash, or .zsh files, Makefile shell snippets, CI shell commands, or choosing between Zsh, Bash, and POSIX sh in this repo.

Developing Shell Scripts

Overview

Choose the simplest shell that meets the runtime constraints, then make the script explicit about safety, dependencies, and I/O behavior. In this repo, prefer Zsh for developer-facing scripts when availability allows, then Bash, then POSIX sh.

When to Use

  • Writing or reviewing shell scripts in this repo
  • Adding shell snippets to Makefiles or CI configuration
  • Choosing between Zsh, Bash, and POSIX sh
  • Hardening script error handling, quoting, option parsing, or cleanup behavior

Do not use this skill for non-shell implementation work or as a substitute for checking the runtime environment the script will actually run in.

Quick Reference

Context Default
Developer-facing script on macOS/Linux Zsh with #!/usr/bin/env zsh
CI or minimal container Bash with #!/usr/bin/env bash
Maximum portability POSIX sh with #!/bin/sh
Safety prologue set -euo pipefail for Bash, add -E when relying on ERR traps, use set -eu for sh, and emulate -L zsh plus explicit options in Zsh functions
Output channels stdout for actual output, stderr for errors and diagnostics
Tool preference Shell built-ins first, then standard utilities, then npx, then python
Bash script directory Resolve the script file with realpath -- "${BASH_SOURCE[0]}", then derive its directory with parameter expansion
Static checks ShellCheck and shfmt for sh or Bash, and zsh -n for Zsh

Implementation

  • Use shell-specific extensions and shebangs for executable scripts; omit the shebang only for sourced shell libraries
  • Keep scripts self-contained and do not rely on interactive init files such as .zshrc or .bashrc
  • In Bash scripts, locate the script with script_path="$(realpath -- "${BASH_SOURCE[0]}")" and script_dir="${script_path%/*}"; this resolves symlinked script files, unlike cd "$(dirname ...)" && pwd, and stays portable across the repo's current macOS and Linux floor when used without GNU-only realpath flags
  • Prefer $() over backticks, and use case or arithmetic contexts where they improve clarity
  • In Zsh, follow Zsh expansion rules: do not quote ordinary scalar expansions just from Bash/POSIX habit; keep quotes where they preserve argv exactly, protect literal text, or are required by another shell or file format
  • Put reusable logic in functions, declare locals locally, and route top-level execution through main "$@"
  • In Zsh functions, start with emulate -L zsh and opt into options explicitly so caller settings do not leak into control flow
  • Check prerequisites with command -v, validate required environment variables, and clean up temporary files with traps
  • Prefer print -r -- in Zsh, keep help text in single quotes or heredocs, and support both short and long GNU-style options when a CLI is user-facing

Read references/operational-details.md for shell-specific safety details, CLI parsing, portability gotchas, toolchain choices, and cleanup patterns.

Common Mistakes

  • Picking a shell that the target environment does not reliably provide
  • Letting caller options leak into Zsh library behavior
  • Relying on interactive shell startup files in non-interactive contexts
  • Leaving variables unquoted or assuming the current working directory
  • Mixing normal output with diagnostics on stdout
Install via CLI
npx skills add https://github.com/nisavid/dotfiles --skill developing-shell-scripts
Repository Details
star Stars 1
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator