Skip to main content
rule official · GitHub

shell — GitHub Copilot rule for safe bash scripts

A rule that makes GitHub Copilot generate clean, safe shell scripts. Applies to *.sh files automatically.

Install into GitHub Copilot · Manually: put the files in place All methods and platforms ↓
.github/instructions/shell.instructions.md
Open on GitHub

What shell does

The rule covers bash, sh, and zsh conventions: set -euo pipefail, double-quoted variable references, mktemp for temp files, trap for cleanup. Copilot follows these when generating code in *.sh files.

For JSON and YAML, the rule demands jq and yq instead of ad-hoc grep or awk. Scripts should fail with a clear message when these tools are missing — that is built into the instructions.

Scripts written under this rule target automation and testing, not production. So verbose logging is discouraged and echo output should stay short.

What it helps with

  • make Copilot add set -euo pipefail to every script
  • generate scripts with safe variable expansions instead of eval
  • parse JSON and YAML with jq/yq instead of grep
  • create temp files via mktemp with automatic cleanup
  • keep a consistent script layout: shebang, header, functions, main

Example prompts for the agent

  • generate a backup script following the shell rule
  • write a bash script that reads config.json and validates fields
  • add error handling and temp file cleanup to this script

How to install shell

Manually: put the files in place

.github/instructions/shell.instructions.md

The applyTo field sets which files it applies to

Step by step, with commands for each platform: AGENTS.md vs CLAUDE.md: what they are and which one to use

Questions about shell

How do I install the shell rule in GitHub Copilot?

Create .github/instructions/shell.instructions.md in your repository root and paste the rule content there. Copilot will pick it up for all *.sh files.

What does the shell rule do?

It sets standards for generated shell scripts: mandatory set -euo pipefail, safe expansions, mktemp for temp files, jq/yq for structured data.

What does the rule require?

Scripts that parse JSON or YAML need jq and yq. The rule says to check for them and fail with a helpful message if they are not installed.

Source text

shell.instructions.md · MIT
---
description: 'Shell scripting best practices and conventions for bash, sh, zsh, and other shells'
applyTo: '**/*.sh'
---

# Shell Scripting Guidelines

Instructions for writing clean, safe, and maintainable shell scripts for bash, sh, zsh, and other shells.

## General Principles

- Generate code that is clean, simple, and concise
- Ensure scripts are easily readable and understandable
- Add comments where helpful for understanding how the script works
- Generate concise and simple echo outputs to provide execution status
- Avoid unnecessary echo output and excessive logging
- Use shellcheck for static analysis when available
- Assume scripts are for automation and testing rather than production systems unless specified otherwise
- Prefer safe expansions: double-quote variable references (`"$var"`), use `${var}` for clarity, and avoid `eval`
- Use modern Bash features (`[[ ]]`, `local`, arrays) when portability requirements allow; fall back to POSIX constructs only when needed
- Choose reliable parsers for structured data instead of ad-hoc text processing

## Error Handling & Safety

- Always enable `set -euo pipefail` to fail fast on errors, catch unset variables, and surface pipeline failures
- Validate all required parameters before execution
- Provide clear error messages with context
- Use `trap` to clean up temporary resources or handle unexpected exits when the script terminates
- Declare immutable values with `readonly` (or `declare -r`) to prevent accidental reassignment
- Use `mktemp` to create temporary files or directories safely and ensure they are removed in your cleanup handler

## Script Structure

- Start with a clear shebang: `#!/bin/bash` unless specified otherwise
- Include a header comment explaining the script's purpose
- Define default values for all variables at the top
- Use functions for reusable code blocks
- Create reusable functions instead of repeating similar blocks of code
- Keep the main execution flow clean and readable

## Working with JSON and YAML

