sane-bash-extended
Extension of sane-bash with explicit style and flow-control conventions for consistency, readability, and strict-mode-friendly Bash.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Extension of sane-bash with explicit style and flow-control conventions for consistency, readability, and strict-mode-friendly Bash.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | sane-bash-extended |
| description | Extension of sane-bash with explicit style and flow-control conventions for consistency, readability, and strict-mode-friendly Bash. |
This skill inherits sane-bash and adds opinionated Bash style conventions.
Base skill: sane-bash
All sane-bash rules still apply. The rules below are additive.
If sane-bash is missing, not installed, or cannot be resolved by name, this extended skill must be ignored entirely (no partial application).
FOO, LOCAL_TMP, ARGS.local keyword so they do
not leak into the global scope: local FOO=bar.function foo_bar_qux() { ... }.
function keyword.foo_bar_qux() { ... } without function in this style
profile.foo_bar_qux.${FOO}.
${FOO} over $FOO, even when unambiguous.[[ CONDITION ]] || COMMAND over a multi-line single-branch if
when no else branch is needed.if when the logic needs else, has multiple steps, or the negative
guard would become harder to read.[[ ... ]] for tests and conditionals; avoid [.getopt + case for option handling.getopt with getopt --test before
relying on it; on macOS the default getopt silently mangles args
containing spaces. For simple one-letter options, prefer the getopts
builtin instead.-- explicitly and reject unexpected extra args.## for help, #- for version) to avoid duplicate strings.
#- version line before the ## usage lines.
#- name 1.0 on its own line, then the ## Usage: block below it.
Keeps version discoverable above help text.on_exit handler (function on_exit() { ... }) and
attach trap on_exit EXIT early — before any resource allocation — so
cleanup actually fires if a later step fails. Start as a no-op and grow it
as resources are acquired."${FOO}" over bare ${FOO} in command args, strings,
tests, and assignments.((++i))), intentionally
word-splitting expansions (caller $i), and the regex on the right of
[[ ... =~ ... ]] are left unquoted on purpose.sane.bash header (see the base skill) is
byte-frozen and exempt from this rule; do not "fix" its unquoted
expansions.COMMAND || true
Validation bouncer: [[ CONDITION ]] || { ...; exit 1; }
Error-and-die: COMMAND || { echo "msg" >&2; exit 1; }IFS= read -r for read.
IFS= so leading/trailing whitespace is preserved.-r so backslashes are literal (not escape sequences).while IFS= read -r LINE; do ...; done < file.-- to destructive commands to stop option injection.
rm -rf -- "${DIR}", find -- "${DIR}", mv -- "${SRC}" "${DST}".-.Order definitions top-to-bottom so each name exists before it is called; the script should read in execution order.
Example:
function foo() { ...; }
function bar() { ...; foo; ... }
bar
foo is defined before bar calls it; bar is defined before the
top-level invocation. Avoid hoisting reliance and forward references.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)""${SCRIPT_DIR}/...", not
via bare names or ${0}. Hardens against being invoked from a
different working directory and against ${0} not being a path.bin/ script resolving its repo root, append /..:
... "${BASH_SOURCE[0]}")/.." ....readonly.
readonly VERSION='1.0', readonly URI_REGEX='^...'.ARGS=(); append with ARGS+=("$1"); expand with "${ARGS[@]}".P="$P '$param'") introduces.command -v, never which.
command -v nc >/dev/null — POSIX builtin, correct exit code, no
external dependency.true/false strings.
FLAG=false; test with [[ "${FLAG}" == "true" ]].0/1/yes/no ambiguity.>&2 echo "msg", >&2 printf '%s\n' "msg" — redirect before the
command.sane.bash header's own trap; reads as "to
stderr: print".${VAR:-...} fallback chains.
Declare empty, then cascade fallbacks top-to-bottom:
ANY_PYTHON=
ANY_PYTHON=${ANY_PYTHON:-$(command -v python3 2>/dev/null || true)}
ANY_PYTHON=${ANY_PYTHON:-$(command -v python2 2>/dev/null || true)}
Reads as a fallback ladder; each line only sets the value if still empty.
SC1091 explicitly before source of a computed path.
# shellcheck disable=SC1091 on the line above
source "${SCRIPT_DIR}/lib.inc.sh".Apply these formatting defaults when generating or editing bash files:
*.sh, *.bash, *.bats, scripts with a bash shebang, and bash snippets
embedded in Makefile or *.mk. These are fallback defaults — use them only
when no other settings apply: a project .editorconfig or .shfmtconf, or
agent/IDE instructions for the target project take precedence.
Validate generated or edited bash files with the three tools below. If a tool is not installed in the current environment, skip it silently — do not block the task on a missing linter.
validate with ShellCheck
validate with shfmt
Run shfmt with these flags:
shfmt --binary-next-line --case-indent --indent 4
Flag-to-behavior mapping:
--binary-next-line — binary operators (&&, ||, |) wrap to the
next line.--case-indent — case patterns are indented (in addition to their
bodies).--indent 4 — 4-space indentation.validate with editorconfig-checker
The following .editorconfig values are the fallback defaults this skill
enforces; a project .editorconfig overrides them for files in that
project:
charset = utf-8end_of_line = lfindent_size = 4indent_style = spaceinsert_final_newline = truetrim_trailing_whitespace = trueThese conventions intentionally prioritize consistency and scanability over minimal typing.