Files
Tarek Rached 5304b75979 fix(setup): use relative symlinks for in-repo skill mirrors (#52)
* fix(setup): use relative symlinks for in-repo skill mirrors

setup.sh has been writing absolute symlinks (e.g. /Users/<name>/obsidian-wiki/.skills/...)
into the in-repo skill mirror directories (.agents/, .claude/, .cursor/, .kiro/,
.windsurf/), even though those mirrors are tracked in git as relative symlinks
(../../.skills/<name>). The result: every fresh clone is left with ~160 modified
files immediately after running setup.sh.

This is the same class of bug that 476ac88 ("complete relative symlink migration
across all mirrors and skills") fixed in the committed tree — the migration
updated the symlinks themselves but missed the installer that recreates them.
A contributor running `git add -A` after setup would silently re-commit their
home directory into the public repo, undoing 476ac88.

Add an optional third `mode` argument to install_skills(). When "relative" is
passed, the link target is hardcoded to ../../.skills/<name> (correct for every
in-repo mirror, all of which live at $REPO/<agent-dir>/skills). The global
target dirs under $HOME continue to use absolute paths, which is what they need.

Also corrects the post-install log line — it previously said "Installed global
skills" even for in-repo dirs.

Tested: on a clean checkout, `bash setup.sh && git status` now reports a clean
tree. In-repo links read ../../.skills/<name>; global links under ~/.codex,
~/.gemini, etc. remain absolute.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* setup: harden install_skills + add CI guard

Addresses review feedback on the in-repo symlink fix:

1. Compute the relative-path prefix from target_dir's depth under
   $SCRIPT_DIR instead of hardcoding ../../. The old comment claimed
   "in-repo mirrors are always two levels deep" — true today, silently
   wrong the moment anyone adds a deeper target. Now correct for any
   depth.

2. Validate the mode arg. A typo at the call site (e.g. "rleative")
   previously fell through to absolute and reintroduced the original
   bug. case-statement now exits with a clear message.

3. Guard against relative mode on out-of-repo targets. Bails rather
   than emitting a wrong link.

4. Assert each new symlink resolves to a SKILL.md. Catches future
   path-math mistakes at install time instead of when an agent later
   fails to discover skills.

5. Fold the inline ~/.claude/skills loop into install_skills via a new
   optional subset argument. Removes 17 lines of duplicated
   delete-and-create logic; continues the consolidation that 9377be4
   started.

6. Compress install_skills docstring from 8 lines to 4.

7. Add .github/workflows/setup.yml: runs setup.sh on every PR and
   fails if it modifies a tracked file. Re-runs to verify idempotency.
   This is the missing guard that let the absolute-symlink regression
   reach main in the first place.

Tested locally:
- bad mode → exits 1 with clear error
- relative + /tmp target → exits 1 with clear error
- subset filter installs exactly the named skills
- 4-deep test target (_test_deep/a/b/skills) gets ../../../../.skills/...
- git status clean after install; re-run is idempotent
- ~/.claude/skills contains only wiki-update + wiki-query (absolute)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Tarek Rached <tarek@kisotechnology.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 15:19:45 +05:30

30 lines
980 B
YAML

name: setup
# Guards setup.sh against the regression where it rewrites committed
# relative symlinks with absolute paths (or any other modification to
# tracked files). See #52 for the original bug.
on:
push:
branches: [main]
pull_request:
jobs:
install-leaves-tree-clean:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run setup.sh
# stdin closed so the vault-path prompt returns empty rather than hang
run: bash setup.sh < /dev/null
- name: Working tree must be unchanged
run: |
if ! git diff --exit-code; then
echo "::error::setup.sh modified tracked files. Likely cause: an" \
"in-repo symlink mirror is being written with an absolute" \
"target instead of a relative one. See install_skills() in setup.sh."
exit 1
fi
- name: Re-run is idempotent
run: bash setup.sh < /dev/null && git diff --exit-code