Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Language-specific super-code guidelines for bash.
.claude/skills/lingxling-bash/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 37% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 43% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 88% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 60% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 112% | 0% |
bash# ❌ Unquoted variable (word splitting + globbing) for f in $files; do rm $f; done # ✅ for f in "${files[@]}"; do rm -- "$f"; done
bash# ❌ Unquoted command substitution path=$(find . -name config) cat $path # breaks on spaces # ✅ path="$(find . -name config)" cat "$path"
bash# ❌ Using backticks for command substitution result=`echo hello` # ✅ — $() nests cleanly result=$(echo hello)
bash# ❌ String comparison without quotes if [ $var = "hello" ]; then # breaks if var is empty or has spaces # ✅ if [[ "$var" = "hello" ]]; then
Rule: double-quote every $variable and $(command) unless you specifically need splitting.
bash# ❌ Single bracket test (POSIX but fragile) if [ -f "$file" -a -r "$file" ]; then # ✅ — [[ is safer, supports &&/||, no word splitting inside if [[ -f "$file" && -r "$file" ]]; then
bash# ❌ Testing command exit status with if [ $? -eq 0 ] grep -q pattern file if [ $? -eq 0 ]; then echo "found"; fi # ✅ — test command directly if grep -q pattern file; then echo "found"; fi
bash# ❌ String equality with == outside [[ if [ "$a" == "$b" ]; then # == not POSIX in [ ] # ✅ if [[ "$a" == "$b" ]]; then # Bash # or POSIX: if [ "$a" = "$b" ]; then
bash# ❌ Arithmetic with [ ] and string comparison if [ "$count" -gt 10 ]; then # ✅ — (( )) for arithmetic if (( count > 10 )); then
bash# ❌ Parsing ls output for f in $(ls *.txt); do process "$f"; done # ✅ — glob directly for f in *.txt; do [[ -e "$f" ]] || continue # handle no-match process "$f" done
bash# ❌ Reading file line-by-line with for for line in $(cat file.txt); do # splits on words, not lines # ✅ while IFS= read -r line; do process "$line" done < file.txt
bash# ❌ Seq for counting for i in $(seq 1 10); do # ✅ — brace expansion (Bash) for i in {1..10}; do # or C-style: for (( i = 1; i <= 10; i++ )); do
bash# ❌ Processing command output line-by-line with pipe (subshell trap) count=0 cat file.txt | while read -r line; do (( count++ )) # count resets after loop — subshell done echo "$count" # always 0 # ✅ — redirect, not pipe count=0 while IFS= read -r line; do (( count++ )) done < file.txt echo "$count"
bash# ❌ Chained grep | grep for AND grep "error" log.txt | grep "timeout" # ✅ — single grep with pattern grep -E "error.*timeout|timeout.*error" log.txt # or awk for complex logic: awk '/error/ && /timeout/' log.txt
bash# ❌ cat + pipe (UUOC — Useless Use of Cat) cat file.txt | grep pattern # ✅ grep pattern file.txt
bash# ❌ Temp file for diff between commands cmd1 > /tmp/a.txt cmd2 > /tmp/b.txt diff /tmp/a.txt /tmp/b.txt rm /tmp/a.txt /tmp/b.txt # ✅ — process substitution diff <(cmd1) <(cmd2)
bash# ❌ Ignoring pipe failures (only last command's exit code) false | true echo $? # 0 — false's failure hidden # ✅ set -o pipefail false | true echo $? # 1
bash# ❌ Using return for string values get_name() { return "Alice" # return is for exit codes (0-255) } # ✅ — echo + capture get_name() { echo "Alice" } name=$(get_name)
bash# ❌ Global variables modified inside functions result="" compute() { result="done"; } # ✅ — use local, return via stdout compute() { local tmp tmp=$(do_work) echo "$tmp" } result=$(compute)
bash# ❌ Function keyword (not POSIX) function my_func { # ✅ my_func() {
bash# ❌ No error handling — script continues after failure cd /some/dir rm -rf * # if cd fails, deletes from wrong directory # ✅ set -euo pipefail cd /some/dir || { echo "cd failed" >&2; exit 1; } rm -rf ./*
bash# ❌ No cleanup on exit tmpfile=$(mktemp) # ... script might exit early, leaving tmpfile # ✅ — trap for cleanup tmpfile=$(mktemp) trap 'rm -f "$tmpfile"' EXIT
bash# ❌ Silencing errors blindly command 2>/dev/null # ✅ — redirect only when you know what you're suppressing command 2>/dev/null || true # explicit: we expect and accept failure
Start every script with set -euo pipefail. Remove selectively where needed.
| Anti-pattern | Preferred | |---|---| | Parsing ls output | glob: for f in *.txt | | cat file \| grep | grep pattern file | | Unquoted $var | "$var" always | | [ ] for complex tests | [[ ]] | | Backtick substitution | $(command) | | $? check after command | if command; then | | echo for debug | printf '%s\n' (portable) | | No set -euo pipefail | always set at script top | | Temp files without cleanup | trap 'rm -f "$tmp"' EXIT | | eval with user input | avoid; use arrays for dynamic commands | | #!/bin/sh with Bash features | #!/usr/bin/env bash | | String math expr 1 + 1 | $(( 1 + 1 )) | | test -z for number comparison | (( )) for arithmetic |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 15,852 | 13,793 | -13% | 1 | 1 | 0% | 3,057 | 4,193 | +37% | 0 | 0 | — |
case-02 | pass→pass | 8,222 | 5,410 | -34% | 1 | 1 | 0% | 1,213 | 2,568 | +112% | 0 | 0 | — |
case-03 | fail→pass | 10,393 | 4,656 | -55% | 1 | 1 | 0% | 1,766 | 2,523 | +43% | 0 | 0 | — |
case-04 | pass→pass | 5,817 | 5,073 | -13% | 1 | 1 | 0% | 869 | 2,645 | +204% | 0 | 0 | — |
case-05 | pass→pass | 4,942 | 2,927 | -41% | 1 | 1 | 0% | 673 | 2,396 | +256% | 0 | 0 | — |
case-06 | pass→pass | 3,904 | 3,522 | -10% | 1 | 1 | 0% | 523 | 2,383 | +356% | 0 | 0 | — |
case-07 | pass→pass | 6,920 | 3,327 | -52% | 1 | 1 | 0% | 997 | 2,369 | +138% | 0 | 0 | — |
case-08 | fail→pass | 9,789 | 5,708 | -42% | 1 | 1 | 0% | 1,431 | 2,696 | +88% | 0 | 0 | — |
case-09 | pass→pass | 9,380 | 4,581 | -51% | 1 | 1 | 0% | 1,429 | 2,693 | +88% | 0 | 0 | — |
case-10 | pass→pass | 5,369 | 2,901 | -46% | 1 | 1 | 0% | 805 | 2,384 | +196% | 0 | 0 | — |
case-11 | pass→pass | 9,201 | 9,592 | +4% | 1 | 1 | 0% | 1,689 | 2,992 | +77% | 0 | 0 | — |
case-12 | fail→pass | 10,983 | 5,234 | -52% | 1 | 1 | 0% | 1,651 | 2,635 | +60% | 0 | 0 | — |
case-13 | pass→pass | 2,954 | 2,711 | -8% | 1 | 1 | 0% | 366 | 2,190 | +498% | 0 | 0 | — |
case-14 | pass→pass | 3,083 | 2,261 | -27% | 1 | 1 | 0% | 496 | 2,277 | +359% | 0 | 0 | — |
case-15 | pass→pass | 5,332 | 4,238 | -21% | 1 | 1 | 0% | 621 | 2,519 | +306% | 0 | 0 | — |
case-16 | pass→pass | 3,190 | 3,935 | +23% | 1 | 1 | 0% | 581 | 2,545 | +338% | 0 | 0 | — |
case-17 | pass→pass | 7,759 | 4,693 | -40% | 1 | 1 | 0% | 1,133 | 2,577 | +127% | 0 | 0 | — |
case-18 | pass→pass | 3,333 | 3,279 | -2% | 1 | 1 | 0% | 439 | 2,259 | +415% | 0 | 0 | — |
case-19 | pass→pass | 3,904 | 3,162 | -19% | 1 | 1 | 0% | 665 | 2,416 | +263% | 0 | 0 | — |
case-20 | pass→pass | 6,973 | 3,574 | -49% | 1 | 1 | 0% | 980 | 2,457 | +151% | 0 | 0 | — |
case-21 | pass→pass | 3,409 | 2,663 | -22% | 1 | 1 | 0% | 458 | 2,308 | +404% | 0 | 0 | — |
case-22 | pass→pass | 8,114 | 5,268 | -35% | 1 | 1 | 0% | 1,085 | 2,719 | +151% | 0 | 0 | — |
case-23 | pass→pass | 8,373 | 6,633 | -21% | 1 | 1 | 0% | 1,289 | 3,224 | +150% | 0 | 0 | — |
case-24 | pass→pass | 10,761 | 7,242 | -33% | 1 | 1 | 0% | 1,579 | 3,131 | +98% | 0 | 0 | — |
case-25 | pass→pass | 27,607 | 23,377 | -15% | 1 | 1 | 0% | 4,026 | 6,330 | +57% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +16 percentage points is the difference between those two pass rates over the 25 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.