Feature request: opt-in to preserve ${var} braces (SC2250 interop)
Summary
Add an option (e.g. --keep-braces, or a --replace/--transform modifier) that makes Shellharden apply its quoting corrections without stripping the curly braces from simple variable expansions — i.e. keep "${var}" as "${var}" instead of rewriting it to "$var".
Motivation — why this adds value
Shellharden's stated purpose is to "make your script ShellCheck compliant in terms of quoting." That is exactly why it is valuable, and exactly why this gap stings: there is one ShellCheck check that Shellharden actively works against.
ShellCheck ships SC2250 — require-variable-braces:
Prefer putting braces around variable references even when not strictly required.
SC2250 is opt-in, but it is enabled deliberately by many projects — either explicitly or via enable=all in .shellcheckrc. For those projects, braces on every expansion are a mandatory house style, enforced as a CI gate.
Today the two tools are in direct opposition:
shellcheck (with SC2250 on) adds braces: "$var" -> "${var}".
shellharden --replace removes them: "${var}" -> "$var".
The result is a loop that cannot converge. Running one tool re-introduces the exact findings the other just fixed. A project that wants Shellharden's quoting hardening and an SC2250-clean tree currently cannot have both from an automated pipeline — it has to disable Shellharden's autofix entirely, losing the quoting benefit, purely to avoid the brace churn.
An opt-in "keep braces" mode fixes this with no downside:
- It broadens adoption — every SC2250/
enable=all codebase becomes a candidate for --replace in CI, instead of report-only.
- It increases Shellharden's ShellCheck conformance, the tool's own headline goal: today
--replace output is not SC2250-clean; with this flag it would be.
- It is purely additive — default behaviour is unchanged, so no existing user is affected.
Current behaviour (reproduction)
Tested with Shellharden 4.3.2 (latest release):
$ shellharden --transform sh_test.sh
#!/usr/bin/env bash
foo=bar
echo "$foo" # <-- braces stripped
echo "$foo"
printf '%s\n' "${foo}/baz" # kept (syntactically required here)
Shellharden already correctly keeps braces where they are load-bearing (${foo}/baz), so the requested mode is a natural extension: keep them in the simple case too, when the user asks for it.
Proposed behaviour
shellharden --replace --keep-braces script.sh
shellharden --transform --keep-braces script.sh
All normal quoting corrections still apply; only ${...} braces are left intact — producing output that satisfies both Shellharden's quoting rules and SC2250. Flag spelling is maintainer's choice; the request is for the capability.
Alternatives considered
- Run Shellharden report-only (current workaround) — throws away the automation.
- Disable SC2250 — not viable where a style guide/
enable=all mandates braces.
- Post-process to re-add braces — fragile, duplicates ShellCheck's logic.
Impact
- Backward compatible: default output byte-for-byte unchanged.
- Unlocks
--replace in CI for every SC2250 / enable=all project.
- Advances Shellharden's own goal of ShellCheck conformance.
Feature request: opt-in to preserve
${var}braces (SC2250 interop)Summary
Add an option (e.g.
--keep-braces, or a--replace/--transformmodifier) that makes Shellharden apply its quoting corrections without stripping the curly braces from simple variable expansions — i.e. keep"${var}"as"${var}"instead of rewriting it to"$var".Motivation — why this adds value
Shellharden's stated purpose is to "make your script ShellCheck compliant in terms of quoting." That is exactly why it is valuable, and exactly why this gap stings: there is one ShellCheck check that Shellharden actively works against.
ShellCheck ships SC2250 —
require-variable-braces:SC2250 is opt-in, but it is enabled deliberately by many projects — either explicitly or via
enable=allin.shellcheckrc. For those projects, braces on every expansion are a mandatory house style, enforced as a CI gate.Today the two tools are in direct opposition:
shellcheck(with SC2250 on) adds braces:"$var"->"${var}".shellharden --replaceremoves them:"${var}"->"$var".The result is a loop that cannot converge. Running one tool re-introduces the exact findings the other just fixed. A project that wants Shellharden's quoting hardening and an SC2250-clean tree currently cannot have both from an automated pipeline — it has to disable Shellharden's autofix entirely, losing the quoting benefit, purely to avoid the brace churn.
An opt-in "keep braces" mode fixes this with no downside:
enable=allcodebase becomes a candidate for--replacein CI, instead of report-only.--replaceoutput is not SC2250-clean; with this flag it would be.Current behaviour (reproduction)
Tested with Shellharden 4.3.2 (latest release):
Shellharden already correctly keeps braces where they are load-bearing (
${foo}/baz), so the requested mode is a natural extension: keep them in the simple case too, when the user asks for it.Proposed behaviour
All normal quoting corrections still apply; only
${...}braces are left intact — producing output that satisfies both Shellharden's quoting rules and SC2250. Flag spelling is maintainer's choice; the request is for the capability.Alternatives considered
enable=allmandates braces.Impact
--replacein CI for every SC2250 /enable=allproject.