@elad12390/bash-cli-refactoring
1.0.0Refactor bash CLI tools systematically. Helper extraction, god function decomposition, bash gotchas (set -e, local masking, ANSI-C quoting), BDD testing with pytest-bdd, command patterns, and a 9-item anti-pattern catalog. Triggers: refactor bash, bash CLI, shell script refactoring, bash best practices, bash anti-patterns, bash god function, BDD bash, test bash CLI, bash set -e, bash debugging, shell script patterns, bash code quality, bash cleanup, refactoring CLI tool
name: bash-cli-refactoring description: | Refactor bash CLI tools systematically using BDD methodology. Covers helper extraction (debug-aware wrappers, interactive pickers, two-tier resolution), god function decomposition (orchestrator pattern, extraction by concern), bash-specific gotchas (set -e traps, local masking, ANSI-C quoting, pipefail), BDD testing for bash (pytest-bdd with subprocess runner, testing without external dependencies), standard command patterns (entry point architecture, two-path flow, argument parsing), and a 9-item anti-pattern catalog with detection signals and fix recipes. Synthesized from real refactoring of a 1500-line kubectl wrapper CLI.
Trigger phrases: "refactor bash", "bash CLI", "shell script refactoring", "bash refactor", "refactor shell script", "bash best practices", "shell script quality", "bash anti-patterns", "bash god function", "bash helper extraction", "BDD bash", "test bash CLI", "bash cleanup", "bash set -e", "bash debugging", "refactoring CLI tool", "bash code quality", "shell script patterns", "bash code review"
Bash CLI Refactoring
Systematic methodology for refactoring bash CLI tools, synthesized from real refactoring of a 1500-line Kubernetes CLI wrapper.
Core Philosophy
- Extract by duplication, decompose by concern — Helper extraction eliminates repeated code. God function decomposition separates concerns. Different triggers, different techniques.
- Two-tier resolution — Pure resolve functions return values or empty. Ensure functions add interactive fallback. Never mix side effects with logic.
- BDD before refactoring — Write tests for existing behavior first. Then refactor with confidence. pytest-bdd + subprocess = zero mocks.
- Bash has landmines —
localmasks exit codes,set -o pipefailbreaks grep, single-quoted ANSI codes are literal strings. Know the gotchas. - Fix anti-patterns, not symptoms — A 9-item catalog with detection signals. Grep for the pattern, apply the recipe.
Quick-Start: Common Problems
"This 200-line function does everything"
- Identify concerns: arg parsing, resolution, data transform, output, tool logic
- Name each concern as
_module_action() - Extract one at a time, test after each extraction
- Keep orchestrator thin (~50 lines)
-> See
references/god-function-decomposition.md
"Same 7 lines copy-pasted in every command"
- Identify the repeated pattern (selection, resolution, cleanup)
- Extract to a helper with edge case handling
- Choose naming:
_fzf_select(infra),select_resource(domain),ensure_pod(resolution) - Replace all occurrences, test each one
-> See
references/helper-extraction.md
"How do I test a CLI that needs a Kubernetes cluster?"
- Set up
.bdd/directory with pytest-bdd - Write subprocess-based CLI runner with ANSI stripping
- Test what does NOT need the cluster: help, validation, routing, error messages
- Test command routing via expected output headers
-> See
references/bdd-for-bash.md
"I'm refactoring and things keep breaking silently"
- Check for
local var=$(cmd)— masks exit codes - Check ANSI quoting: use
$'\033[1m'not'\033[1m' - Check
set -eis in ALL sourced library files - Do NOT add
set -o pipefailif using grep in pipelines -> Seereferences/bash-gotchas.md
"Where do I even start with this messy CLI?"
- Run the anti-pattern detection grep commands
- Prioritize: blind stderr suppression > duplication > god functions
- Add BDD tests for existing behavior first
- Refactor one anti-pattern at a time
-> See
references/anti-pattern-catalog.md
Decision Trees
What to Refactor First
| Signal | Priority | Action |
|---|---|---|
2>/dev/null on data-fetching calls | High | Debug-aware wrapper |
| Same 5+ lines in 3+ commands | High | Helper extraction |
| Function >100 lines | Medium | God function decomposition |
No set -e in library files | Medium | Add to all files |
| No tests | Medium | BDD test suite first |
| Hardcoded credentials | Low | Env var override |
| Dead code | Low | Remove + update routing |
Extraction Type Selection
| Pattern | Technique | Reference |
|---|---|---|
| Same code in multiple commands | Helper extraction | references/helper-extraction.md |
| One huge function, many concerns | God function decomposition | references/god-function-decomposition.md |
| Repeated interactive selection | Generic picker + domain layer | references/helper-extraction.md |
| Repeated resource resolution | Two-tier resolve/ensure | references/helper-extraction.md |
| Missing validation | Regex guard pattern | references/anti-pattern-catalog.md |
Communication Between Bash Functions
| Data Type | Mechanism | Example |
|---|---|---|
| Return values | stdout | local ns=$(resolve_namespace "$app") |
| Configuration | Global variables | _LOGS_FOLLOW="-f" set by orchestrator |
| Input parameters | Function arguments | _logs_stream_stern "$namespace" "${apps[@]}" |
| Error signaling | Return code + stderr | print_error "msg" >&2; return 1 |
| Status messages | stderr | print_warning "msg" >&2 |
Reference Files
| File | Contents |
|---|---|
references/helper-extraction.md | Debug-aware wrappers, interactive pickers, two-tier resolution, cleanup patterns — when and how to extract reusable helpers |
references/god-function-decomposition.md | Orchestrator pattern, extraction by concern, naming conventions, step-by-step decomposition procedure |
references/bash-gotchas.md | set -e traps, local masking exit codes, pipefail vs grep, ANSI-C quoting, heredoc escaping, array handling, subshell scope |
references/bdd-for-bash.md | pytest-bdd setup for CLIs, subprocess runner with ANSI stripping, testing without external dependencies, feature file categories |
references/command-patterns.md | Entry point architecture, standard cmd_* pattern, two-path flow, argument parsing, library module organization, help system, debug mode |
references/anti-pattern-catalog.md | 9 anti-patterns with detection signals, fix recipes, before/after code, and grep-based detection commands |