-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·82 lines (72 loc) · 2.56 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·82 lines (72 loc) · 2.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/usr/bin/env bash
# Install these skills for Claude Code by linking them into ~/.claude/skills/.
#
# Symlinks by default, so editing a skill here takes effect immediately with no
# reinstall — the repo stays the single source of truth. Use --copy where
# symlinks are awkward (some Windows setups, or a sandbox that resolves links
# oddly); copies then need a re-run after every edit.
#
# ./install.sh link every skill
# ./install.sh --copy copy instead of linking
# ./install.sh --dry-run show what would happen
# ./install.sh handover just one skill
set -euo pipefail
SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/skills"
DEST="${CLAUDE_SKILLS_DIR:-$HOME/.claude/skills}"
MODE=link
DRY=0
WANTED=()
for arg in "$@"; do
case "$arg" in
--copy) MODE=copy ;;
--dry-run) DRY=1 ;;
-h|--help) sed -n '2,12p' "${BASH_SOURCE[0]}"; exit 0 ;;
-*) echo "unknown option: $arg" >&2; exit 2 ;;
*) WANTED+=("$arg") ;;
esac
done
[ -d "$SRC" ] || { echo "no skills/ directory beside install.sh" >&2; exit 1; }
mkdir -p "$DEST"
installed=0 skipped=0 conflicts=0
for path in "$SRC"/*/; do
name="$(basename "$path")"
# Only what was asked for, when names were given.
if [ ${#WANTED[@]} -gt 0 ]; then
match=0
for w in "${WANTED[@]}"; do [ "$w" = "$name" ] && match=1; done
[ $match -eq 1 ] || continue
fi
[ -f "$path/SKILL.md" ] || { echo "skip $name — no SKILL.md"; continue; }
target="$DEST/$name"
# Already pointing at this repo: nothing to do.
if [ -L "$target" ] && [ "$(readlink "$target")" = "${path%/}" ]; then
echo "ok $name (already linked)"
skipped=$((skipped + 1))
continue
fi
# Something else is there. Refuse rather than delete someone's work: a real
# directory here is a hand-written skill, and losing it silently would be
# exactly the kind of thing this repo exists to prevent.
if [ -e "$target" ] && [ ! -L "$target" ]; then
echo "CONFLICT $name — $target exists and is not a link from this repo."
echo " Move or delete it, then re-run."
conflicts=$((conflicts + 1))
continue
fi
if [ $DRY -eq 1 ]; then
echo "would $MODE $name -> $target"
continue
fi
rm -f "$target" # only ever a stale symlink by this point
if [ "$MODE" = copy ]; then
cp -R "${path%/}" "$target"
else
ln -s "${path%/}" "$target"
fi
echo "$MODE $name"
installed=$((installed + 1))
done
echo
echo "installed: $installed · already present: $skipped · conflicts: $conflicts"
echo "destination: $DEST"
[ $conflicts -eq 0 ] || exit 1