- Prefer dedicated parsers (`jq` for JSON, `yq` for YAML—or `jq` on JSON converted via `yq`) over ad-hoc text processing with `grep`, `awk`, or shell string splitting
- When `jq`/`yq` are unavailable or not appropriate, choose the next most reliable parser available in your environment, and be explicit about how it should be used safely
- Validate that required fields exist and handle missing/invalid data paths explicitly (e.g., by checking `jq` exit status or using `// empty`)
- Quote jq/yq filters to prevent shell expansion and prefer `--raw-output` when you need plain strings
- Treat parser errors as fatal: combine with `set -euo pipefail` or test command success before using results
- Document parser dependencies at the top of the script and fail fast with a helpful message if `jq`/`yq` (or alternative tools) are required but not installed

```bash
#!/bin/bash

# ============================================================================
# Script Description Here
# ============================================================================

set -euo pipefail

cleanup() {
    # Remove temporary resources or perform other teardown steps as needed
    if [[ -n "${TEMP_DIR:-}" && -d "$TEMP_DIR" ]]; then
        rm -rf "$TEMP_DIR"
    fi
}

trap cleanup EXIT

# Default values
RESOURCE_GROUP=""
REQUIRED_PARAM=""
OPTIONAL_PARAM="default-value"
readonly SCRIPT_NAME="$(basename "$0")"

TEMP_DIR=""

# Functions
usage() {
    echo "Usage: $SCRIPT_NAME [OPTIONS]"
    echo "Options:"
    echo "  -g, --resource-group   Resource group (required)"
    echo "  -h, --help            Show this help"
    exit 0
}

validate_requirements() {
    if [[ -z "$RESOURCE_GROUP" ]]; then
        echo "Error: Resource group is required"
        exit 1
    fi
}

main() {
    validate_requirements

    TEMP_DIR="$(mktemp -d)"
    if [[ ! -d "$TEMP_DIR" ]]; then
        echo "Error: failed to create temporary directory" >&2
        exit 1
    fi
    
    echo "============================================================================"
    echo "Script Execution Started"
    echo "============================================================================"
    
    # Main logic here
    
    echo "============================================================================"
    echo "Script Execution Completed"
    echo "============================================================================"
}

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        -g|--resource-group)
            RESOURCE_GROUP="$2"
            shift 2
            ;;
        -h|--help)
            usage
            ;;
        *)
            echo "Unknown option: $1"
            exit 1
            ;;
    esac
done

# Execute main function
main "$@"

```

© github · MIT · github/awesome-copilot

Similar IDE rules

All IDE rules for Agent setup: memory, context, orchestration →

From the same set732

The whole set →
update-docs-on-code-change A GitHub Copilot rule that flags when README.md and other docs need updating after code changes. Useful when your docs drift behind the code. ★ 40,418repo stars terraform-azure A Copilot rule that sets file layout, Azure Verified Modules and hard limits for Terraform work on Azure, including a ban on secrets in state. ★ 40,418repo stars tanstack-start-shadcn-tailwind A Copilot instruction file that pins the stack to TanStack Start, Shadcn/ui and Tailwind CSS, with Zod validating every external payload. ★ 40,418repo stars swift-mcp-server A Copilot rule that supplies patterns for building MCP servers in Swift with the official SDK: tools, resources, prompts and transports. ★ 40,418repo stars scala2 This rule steers Copilot toward the Databricks Scala style: immutability, pure functions, naming. Useful when your codebase runs on Scala 2.12 or 2.13. ★ 40,418repo stars rust-mcp-server A Copilot rule that guides the agent when you build MCP servers in Rust with the official rmcp SDK. Useful when the project is Rust and you need a custom MCP server. ★ 40,418repo stars r Tells Copilot how to write R: follow the file's style, avoid unsafe calls, keep paths project-relative. Useful when a repo has .R, .Rmd or .qmd files. ★ 40,418repo stars qa-engineering-best-practices A GitHub Copilot instruction file covering test strategy, the test pyramid, naming, assertions and bug reports. Useful when Copilot writes or reviews tests in your repo. ★ 40,418repo stars

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor