---
name: writing-bash-scripts
description: Generates production-grade Bash scripts with strict mode, modular structure, unified logging, error handling, and ShellCheck compliance. Triggered by requests like "write a bash script", "create shell script", "generate CLI tool in bash". Keywords: bash, shell, script, devops.
argument-hint: "<functional-requirement-description>"
allowed-tools:
  - Read
  - Write
  - Bash
  - Glob
  - Grep
---

# Writing Production-Grade Bash Scripts

## Purpose
Transform functional requirements into a single, deployable Bash script following engineering best practices.

## Arguments
`$ARGUMENTS` = functional requirement description (目标、输入/输出、流程、约束、示例数据等)

If `$ARGUMENTS` is empty, prompt user for:
- Target functionality
- Input/output specification
- Constraints (OS, permissions, dependencies)

## Dynamic Context

!`echo "Current working directory: $(pwd)"`

!`bash --version | head -1`

---

## Plan Phase

### Deliverables Checklist
- [ ] Single `.sh` file with shebang `#!/usr/bin/env bash`
- [ ] Bash >= 5.0 requirement documented
- [ ] ASCII call graph at script top
- [ ] usage/help function (-h/--help)
- [ ] Parameter parsing (getopts)
- [ ] Exit code documentation
- [ ] --dry-run support
- [ ] --verbose/--quiet support
- [ ] Cleanup trap for temp files

### Decision Points
| Decision | Default | Override Condition |
|----------|---------|-------------------|
| POSIX vs Bash-specific | POSIX preferred | Use Bash features only when necessary (arrays, `[[ ]]`, mapfile); comment reason |
| Destructive ops | Require `--force` | Never auto-delete without confirmation |
| Temp file location | `mktemp -d` | User-specified via `--tmp-dir` |

---

## Execute Phase

### Script Structure (固定顺序)

```
1. Shebang + Metadata
2. ASCII Call Graph
3. Global Constants (readonly)
4. Strict Mode Setup
5. Dependency/Environment Checks
6. Logging & Error Handling Functions
7. Business Functions
8. main() + Entry Point
9. Self-test Examples (comments)
```

### Strict Mode (必须)
```bash
set -Eeuo pipefail
IFS=$' \t\n'
```

### Required Functions

| Function | Purpose |
|----------|---------|
| `usage` | Print help with examples |
| `die` | `die <msg> <exit_code>` - unified error exit |
| `log_debug/info/warn/error` | Timestamped logging with LOG_LEVEL control |
| `run_cmd` | Command wrapper: dry-run, retry, error capture |
| `cleanup` | Remove temp files/locks on EXIT/ERR/INT/TERM |

### Function Documentation Format
```bash
### <one-line description>
### @param <name> <type> <purpose>
### @return <exit_code> <status>
### @require <dependency/permission>
### @side_effect <file/network/system impact>
function_name() {
    ...
}
```

### Exit Codes
| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | General error |
| 2 | Invalid arguments |
| 3 | Missing dependency |
| 4 | Permission denied |
| 5 | File/resource not found |
| 126 | Command not executable |
| 127 | Command not found |

> See `reference/exit-codes.md` for extended codes.

### Logging Format
```
[YYYY-MM-DD HH:MM:SS] [LEVEL] message
```

---

## Verify Phase

### Pre-Delivery Checklist

#### Frontmatter & Structure
- [ ] Shebang is `#!/usr/bin/env bash`
- [ ] Bash version requirement stated
- [ ] ASCII call graph present
- [ ] Sections in correct order

#### Safety & Defaults
- [ ] `set -Eeuo pipefail` enabled
- [ ] All variables double-quoted (except intentional word splitting with comment)
- [ ] No unquoted `$@` or `$*`
- [ ] No unsafe `eval`
- [ ] `--dry-run` implemented
- [ ] `--force` required for destructive ops
- [ ] `mktemp` used for temp files
- [ ] trap covers EXIT/ERR/INT/TERM

#### Functions
- [ ] Every function has `###` doc block
- [ ] `@param`, `@return`, `@require` present
- [ ] snake_case naming
- [ ] Input validation on all external inputs

#### Logging & Errors
- [ ] `log_*` functions implemented
- [ ] LOG_LEVEL controls output
- [ ] `die` includes line number and function stack
- [ ] `run_cmd` wrapper used for external commands

#### Quality
- [ ] Passes ShellCheck (or disables with `# shellcheck disable=SCxxxx` + reason)
- [ ] 3+ self-test examples in comments (normal, error, dry-run)
- [ ] No hardcoded paths without override option

### ShellCheck Validation
```bash
shellcheck -x -s bash <script.sh>
```

> Use `scripts/shellcheck-wrapper.sh` for automated checking.

---

## Common Pitfalls

| Pitfall | Fix |
|---------|-----|
| Unquoted variables in paths with spaces | Always `"$var"` |
| Missing `local` in functions | Declare with `local var=...` |
| Assuming GNU tools on macOS | Check `uname` or use portable flags |
| Ignoring exit code of piped commands | `set -o pipefail` + check `${PIPESTATUS[@]}` |
| Temp files left on error | Trap cleanup on ERR/EXIT |

---

## Reference Files

| When | Read |
|------|------|
| Need detailed code structure | `reference/code-structure.md` |
| Writing function docs | `reference/function-template.md` |
| Defining custom exit codes | `reference/exit-codes.md` |
| Starting from scratch | `examples/minimal-template.sh` |

---

## Minimal Self-Test Commands

```bash
# 1. Help
./script.sh --help

# 2. Dry-run
./script.sh --dry-run <args>

# 3. Invalid argument (expect exit 2)
./script.sh --invalid-option

# 4. Verbose mode
./script.sh --verbose <args>
```
