@objctp/opencode-shell-routines 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -0
  3. package/agents/shell-architect.md +88 -0
  4. package/agents/shell-expert.md +60 -0
  5. package/commands/shell-audit.md +47 -0
  6. package/commands/shell-batch-exec.md +48 -0
  7. package/commands/shell-new.md +57 -0
  8. package/commands/shell-routines-setup.md +66 -0
  9. package/commands/shell-test-run.md +46 -0
  10. package/opencode.json +19 -0
  11. package/package.json +34 -0
  12. package/plugins/shell-hooks.ts +150 -0
  13. package/scripts/lib-batch.sh +297 -0
  14. package/scripts/lib-common.sh +332 -0
  15. package/skills/shell-batch-operations/SKILL.md +97 -0
  16. package/skills/shell-batch-operations/assets/batch-template.sh +124 -0
  17. package/skills/shell-batch-operations/examples/data-pipeline.sh +157 -0
  18. package/skills/shell-batch-operations/examples/file-batch.sh +140 -0
  19. package/skills/shell-batch-operations/references/decision-tree.md +53 -0
  20. package/skills/shell-best-practices/SKILL.md +313 -0
  21. package/skills/shell-best-practices/assets/library.sh +142 -0
  22. package/skills/shell-best-practices/assets/minimal.sh +54 -0
  23. package/skills/shell-best-practices/assets/posix.sh +180 -0
  24. package/skills/shell-best-practices/assets/standard.sh +203 -0
  25. package/skills/shell-best-practices/references/patterns.md +386 -0
  26. package/skills/shell-best-practices/references/security.md +195 -0
  27. package/skills/shell-debugging/SKILL.md +115 -0
  28. package/skills/shell-debugging/examples/debug-session.md +165 -0
  29. package/skills/shell-debugging/references/debugging-guide.md +336 -0
  30. package/skills/shell-profiling/SKILL.md +154 -0
  31. package/skills/shell-profiling/examples/profile-session.md +225 -0
  32. package/skills/shell-profiling/references/optimisation-patterns.md +373 -0
  33. package/skills/shell-profiling/references/profiling-tools.md +318 -0
  34. package/skills/shell-profiling/scripts/bench.sh +82 -0
  35. package/skills/shell-profiling/scripts/trace-aggregate.sh +34 -0
  36. package/skills/shell-review/SKILL.md +61 -0
  37. package/skills/shell-review/examples/sample-review.md +42 -0
  38. package/skills/shell-review/references/guidelines.md +48 -0
  39. package/skills/shell-review/references/review-template.md +56 -0
  40. package/skills/shell-security/SKILL.md +128 -0
  41. package/skills/shell-security/examples/dangerous-command-review.md +231 -0
  42. package/skills/shell-security/examples/secure-script-example.sh +317 -0
  43. package/skills/shell-security/references/dangerous-commands.md +561 -0
  44. package/skills/shell-security/references/security-patterns.md +30 -0
  45. package/skills/shell-security/references/sensitive-files.md +525 -0
  46. package/skills/shell-security/scripts/security-audit.sh +208 -0
  47. package/skills/shell-test/SKILL.md +237 -0
  48. package/skills/shell-test/examples/test-example.md +74 -0
  49. package/skills/shell-test/references/advanced-patterns.md +52 -0
  50. package/skills/shell-test/references/assertions.md +184 -0
  51. package/skills/shell-test/references/test-template.md +60 -0
  52. package/skills/shell-test/scripts/public-coverage.sh +93 -0
