@vikasagarwal101/skill-sync 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +206 -0
- package/bin/skill-sync.js +38 -0
- package/bin/skill-sync.sh +1250 -0
- package/install.sh +516 -0
- package/lib/authoring.sh +200 -0
- package/lib/core.sh +221 -0
- package/lib/health.sh +136 -0
- package/lib/inspect.sh +210 -0
- package/lib/sync.sh +281 -0
- package/lib/targets.sh +73 -0
- package/package.json +42 -0
- package/rules/skill-sync.md +96 -0
- package/scripts/bundle.sh +28 -0
- package/skill-sync +131 -0
package/install.sh
ADDED
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# skill-sync installer
|
|
5
|
+
# Usage: ./install.sh [options]
|
|
6
|
+
# --with-rules <agents> Register rules (non-interactive). Agents: opencode,claude,codex,kilo,gemini,auggie,devin,all
|
|
7
|
+
# --no-rules Skip agent rule registration (CLI only)
|
|
8
|
+
# --uninstall Remove everything (prompts for rule removal)
|
|
9
|
+
# (no flags) Interactive: prompt for each detected agent
|
|
10
|
+
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
|
+
BIN_DIR="${SKILLSYNC_BIN_DIR:-$HOME/.local/bin}"
|
|
13
|
+
CONFIG_DIR="${SKILLSYNC_CONFIG_DIR:-$HOME/.config/skill-sync}"
|
|
14
|
+
|
|
15
|
+
# Agent paths
|
|
16
|
+
OPENCODE_CONFIG="$HOME/.config/opencode/opencode.json"
|
|
17
|
+
OPENCODE_RULES_DIR="$HOME/.config/opencode/rules"
|
|
18
|
+
CLAUDE_DIR="$HOME/.claude"
|
|
19
|
+
CLAUDE_RULES_DIR="$CLAUDE_DIR/rules"
|
|
20
|
+
CLAUDE_MD="$CLAUDE_DIR/CLAUDE.md"
|
|
21
|
+
CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
|
|
22
|
+
CODEX_AGENTS_MD="$CODEX_HOME/AGENTS.md"
|
|
23
|
+
KILO_CONFIG_DIR="$HOME/.config/kilo"
|
|
24
|
+
KILO_RULES_DIR="$KILO_CONFIG_DIR/rules"
|
|
25
|
+
KILO_CONFIG="$KILO_CONFIG_DIR/kilo.jsonc"
|
|
26
|
+
GEMINI_DIR="$HOME/.gemini"
|
|
27
|
+
GEMINI_RULES_DIR="$GEMINI_DIR/rules"
|
|
28
|
+
GEMINI_MD="$GEMINI_DIR/GEMINI.md"
|
|
29
|
+
AUGMENT_DIR="$HOME/.augment"
|
|
30
|
+
AUGMENT_RULES_DIR="$AUGMENT_DIR/rules"
|
|
31
|
+
DEVIN_DIR="$HOME/.devin"
|
|
32
|
+
DEVIN_AGENTS_MD="$DEVIN_DIR/AGENTS.md"
|
|
33
|
+
ANTIGRAVITY_DIR="$HOME/.gemini/antigravity"
|
|
34
|
+
|
|
35
|
+
# Codex AGENTS.md section markers
|
|
36
|
+
CODEX_SECTION_START="<!-- SKILL_SYNC_START -->"
|
|
37
|
+
CODEX_SECTION_END="<!-- SKILL_SYNC_END -->"
|
|
38
|
+
# Shared markers for codex + devin (same pattern)
|
|
39
|
+
SECTION_START="<!-- SKILL_SYNC_START -->"
|
|
40
|
+
SECTION_END="<!-- SKILL_SYNC_END -->"
|
|
41
|
+
|
|
42
|
+
# Defaults
|
|
43
|
+
UNINSTALL=false
|
|
44
|
+
RULES_MODE="prompt"
|
|
45
|
+
RULES_AGENTS=""
|
|
46
|
+
|
|
47
|
+
# Parse args
|
|
48
|
+
while [[ $# -gt 0 ]]; do
|
|
49
|
+
case "$1" in
|
|
50
|
+
--uninstall) UNINSTALL=true; shift ;;
|
|
51
|
+
--with-rules) RULES_MODE="with"; RULES_AGENTS="${2:-all}"; shift 2 ;;
|
|
52
|
+
--no-rules) RULES_MODE="without"; shift ;;
|
|
53
|
+
*) shift ;;
|
|
54
|
+
esac
|
|
55
|
+
done
|
|
56
|
+
|
|
57
|
+
info() { echo " $*"; }
|
|
58
|
+
|
|
59
|
+
prompt_yesno() {
|
|
60
|
+
local question="$1" default="${2:-y}"
|
|
61
|
+
local hint
|
|
62
|
+
[ "$default" = "y" ] && hint="[Y/n]" || hint="[y/N]"
|
|
63
|
+
printf "%s %s " "$question" "$hint" >&2
|
|
64
|
+
read -r answer </dev/tty 2>/dev/null || answer="$default"
|
|
65
|
+
answer="${answer:-$default}"
|
|
66
|
+
[[ "$answer" =~ ^[Yy] ]] && return 0 || return 1
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# ── Agent detection ──
|
|
70
|
+
|
|
71
|
+
agent_exists() {
|
|
72
|
+
case "$1" in
|
|
73
|
+
opencode) [ -d "$HOME/.config/opencode" ] ;;
|
|
74
|
+
claude) [ -d "$CLAUDE_DIR" ] ;;
|
|
75
|
+
codex) [ -d "$CODEX_HOME" ] ;;
|
|
76
|
+
kilo) [ -d "$KILO_CONFIG_DIR" ] ;;
|
|
77
|
+
gemini) [ -d "$GEMINI_DIR" ] ;;
|
|
78
|
+
auggie) [ -d "$AUGMENT_DIR" ] ;;
|
|
79
|
+
devin) [ -d "$DEVIN_DIR" ] ;;
|
|
80
|
+
antigravity) [ -d "$ANTIGRAVITY_DIR" ] ;;
|
|
81
|
+
esac
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
list_agents() {
|
|
85
|
+
local found=()
|
|
86
|
+
for agent in opencode claude codex kilo gemini auggie devin antigravity; do
|
|
87
|
+
agent_exists "$agent" && found+=("$agent")
|
|
88
|
+
done
|
|
89
|
+
echo "${found[*]:-}"
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
agent_wants() {
|
|
93
|
+
# Check if agent is in the selected list
|
|
94
|
+
local agent="$1"
|
|
95
|
+
[[ "$RULES_AGENTS" == *"all"* ]] && return 0
|
|
96
|
+
[[ "$RULES_AGENTS" == *"$agent"* ]] && return 0
|
|
97
|
+
return 1
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# ── OpenCode registration ──
|
|
101
|
+
|
|
102
|
+
register_opencode() {
|
|
103
|
+
_register_rule_file "$OPENCODE_RULES_DIR" "opencode"
|
|
104
|
+
if [ -f "$OPENCODE_CONFIG" ]; then
|
|
105
|
+
if ! grep -q 'skill-sync.md' "$OPENCODE_CONFIG"; then
|
|
106
|
+
sed -i '/]/i\ "~/.config/opencode/rules/skill-sync.md"' "$OPENCODE_CONFIG" 2>/dev/null || true
|
|
107
|
+
info "✅ Added to opencode.json instructions"
|
|
108
|
+
else
|
|
109
|
+
info " Already in opencode.json"
|
|
110
|
+
fi
|
|
111
|
+
fi
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
unregister_opencode() {
|
|
115
|
+
rm -f "$OPENCODE_RULES_DIR/skill-sync.md" && info "Removed opencode rule"
|
|
116
|
+
if [ -f "$OPENCODE_CONFIG" ]; then
|
|
117
|
+
local tmp; tmp=$(mktemp)
|
|
118
|
+
grep -v 'skill-sync.md' "$OPENCODE_CONFIG" > "$tmp" || true
|
|
119
|
+
cp "$tmp" "$OPENCODE_CONFIG" && rm "$tmp"
|
|
120
|
+
info "Removed from opencode.json"
|
|
121
|
+
fi
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# ── Claude Code registration ──
|
|
125
|
+
|
|
126
|
+
register_claude() {
|
|
127
|
+
_register_rule_file "$CLAUDE_RULES_DIR" "claude"
|
|
128
|
+
if [ -f "$CLAUDE_MD" ]; then
|
|
129
|
+
if ! grep -q '@rules/skill-sync.md' "$CLAUDE_MD"; then
|
|
130
|
+
local last_import_line
|
|
131
|
+
last_import_line=$(grep -n '@rules/' "$CLAUDE_MD" | tail -1 | cut -d: -f1)
|
|
132
|
+
if [ -n "$last_import_line" ]; then
|
|
133
|
+
sed -i "${last_import_line}a\\@rules/skill-sync.md" "$CLAUDE_MD"
|
|
134
|
+
else
|
|
135
|
+
echo "" >> "$CLAUDE_MD"
|
|
136
|
+
echo "## Skill Management" >> "$CLAUDE_MD"
|
|
137
|
+
echo "@rules/skill-sync.md" >> "$CLAUDE_MD"
|
|
138
|
+
fi
|
|
139
|
+
info "✅ Added @rules/skill-sync.md to CLAUDE.md"
|
|
140
|
+
else
|
|
141
|
+
info " Already in CLAUDE.md"
|
|
142
|
+
fi
|
|
143
|
+
else
|
|
144
|
+
mkdir -p "$CLAUDE_DIR"
|
|
145
|
+
cat > "$CLAUDE_MD" << 'EOF'
|
|
146
|
+
# Claude Code Instructions
|
|
147
|
+
|
|
148
|
+
## Skill Management
|
|
149
|
+
|
|
150
|
+
@rules/skill-sync.md
|
|
151
|
+
EOF
|
|
152
|
+
info "✅ Created CLAUDE.md with skill-sync rule"
|
|
153
|
+
fi
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
unregister_claude() {
|
|
157
|
+
rm -f "$CLAUDE_RULES_DIR/skill-sync.md" && info "Removed claude rule file"
|
|
158
|
+
if [ -f "$CLAUDE_MD" ]; then
|
|
159
|
+
local tmp; tmp=$(mktemp)
|
|
160
|
+
grep -v '@rules/skill-sync.md' "$CLAUDE_MD" > "$tmp" || true
|
|
161
|
+
cp "$tmp" "$CLAUDE_MD" && rm "$tmp"
|
|
162
|
+
info "Removed from CLAUDE.md"
|
|
163
|
+
fi
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
# ── Codex registration ──
|
|
167
|
+
|
|
168
|
+
register_codex() {
|
|
169
|
+
mkdir -p "$CODEX_HOME"
|
|
170
|
+
_register_section "$CODEX_AGENTS_MD" "codex (~/.codex/AGENTS.md)"
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
unregister_codex() {
|
|
174
|
+
_unregister_section "$CODEX_AGENTS_MD"
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
# ── Shared marker-section helper (codex, devin) ──
|
|
178
|
+
|
|
179
|
+
_register_section() {
|
|
180
|
+
local target_file="$1" target_name="$2"
|
|
181
|
+
mkdir -p "$(dirname "$target_file")"
|
|
182
|
+
|
|
183
|
+
local section
|
|
184
|
+
section=$(cat << EOF
|
|
185
|
+
$SECTION_START
|
|
186
|
+
|
|
187
|
+
## Skill Management — \`skill-sync\`
|
|
188
|
+
|
|
189
|
+
**Use \`skill-sync\` for all skill deployment and syncing.** Do not \`cp -r\` skills between directories manually — \`skill-sync\` tracks what syncs where via a manifest and prevents drift.
|
|
190
|
+
|
|
191
|
+
The CLI is self-documenting — run \`skill-sync help\` for the full command reference.
|
|
192
|
+
|
|
193
|
+
**Quick reference:**
|
|
194
|
+
\`\`\`bash
|
|
195
|
+
skill-sync # sync all tracked skills
|
|
196
|
+
skill-sync add <name> # deploy skill to a target
|
|
197
|
+
skill-sync create <name> # scaffold new skill
|
|
198
|
+
skill-sync search <query> # find skills by keyword
|
|
199
|
+
skill-sync doctor # full health check
|
|
200
|
+
\`\`\`
|
|
201
|
+
$SECTION_END
|
|
202
|
+
EOF
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
if [ -f "$target_file" ] && grep -q "$SECTION_START" "$target_file"; then
|
|
206
|
+
local tmp; tmp=$(mktemp)
|
|
207
|
+
awk -v start="$SECTION_START" -v end="$SECTION_END" -v section="$section" '
|
|
208
|
+
$0 ~ start { print section; in_section=1; next }
|
|
209
|
+
in_section && $0 ~ end { in_section=0; next }
|
|
210
|
+
!in_section
|
|
211
|
+
' "$target_file" > "$tmp"
|
|
212
|
+
cp "$tmp" "$target_file" && rm "$tmp"
|
|
213
|
+
info "✅ Updated $target_name section"
|
|
214
|
+
else
|
|
215
|
+
echo "" >> "$target_file"
|
|
216
|
+
echo "$section" >> "$target_file"
|
|
217
|
+
info "✅ Added section to $target_file"
|
|
218
|
+
fi
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
_unregister_section() {
|
|
222
|
+
local target_file="$1"
|
|
223
|
+
if [ -f "$target_file" ] && grep -q "$SECTION_START" "$target_file"; then
|
|
224
|
+
local tmp; tmp=$(mktemp)
|
|
225
|
+
awk -v start="$SECTION_START" -v end="$SECTION_END" '
|
|
226
|
+
$0 ~ start { skip=1; next }
|
|
227
|
+
skip && $0 ~ end { skip=0; next }
|
|
228
|
+
!skip
|
|
229
|
+
' "$target_file" > "$tmp"
|
|
230
|
+
cp "$tmp" "$target_file" && rm "$tmp"
|
|
231
|
+
info "Removed section from $target_file"
|
|
232
|
+
fi
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
# ── Shared rule-file helper (opencode, claude, kilo, gemini, auggie) ──
|
|
236
|
+
|
|
237
|
+
_register_rule_file() {
|
|
238
|
+
local rules_dir="$1" agent_name="$2"
|
|
239
|
+
mkdir -p "$rules_dir"
|
|
240
|
+
|
|
241
|
+
if [ -f "$rules_dir/skill-sync.md" ]; then
|
|
242
|
+
if ! diff -q "$SCRIPT_DIR/rules/skill-sync.md" "$rules_dir/skill-sync.md" >/dev/null 2>&1; then
|
|
243
|
+
cp "$SCRIPT_DIR/rules/skill-sync.md" "$rules_dir/skill-sync.md"
|
|
244
|
+
info "✅ Updated $agent_name rule file"
|
|
245
|
+
else
|
|
246
|
+
info " Rule file already current"
|
|
247
|
+
fi
|
|
248
|
+
else
|
|
249
|
+
cp "$SCRIPT_DIR/rules/skill-sync.md" "$rules_dir/skill-sync.md"
|
|
250
|
+
info "✅ Installed $agent_name rule → $rules_dir/skill-sync.md"
|
|
251
|
+
fi
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
_unregister_rule_file() {
|
|
255
|
+
local rules_dir="$1" agent_name="$2"
|
|
256
|
+
rm -f "$rules_dir/skill-sync.md" && info "Removed $agent_name rule file"
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
# ── Kilo Code registration ──
|
|
260
|
+
|
|
261
|
+
register_kilo() {
|
|
262
|
+
_register_rule_file "$KILO_RULES_DIR" "kilo"
|
|
263
|
+
|
|
264
|
+
if [ ! -f "$KILO_CONFIG" ]; then
|
|
265
|
+
# Create minimal kilo.jsonc
|
|
266
|
+
mkdir -p "$KILO_CONFIG_DIR"
|
|
267
|
+
cat > "$KILO_CONFIG" << 'EOF'
|
|
268
|
+
{
|
|
269
|
+
"instructions": [
|
|
270
|
+
"~/.config/kilo/rules/skill-sync.md"
|
|
271
|
+
]
|
|
272
|
+
}
|
|
273
|
+
EOF
|
|
274
|
+
info "✅ Created kilo.jsonc with skill-sync instruction"
|
|
275
|
+
elif grep -q 'skill-sync.md' "$KILO_CONFIG"; then
|
|
276
|
+
info " Already in kilo.jsonc"
|
|
277
|
+
elif grep -q '"instructions"' "$KILO_CONFIG"; then
|
|
278
|
+
# Add to existing instructions array (before its closing ])
|
|
279
|
+
local tmp; tmp=$(mktemp)
|
|
280
|
+
awk '
|
|
281
|
+
/^ "instructions"/ { in_instr=1 }
|
|
282
|
+
in_instr && /\]/ {
|
|
283
|
+
sub(/\]/, " \"~/.config/kilo/rules/skill-sync.md\"\n ]")
|
|
284
|
+
in_instr=0
|
|
285
|
+
}
|
|
286
|
+
{ print }
|
|
287
|
+
' "$KILO_CONFIG" > "$tmp"
|
|
288
|
+
cp "$tmp" "$KILO_CONFIG" && rm "$tmp"
|
|
289
|
+
info "✅ Added to kilo.jsonc instructions"
|
|
290
|
+
else
|
|
291
|
+
# No instructions key — add one after opening {
|
|
292
|
+
local tmp; tmp=$(mktemp)
|
|
293
|
+
awk 'NR==1{print; print " \"instructions\": ["; print " \"~/.config/kilo/rules/skill-sync.md\""; print " ],"; next} {print}' "$KILO_CONFIG" > "$tmp"
|
|
294
|
+
cp "$tmp" "$KILO_CONFIG" && rm "$tmp"
|
|
295
|
+
info "✅ Added instructions array to kilo.jsonc"
|
|
296
|
+
fi
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
unregister_kilo() {
|
|
300
|
+
_unregister_rule_file "$KILO_RULES_DIR" "kilo"
|
|
301
|
+
if [ -f "$KILO_CONFIG" ]; then
|
|
302
|
+
local tmp; tmp=$(mktemp)
|
|
303
|
+
grep -v 'skill-sync.md' "$KILO_CONFIG" > "$tmp" || true
|
|
304
|
+
cp "$tmp" "$KILO_CONFIG" && rm "$tmp"
|
|
305
|
+
info "Removed from kilo.jsonc"
|
|
306
|
+
fi
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
# ── Gemini CLI registration ──
|
|
310
|
+
|
|
311
|
+
register_gemini() {
|
|
312
|
+
_register_rule_file "$GEMINI_RULES_DIR" "gemini"
|
|
313
|
+
if [ -f "$GEMINI_MD" ]; then
|
|
314
|
+
if ! grep -q '@rules/skill-sync.md' "$GEMINI_MD"; then
|
|
315
|
+
echo "" >> "$GEMINI_MD"
|
|
316
|
+
echo "@rules/skill-sync.md" >> "$GEMINI_MD"
|
|
317
|
+
info "✅ Added @rules/skill-sync.md to GEMINI.md"
|
|
318
|
+
else
|
|
319
|
+
info " Already in GEMINI.md"
|
|
320
|
+
fi
|
|
321
|
+
else
|
|
322
|
+
mkdir -p "$GEMINI_DIR"
|
|
323
|
+
echo "@rules/skill-sync.md" > "$GEMINI_MD"
|
|
324
|
+
info "✅ Created GEMINI.md with skill-sync import"
|
|
325
|
+
fi
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
unregister_gemini() {
|
|
329
|
+
_unregister_rule_file "$GEMINI_RULES_DIR" "gemini"
|
|
330
|
+
if [ -f "$GEMINI_MD" ]; then
|
|
331
|
+
local tmp; tmp=$(mktemp)
|
|
332
|
+
grep -v '@rules/skill-sync.md' "$GEMINI_MD" > "$tmp" || true
|
|
333
|
+
cp "$tmp" "$GEMINI_MD" && rm "$tmp"
|
|
334
|
+
info "Removed from GEMINI.md"
|
|
335
|
+
fi
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
# ── Auggie (Augment Code) registration ──
|
|
339
|
+
|
|
340
|
+
register_auggie() {
|
|
341
|
+
_register_rule_file "$AUGMENT_RULES_DIR" "auggie"
|
|
342
|
+
info " (auto-discovered by Auggie — no config change needed)"
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
unregister_auggie() {
|
|
346
|
+
_unregister_rule_file "$AUGMENT_RULES_DIR" "auggie"
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
# ── Devin CLI registration ──
|
|
350
|
+
|
|
351
|
+
register_devin() {
|
|
352
|
+
_register_section "$DEVIN_AGENTS_MD" "devin"
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
unregister_devin() {
|
|
356
|
+
_unregister_section "$DEVIN_AGENTS_MD"
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
# ── Generic register/unregister dispatchers ──
|
|
360
|
+
|
|
361
|
+
do_register() {
|
|
362
|
+
local agent="$1"
|
|
363
|
+
case "$agent" in
|
|
364
|
+
opencode) register_opencode ;;
|
|
365
|
+
claude) register_claude ;;
|
|
366
|
+
codex) register_codex ;;
|
|
367
|
+
kilo) register_kilo ;;
|
|
368
|
+
gemini) register_gemini ;;
|
|
369
|
+
auggie) register_auggie ;;
|
|
370
|
+
devin) register_devin ;;
|
|
371
|
+
antigravity) info "⏭️ Antigravity reads AGENTS.md + scans ~/.agents/skills/ natively — no registration needed" ;;
|
|
372
|
+
esac
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
do_unregister() {
|
|
376
|
+
local agent="$1"
|
|
377
|
+
case "$agent" in
|
|
378
|
+
opencode) unregister_opencode ;;
|
|
379
|
+
claude) unregister_claude ;;
|
|
380
|
+
codex) unregister_codex ;;
|
|
381
|
+
kilo) unregister_kilo ;;
|
|
382
|
+
gemini) unregister_gemini ;;
|
|
383
|
+
auggie) unregister_auggie ;;
|
|
384
|
+
devin) unregister_devin ;;
|
|
385
|
+
antigravity) ;; # nothing to unregister
|
|
386
|
+
esac
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
# ── Uninstall ──
|
|
390
|
+
|
|
391
|
+
do_uninstall() {
|
|
392
|
+
echo "Uninstalling skill-sync..."
|
|
393
|
+
echo ""
|
|
394
|
+
|
|
395
|
+
rm -f "$BIN_DIR/skill-sync" && info "Removed CLI from $BIN_DIR/"
|
|
396
|
+
rm -rf "$CONFIG_DIR" && info "Removed config from $CONFIG_DIR/"
|
|
397
|
+
|
|
398
|
+
# Check each agent for existing registrations
|
|
399
|
+
echo ""
|
|
400
|
+
echo "Checking agent registrations..."
|
|
401
|
+
for agent in opencode claude codex kilo gemini auggie devin; do
|
|
402
|
+
if agent_exists "$agent"; then
|
|
403
|
+
local has_reg=false
|
|
404
|
+
case "$agent" in
|
|
405
|
+
opencode) [ -f "$OPENCODE_RULES_DIR/skill-sync.md" ] && has_reg=true ;;
|
|
406
|
+
claude) [ -f "$CLAUDE_RULES_DIR/skill-sync.md" ] && has_reg=true ;;
|
|
407
|
+
codex) grep -q "$SECTION_START" "$CODEX_AGENTS_MD" 2>/dev/null && has_reg=true ;;
|
|
408
|
+
kilo) [ -f "$KILO_RULES_DIR/skill-sync.md" ] && has_reg=true ;;
|
|
409
|
+
gemini) [ -f "$GEMINI_RULES_DIR/skill-sync.md" ] && has_reg=true ;;
|
|
410
|
+
auggie) [ -f "$AUGMENT_RULES_DIR/skill-sync.md" ] && has_reg=true ;;
|
|
411
|
+
devin) grep -q "$SECTION_START" "$DEVIN_AGENTS_MD" 2>/dev/null && has_reg=true ;;
|
|
412
|
+
esac
|
|
413
|
+
|
|
414
|
+
if $has_reg; then
|
|
415
|
+
if [ "$RULES_MODE" = "with" ] || { [ "$RULES_MODE" = "prompt" ] && prompt_yesno "Remove $agent registration?" "y"; }; then
|
|
416
|
+
do_unregister "$agent"
|
|
417
|
+
else
|
|
418
|
+
info "Kept $agent registration"
|
|
419
|
+
fi
|
|
420
|
+
fi
|
|
421
|
+
fi
|
|
422
|
+
done
|
|
423
|
+
|
|
424
|
+
echo ""
|
|
425
|
+
echo "Uninstalled. Skill directories are untouched."
|
|
426
|
+
exit 0
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
# ── Install ──
|
|
430
|
+
|
|
431
|
+
do_install() {
|
|
432
|
+
echo "Installing skill-sync..."
|
|
433
|
+
echo ""
|
|
434
|
+
|
|
435
|
+
# 1. CLI (always) — bundle lib modules into single file
|
|
436
|
+
mkdir -p "$BIN_DIR"
|
|
437
|
+
{
|
|
438
|
+
echo '#!/usr/bin/env bash'
|
|
439
|
+
echo 'set -euo pipefail'
|
|
440
|
+
echo ''
|
|
441
|
+
for _lib in core sync authoring inspect health targets; do
|
|
442
|
+
cat "$SCRIPT_DIR/lib/$_lib.sh" 2>/dev/null || true
|
|
443
|
+
echo ''
|
|
444
|
+
done
|
|
445
|
+
# Dispatch (everything from Main dispatch onward)
|
|
446
|
+
awk '/^# ── Main dispatch/{p=1} p' "$SCRIPT_DIR/skill-sync"
|
|
447
|
+
} > "$BIN_DIR/skill-sync"
|
|
448
|
+
chmod +x "$BIN_DIR/skill-sync"
|
|
449
|
+
info "✅ CLI installed → $BIN_DIR/skill-sync"
|
|
450
|
+
|
|
451
|
+
# 2. Config dir (always)
|
|
452
|
+
mkdir -p "$CONFIG_DIR"
|
|
453
|
+
info "✅ Config dir → $CONFIG_DIR/"
|
|
454
|
+
|
|
455
|
+
# 3. Agent rule registration
|
|
456
|
+
local found
|
|
457
|
+
found=$(list_agents)
|
|
458
|
+
|
|
459
|
+
if [ -z "$found" ]; then
|
|
460
|
+
echo ""
|
|
461
|
+
info "No AI agents detected — CLI installed without rule registration"
|
|
462
|
+
elif [ "$RULES_MODE" = "without" ]; then
|
|
463
|
+
echo ""
|
|
464
|
+
info "⏭️ Skipped agent rule registration (--no-rules)"
|
|
465
|
+
info " Register later with: ./install.sh --with-rules all"
|
|
466
|
+
else
|
|
467
|
+
echo ""
|
|
468
|
+
echo "Detected agents: ${found// /, }"
|
|
469
|
+
echo ""
|
|
470
|
+
|
|
471
|
+
for agent in $found; do
|
|
472
|
+
local should_register=false
|
|
473
|
+
|
|
474
|
+
if [ "$RULES_MODE" = "with" ]; then
|
|
475
|
+
agent_wants "$agent" && should_register=true
|
|
476
|
+
elif [ "$RULES_MODE" = "prompt" ]; then
|
|
477
|
+
local desc=""
|
|
478
|
+
case "$agent" in
|
|
479
|
+
opencode) desc="rule file + opencode.json" ;;
|
|
480
|
+
claude) desc="rule file + CLAUDE.md import" ;;
|
|
481
|
+
codex) desc="AGENTS.md section" ;;
|
|
482
|
+
kilo) desc="rule file + kilo.jsonc instructions" ;;
|
|
483
|
+
gemini) desc="rule file + GEMINI.md import" ;;
|
|
484
|
+
auggie) desc="rule file (auto-discovered)" ;;
|
|
485
|
+
devin) desc="AGENTS.md section" ;;
|
|
486
|
+
antigravity) desc="automatic — no registration needed" ;;
|
|
487
|
+
esac
|
|
488
|
+
if prompt_yesno " Register with $agent ($desc)?" "y"; then
|
|
489
|
+
should_register=true
|
|
490
|
+
fi
|
|
491
|
+
fi
|
|
492
|
+
|
|
493
|
+
if $should_register; then
|
|
494
|
+
do_register "$agent"
|
|
495
|
+
else
|
|
496
|
+
info " ⏭️ Skipped $agent"
|
|
497
|
+
fi
|
|
498
|
+
done
|
|
499
|
+
fi
|
|
500
|
+
|
|
501
|
+
echo ""
|
|
502
|
+
info "💡 Run 'skill-sync help' anytime for full command reference"
|
|
503
|
+
|
|
504
|
+
# 4. Generate manifest
|
|
505
|
+
echo ""
|
|
506
|
+
"$BIN_DIR/skill-sync" init 2>/dev/null || true
|
|
507
|
+
|
|
508
|
+
echo ""
|
|
509
|
+
echo "Installation complete!"
|
|
510
|
+
echo "Verify with: skill-sync doctor"
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
# ── Main ──
|
|
514
|
+
|
|
515
|
+
$UNINSTALL && do_uninstall
|
|
516
|
+
do_install
|