fix: copy skill directories instead of creating symlinks

Claude Desktop mounts ~/.claude/skills/ at /mnt/skills/user but does
not follow symlinks. Skills registered as symlinks (the previous
behavior) are invisible to Claude Desktop — only real directories are
exposed.

This changes setup to copy each skill directory from gstack/ into the
parent skills/ directory instead of symlinking. Running ./setup now
always refreshes the copies so skills stay in sync after upgrades.

Updated README uninstall commands from `rm -f` to `rm -rf` since the
registered skills are now directories, not symlinks.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalil Santiago 2026-03-12 20:40:49 -07:00
parent 1b317aae9a
commit cb244cb954
2 changed files with 14 additions and 13 deletions

View File

@ -403,7 +403,7 @@ It saves a JSON snapshot to `.context/retros/` so the next run can show trends.
## Troubleshooting
**Skill not showing up in Claude Code?**
Run `cd ~/.claude/skills/gstack && ./setup` (or `cd .claude/skills/gstack && ./setup` for project installs). This rebuilds symlinks so Claude can discover the skills.
Run `cd ~/.claude/skills/gstack && ./setup` (or `cd .claude/skills/gstack && ./setup` for project installs). This rebuilds skill directories so Claude can discover the skills.
**`/browse` fails or binary not found?**
Run `cd ~/.claude/skills/gstack && bun install && bun run build`. This compiles the browser binary. Requires Bun v1.0+.
@ -420,13 +420,13 @@ Paste this into Claude Code:
> Update gstack: run `cd ~/.claude/skills/gstack && git fetch origin && git reset --hard origin/main && ./setup`. If this project also has gstack at .claude/skills/gstack, update it too: run `for s in browse plan-ceo-review plan-eng-review review ship retro; do rm -f .claude/skills/$s; done && rm -rf .claude/skills/gstack && cp -Rf ~/.claude/skills/gstack .claude/skills/gstack && rm -rf .claude/skills/gstack/.git && cd .claude/skills/gstack && ./setup`
The `setup` script rebuilds the browser binary and re-symlinks skills. It takes a few seconds.
The `setup` script rebuilds the browser binary and re-registers skills. It takes a few seconds.
## Uninstalling
Paste this into Claude Code:
> Uninstall gstack: remove the skill symlinks by running `for s in browse plan-ceo-review plan-eng-review review ship retro; do rm -f ~/.claude/skills/$s; done` then run `rm -rf ~/.claude/skills/gstack` and remove the gstack section from CLAUDE.md. If this project also has gstack at .claude/skills/gstack, remove it by running `for s in browse plan-ceo-review plan-eng-review review ship retro; do rm -f .claude/skills/$s; done && rm -rf .claude/skills/gstack` and remove the gstack section from the project CLAUDE.md too.
> Uninstall gstack: remove the skill directories by running `for s in browse plan-ceo-review plan-eng-review review ship retro; do rm -rf ~/.claude/skills/$s; done` then run `rm -rf ~/.claude/skills/gstack` and remove the gstack section from CLAUDE.md. If this project also has gstack at .claude/skills/gstack, remove it by running `for s in browse plan-ceo-review plan-eng-review review ship retro; do rm -rf .claude/skills/$s; done && rm -rf .claude/skills/gstack` and remove the gstack section from the project CLAUDE.md too.
## Development

21
setup
View File

@ -32,31 +32,32 @@ if [ ! -x "$BROWSE_BIN" ]; then
exit 1
fi
# 2. Only create skill symlinks if we're inside a .claude/skills directory
# 2. Only register skills if we're inside a .claude/skills directory
# Uses real directory copies instead of symlinks so skills are discoverable
# by Claude Desktop, which mounts ~/.claude/skills/ but does not follow symlinks.
SKILLS_BASENAME="$(basename "$SKILLS_DIR")"
if [ "$SKILLS_BASENAME" = "skills" ]; then
linked=()
registered=()
for skill_dir in "$GSTACK_DIR"/*/; do
if [ -f "$skill_dir/SKILL.md" ]; then
skill_name="$(basename "$skill_dir")"
# Skip node_modules
[ "$skill_name" = "node_modules" ] && continue
target="$SKILLS_DIR/$skill_name"
# Create or update symlink; skip if a real file/directory exists
if [ -L "$target" ] || [ ! -e "$target" ]; then
ln -snf "gstack/$skill_name" "$target"
linked+=("$skill_name")
fi
# Remove any existing symlink or stale copy, then copy fresh
rm -rf "$target"
cp -Rf "$GSTACK_DIR/$skill_name" "$target"
registered+=("$skill_name")
fi
done
echo "gstack ready."
echo " browse: $BROWSE_BIN"
if [ ${#linked[@]} -gt 0 ]; then
echo " linked skills: ${linked[*]}"
if [ ${#registered[@]} -gt 0 ]; then
echo " registered skills: ${registered[*]}"
fi
else
echo "gstack ready."
echo " browse: $BROWSE_BIN"
echo " (skipped skill symlinks — not inside .claude/skills/)"
echo " (skipped skill registration — not inside .claude/skills/)"
fi