@@ -0,0 +1,386 @@
1
+ # Common Bash Patterns
2
+
3
+ ## Argument Parsing
4
+
5
+ ### Basic positional arguments
6
+ ```bash
7
+ #!/usr/bin/env bash
8
+ set -euo pipefail
9
+
10
+ usage() {
11
+ echo "Usage: $0 <input> <output>" >&2
12
+ exit 2
13
+ }
14
+
15
+ [[ $# -eq 2 ]] || usage
16
+
17
+ input="$1"
18
+ output="$2"
19
+ ```
20
+
21
+ ### getopts (flag-based)
22
+ ```bash
23
+ #!/usr/bin/env bash
24
+ set -euo pipefail
25
+
26
+ verbose=0
27
+ output_file=""
28
+
29
+ while getopts "vo:" opt; do
30
+ case "$opt" in
31
+ v) verbose=1 ;;
32
+ o) output_file="$OPTARG" ;;
33
+ \?) echo "Invalid option: -$OPTARG" >&2; exit 2 ;;
34
+ esac
35
+ done
36
+
37
+ shift $((OPTIND - 1))
38
+ ```
39
+
40
+ ## Temporary Files
41
+
42
+ ### Safe temp file with cleanup
43
+ ```bash
44
+ tmp_file=$(mktemp)
45
+ trap 'rm -f "$tmp_file"' EXIT
46
+
47
+ # Process with temp file
48
+ process_data > "$tmp_file"
49
+ result=$(cat "$tmp_file")
50
+ ```
51
+
52
+ ### Safe temp directory
53
+ ```bash
54
+ tmp_dir=$(mktemp -d)
55
+ trap 'rm -rf "$tmp_dir"' EXIT
56
+
57
+ # Create files in temp directory
58
+ output="$tmp_dir/output.txt"
59
+ ```
60
+
61
+ ## Arrays
62
+
63
+ ### Iteration
64
+ ```bash
65
+ items=("apple" "banana" "cherry")
66
+ for item in "${items[@]}"; do
67
+ echo "$item"
68
+ done
69
+ ```
70
+
71
+ ### Building array from command output
72
+ ```bash
73
+ readarray -t files < <(find . -name "*.txt" -type f)
74
+ for file in "${files[@]}"; do
75
+ process "$file"
76
+ done
77
+ ```
78
+
79
+ ### Associative arrays (bash 4+)
80
+ ```bash
81
+ declare -A config
82
+ config[host]="localhost"
83
+ config[port]="8080"
84
+
85
+ for key in "${!config[@]}"; do
86
+ echo "$key = ${config[$key]}"
87
+ done
88
+ ```
89
+
90
+ ## String Manipulation
91
+
92
+ ### Parameter expansion (bash 4+)
93
+ ```bash
94
+ string="Hello, World!"
95
+
96
+ # Uppercase
97
+ echo "${string^^}" # HELLO, WORLD!
98
+
99
+ # Lowercase
100
+ echo "${string,,}" # hello, world!
101
+
102
+ # Remove suffix
103
+ path="/path/to/file.txt"
104
+ echo "${path%.txt}" # /path/to/file
105
+
106
+ # Remove prefix
107
+ echo "${path##*/}" # file.txt
108
+
109
+ # Replace first match
110
+ echo "${string/World/Bash}" # Hello, Bash!
111
+
112
+ # Replace all matches
113
+ echo "${string//l/L}" # HeLLo, WorLd!
114
+ ```
115
+
116
+ ### Use braces for variable expansion
117
+ ```bash
118
+ # BAD - ambiguous without braces
119
+ echo "$var_name" # Is this ${var_name} or ${var}_name?
120
+
121
+ # GOOD - braces make intent explicit
122
+ echo "${var}_name"
123
+ echo "${var_name}"
124
+
125
+ # GOOD - braces required for array, length, and manipulation
126
+ echo "${items[@]}"
127
+ echo "${#items[@]}"
128
+ echo "${var:-default}"
129
+ ```
130
+
131
+ ### Indirect expansion
132
+ ```bash
133
+ # Access variable whose name is stored in another variable
134
+ var_name="colour"
135
+ colour="blue"
136
+
137
+ echo "${!var_name}" # blue
138
+
139
+ # Use case: dynamic config lookup
140
+ declare -A config
141
+ config[host]="localhost"
142
+ config[port]="8080"
143
+
144
+ for key in host port; do
145
+ echo "${config[$key]}"
146
+ done
147
+ ```
148
+
149
+ ### Numeric vs string comparison
150
+ ```bash
151
+ # BAD - '>' inside [[ ]] is lexicographic: "9" < "7"
152
+ if [[ $count > 7 ]]; then ...
153
+
154
+ # GOOD - use (( )) for arithmetic
155
+ if (( count > 7 )); then ...
156
+
157
+ # GOOD - or -gt inside [[ ]]
158
+ if [[ $count -gt 7 ]]; then ...
159
+ ```
160
+
161
+ ### Exact equality vs pattern matching in [[ ]]
162
+ ```bash
163
+ bar="*.txt"
164
+
165
+ # BAD - unquoted RHS enables glob pattern matching
166
+ [[ "file.txt" = $bar ]] && echo yes # matches!
167
+
168
+ # GOOD - quote RHS for exact string equality
169
+ [[ "file.txt" = "$bar" ]] && echo yes # no match
170
+
171
+ # For intentional glob matching, leave RHS unquoted
172
+ [[ "file.txt" == *.txt ]] # matches
173
+ ```
174
+
175
+ ### IFS splitting drops trailing empty fields
176
+ ```bash
177
+ # BAD - trailing empty field silently lost
178
+ IFS=, read -ra arr <<< "a,b,"
179
+ echo "${#arr[@]}" # 2, not 3
180
+
181
+ # GOOD - use -d '' to preserve trailing empties
182
+ IFS=, read -d '' -ra arr <<< "a,b,"
183
+ echo "${#arr[@]}" # 3
184
+
185
+ # GOOD - for CSV rows, handle trailing empties explicitly
186
+ line="a,b,"
187
+ IFS=, read -ra arr <<< "$line"
188
+ expected=3
189
+ while (( ${#arr[@]} < expected )); do
190
+ arr+=("")
191
+ done
192
+ ```
193
+
194
+ ## File Operations
195
+
196
+ ### Check file existence and type
197
+ ```bash
198
+ if [[ -f "$file" ]]; then
199
+ echo "Regular file exists"
200
+ elif [[ -d "$file" ]]; then
201
+ echo "Directory exists"
202
+ elif [[ -e "$file" ]]; then
203
+ echo "Something exists (not regular file or directory)"
204
+ else
205
+ echo "Does not exist"
206
+ fi
207
+ ```
208
+
209
+ **Note**: `[[ -e ]]` returns false for broken symlinks. Use `[[ -L ]]` to test symlink existence regardless of target:
210
+ ```bash
211
+ # BAD - broken symlinks report as non-existent
212
+ if [[ -e "$link" ]]; then ... fi # false for broken symlink
213
+
214
+ # GOOD - test the link itself
215
+ if [[ -L "$link" ]]; then ... fi # true for any symlink
216
+
217
+ # GOOD - check both link existence AND target
218
+ if [[ -L "$link" && -e "$link" ]]; then
219
+ echo "Symlink with valid target"
220
+ elif [[ -L "$link" ]]; then
221
+ echo "Broken symlink"
222
+ fi
223
+ ```
224
+
225
+ ### Read file line by line
226
+ ```bash
227
+ while IFS= read -r line; do
228
+ process_line "$line"
229
+ done < "$input_file"
230
+ ```
231
+
232
+ ### Process files in directory
233
+ ```bash
234
+ for file in *.txt; do
235
+ [[ -f "$file" ]] || continue
236
+ process "$file"
237
+ done
238
+ ```
239
+
240
+ ### Use `--` before variable file arguments
241
+ ```bash
242
+ # BAD - filename starting with '-' parsed as option
243
+ rm "$file"
244
+ cp "$src" "$dst"
245
+
246
+ # GOOD - '--' ends option parsing
247
+ rm -- "$file"
248
+ cp -- "$src" "$dst"
249
+
250
+ # GOOD - './' prefix prevents dash interpretation
251
+ mv "./$file" "$dest"
252
+ ```
253
+
254
+ ### Safely rewrite a file in-place
255
+ ```bash
256
+ # BAD - file truncated before cat reads it
257
+ cat file | sort > file # file is now empty
258
+ grep pattern file > file # file is now empty
259
+
260
+ # GOOD - write to temp file, then replace
261
+ sort file > tmp && mv tmp file
262
+
263
+ # GOOD - use sponge (moreutils) for in-place
264
+ sort file | sponge file
265
+ ```
266
+
267
+ ### Redirect stderr to /dev/null, never close it
268
+ ```bash
269
+ # BAD - closing stderr can cause programs to crash or misbehave
270
+ cmd 2>&-
271
+
272
+ # GOOD - redirect to /dev/null instead
273
+ cmd 2>/dev/null
274
+
275
+ # GOOD - suppress both stdout and stderr
276
+ cmd >/dev/null 2>&1
277
+ ```
278
+
279
+ ### Preserve variables set inside a read loop
280
+ ```bash
281
+ # BAD - pipe creates subshell; counter lost
282
+ count=0
283
+ cat file | while IFS= read -r line; do
284
+ ((count++))
285
+ done
286
+ echo "$count" # always 0
287
+
288
+ # GOOD - process substitution keeps same shell
289
+ count=0
290
+ while IFS= read -r line; do
291
+ ((count++))
292
+ done < <(cat file)
293
+ echo "$count" # correct count
294
+ ```
295
+
296
+ ## Parallel Processing
297
+
298
+ ### Simple parallel with xargs
299
+ ```bash
300
+ find . -name "*.log" -print0 | \
301
+ xargs -0 -P 4 -I {} process_log "{}"
302
+ ```
303
+
304
+ ### Background jobs with wait
305
+ ```bash
306
+ pids=()
307
+ for item in "${items[@]}"; do
308
+ process "$item" &
309
+ pids+=($!)
310
+ done
311
+
312
+ # Wait for all background jobs
313
+ for pid in "${pids[@]}"; do
314
+ wait "$pid"
315
+ done
316
+ ```
317
+
318
+ ## Progress Indication
319
+
320
+ ### Simple counter
321
+ ```bash
322
+ total=$(wc -l < "$file")
323
+ current=0
324
+
325
+ while IFS= read -r line; do
326
+ ((current++))
327
+ printf "\rProcessing: %d/%d" "$current" "$total"
328
+ process "$line"
329
+ done
330
+ printf "\n"
331
+ ```
332
+
333
+ ## Exit Code Handling
334
+
335
+ ### Check command success
336
+ ```bash
337
+ if ! command_that_might_fail; then
338
+ echo "Command failed" >&2
339
+ exit 1
340
+ fi
341
+ ```
342
+
343
+ ### Capture and check exit code
344
+ ```bash
345
+ if output=$(some_command); then
346
+ echo "Success: $output"
347
+ else
348
+ exit_code=$?
349
+ echo "Failed with code: $exit_code" >&2
350
+ exit "$exit_code"
351
+ fi
352
+ ```
353
+
354
+ ## Input Validation
355
+
356
+ ### Validate numeric input
357
+ ```bash
358
+ is_number() {
359
+ local value="$1"
360
+ [[ "$value" =~ ^[0-9]+$ ]]
361
+ }
362
+
363
+ # Usage
364
+ if is_number "$port"; then
365
+ echo "Valid port number"
366
+ fi
367
+ ```
368
+
369
+ ### Validate within range
370
+ ```bash
371
+ validate_port() {
372
+ local port="$1"
373
+ (( port >= 1 && port <= 65535 ))
374
+ }
375
+ ```
376
+
377
+ ### Validate required arguments
378
+ ```bash
379
+ validate_inputs() {
380
+ local name="$1"
381
+ local port="$2"
382
+
383
+ [[ -n "$name" ]] || { echo "Error: name is required" >&2; return 1; }
384
+ validate_port "$port" || { echo "Error: port out of range" >&2; return 1; }
385
+ }
386
+ ```
@@ -0,0 +1,195 @@
1
+ # Writing Secure Shell Scripts
2
+
3
+ Preventive patterns to apply while writing shell scripts. For auditing existing scripts for security vulnerabilities (destructive commands, credential exposure, system file risks), use `shell-security` instead.
4
+
5
+ ## Command Injection Prevention
6
+
7
+ ### NEVER use eval
8
+ ```bash
9
+ # BAD - User can execute arbitrary commands
10
+ eval "echo $user_input"
11
+
12
+ # GOOD - Use arrays or direct execution
13
+ echo "$user_input"
14
+ ```
15
+
16
+ ### NEVER pipe to sh/bash
17
+ ```bash
18
+ # BAD - Downloads and executes untrusted code
19
+ curl http://example.com/script.sh | sh
20
+
21
+ # GOOD - Download, review, then execute
22
+ curl -O http://example.com/script.sh
23
+ less script.sh
24
+ sh script.sh
25
+ ```
26
+
27
+ ### ALWAYS quote variables in command positions
28
+ ```bash
29
+ # BAD - Word splitting and globbing
30
+ func $user_var
31
+
32
+ # GOOD - Properly quoted
33
+ func "$user_var"
34
+ ```
35
+
36
+ ## Input Validation
37
+
38
+ ### Validate filenames against path traversal
39
+ ```bash
40
+ validate_filename() {
41
+ local filename="$1"
42
+
43
+ # Reject paths with directory traversal
44
+ if [[ "$filename" == *".."* ]]; then
45
+ echo "Error: invalid filename" >&2
46
+ return 1
47
+ fi
48
+
49
+ # Reject absolute paths if not expected
50
+ if [[ "$filename" == /* ]]; then
51
+ echo "Error: absolute paths not allowed" >&2
52
+ return 1
53
+ fi
54
+
55
+ # Only allow safe characters
56
+ if [[ ! "$filename" =~ ^[a-zA-Z0-9._-]+$ ]]; then
57
+ echo "Error: filename contains invalid characters" >&2
58
+ return 1
59
+ fi
60
+ }
61
+ ```
62
+
63
+ For type/range validation helpers (e.g. `is_number`, `validate_port`), see `references/patterns.md`.
64
+
65
+ ### Sanitise environment variables
66
+ ```bash
67
+ # Clear PATH before using untrusted input
68
+ if [[ "$untrusted_mode" == "true" ]]; then
69
+ export PATH="/usr/bin:/bin"
70
+ fi
71
+ ```
72
+
73
+ ## Secrets Handling
74
+
75
+ ### NEVER hardcode credentials
76
+ ```bash
77
+ # BAD
78
+ api_key="sk-live-1234567890abcdef"
79
+
80
+ # GOOD - Read from environment
81
+ api_key="${API_KEY:-}"
82
+ [[ -n "$api_key" ]] || { echo "Error: API_KEY not set" >&2; exit 1; }
83
+ ```
84
+
85
+ ### Prevent secrets in process list
86
+ ```bash
87
+ # BAD - Secret visible in ps
88
+ curl -H "Authorization: Bearer $secret_token" https://api.example.com
89
+
90
+ # GOOD - Use file for secrets
91
+ echo "Authorization: Bearer $secret_token" > "$tmp_headers"
92
+ curl -H @"$tmp_headers" https://api.example.com
93
+ rm -f "$tmp_headers"
94
+ ```
95
+
96
+ ### Prevent secrets in logs
97
+ ```bash
98
+ # Redirect debug output that may contain secrets
99
+ process_with_secrets 2>/dev/null
100
+
101
+ # Or filter sensitive patterns
102
+ process_with_secrets 2>&1 | grep -v "password\|token\|secret"
103
+ ```
104
+
105
+ ## Temporary Files
106
+
107
+ ### ALWAYS use mktemp
108
+ ```bash
109
+ # BAD - Predictable filename, race condition
110
+ tmp_file="/tmp/my_script_$$"
111
+
112
+ # GOOD - Atomic, unpredictable
113
+ tmp_file=$(mktemp)
114
+ trap 'rm -f "$tmp_file"' EXIT
115
+ ```
116
+
117
+ ### Set restrictive permissions on temp files
118
+ ```bash
119
+ tmp_file=$(mktemp)
120
+ chmod 600 "$tmp_file"
121
+ ```
122
+
123
+ ## File Permissions
124
+
125
+ ### Use restrictive defaults
126
+ ```bash
127
+ # Create files with owner-only permissions
128
+ umask 077
129
+
130
+ # Or set explicitly
131
+ output_file=$(mktemp)
132
+ chmod 600 "$output_file"
133
+ ```
134
+
135
+ ### Avoid world-writable locations
136
+ ```bash
137
+ # BAD - /tmp is world-writable
138
+ output="/tmp/data.txt"
139
+
140
+ # GOOD - Use user's cache
141
+ output="$HOME/.cache/script/data.txt"
142
+ mkdir -p "$(dirname "$output")"
143
+ ```
144
+
145
+ ## Safe Command Execution
146
+
147
+ ### Use arrays for arguments
148
+ ```bash
149
+ # BAD - Word splitting
150
+ files="*.txt"
151
+ cat $files
152
+
153
+ # GOOD - Proper expansion
154
+ files=("*.txt")
155
+ cat "${files[@]}"
156
+ ```
157
+
158
+ ### Use set -f to disable globbing
159
+ ```bash
160
+ # Disable glob expansion when processing untrusted input
161
+ set -f
162
+ process_untrusted "$user_input"
163
+ set +f
164
+ ```
165
+
166
+ ## Signal Handling
167
+
168
+ ### Clean up on interruption
169
+ ```bash
170
+ cleanup() {
171
+ rm -f "$tmp_file"
172
+ rm -rf "$tmp_dir"
173
+ echo "Cleaned up temporary files" >&2
174
+ }
175
+
176
+ trap cleanup EXIT INT TERM HUP
177
+
178
+ tmp_file=$(mktemp)
179
+ tmp_dir=$(mktemp -d)
180
+ ```
181
+
182
+ ### Prevent partial state on exit
183
+ ```bash
184
+ cleanup() {
185
+ # Remove incomplete output
186
+ [[ -f "${output}.partial" ]] && rm -f "${output}.partial"
187
+ }
188
+
189
+ trap cleanup EXIT
190
+
191
+ # Write to partial file, rename on success
192
+ output="result.txt"
193
+ process_data > "${output}.partial"
194
+ mv "${output}.partial" "$output"
195
+ ```
@@ -0,0 +1,115 @@
1
+ ---
2
+ name: shell-debugging
3
+ description: Debug a failing bash script: reproduce the failure, isolate the cause with non-invasive tracing (bash -x, bash -n, ShellCheck), then apply and verify the fix. Use when a script errors at runtime, crashes, exits non-zero, or produces wrong output ("debug this script", "fix my script", "why is this failing"). For a script that works but runs slowly, use shell-profiling; for quality review of a working script, use shell-review.
4
+ allowed-tools: Read, Edit, Bash, Grep, Glob
5
+ argument-hint: [script-path]
6
+ ---
7
+
8
+ # Shell Debugging Skill
9
+
10
+ Guides systematic debugging of bash scripts to identify and resolve issues efficiently.
11
+
12
+ **Scope**: This skill handles runtime failures — scripts that error, crash, or produce wrong output. For quality assessment of a working script, use `shell-review` instead.
13
+
14
+ **Design principle**: Never leave debug instrumentation in the target script. Use non-invasive methods (`bash -x`) first; when targeted tracing is needed, instrument a temporary copy and discard it afterwards.
15
+
16
+ ## Debugging Workflow
17
+
18
+ ### 1. Gather Information
19
+
20
+ **Target script:** `$ARGUMENTS`
21
+
22
+ If `$ARGUMENTS` is not provided, ask the user which script needs debugging.
23
+
24
+ Understand the failure:
25
+
26
+ - **Error message**: What is the exact error?
27
+ - **Exit code**: What is `$?` after the failing command?
28
+ - **Failure point**: Where exactly does the script fail?
29
+ - **Reproduction**: Can the failure be reproduced consistently?
30
+
31
+ ### 2. Read the Target Script
32
+
33
+ Read `$ARGUMENTS` to understand:
34
+
35
+ - Overall structure and purpose
36
+ - Functions called near the failure point
37
+ - Variable dependencies
38
+ - Error handling patterns
39
+
40
+ ### 3. Enable Debug Mode
41
+
42
+ **Non-invasive** — run with tracing from the command line, no file modification:
43
+
44
+ ```bash
45
+ bash -x script.sh args
46
+ ```
47
+
48
+ - `+` prefix indicates the command being executed
49
+ - Variables are expanded before printing
50
+
51
+ **Targeted tracing** — when you need tracing around a specific section only, create a temporary copy:
52
+
53
+ ```bash
54
+ cp script.sh /tmp/script.debug.sh
55
+ # Add set -x / set +x around the suspect section in the copy
56
+ bash /tmp/script.debug.sh args
57
+ rm /tmp/script.debug.sh
58
+ ```
59
+
60
+ ### 4. Syntax Validation
61
+
62
+ ```bash
63
+ bash -n script.sh
64
+ ```
65
+
66
+ ### 5. Incremental Execution
67
+
68
+ **Warning**: `source` executes all top-level code in the script. Before sourcing a broken script, inspect it for side effects (file operations, network calls, deployments). Consider using a container or VM for untrusted scripts.
69
+
70
+ ```bash
71
+ # Source the script to load functions
72
+ source script.sh
73
+
74
+ # Call functions individually with test data
75
+ your_function "test_input"
76
+ ```
77
+
78
+ ### 6. Identify the Issue
79
+
80
+ Consult `references/debugging-guide.md` for:
81
+
82
+ - Error pattern tables and fixes (unbound variables, pipelines, subshells, whitespace)
83
+ - Advanced techniques: custom PS4, timing, call logging
84
+ - ShellCheck quick-reference table for common warning codes
85
+
86
+ ### 7. Apply the Fix
87
+
88
+ Make the minimal change that resolves the root cause, not the symptom.
89
+
90
+ ### 8. Verify
91
+
92
+ - Re-run the originally failing invocation — it now succeeds
93
+ - `bash -n` is clean; no new errors introduced
94
+ - No debug instrumentation remains in the script
95
+
96
+ **Done when** the reported failure no longer reproduces under the original invocation, `bash -n` and ShellCheck are clean, and the script holds no leftover `set -x` or debug prints.
97
+
98
+ ## Additional Resources
99
+
100
+ ### References
101
+
102
+ - `references/debugging-guide.md` -- Error pattern tables, debugging checklist, common issue solutions, advanced techniques (custom PS4, timing, call logging), ShellCheck quick reference
103
+
104
+ Always read all references and examples before producing output.
105
+
106
+ ### Examples
107
+
108
+ - `examples/debug-session.md` -- Walks through diagnosing an unbound variable error from start to finish
109
+
110
+ ## Integration
111
+
112
+ - **`shell-best-practices`** -- Prevent issues before they occur
113
+ - **`shell-review`** -- Quality assessment once the script is working
114
+ - **`shell-profiling`** -- For scripts that work correctly but run too slowly. See profiling workflow for timing, tracing, and benchmarking.
115
+ - **`/shell-audit`** command -- Comprehensive quality checks