Skip to content
Agentmart
Submit a tool

tdd-pro-bash32-portability

macOS bash 3.2 + BSD-tool portability checklist for substrate writing in claude-tdd-pro.

Skill by drumfiend21

IndexedApache-2.0
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/drumfiend21-tdd-pro-bash32-portability

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

macOS bash 3.2 + BSD-tool portability checklist for substrate writing in claude-tdd-pro. Reference BEFORE any new Write/Edit of a .sh file. Catches the 9 recurring portability gotchas (associative arrays, wc -l padding, printf %, env-var-passing-first, set -u + empty arrays, BSD grep --, redirect order, help-to-stderr, node -e top-level return, CLAUDE_PLUGIN_ROOT vs cwd).

Use cases: testing, writing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/tdd-pro-bash32-portability

What's inside

Skill name
tdd-pro-bash32-portability
Description
macOS bash 3.2 + BSD-tool portability checklist for substrate writing in claude-tdd-pro. Reference BEFORE any new Write/Edit of a .sh file. Catches the 9 recurring portability gotchas (associative arrays, wc -l padding, printf %, env-var-passing-first, set -u + empty arrays, BSD grep --, redirect order, help-to-stderr, node -e top-level return, CLAUDE_PLUGIN_ROOT vs cwd).
License
Apache-2.0
Instructions
178 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

# macOS Bash 3.2 + BSD-Tool Portability Checklist

**Rule:** Before writing or editing any new bash substrate, walk through this list. Don't catch these failures via spec runs — they're well-known and avoidable.

**Why:** Across CL-146..196 the same five portability bugs were repeatedly hit (associative arrays, `wc -l` padding, `printf %`, env-var passing, `set -u` + empty arrays). Each costs a debug-test-fix cycle of ~2 minutes. Treating this as a known-defect catalog saves ~10% per CL. Validated on CL-197: full H-8 promotion passed 10/10 first-run after applying this checklist (vs. ~4 spec-fix cycles per CL without it).

The canonical source-of-truth is [docs/memory/feedback-bash32-portability-checklist.md](../../../docs/memory/feedback-bash32-portability-checklist.md).

## The nine recurring portability bugs

### 1. No associative arrays

bash 3.2 (macOS default) rejects `declare -A`. Use `node -e '...'` for map/dict operations:

```bash
# WRONG — fails on macOS
declare -A counts
counts[apple]=3

# RIGHT — node handles maps
COUNT_JSON=$(KEY=apple VAL=3 node -e '
  const out = { [process.env.KEY]: Number(process.env.VAL) };
  process.stdout.write(JSON.stringify(out));
')
```

### 2. `wc -l < file` pads output with whitespace on macOS

```bash
# WRONG — actual value is "       2", not "2"
[ "$(wc -l < file)" = "2" ]

# RIGHT — strip whitespace
[ "$(wc -l < file | tr -d ' ')" = "2" ]
```

**Also patch spec files** — never trust a raw `wc -l` substring comparison.

### 3. `printf '...%\n'` is malformed

`%` starts a format spec; `%\n` is invalid. To emit a literal `%`, use `%%\n`:

```bash
# WRONG — silently produces nothing
printf 'similarity index 90%\n'

# RIGHT
printf 'similarity index 90%%\n'
```

Caught in W-9 spec setup with `similarity index 90%\n`.

### 4. Env-var passing into subshells must come FIRST

```bash
# WRONG — sets VAR in parent shell but NOT in node child
VAR=val RESULT=$(node -e 'console.log(process.env.VAR)')

# RIGHT — env-var goes inside the subshell, before the command
RESULT=$(VAR=val node -e 'console.log(process.env.VAR)')
```

Bites every node-via-bash one-liner.

### 5. `set -u` + empty array reference errors

`set -uo pipefail` + `"${ARR[@]}"` on an empty array → unbound variable error:

```bash
# WRONG — errors when ARR is empty
set -uo pipefail
ARR=()
for x in "${ARR[@]}"; do echo "$x"; done

# RIGHT — guard or use the empty-safe expansion
[[ ${#ARR[@]} -gt 0 ]] && for x in "${ARR[@]}"; do echo "$x"; done
# OR
for x in "${ARR[@]+"${ARR[@]}"}"; do echo "$x"; done
```

### 6. BSD `grep --flag-arg` confusion

`grep -E "--json..."` is read as a flag. Use `--` to end flag parsing:

```bash
# WRONG — BSD grep tries to parse --json as a flag
grep -E "--json-input" file

# RIGHT
grep -E -- "--json-input" file
```

### 7. Redirect order matters

`find ... 2>/dev/null >&2` sends find's stdout to /dev/null because `>&2` is evaluated when fd2 was just redirected:

```bash
# WRONG — stdout goes to /dev/null, not to original stderr
find . -type f 2>/dev/null >&2

# RIGHT — stdout to original stderr, then fd2 to /dev/null
find . -type f >&2 2>/dev/null
```

### 8. `node -e` does not allow top-level `return`

Code passed via `-e` runs at the top of a module, not inside a function:

```bash
# WRONG — SyntaxError: Illegal return statement
node -e '
  const x = check();
  if (!x) { return; }
  doMore(x);
'

# RIGHT — invert the condition
node -e '
  const x = check();

From drumfiend21/claude-tdd-pro, Apache-2.0.

More from drumfiend21/claude-tdd-pro

Signals

Stars
0
Forks
0
Open issues
0
Last commit (this folder)
May 24, 2026 (5 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
Apache-2.0
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from drumfiend21

Cite this page

tdd-pro-bash32-portability skill. Agent Mart. https://agentmart.dev/skills/drumfiend21-tdd-pro-bash32-portability (last updated 2026-10-24)