{"id":"465bdd29-8c50-44e5-bf73-c47e63364c24","shortId":"nJakpK","kind":"skill","title":"bash","tagline":"Use when editing shell scripts, .sh files, bash shebangs, CLI automation, text processing pipelines, shell error handling, quoting, traps, functions, or portable Bash patterns.","description":"# Bash Scripting\n\n## Overview\n\nBash is the default shell on most Linux distributions. This skill covers idiomatic scripting patterns following the Google Shell Style Guide, with emphasis on safety, readability, and maintainability.\n\n## Quick Reference\n\n### Safety Header (always include)\n\n```bash\n#!/usr/bin/env bash\nset -euo pipefail\nIFS=$'\\n\\t'\n```\n\n| Flag | Effect |\n|------|--------|\n| `set -e` | Exit immediately on non-zero return |\n| `set -u` | Error on unset variables |\n| `set -o pipefail` | Pipe returns rightmost non-zero exit code |\n| `IFS=$'\\n\\t'` | Safer word splitting (no space splitting) |\n\n### Style Essentials\n\n| Rule | Good | Bad |\n|------|------|-----|\n| Function declaration | `my_func() { ... }` | `function my_func { ... }` |\n| Local variables | `local file_path=\"$1\"` | `file_path=$1` |\n| Constants | `readonly MAX_RETRIES=3` | `MAX_RETRIES=3` |\n| Variable expansion | `\"${var}\"` | `$var` |\n| Command substitution | `\"$(command)\"` | `` `command` `` |\n| Declare + assign | `local out; out=\"$(cmd)\"` | `local out=\"$(cmd)\"` |\n| File test | `[[ -f \"${file}\" ]]` | `[ -f $file ]` |\n\n### Common ShellCheck Fixes\n\n| Code | Issue | Fix |\n|------|-------|-----|\n| SC2086 | Unquoted variable | Double-quote: `\"${var}\"` |\n| SC2046 | Unquoted command sub | Quote or use `mapfile` |\n| SC2155 | Declare and assign together | Separate into two statements |\n| SC2034 | Unused variable | Add `export` or `# shellcheck disable=SC2034` |\n\n<workflow>\n\n## Workflow\n\n### Step 1: Start with the Safety Header\n\nEvery script begins with the shebang, strict mode, and a usage comment block describing purpose, usage, and examples.\n\n### Step 2: Define Functions\n\nOrganize logic into functions. Use `local` for all function-scoped variables. Use `main()` as the entry point, called at the bottom with `main \"$@\"`.\n\n### Step 3: Handle Arguments\n\nUse `getopts` for simple flags, or manual `while [[ $# -gt 0 ]]` parsing for long options. Always validate required arguments and print usage on error.\n\n### Step 4: Add Cleanup Traps\n\nUse `trap cleanup EXIT` for any script that creates temporary files, acquires locks, or needs to restore state on failure.\n\n### Step 5: Run ShellCheck\n\nValidate the script with `shellcheck script.sh` before committing. Fix all warnings; disable specific rules only with a justifying comment.\n\n</workflow>\n\n<guardrails>\n\n## Guardrails\n\n- **Always quote variables** — unquoted variables cause word splitting and glob expansion bugs; use `\"${var}\"` everywhere\n- **Always use ShellCheck** — run `shellcheck` on every script; it catches the majority of common bash pitfalls\n- **Prefer functions over inline code** — functions with `local` variables prevent accidental global state leaks\n- **Never use `eval`** unless absolutely necessary — it is the most common source of injection vulnerabilities in shell scripts\n- **Use `[[ ]]` not `[ ]`** — double brackets prevent word splitting and support regex matching\n- **Use `mktemp` for temporary files** — never hardcode `/tmp/myscript.tmp`; it creates race conditions\n- **Avoid parsing `ls` output** — use globs (`*.txt`) or `find` with `-print0` and `read -d ''` for safe file iteration\n\n</guardrails>\n\n<validation>\n\n### Validation Checkpoint\n\nBefore delivering a script, verify:\n\n- [ ] Script starts with `#!/usr/bin/env bash` and `set -euo pipefail`\n- [ ] All variables are quoted with `\"${var}\"`\n- [ ] All function variables use `local`\n- [ ] `trap cleanup EXIT` is set if the script creates temporary resources\n- [ ] ShellCheck passes with no unacknowledged warnings\n- [ ] Script has a usage/help function accessible via `-h` or `--help`\n\n</validation>\n\n<example>\n\n## Example\n\nA safe script template with error handling, argument parsing, and cleanup:\n\n```bash\n#!/usr/bin/env bash\n#\n# Deploy an application to the target environment.\n#\n# Usage:\n#   deploy.sh [-v] [-e environment] <app_name>\n#\nset -euo pipefail\nIFS=$'\\n\\t'\n\nreadonly SCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nreadonly TMPDIR=\"$(mktemp -d)\"\n\ncleanup() {\n    rm -rf \"${TMPDIR}\"\n}\ntrap cleanup EXIT\n\nusage() {\n    cat <<EOF\nUsage: $(basename \"$0\") [-v] [-e environment] <app_name>\n\nOptions:\n  -v              Verbose output\n  -e ENVIRONMENT  Target environment (default: staging)\n  -h              Show this help\nEOF\n}\n\nmain() {\n    local verbose=false\n    local environment=\"staging\"\n\n    while getopts \":ve:h\" opt; do\n        case \"${opt}\" in\n            v) verbose=true ;;\n            e) environment=\"${OPTARG}\" ;;\n            h) usage; exit 0 ;;\n            :) echo \"Error: -${OPTARG} requires an argument\" >&2; exit 1 ;;\n            ?) echo \"Error: Unknown option -${OPTARG}\" >&2; exit 1 ;;\n        esac\n    done\n    shift $((OPTIND - 1))\n\n    if [[ $# -eq 0 ]]; then\n        echo \"Error: app_name is required\" >&2\n        usage >&2\n        exit 1\n    fi\n\n    local app_name=\"$1\"\n\n    if [[ \"${verbose}\" == true ]]; then\n        echo \"Deploying ${app_name} to ${environment}...\"\n    fi\n\n    # Build and deploy logic here\n    echo \"Deployed ${app_name} to ${environment} successfully.\"\n}\n\nmain \"$@\"\n```\n\n</example>\n\n---\n\n## References Index\n\nFor detailed guides and code examples, refer to the following documents in `references/`:\n\n- **[Style Guide](references/style.md)**\n  - Google Shell Style Guide patterns: file headers, function naming, variable naming, quoting rules, error handling.\n- **[Common Patterns](references/patterns.md)**\n  - Argument parsing (getopts), trap for cleanup, here-docs, process substitution, array manipulation, associative arrays.\n- **[Safety & Defensive Scripting](references/safety.md)**\n  - Shellcheck compliance, avoiding common pitfalls, handling spaces in filenames, proper exit codes, signal handling.\n\n---\n\n## Official References\n\n- <https://google.github.io/styleguide/shellguide.html>\n- <https://www.gnu.org/software/bash/manual/>\n\n## Shared Styleguide Baseline\n\n- Use shared styleguides for generic language/framework rules to reduce duplication in this skill.\n- [General Principles](https://github.com/cofin/flow/blob/main/templates/styleguides/general.md)\n- [Bash](https://github.com/cofin/flow/blob/main/templates/styleguides/languages/bash.md)\n- Keep this skill focused on tool-specific workflows, edge cases, and integration details.","tags":["bash","flow","cofin","agent-skills","ai-agents","beads","claude-code","codex","cursor","developer-tools","gemini-cli","opencode"],"capabilities":["skill","source-cofin","skill-bash","topic-agent-skills","topic-ai-agents","topic-beads","topic-claude-code","topic-codex","topic-cursor","topic-developer-tools","topic-gemini-cli","topic-opencode","topic-plugin","topic-slash-commands","topic-spec-driven-development"],"categories":["flow"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cofin/flow/bash","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cofin/flow","source_repo":"https://github.com/cofin/flow","install_from":"skills.sh"}},"qualityScore":"0.455","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 11 github stars · SKILL.md body (6,239 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:07:35.344Z","embedding":null,"createdAt":"2026-04-23T13:03:57.779Z","updatedAt":"2026-05-18T19:07:35.344Z","lastSeenAt":"2026-05-18T19:07:35.344Z","tsv":"'/cofin/flow/blob/main/templates/styleguides/general.md)':754 '/cofin/flow/blob/main/templates/styleguides/languages/bash.md)':758 '/software/bash/manual/':733 '/styleguide/shellguide.html':730 '/tmp/myscript.tmp':411 '/usr/bin/env':64,444,501 '0':267,528,546,590,615 '1':126,129,202,599,607,612,627,632 '2':227,597,605,623,625 '3':134,137,255 '4':282 '5':307 'absolut':379 'access':483 'accident':371 'acquir':297 'add':194,283 'alway':61,272,330,345 'app':619,630,639,651 'applic':505 'argument':257,275,496,596,693 'array':704,707 'assign':147,185 'associ':706 'autom':12 'avoid':416,714 'bad':113 'baselin':736 'basenam':545 'bash':1,9,24,26,29,63,65,359,445,500,502,526,755 'begin':210 'block':220 'bottom':251 'bracket':396 'bug':341 'build':644 'call':248 'case':578,769 'cat':542 'catch':354 'caus':335 'cd':524 'checkpoint':435 'cleanup':284,288,462,499,534,539,698 'cli':11 'cmd':151,154 'code':99,164,365,663,723 'command':142,144,145,176 'comment':219,328 'commit':317 'common':161,358,385,690,715 'complianc':713 'condit':415 'constant':130 'cover':40 'creat':294,413,469 'd':429,533 'declar':115,146,183 'default':32,558 'defens':709 'defin':228 'deliv':437 'deploy':503,638,646,650 'deploy.sh':511 'describ':221 'detail':660,772 'dir':523 'dirnam':525 'disabl':198,321 'distribut':37 'doc':701 'document':669 'done':609 'doubl':171,395 'double-quot':170 'duplic':746 'e':75,513,548,554,584 'echo':591,600,617,637,649 'edg':768 'edit':4 'effect':73 'emphasi':51 'entri':246 'environ':509,514,549,555,557,570,585,642,654 'eof':543,564 'eq':614 'error':17,85,280,494,592,601,618,688 'esac':608 'essenti':110 'euo':67,448,516 'eval':377 'everi':208,351 'everywher':344 'exampl':225,488,664 'exit':76,98,289,463,540,589,598,606,626,722 'expans':139,340 'export':195 'f':157,159 'failur':305 'fals':568 'fi':628,643 'file':8,124,127,155,158,160,296,408,432,680 'filenam':720 'find':424 'fix':163,166,318 'flag':72,262 'focus':762 'follow':44,668 'func':117,120 'function':21,114,118,229,233,239,362,366,457,482,682 'function-scop':238 'general':750 'generic':741 'getopt':259,573,695 'github.com':753,757 'github.com/cofin/flow/blob/main/templates/styleguides/general.md)':752 'github.com/cofin/flow/blob/main/templates/styleguides/languages/bash.md)':756 'glob':339,421 'global':372 'good':112 'googl':46,675 'google.github.io':729 'google.github.io/styleguide/shellguide.html':728 'gt':266 'guardrail':329 'guid':49,661,673,678 'h':485,560,575,587 'handl':18,256,495,689,717,725 'hardcod':410 'header':60,207,681 'help':487,563 'here-doc':699 'idiomat':41 'if':69,100,518 'immedi':77 'includ':62 'index':658 'inject':388 'inlin':364 'integr':771 'issu':165 'iter':433 'justifi':327 'keep':759 'language/framework':742 'leak':374 'linux':36 'local':121,123,148,152,235,368,460,566,569,629 'lock':298 'logic':231,647 'long':270 'ls':418 'main':243,253,565,656 'maintain':56 'major':356 'manipul':705 'manual':264 'mapfil':181 'match':403 'max':132,135 'mktemp':405,532 'mode':215 'n':70,101,519 'name':620,631,640,652,683,685 'necessari':380 'need':300 'never':375,409 'non':80,96 'non-zero':79,95 'o':90 'offici':726 'opt':576,579 'optarg':586,593,604 'optind':611 'option':271,550,603 'organ':230 'output':419,553 'overview':28 'pars':268,417,497,694 'pass':473 'path':125,128 'pattern':25,43,679,691 'pipe':92 'pipefail':68,91,449,517 'pipelin':15 'pitfal':360,716 'point':247 'portabl':23 'prefer':361 'prevent':370,397 'principl':751 'print':277 'print0':426 'process':14,702 'proper':721 'purpos':222 'pwd':529 'quick':57 'quot':19,172,178,331,453,686 'race':414 'read':428 'readabl':54 'readon':131,521,530 'reduc':745 'refer':58,657,665,671,727 'references/patterns.md':692 'references/safety.md':711 'references/style.md':674 'regex':402 'requir':274,594,622 'resourc':471 'restor':302 'retri':133,136 'return':82,93 'rf':536 'rightmost':94 'rm':535 'rule':111,323,687,743 'run':308,348 'safe':431,490 'safer':103 'safeti':53,59,206,708 'sc2034':191,199 'sc2046':174 'sc2086':167 'sc2155':182 'scope':240 'script':6,27,42,209,292,312,352,392,439,441,468,478,491,522,710 'script.sh':315 'separ':187 'set':66,74,83,89,447,465,515 'sh':7 'share':734,738 'shebang':10,213 'shell':5,16,33,47,391,676 'shellcheck':162,197,309,314,347,349,472,712 'shift':610 'show':561 'signal':724 'simpl':261 'skill':39,749,761 'skill-bash' 'sourc':386,527 'source-cofin' 'space':107,718 'specif':322,766 'split':105,108,337,399 'stage':559,571 'start':203,442 'state':303,373 'statement':190 'step':201,226,254,281,306 'strict':214 'style':48,109,672,677 'styleguid':735,739 'sub':177 'substitut':143,703 'success':655 'support':401 'target':508,556 'templat':492 'temporari':295,407,470 'test':156 'text':13 'tmpdir':531,537 'togeth':186 'tool':765 'tool-specif':764 'topic-agent-skills' 'topic-ai-agents' 'topic-beads' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-developer-tools' 'topic-gemini-cli' 'topic-opencode' 'topic-plugin' 'topic-slash-commands' 'topic-spec-driven-development' 'trap':20,285,287,461,538,696 'true':583,635 'two':189 'txt':422 'u':84 'unacknowledg':476 'unknown':602 'unless':378 'unquot':168,175,333 'unset':87 'unus':192 'usag':218,223,278,510,541,544,588,624 'usage/help':481 'use':2,180,234,242,258,286,342,346,376,393,404,420,459,737 'v':512,547,551,581 'valid':273,310,434 'var':140,141,173,343,455 'variabl':88,122,138,169,193,241,332,334,369,451,458,684 've':574 'verbos':552,567,582,634 'verifi':440 'via':484 'vulner':389 'warn':320,477 'word':104,336,398 'workflow':200,767 'www.gnu.org':732 'www.gnu.org/software/bash/manual/':731 'zero':81,97","prices":[{"id":"6458c779-853d-48cb-8e39-91a49ae35e9f","listingId":"465bdd29-8c50-44e5-bf73-c47e63364c24","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cofin","category":"flow","install_from":"skills.sh"},"createdAt":"2026-04-23T13:03:57.779Z"}],"sources":[{"listingId":"465bdd29-8c50-44e5-bf73-c47e63364c24","source":"github","sourceId":"cofin/flow/bash","sourceUrl":"https://github.com/cofin/flow/tree/main/skills/bash","isPrimary":false,"firstSeenAt":"2026-04-23T13:03:57.779Z","lastSeenAt":"2026-05-18T19:07:35.344Z"}],"details":{"listingId":"465bdd29-8c50-44e5-bf73-c47e63364c24","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cofin","slug":"bash","github":{"repo":"cofin/flow","stars":11,"topics":["agent-skills","ai-agents","beads","claude-code","codex","context-driven-development","cursor","developer-tools","gemini-cli","opencode","plugin","slash-commands","spec-driven-development","subagents","tdd","workflow"],"license":"apache-2.0","html_url":"https://github.com/cofin/flow","pushed_at":"2026-04-27T19:07:26Z","description":"Context-Driven Development toolkit for AI agents — spec-first planning, TDD workflow, and Beads integration.","skill_md_sha":"9441e6d60af7ef67bb2146840b6e84f86ff785df","skill_md_path":"skills/bash/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cofin/flow/tree/main/skills/bash"},"layout":"multi","source":"github","category":"flow","frontmatter":{"name":"bash","description":"Use when editing shell scripts, .sh files, bash shebangs, CLI automation, text processing pipelines, shell error handling, quoting, traps, functions, or portable Bash patterns."},"skills_sh_url":"https://skills.sh/cofin/flow/bash"},"updatedAt":"2026-05-18T19:07:35.344Z"}}