Skip to content

Commit 9b885c7

Browse files
supernormxlclaude
andcommitted
fix: statusline breaks on .alive → .walnut migration and iCloud paths
Two bugs fixed in session-new hook: 1. User-level ~/.claude/settings.json was never updated during migration, leaving statusLine pointing to .alive/statusline.sh (file no longer exists after rename to .walnut/). Now detects and fixes stale .alive/ references in both project-level and user-level settings. 2. Statusline path was injected without quoting, breaking on paths with spaces (iCloud: "Mobile Documents/com~apple~CloudDocs"). Now wraps command in bash "..." for safe execution. Self-healing: existing users who already updated to v1.0.0 will get their statusline auto-fixed on next session start — no manual action needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b202c87 commit 9b885c7

1 file changed

Lines changed: 48 additions & 13 deletions

File tree

plugins/walnut/hooks/scripts/walnut-session-new.sh

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -136,41 +136,76 @@ if [ -f "$STATUSLINE_SRC" ]; then
136136
fi
137137
fi
138138

139-
# Inject statusline into settings.json — absolute path with self-heal
140-
SETTINGS_DIR="$WORLD_ROOT/.claude"
141-
SETTINGS_FILE="$SETTINGS_DIR/settings.json"
142-
mkdir -p "$SETTINGS_DIR"
143-
if [ ! -f "$SETTINGS_FILE" ]; then
144-
cat > "$SETTINGS_FILE" << SETTINGSEOF
139+
# Inject statusline into settings.json — quoted path for spaces (iCloud etc.)
140+
# Fix BOTH project-level and user-level settings to handle .alive → .walnut migration.
141+
STATUSLINE_CMD="bash \"$WORLD_ROOT/.walnut/statusline.sh\""
142+
143+
# Helper: fix statusline in a settings.json file (create or self-heal)
144+
fix_statusline_in_settings() {
145+
local settings_file="$1"
146+
local settings_dir
147+
settings_dir="$(dirname "$settings_file")"
148+
mkdir -p "$settings_dir"
149+
150+
if [ ! -f "$settings_file" ]; then
151+
# Only create project-level settings, not user-level
152+
if [ "$settings_file" = "$WORLD_ROOT/.claude/settings.json" ]; then
153+
cat > "$settings_file" << SETTINGSEOF
145154
{
146155
"statusLine": {
147156
"type": "command",
148-
"command": "$WORLD_ROOT/.walnut/statusline.sh"
157+
"command": $( printf '%s' "$STATUSLINE_CMD" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo "\"$STATUSLINE_CMD\"" )
149158
}
150159
}
151160
SETTINGSEOF
152-
else
153-
# settings.json exists — ensure statusLine is present and uses absolute path
161+
fi
162+
return
163+
fi
164+
165+
# settings.json exists — ensure statusLine uses correct .walnut/ path with quoting
154166
if command -v python3 &>/dev/null; then
155-
WALNUT_SETTINGS_FILE="$SETTINGS_FILE" WALNUT_WORLD_ROOT="$WORLD_ROOT" python3 -c "
167+
WALNUT_SETTINGS_FILE="$settings_file" WALNUT_WORLD_ROOT="$WORLD_ROOT" python3 -c "
156168
import json, os, sys
157169
sf = os.environ['WALNUT_SETTINGS_FILE']
158170
wr = os.environ['WALNUT_WORLD_ROOT']
159-
expected = wr + '/.walnut/statusline.sh'
171+
# Quoted command handles paths with spaces (iCloud, etc.)
172+
expected_cmd = 'bash \"' + wr + '/.walnut/statusline.sh\"'
160173
try:
161174
with open(sf) as f:
162175
data = json.load(f)
163176
except (json.JSONDecodeError, ValueError):
164177
print('WALNUT: settings.json is malformed, cannot inject statusLine', file=sys.stderr)
165178
sys.exit(0)
166179
current = data.get('statusLine', {}).get('command', '')
167-
if current != expected:
168-
data['statusLine'] = {'type': 'command', 'command': expected}
180+
# Fix if: missing, wrong path, stale .alive/ reference, or unquoted path with spaces
181+
needs_fix = (
182+
current != expected_cmd
183+
and (
184+
not current
185+
or '.alive/' in current
186+
or ('.walnut/statusline.sh' in current and 'bash ' not in current and ' ' in wr)
187+
)
188+
)
189+
if needs_fix:
190+
data['statusLine'] = {'type': 'command', 'command': expected_cmd}
169191
with open(sf, 'w') as f:
170192
json.dump(data, f, indent=2)
171193
f.write('\n')
194+
print('WALNUT: fixed statusLine in ' + sf, file=sys.stderr)
172195
" 2>/dev/null || true
173196
fi
197+
}
198+
199+
# Fix project-level settings
200+
fix_statusline_in_settings "$WORLD_ROOT/.claude/settings.json"
201+
202+
# Fix user-level settings — catches stale .alive/ paths from pre-migration installs
203+
USER_SETTINGS="$HOME/.claude/settings.json"
204+
if [ -f "$USER_SETTINGS" ]; then
205+
# Only touch user settings if it has a stale .alive/ statusline reference
206+
if grep -q '\.alive/statusline' "$USER_SETTINGS" 2>/dev/null; then
207+
fix_statusline_in_settings "$USER_SETTINGS"
208+
fi
174209
fi
175210

176211
# Read world key (.walnut/key.md) for injection

0 commit comments

Comments
 (0)