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
Every skill's SKILL.md hardcodes the absolute string ~/.claude/skills/gstack/... for its own bin/ and asset calls (e.g. the telemetry/config preamble that runs on every skill invocation). setup, however, is parameterised on its own checkout location and wires the skill symlinks correctly for any directory name. The result: if gstack is installed at ~/.claude/skills/<name> where <name> isn't literally gstack, the symlinks resolve but the skills' internal bin/asset references point at a non-existent ~/.claude/skills/gstack/ and fail silently, at skill-invocation time.
This is the gstack-dir-name sibling of #349 ($CLAUDE_CONFIG_DIR, the ~/.claude prefix). Same underlying cause — hardcoded absolute self-paths — different segment. Both ladder up to the "make path resolution dynamic rather than hardcoded" direction from #289.
Root cause (with file:line)
setup:17-18 — the install dir is derived, not fixed:
So setup is designed to run from wherever the repo lives, and INSTALL_SKILLS_DIR="$(dirname "$INSTALL_GSTACK_DIR")" (setup:19). The per-skill install (setup:535-569) creates a real dir at ~/.claude/skills/<skill>/ with an absoluteSKILL.md symlink into the actual checkout — correct for any dir name.
But the skill bodies are committed with the literal absolute path. Example — qa/SKILL.md at HEAD contains 52 occurrences of ~/.claude/skills/gstack/ across 51 lines (the preamble alone calls ~/.claude/skills/gstack/bin/gstack-config, .../bin/gstack-telemetry-log, etc.).
setupalready rewrites these paths when it generates the non-Claude host copies — e.g. setup:~1012-1028 rewrites .claude/skills/gstack → .kiro/skills/gstack (and the codex/cursor/factory/gbrain equivalents). The primary Claude install is the one host that never gets its in-file paths reconciled with INSTALL_GSTACK_DIR's actual basename.
Reproduction
# install under any name that isn't "gstack"
git clone https://github.com/garrytan/gstack ~/.claude/skills/gstack-dev
cd~/.claude/skills/gstack-dev && ./setup
# the skill symlinks are correct, but the in-file paths are not:
grep -c '~/.claude/skills/gstack/'~/.claude/skills/gstack-dev/qa/SKILL.md # > 0
ls ~/.claude/skills/gstack/bin/gstack-config 2>&1# No such file or directory
Then invoke any skill (e.g. /qa): its preamble shells out to ~/.claude/skills/gstack/bin/gstack-config …, which doesn't exist. No error surfaces to the user at install time — it only fails when a skill runs.
Observed directly while upgrading an install located at ~/.claude/skills/i-gstack: after git reset --hard origin/main && ./setup, every top-level */SKILL.md that references the install path (52 files on that checkout) still pointed at ~/.claude/skills/gstack/, and setup did not reconcile them.
Impact
Affects anyone whose global install lives at ~/.claude/skills/<name> where <name> != gstack (setup installs the skill siblings into INSTALL_SKILLS_DIR="$(dirname "$INSTALL_GSTACK_DIR")", so it accepts this layout — it just doesn't reconcile the in-file paths).
Silent: nothing fails at install; skills break later, at invocation, in a way that looks like the skill itself is broken.
Affects every skill (the shared preamble), not a subset.
Suggested fixes (maintainer's call)
Compatibility symlink (smallest). When basename "$INSTALL_GSTACK_DIR" != gstack, create/refresh $INSTALL_SKILLS_DIR/gstack -> $INSTALL_GSTACK_DIR so the hardcoded references resolve with zero file edits. Caveat: must not let Claude Code discover the repo-shaped dir as duplicate skills — setup:589 already has handling for skipping the repo-shaped gstack dir, so this needs to compose with that.
Runtime-relative resolution (cleanest, aligns with RFC: define a standard host integration contract for gstack #289). Have the preamble resolve its own bin/asset dir relative to the SKILL.md location instead of a hardcoded absolute path (a resolved $GSTACK_DIR), removing the dir-name dependency entirely. Larger change (touches the shared preamble across all skills).
Extend the existing rewrite to the Claude host (symmetric). Apply the same path rewrite setup already does for kiro/codex to the primary install, mapping ~/.claude/skills/gstack/ → $INSTALL_GSTACK_DIR. Caveat: the Claude install symlinks to source rather than copying, so this would either dirty the working tree or require switching that host to a copy-and-rewrite step.
Workaround (for affected users today)
After each install/upgrade, re-point the hardcoded references in the top-level skill files to the real install dir:
cd~/.claude/skills/<your-dir># macOS/BSD sed shown; on GNU/Linux use `sed -i` (no '').
find . -maxdepth 2 -name SKILL.md -not -path './.*' -print0 \
| xargs -0 sed -i ''"s|skills/gstack|skills/$(basename "$PWD")|g"
Scope to top-level */SKILL.md only; the generated host copies under .agents/.cursor/.factory/.gbrain/hosts use a gstack- prefix convention and should be left as-is. (This needs re-running after every upgrade, since git reset --hard reverts it — which is the motivation for fix #1 or #2.)
Summary
Every skill's
SKILL.mdhardcodes the absolute string~/.claude/skills/gstack/...for its ownbin/and asset calls (e.g. the telemetry/config preamble that runs on every skill invocation).setup, however, is parameterised on its own checkout location and wires the skill symlinks correctly for any directory name. The result: if gstack is installed at~/.claude/skills/<name>where<name>isn't literallygstack, the symlinks resolve but the skills' internalbin/asset references point at a non-existent~/.claude/skills/gstack/and fail silently, at skill-invocation time.This is the
gstack-dir-name sibling of #349 ($CLAUDE_CONFIG_DIR, the~/.claudeprefix). Same underlying cause — hardcoded absolute self-paths — different segment. Both ladder up to the "make path resolution dynamic rather than hardcoded" direction from #289.Root cause (with file:line)
setup:17-18— the install dir is derived, not fixed:So
setupis designed to run from wherever the repo lives, andINSTALL_SKILLS_DIR="$(dirname "$INSTALL_GSTACK_DIR")"(setup:19). The per-skill install (setup:535-569) creates a real dir at~/.claude/skills/<skill>/with an absoluteSKILL.mdsymlink into the actual checkout — correct for any dir name.But the skill bodies are committed with the literal absolute path. Example —
qa/SKILL.mdat HEAD contains 52 occurrences of~/.claude/skills/gstack/across 51 lines (the preamble alone calls~/.claude/skills/gstack/bin/gstack-config,.../bin/gstack-telemetry-log, etc.).setupalready rewrites these paths when it generates the non-Claude host copies — e.g.setup:~1012-1028rewrites.claude/skills/gstack→.kiro/skills/gstack(and the codex/cursor/factory/gbrain equivalents). The primary Claude install is the one host that never gets its in-file paths reconciled withINSTALL_GSTACK_DIR's actual basename.Reproduction
Then invoke any skill (e.g.
/qa): its preamble shells out to~/.claude/skills/gstack/bin/gstack-config …, which doesn't exist. No error surfaces to the user at install time — it only fails when a skill runs.Observed directly while upgrading an install located at
~/.claude/skills/i-gstack: aftergit reset --hard origin/main && ./setup, every top-level*/SKILL.mdthat references the install path (52 files on that checkout) still pointed at~/.claude/skills/gstack/, andsetupdid not reconcile them.Impact
~/.claude/skills/<name>where<name> != gstack(setupinstalls the skill siblings intoINSTALL_SKILLS_DIR="$(dirname "$INSTALL_GSTACK_DIR")", so it accepts this layout — it just doesn't reconcile the in-file paths).Suggested fixes (maintainer's call)
Compatibility symlink (smallest). When
basename "$INSTALL_GSTACK_DIR" != gstack, create/refresh$INSTALL_SKILLS_DIR/gstack -> $INSTALL_GSTACK_DIRso the hardcoded references resolve with zero file edits. Caveat: must not let Claude Code discover the repo-shaped dir as duplicate skills —setup:589already has handling for skipping the repo-shapedgstackdir, so this needs to compose with that.Runtime-relative resolution (cleanest, aligns with RFC: define a standard host integration contract for gstack #289). Have the preamble resolve its own bin/asset dir relative to the
SKILL.mdlocation instead of a hardcoded absolute path (a resolved$GSTACK_DIR), removing the dir-name dependency entirely. Larger change (touches the shared preamble across all skills).Extend the existing rewrite to the Claude host (symmetric). Apply the same path rewrite
setupalready does for kiro/codex to the primary install, mapping~/.claude/skills/gstack/→$INSTALL_GSTACK_DIR. Caveat: the Claude install symlinks to source rather than copying, so this would either dirty the working tree or require switching that host to a copy-and-rewrite step.Workaround (for affected users today)
After each install/upgrade, re-point the hardcoded references in the top-level skill files to the real install dir:
Scope to top-level
*/SKILL.mdonly; the generated host copies under.agents/.cursor/.factory/.gbrain/hostsuse agstack-prefix convention and should be left as-is. (This needs re-running after every upgrade, sincegit reset --hardreverts it — which is the motivation for fix #1 or #2.)Related
$CLAUDE_CONFIG_DIRsupport: the~/.claudeprefix counterpart of this same hardcoded-self-path problem.