forked from manaflow-ai/cmux
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathskills.sh
More file actions
executable file
·164 lines (142 loc) · 4.09 KB
/
Copy pathskills.sh
File metadata and controls
executable file
·164 lines (142 loc) · 4.09 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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage: skills.sh [options]
Install cmux agent skills into the Codex skills directory.
Options:
--dest DIR Destination directory. Default: ${CODEX_HOME:-$HOME/.codex}/skills
--source DIR Source checkout or skills directory. Default: local checkout, or GitHub when piped
--ref REF GitHub ref to download when no local skills directory is available. Default: main
--skill NAME Install one skill. Repeat to install multiple. Default: all skills
--list List available skills and exit
--dry-run Print what would be installed
-h, --help Show this help
Examples:
./skills.sh
./skills.sh --list
./skills.sh --skill cmux --skill cmux-browser
curl -fsSL https://raw.githubusercontent.com/manaflow-ai/cmux/main/skills.sh | bash
EOF
}
die() {
printf 'skills.sh: %s\n' "$*" >&2
exit 1
}
need_cmd() {
command -v "$1" >/dev/null 2>&1 || die "missing required command: $1"
}
normalize_source_dir() {
local source="$1"
if [[ -d "$source/skills" ]]; then
source="$source/skills"
fi
printf '%s\n' "$source"
}
dest_dir="${CODEX_HOME:-$HOME/.codex}/skills"
source_dir=""
ref="${CMUX_SKILLS_REF:-main}"
list_only=0
dry_run=0
selected_skills=()
while [[ $# -gt 0 ]]; do
case "$1" in
--dest)
[[ $# -ge 2 ]] || die "--dest requires a directory"
dest_dir="$2"
shift 2
;;
--source)
[[ $# -ge 2 ]] || die "--source requires a directory"
source_dir="$(normalize_source_dir "$2")"
shift 2
;;
--ref)
[[ $# -ge 2 ]] || die "--ref requires a GitHub ref"
ref="$2"
shift 2
;;
--skill)
[[ $# -ge 2 ]] || die "--skill requires a skill name"
selected_skills+=("$2")
shift 2
;;
--list)
list_only=1
shift
;;
--dry-run)
dry_run=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
die "unknown option: $1"
;;
esac
done
script_path="${BASH_SOURCE[0]:-}"
script_dir=""
if [[ -n "$script_path" && -f "$script_path" ]]; then
script_dir="$(cd -- "$(dirname -- "$script_path")" >/dev/null 2>&1 && pwd || true)"
fi
if [[ -z "$source_dir" && -n "$script_dir" && -d "$script_dir/skills" ]]; then
source_dir="$script_dir/skills"
fi
tmp_dir=""
cleanup() {
if [[ -n "$tmp_dir" ]]; then
rm -rf "$tmp_dir"
fi
}
trap cleanup EXIT
if [[ -z "$source_dir" ]]; then
need_cmd curl
need_cmd tar
need_cmd mktemp
tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/cmux-skills.XXXXXX")"
archive_url="https://codeload.github.com/manaflow-ai/cmux/tar.gz/${ref}"
curl -fsSL "$archive_url" | tar -xz -C "$tmp_dir"
checkout_dir="$(find "$tmp_dir" -mindepth 1 -maxdepth 1 -type d | head -n 1)"
[[ -n "$checkout_dir" ]] || die "downloaded archive was empty"
source_dir="$checkout_dir/skills"
fi
[[ -d "$source_dir" ]] || die "skills directory not found: $source_dir"
available_skills() {
find "$source_dir" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort
}
if [[ "$list_only" -eq 1 ]]; then
available_skills
exit 0
fi
if [[ "${#selected_skills[@]}" -eq 0 ]]; then
while IFS= read -r skill_name; do
selected_skills+=("$skill_name")
done < <(available_skills)
fi
[[ "${#selected_skills[@]}" -gt 0 ]] || die "no skills found in $source_dir"
[[ -n "$dest_dir" ]] || die "destination directory must not be empty"
for skill_name in "${selected_skills[@]}"; do
[[ "$skill_name" =~ ^[A-Za-z0-9._-]+$ ]] || die "invalid skill name: $skill_name"
[[ -d "$source_dir/$skill_name" ]] || die "skill not found: $skill_name"
done
if [[ "$dry_run" -eq 1 ]]; then
printf 'Would install to %s:\n' "$dest_dir"
for skill_name in "${selected_skills[@]}"; do
printf ' %s\n' "$skill_name"
done
exit 0
fi
mkdir -p "$dest_dir"
for skill_name in "${selected_skills[@]}"; do
src="$source_dir/$skill_name"
tmp_target="${dest_dir:?}/.${skill_name}.tmp.$$"
rm -rf "$tmp_target"
cp -R "$src" "$tmp_target"
rm -rf "${dest_dir:?}/$skill_name"
mv "$tmp_target" "${dest_dir:?}/$skill_name"
printf 'Installed %s -> %s\n' "$skill_name" "${dest_dir:?}/$skill_name"
done