From 94b83759afb8b43681a21e1e2979fb465c4c2ade Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Wed, 18 Mar 2026 11:55:21 -0400 Subject: [PATCH] fix: use arrays for RUNTIME_DIRS to fix zsh word-splitting (#1173) (#1183) The version detection script in update.md used a space-separated string for RUNTIME_DIRS and iterated with `for entry in $RUNTIME_DIRS`. This relies on word-splitting which works in bash but fails in zsh (zsh does not word-split unquoted variables by default), causing the entire string to be treated as one entry and detection to fall through to UNKNOWN. Fix: convert RUNTIME_DIRS and ORDERED_RUNTIME_DIRS from space-separated strings to proper arrays, and iterate with ${array[@]} syntax which works correctly in both bash and zsh. Closes #1173 --- get-shit-done/workflows/update.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/get-shit-done/workflows/update.md b/get-shit-done/workflows/update.md index 7d276eae4..fa910c927 100644 --- a/get-shit-done/workflows/update.md +++ b/get-shit-done/workflows/update.md @@ -20,8 +20,11 @@ First, derive `PREFERRED_RUNTIME` from the invoking prompt's `execution_context` Use `PREFERRED_RUNTIME` as the first runtime checked so `/gsd:update` targets the runtime that invoked it. ```bash -# Runtime candidates: ":" -RUNTIME_DIRS="claude:.claude opencode:.config/opencode opencode:.opencode gemini:.gemini codex:.codex" +# Runtime candidates: ":" stored as an array. +# Using an array instead of a space-separated string ensures correct +# iteration in both bash and zsh (zsh does not word-split unquoted +# variables by default). Fixes #1173. +RUNTIME_DIRS=( "claude:.claude" "opencode:.config/opencode" "opencode:.opencode" "gemini:.gemini" "codex:.codex" ) # PREFERRED_RUNTIME should be set from execution_context before running this block. # If not set, infer from runtime env vars; fallback to claude. @@ -40,23 +43,23 @@ if [ -z "$PREFERRED_RUNTIME" ]; then fi # Reorder entries so preferred runtime is checked first. -ORDERED_RUNTIME_DIRS="" -for entry in $RUNTIME_DIRS; do +ORDERED_RUNTIME_DIRS=() +for entry in "${RUNTIME_DIRS[@]}"; do runtime="${entry%%:*}" if [ "$runtime" = "$PREFERRED_RUNTIME" ]; then - ORDERED_RUNTIME_DIRS="$ORDERED_RUNTIME_DIRS $entry" + ORDERED_RUNTIME_DIRS+=( "$entry" ) fi done -for entry in $RUNTIME_DIRS; do +for entry in "${RUNTIME_DIRS[@]}"; do runtime="${entry%%:*}" if [ "$runtime" != "$PREFERRED_RUNTIME" ]; then - ORDERED_RUNTIME_DIRS="$ORDERED_RUNTIME_DIRS $entry" + ORDERED_RUNTIME_DIRS+=( "$entry" ) fi done # Check local first (takes priority only if valid and distinct from global) LOCAL_VERSION_FILE="" LOCAL_MARKER_FILE="" LOCAL_DIR="" LOCAL_RUNTIME="" -for entry in $ORDERED_RUNTIME_DIRS; do +for entry in "${ORDERED_RUNTIME_DIRS[@]}"; do runtime="${entry%%:*}" dir="${entry#*:}" if [ -f "./$dir/get-shit-done/VERSION" ] || [ -f "./$dir/get-shit-done/workflows/update.md" ]; then @@ -69,7 +72,7 @@ for entry in $ORDERED_RUNTIME_DIRS; do done GLOBAL_VERSION_FILE="" GLOBAL_MARKER_FILE="" GLOBAL_DIR="" GLOBAL_RUNTIME="" -for entry in $ORDERED_RUNTIME_DIRS; do +for entry in "${ORDERED_RUNTIME_DIRS[@]}"; do runtime="${entry%%:*}" dir="${entry#*:}" if [ -f "$HOME/$dir/get-shit-done/VERSION" ] || [ -f "$HOME/$dir/get-shit-done/workflows/update.md" ]; then