You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(host-paths): use $HOME instead of ~ in non-env-var host paths
`HOST_PATHS` for Claude (and any future host with `usesEnvVars=false`) was
built from `~/${config.globalRoot}`. The resulting binDir is then
interpolated into double-quoted bash strings by several preamble emitters,
e.g. `generate-brain-sync-block.ts:45`:
_BRAIN_SYNC_BIN="${ctx.paths.binDir}/gstack-brain-sync"
POSIX shells do NOT expand `~` inside double quotes. The emitted line
becomes a literal `"~/.claude/.../gstack-brain-sync"`, which fails with
`exit 127, No such file or directory` when invoked. Both stderr and the
exit code are suppressed by `2>/dev/null || true`, so the failure is
silent: skill preambles call `gstack-brain-sync --once` on every skill
boundary, but it never runs. The artifacts queue (~/.gstack/.brain-queue.jsonl)
grows indefinitely while last-push stays at "never". Codex/Factory hosts
are unaffected because they use `$GSTACK_BIN`, which DOES expand inside
double quotes.
Fix: emit `$HOME/${config.globalRoot}` instead. Identical semantics outside
quotes, correct semantics inside quotes.
Why CI didn't catch it:
- `test/host-config.test.ts:246` asserted the broken form as the
expected value (`expect(...).toBe('~/.claude/skills/gstack/bin')`).
- The Claude golden fixture (`test/fixtures/golden/claude-ship-SKILL.md`)
was generated from the broken code path, so the regression suite was
comparing the bug against itself.
Changes:
- `scripts/resolvers/types.ts`: emit `$HOME/...` for non-env-var hosts
(one-line change + WHY comment).
- `test/host-config.test.ts`: update existing assertions to expect
`$HOME/...`. Add a narrow regression guard that asserts no non-env-var
host's binDir/skillRoot/browseDir/designDir/makePdfDir begins with `~`
(i.e., is safe to interpolate inside double quotes).
- Regenerated artifacts via `bun run gen:skill-docs --host all`:
42 Claude-host SKILL.md files + the claude-ship golden fixture flip
from `~/...` to `$HOME/...`. Codex/Factory artifacts unchanged.
Test plan:
- `bun test test/host-config.test.ts` — 74 pass, 0 fail (includes new guard).
- `bun test test/gen-skill-docs.test.ts test/brain-sync.test.ts` —
412 pass, 0 fail.
- `bun run test` (main suite, e2e excluded) — green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@@ -111,15 +111,15 @@ If the user invokes a skill in plan mode, the skill takes precedence over generi
111
111
112
112
If `PROACTIVE` is `"false"`, do not auto-invoke or proactively suggest skills. If a skill seems useful, ask: "I think /skillname might help here — want me to run it?"
113
113
114
-
If `SKILL_PREFIX` is `"true"`, suggest/invoke `/gstack-*` names. Disk paths stay `~/.claude/skills/gstack/[skill-name]/SKILL.md`.
114
+
If `SKILL_PREFIX` is `"true"`, suggest/invoke `/gstack-*` names. Disk paths stay `$HOME/.claude/skills/gstack/[skill-name]/SKILL.md`.
115
115
116
-
If output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined).
116
+
If output shows `UPGRADE_AVAILABLE <old> <new>`: read `$HOME/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined).
117
117
118
118
If output shows `JUST_UPGRADED <from> <to>`: print "Running gstack v{to} (just updated!)". If `SPAWNED_SESSION` is true, skip feature discovery.
119
119
120
120
Feature discovery, max one prompt per session:
121
-
- Missing `~/.claude/skills/gstack/.feature-prompted-continuous-checkpoint`: AskUserQuestion for Continuous checkpoint auto-commits. If accepted, run `~/.claude/skills/gstack/bin/gstack-config set checkpoint_mode continuous`. Always touch marker.
122
-
- Missing `~/.claude/skills/gstack/.feature-prompted-model-overlay`: inform "Model overlays are active. MODEL_OVERLAY shows the patch." Always touch marker.
121
+
- Missing `$HOME/.claude/skills/gstack/.feature-prompted-continuous-checkpoint`: AskUserQuestion for Continuous checkpoint auto-commits. If accepted, run `$HOME/.claude/skills/gstack/bin/gstack-config set checkpoint_mode continuous`. Always touch marker.
122
+
- Missing `$HOME/.claude/skills/gstack/.feature-prompted-model-overlay`: inform "Model overlays are active. MODEL_OVERLAY shows the patch." Always touch marker.
123
123
124
124
After upgrade prompts, continue workflow.
125
125
@@ -132,7 +132,7 @@ Options:
132
132
- B) Restore V0 prose — set `explain_level: terse`
133
133
134
134
If A: leave `explain_level` unset (defaults to `default`).
135
-
If B: run `~/.claude/skills/gstack/bin/gstack-config set explain_level terse`.
135
+
If B: run `$HOME/.claude/skills/gstack/bin/gstack-config set explain_level terse`.
136
136
137
137
Always run (regardless of choice):
138
138
```bash
@@ -159,7 +159,7 @@ Options:
159
159
- A) Help gstack get better! (recommended)
160
160
- B) No thanks
161
161
162
-
If A: run `~/.claude/skills/gstack/bin/gstack-config set telemetry community`
162
+
If A: run `$HOME/.claude/skills/gstack/bin/gstack-config set telemetry community`
163
163
164
164
If B: ask follow-up:
165
165
@@ -169,8 +169,8 @@ Options:
169
169
- A) Sure, anonymous is fine
170
170
- B) No thanks, fully off
171
171
172
-
If B→A: run `~/.claude/skills/gstack/bin/gstack-config set telemetry anonymous`
173
-
If B→B: run `~/.claude/skills/gstack/bin/gstack-config set telemetry off`
172
+
If B→A: run `$HOME/.claude/skills/gstack/bin/gstack-config set telemetry anonymous`
173
+
If B→B: run `$HOME/.claude/skills/gstack/bin/gstack-config set telemetry off`
174
174
175
175
Always run:
176
176
```bash
@@ -187,8 +187,8 @@ Options:
187
187
- A) Keep it on (recommended)
188
188
- B) Turn it off — I'll type /commands myself
189
189
190
-
If A: run `~/.claude/skills/gstack/bin/gstack-config set proactive true`
191
-
If B: run `~/.claude/skills/gstack/bin/gstack-config set proactive false`
190
+
If A: run `$HOME/.claude/skills/gstack/bin/gstack-config set proactive true`
191
+
If B: run `$HOME/.claude/skills/gstack/bin/gstack-config set proactive false`
192
192
193
193
Always run:
194
194
```bash
@@ -233,7 +233,7 @@ Key routing rules:
233
233
234
234
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
235
235
236
-
If B: run `~/.claude/skills/gstack/bin/gstack-config set routing_declined true` and say they can re-enable with `gstack-config set routing_declined false`.
236
+
If B: run `$HOME/.claude/skills/gstack/bin/gstack-config set routing_declined true` and say they can re-enable with `gstack-config set routing_declined false`.
237
237
238
238
This only happens once per project. Skip if `HAS_ROUTING` is `yes` or `ROUTING_DECLINED` is `true`.
239
239
@@ -249,15 +249,15 @@ Options:
249
249
If A:
250
250
1. Run `git rm -r .claude/skills/gstack/`
251
251
2. Run `echo '.claude/skills/gstack/' >> .gitignore`
252
-
3. Run `~/.claude/skills/gstack/bin/gstack-team-init required` (or `optional`)
252
+
3. Run `$HOME/.claude/skills/gstack/bin/gstack-team-init required` (or `optional`)
253
253
4. Run `git add .claude/ .gitignore CLAUDE.md && git commit -m "chore: migrate gstack from vendored to team mode"`
254
254
5. Tell the user: "Done. Each developer now runs: `cd ~/.claude/skills/gstack && ./setup --team`"
255
255
256
256
If B: say "OK, you're on your own to keep the vendored copy up to date."
0 commit comments