Back to Skills

shell-best-practices

verified

Use when writing shell scripts following modern best practices. Covers portable scripting, Bash patterns, error handling, and secure coding.

View on GitHub

Marketplace

han

TheBushidoCollective/han

Plugin

jutsu-shfmt

Technique

Repository

TheBushidoCollective/han
60stars

jutsu/jutsu-shfmt/skills/shell-best-practices/SKILL.md

Last Verified

January 24, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/TheBushidoCollective/han/blob/main/jutsu/jutsu-shfmt/skills/shell-best-practices/SKILL.md -a claude-code --skill shell-best-practices

Installation paths:

Claude
.claude/skills/shell-best-practices/
Powered by add-skill CLI

Instructions

# Shell Scripting Best Practices

Comprehensive guide to writing robust, maintainable, and secure shell scripts following modern best practices.

## Script Foundation

### Shebang Selection

Choose the appropriate shebang for your needs:

```bash
# Portable bash (recommended)
#!/usr/bin/env bash

# Direct bash path (faster, less portable)
#!/bin/bash

# POSIX-compliant shell (most portable)
#!/bin/sh

# Specific shell version
#!/usr/bin/env bash
# Requires Bash 4.0+
```

### Strict Mode

Always enable strict error handling:

```bash
#!/usr/bin/env bash
set -euo pipefail

# What these do:
# -e: Exit immediately on command failure
# -u: Treat unset variables as errors
# -o pipefail: Pipeline fails if any command fails
```

For debugging, add:

```bash
set -x  # Print commands as they execute
```

### Script Header Template

```bash
#!/usr/bin/env bash
set -euo pipefail

# Script: script-name.sh
# Description: Brief description of what this script does
# Usage: ./script-name.sh [options] <arguments>

readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
```

## Variable Handling

### Always Quote Variables

Prevents word splitting and glob expansion:

```bash
# Good
echo "$variable"
cp "$source" "$destination"
if [ -f "$file" ]; then

# Bad - can break on spaces/special chars
echo $variable
cp $source $destination
if [ -f $file ]; then
```

### Use Meaningful Names

```bash
# Good
readonly config_file="/etc/app/config.yml"
local user_input="$1"
declare -a log_files=()

# Bad
readonly f="/etc/app/config.yml"
local x="$1"
declare -a arr=()
```

### Default Values

```bash
# Use default if unset
name="${NAME:-default_value}"

# Use default if unset or empty
name="${NAME:-}"

# Assign default if unset
: "${NAME:=default_value}"

# Error if unset (with message)
: "${REQUIRED_VAR:?Error: REQUIRED_VAR must be set}"
```

### Readonly and Local

```bash
# Constants
readonly MAX_RETRIES=3
readonly CONFIG_DIR="/

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
10669 chars