@brickhouse-tech/sync-agents 0.1.9 → 0.1.11
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/package.json +6 -2
- package/src/sh/sync-agents.sh +335 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brickhouse-tech/sync-agents",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Simple scripts to DRY up common agent interactions across multiple LLM providers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"src/**/*"
|
|
27
27
|
],
|
|
28
|
+
"overrides": {
|
|
29
|
+
"file-type": ">=22",
|
|
30
|
+
"picomatch": ">=4.0.4"
|
|
31
|
+
},
|
|
28
32
|
"scripts": {
|
|
29
33
|
"lint": "shellcheck src/sh/*.sh",
|
|
30
34
|
"test": "npx bats test/"
|
|
@@ -34,6 +38,6 @@
|
|
|
34
38
|
"@commitlint/config-conventional": "^20",
|
|
35
39
|
"commitlint": "20",
|
|
36
40
|
"shellcheck": "^4.1.0",
|
|
37
|
-
"sort-package-json": "3
|
|
41
|
+
"sort-package-json": ">=3"
|
|
38
42
|
}
|
|
39
43
|
}
|
package/src/sh/sync-agents.sh
CHANGED
|
@@ -75,6 +75,9 @@ ${BOLD}COMMANDS${RESET}
|
|
|
75
75
|
watch Watch .agents/ for changes and auto-regenerate index
|
|
76
76
|
import <url> Import a rule/skill/workflow from a URL
|
|
77
77
|
hook Install a pre-commit git hook for auto-sync
|
|
78
|
+
fix [type] Migrate legacy dirs + repair broken symlinks
|
|
79
|
+
type: skills, rules, workflows, or all
|
|
80
|
+
--no-clobber: skip items that already exist in .agents/
|
|
78
81
|
inherit <label> <path> Add an inheritance link to AGENTS.md (convention-based)
|
|
79
82
|
inherit --list List current inheritance links
|
|
80
83
|
inherit --remove <label> Remove an inheritance link by label
|
|
@@ -249,7 +252,14 @@ cmd_add() {
|
|
|
249
252
|
|
|
250
253
|
ensure_agents_dir
|
|
251
254
|
|
|
252
|
-
|
|
255
|
+
# Skills use directory layout: skills/name/SKILL.md
|
|
256
|
+
# Rules and workflows use flat files: rules/name.md, workflows/name.md
|
|
257
|
+
local filepath
|
|
258
|
+
if [[ "$type" == "skills" ]]; then
|
|
259
|
+
filepath="$PROJECT_ROOT/$AGENTS_DIR/$type/$name/SKILL.md"
|
|
260
|
+
else
|
|
261
|
+
filepath="$PROJECT_ROOT/$AGENTS_DIR/$type/$name.md"
|
|
262
|
+
fi
|
|
253
263
|
|
|
254
264
|
if [[ -f "$filepath" ]] && [[ "$FORCE" != "true" ]]; then
|
|
255
265
|
error "File already exists: $filepath (use --force to overwrite)"
|
|
@@ -265,6 +275,9 @@ cmd_add() {
|
|
|
265
275
|
*) template_name="RULE_TEMPLATE.md" ;;
|
|
266
276
|
esac
|
|
267
277
|
|
|
278
|
+
# Create parent directory for skills
|
|
279
|
+
mkdir -p "$(dirname "$filepath")"
|
|
280
|
+
|
|
268
281
|
if [[ -f "$TEMPLATES_DIR/$template_name" ]]; then
|
|
269
282
|
sed "s/\${NAME}/$name/g" "$TEMPLATES_DIR/$template_name" > "$filepath"
|
|
270
283
|
elif [[ -f "$TEMPLATES_DIR/RULE_TEMPLATE.md" ]]; then
|
|
@@ -287,6 +300,308 @@ TMPL_EOF
|
|
|
287
300
|
info "Updated $AGENTS_MD index"
|
|
288
301
|
}
|
|
289
302
|
|
|
303
|
+
cmd_fix() {
|
|
304
|
+
ensure_agents_dir
|
|
305
|
+
|
|
306
|
+
# Parse fix-specific flags
|
|
307
|
+
local no_clobber="false"
|
|
308
|
+
local fix_args=()
|
|
309
|
+
for arg in "$@"; do
|
|
310
|
+
case "$arg" in
|
|
311
|
+
--no-clobber) no_clobber="true" ;;
|
|
312
|
+
*) fix_args+=("$arg") ;;
|
|
313
|
+
esac
|
|
314
|
+
done
|
|
315
|
+
|
|
316
|
+
local fix_type="${fix_args[0]:-all}"
|
|
317
|
+
local subdirs=()
|
|
318
|
+
|
|
319
|
+
case "$fix_type" in
|
|
320
|
+
skills|rules|workflows)
|
|
321
|
+
subdirs=("$fix_type")
|
|
322
|
+
;;
|
|
323
|
+
all)
|
|
324
|
+
subdirs=(skills rules workflows)
|
|
325
|
+
;;
|
|
326
|
+
*)
|
|
327
|
+
error "Unknown type: $fix_type (expected: skills, rules, workflows, or all)"
|
|
328
|
+
exit 1
|
|
329
|
+
;;
|
|
330
|
+
esac
|
|
331
|
+
|
|
332
|
+
local agents_abs
|
|
333
|
+
agents_abs="$(cd "$PROJECT_ROOT/$AGENTS_DIR" && pwd)"
|
|
334
|
+
local fixed=0
|
|
335
|
+
local skipped=0
|
|
336
|
+
local merged=0
|
|
337
|
+
|
|
338
|
+
# Helper: compare inodes of two directories (portable across macOS/Linux)
|
|
339
|
+
same_inode() {
|
|
340
|
+
local inode_a inode_b
|
|
341
|
+
if stat --version >/dev/null 2>&1; then
|
|
342
|
+
# GNU stat (Linux)
|
|
343
|
+
inode_a="$(stat -c '%i' "$1" 2>/dev/null)"
|
|
344
|
+
inode_b="$(stat -c '%i' "$2" 2>/dev/null)"
|
|
345
|
+
else
|
|
346
|
+
# BSD stat (macOS)
|
|
347
|
+
inode_a="$(stat -f '%i' "$1" 2>/dev/null)"
|
|
348
|
+
inode_b="$(stat -f '%i' "$2" 2>/dev/null)"
|
|
349
|
+
fi
|
|
350
|
+
[[ -n "$inode_a" ]] && [[ "$inode_a" == "$inode_b" ]]
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
for subdir in "${subdirs[@]}"; do
|
|
354
|
+
local legacy_dir="$PROJECT_ROOT/$subdir"
|
|
355
|
+
local agents_subdir="$agents_abs/$subdir"
|
|
356
|
+
|
|
357
|
+
# Skip if legacy dir doesn't exist or is already a symlink
|
|
358
|
+
if [[ ! -d "$legacy_dir" ]]; then
|
|
359
|
+
continue
|
|
360
|
+
fi
|
|
361
|
+
if [[ -L "$legacy_dir" ]]; then
|
|
362
|
+
info "$subdir/ is already a symlink — nothing to do."
|
|
363
|
+
continue
|
|
364
|
+
fi
|
|
365
|
+
|
|
366
|
+
# Detect same-inode (legacy dir IS .agents/subdir — e.g. hardlink or bind mount)
|
|
367
|
+
if [[ -d "$agents_subdir" ]] && same_inode "$legacy_dir" "$agents_subdir"; then
|
|
368
|
+
warn "$subdir/ and $AGENTS_DIR/$subdir/ are the same directory (same inode)."
|
|
369
|
+
warn "Replacing $subdir/ with a symlink to $AGENTS_DIR/$subdir/."
|
|
370
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
371
|
+
echo " would remove $subdir/ (same inode as $AGENTS_DIR/$subdir/)"
|
|
372
|
+
echo " would create symlink $subdir/ -> $AGENTS_DIR/$subdir"
|
|
373
|
+
else
|
|
374
|
+
rm -rf "$legacy_dir"
|
|
375
|
+
ln -s "$AGENTS_DIR/$subdir" "$legacy_dir"
|
|
376
|
+
info "Replaced $subdir/ with symlink -> $AGENTS_DIR/$subdir"
|
|
377
|
+
fi
|
|
378
|
+
fixed=$((fixed + 1))
|
|
379
|
+
continue
|
|
380
|
+
fi
|
|
381
|
+
|
|
382
|
+
info "Found legacy directory: $subdir/"
|
|
383
|
+
mkdir -p "$agents_subdir"
|
|
384
|
+
|
|
385
|
+
# Move each item from legacy dir into .agents/subdir
|
|
386
|
+
for item in "$legacy_dir"/*/; do
|
|
387
|
+
[[ -d "$item" ]] || continue
|
|
388
|
+
local name
|
|
389
|
+
name="$(basename "$item")"
|
|
390
|
+
|
|
391
|
+
if [[ -d "$agents_subdir/$name" ]]; then
|
|
392
|
+
if [[ "$no_clobber" == "true" ]]; then
|
|
393
|
+
warn "Skipping $subdir/$name — already exists in $AGENTS_DIR/$subdir/ (--no-clobber)"
|
|
394
|
+
skipped=$((skipped + 1))
|
|
395
|
+
continue
|
|
396
|
+
fi
|
|
397
|
+
# Merge: legacy content wins (overwrite into .agents/)
|
|
398
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
399
|
+
echo " would merge: $subdir/$name -> $AGENTS_DIR/$subdir/$name (overwrite)"
|
|
400
|
+
else
|
|
401
|
+
rm -rf "${agents_subdir:?}/${name:?}"
|
|
402
|
+
mv "$item" "$agents_subdir/$name"
|
|
403
|
+
info "Merged: $subdir/$name -> $AGENTS_DIR/$subdir/$name (overwrote existing)"
|
|
404
|
+
fi
|
|
405
|
+
merged=$((merged + 1))
|
|
406
|
+
fixed=$((fixed + 1))
|
|
407
|
+
continue
|
|
408
|
+
fi
|
|
409
|
+
|
|
410
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
411
|
+
echo " would move: $subdir/$name -> $AGENTS_DIR/$subdir/$name"
|
|
412
|
+
else
|
|
413
|
+
mv "$item" "$agents_subdir/$name"
|
|
414
|
+
info "Moved: $subdir/$name -> $AGENTS_DIR/$subdir/$name"
|
|
415
|
+
fi
|
|
416
|
+
fixed=$((fixed + 1))
|
|
417
|
+
done
|
|
418
|
+
|
|
419
|
+
# Also move any top-level files (e.g. loose .md rules)
|
|
420
|
+
for item in "$legacy_dir"/*; do
|
|
421
|
+
[[ -f "$item" ]] || continue
|
|
422
|
+
local name
|
|
423
|
+
name="$(basename "$item")"
|
|
424
|
+
|
|
425
|
+
if [[ -f "$agents_subdir/$name" ]]; then
|
|
426
|
+
if [[ "$no_clobber" == "true" ]]; then
|
|
427
|
+
warn "Skipping $subdir/$name — already exists in $AGENTS_DIR/$subdir/ (--no-clobber)"
|
|
428
|
+
skipped=$((skipped + 1))
|
|
429
|
+
continue
|
|
430
|
+
fi
|
|
431
|
+
# Merge: legacy content wins
|
|
432
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
433
|
+
echo " would merge: $subdir/$name -> $AGENTS_DIR/$subdir/$name (overwrite)"
|
|
434
|
+
else
|
|
435
|
+
mv "$item" "$agents_subdir/$name"
|
|
436
|
+
info "Merged: $subdir/$name -> $AGENTS_DIR/$subdir/$name (overwrote existing)"
|
|
437
|
+
fi
|
|
438
|
+
merged=$((merged + 1))
|
|
439
|
+
fixed=$((fixed + 1))
|
|
440
|
+
continue
|
|
441
|
+
fi
|
|
442
|
+
|
|
443
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
444
|
+
echo " would move: $subdir/$name -> $AGENTS_DIR/$subdir/$name"
|
|
445
|
+
else
|
|
446
|
+
mv "$item" "$agents_subdir/$name"
|
|
447
|
+
info "Moved: $subdir/$name -> $AGENTS_DIR/$subdir/$name"
|
|
448
|
+
fi
|
|
449
|
+
fixed=$((fixed + 1))
|
|
450
|
+
done
|
|
451
|
+
|
|
452
|
+
# Remove the now-empty legacy dir and replace with symlink
|
|
453
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
454
|
+
echo " would replace $subdir/ with symlink -> $AGENTS_DIR/$subdir"
|
|
455
|
+
else
|
|
456
|
+
# Check if dir is empty (only . and .. remain)
|
|
457
|
+
if [[ -z "$(ls -A "$legacy_dir" 2>/dev/null)" ]]; then
|
|
458
|
+
rmdir "$legacy_dir"
|
|
459
|
+
ln -s "$AGENTS_DIR/$subdir" "$legacy_dir"
|
|
460
|
+
info "Replaced $subdir/ with symlink -> $AGENTS_DIR/$subdir"
|
|
461
|
+
else
|
|
462
|
+
warn "$subdir/ is not empty after migration — skipping symlink replacement"
|
|
463
|
+
warn "Remaining items:"
|
|
464
|
+
find "$legacy_dir" -mindepth 1 -maxdepth 1 -exec basename {} \; | sed 's/^/ /'
|
|
465
|
+
fi
|
|
466
|
+
fi
|
|
467
|
+
done
|
|
468
|
+
|
|
469
|
+
# --- Phase 1b: Convert flat skill files to directory layout ---
|
|
470
|
+
# e.g. .agents/skills/foo.md -> .agents/skills/foo/SKILL.md
|
|
471
|
+
for subdir in "${subdirs[@]}"; do
|
|
472
|
+
[[ "$subdir" == "skills" ]] || continue
|
|
473
|
+
local skills_dir="$agents_abs/skills"
|
|
474
|
+
[[ -d "$skills_dir" ]] || continue
|
|
475
|
+
|
|
476
|
+
for flat_file in "$skills_dir"/*.md; do
|
|
477
|
+
[[ -f "$flat_file" ]] || continue
|
|
478
|
+
local name
|
|
479
|
+
name="$(basename "$flat_file" .md)"
|
|
480
|
+
local target_dir="$skills_dir/$name"
|
|
481
|
+
local target_file="$target_dir/SKILL.md"
|
|
482
|
+
|
|
483
|
+
if [[ -d "$target_dir" ]] && [[ -f "$target_file" ]]; then
|
|
484
|
+
if [[ "$no_clobber" == "true" ]]; then
|
|
485
|
+
warn "Skipping flat skill $name.md — $name/SKILL.md already exists (--no-clobber)"
|
|
486
|
+
skipped=$((skipped + 1))
|
|
487
|
+
continue
|
|
488
|
+
fi
|
|
489
|
+
# Flat file wins (same merge behavior as legacy migration)
|
|
490
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
491
|
+
echo " would convert: skills/$name.md -> skills/$name/SKILL.md (overwrite)"
|
|
492
|
+
else
|
|
493
|
+
mv "$flat_file" "$target_file"
|
|
494
|
+
info "Converted: skills/$name.md -> skills/$name/SKILL.md (overwrote existing)"
|
|
495
|
+
fi
|
|
496
|
+
merged=$((merged + 1))
|
|
497
|
+
fixed=$((fixed + 1))
|
|
498
|
+
continue
|
|
499
|
+
fi
|
|
500
|
+
|
|
501
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
502
|
+
echo " would convert: skills/$name.md -> skills/$name/SKILL.md"
|
|
503
|
+
else
|
|
504
|
+
mkdir -p "$target_dir"
|
|
505
|
+
mv "$flat_file" "$target_file"
|
|
506
|
+
info "Converted: skills/$name.md -> skills/$name/SKILL.md"
|
|
507
|
+
fi
|
|
508
|
+
fixed=$((fixed + 1))
|
|
509
|
+
done
|
|
510
|
+
done
|
|
511
|
+
|
|
512
|
+
# --- Phase 2: Repair broken/missing symlinks ---
|
|
513
|
+
local repaired=0
|
|
514
|
+
|
|
515
|
+
for target in "${ACTIVE_TARGETS[@]}"; do
|
|
516
|
+
local target_dir
|
|
517
|
+
target_dir="$(resolve_target_dir "$target" "$PROJECT_ROOT")"
|
|
518
|
+
local agents_rel
|
|
519
|
+
agents_rel="$(resolve_agents_rel "$target")"
|
|
520
|
+
|
|
521
|
+
for subdir in "${subdirs[@]}"; do
|
|
522
|
+
if [[ ! -d "$agents_abs/$subdir" ]]; then
|
|
523
|
+
continue
|
|
524
|
+
fi
|
|
525
|
+
local expected_link="$target_dir/$subdir"
|
|
526
|
+
local expected_source="$agents_rel/$subdir"
|
|
527
|
+
|
|
528
|
+
if [[ -L "$expected_link" ]]; then
|
|
529
|
+
local current_target
|
|
530
|
+
current_target="$(readlink "$expected_link")"
|
|
531
|
+
if [[ "$current_target" == "$expected_source" ]]; then
|
|
532
|
+
continue # Already correct
|
|
533
|
+
fi
|
|
534
|
+
# Symlink exists but points to wrong target
|
|
535
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
536
|
+
echo " would relink: $expected_link -> $expected_source (was $current_target)"
|
|
537
|
+
else
|
|
538
|
+
rm "$expected_link"
|
|
539
|
+
create_symlink "$expected_source" "$expected_link" "false"
|
|
540
|
+
info "Repaired: $expected_link -> $expected_source (was $current_target)"
|
|
541
|
+
fi
|
|
542
|
+
repaired=$((repaired + 1))
|
|
543
|
+
elif [[ -e "$expected_link" ]]; then
|
|
544
|
+
# Something exists but isn't a symlink — skip unless --force
|
|
545
|
+
if [[ "$FORCE" == "true" ]]; then
|
|
546
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
547
|
+
echo " would replace: $expected_link with symlink -> $expected_source"
|
|
548
|
+
else
|
|
549
|
+
rm -rf "$expected_link"
|
|
550
|
+
create_symlink "$expected_source" "$expected_link" "false"
|
|
551
|
+
info "Repaired: replaced $expected_link with symlink -> $expected_source"
|
|
552
|
+
fi
|
|
553
|
+
repaired=$((repaired + 1))
|
|
554
|
+
else
|
|
555
|
+
warn "$expected_link exists but is not a symlink (use --force to replace)"
|
|
556
|
+
fi
|
|
557
|
+
else
|
|
558
|
+
# Missing entirely
|
|
559
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
560
|
+
echo " would create: $expected_link -> $expected_source"
|
|
561
|
+
else
|
|
562
|
+
create_symlink "$expected_source" "$expected_link" "false"
|
|
563
|
+
fi
|
|
564
|
+
repaired=$((repaired + 1))
|
|
565
|
+
fi
|
|
566
|
+
done
|
|
567
|
+
done
|
|
568
|
+
|
|
569
|
+
# Repair CLAUDE.md symlink
|
|
570
|
+
if [[ -f "$PROJECT_ROOT/$AGENTS_MD" ]]; then
|
|
571
|
+
if [[ -L "$PROJECT_ROOT/CLAUDE.md" ]]; then
|
|
572
|
+
local current_target
|
|
573
|
+
current_target="$(readlink "$PROJECT_ROOT/CLAUDE.md")"
|
|
574
|
+
if [[ "$current_target" != "$AGENTS_MD" ]]; then
|
|
575
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
576
|
+
echo " would relink: CLAUDE.md -> $AGENTS_MD (was $current_target)"
|
|
577
|
+
else
|
|
578
|
+
rm "$PROJECT_ROOT/CLAUDE.md"
|
|
579
|
+
create_symlink "$AGENTS_MD" "$PROJECT_ROOT/CLAUDE.md" "false"
|
|
580
|
+
fi
|
|
581
|
+
repaired=$((repaired + 1))
|
|
582
|
+
fi
|
|
583
|
+
elif [[ ! -e "$PROJECT_ROOT/CLAUDE.md" ]]; then
|
|
584
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
585
|
+
echo " would create: CLAUDE.md -> $AGENTS_MD"
|
|
586
|
+
else
|
|
587
|
+
create_symlink "$AGENTS_MD" "$PROJECT_ROOT/CLAUDE.md" "false"
|
|
588
|
+
fi
|
|
589
|
+
repaired=$((repaired + 1))
|
|
590
|
+
fi
|
|
591
|
+
fi
|
|
592
|
+
|
|
593
|
+
# Summary
|
|
594
|
+
if [[ "$fixed" -eq 0 ]] && [[ "$skipped" -eq 0 ]] && [[ "$repaired" -eq 0 ]]; then
|
|
595
|
+
info "Nothing to fix — all directories and symlinks are correct."
|
|
596
|
+
else
|
|
597
|
+
if [[ "$fixed" -gt 0 ]]; then info "Fixed $fixed item(s)."; fi
|
|
598
|
+
if [[ "$merged" -gt 0 ]]; then info "Merged $merged item(s) (legacy overwrote existing)."; fi
|
|
599
|
+
if [[ "$skipped" -gt 0 ]]; then warn "Skipped $skipped item(s) (use without --no-clobber to merge)."; fi
|
|
600
|
+
if [[ "$repaired" -gt 0 ]]; then info "Repaired $repaired symlink(s)."; fi
|
|
601
|
+
if [[ "$fixed" -gt 0 ]]; then info "Run 'sync-agents sync' to update agent target symlinks."; fi
|
|
602
|
+
fi
|
|
603
|
+
}
|
|
604
|
+
|
|
290
605
|
cmd_sync() {
|
|
291
606
|
ensure_agents_dir
|
|
292
607
|
|
|
@@ -936,16 +1251,30 @@ HEADER
|
|
|
936
1251
|
fi
|
|
937
1252
|
echo ""
|
|
938
1253
|
|
|
939
|
-
# Skills
|
|
1254
|
+
# Skills (directory layout: skills/name/SKILL.md, or legacy flat: skills/name.md)
|
|
940
1255
|
echo "## Skills"
|
|
941
1256
|
echo ""
|
|
1257
|
+
local has_skills="false"
|
|
1258
|
+
# Directory skills: skills/name/SKILL.md
|
|
1259
|
+
for d in "$agents_dir/skills/"*/; do
|
|
1260
|
+
[[ -d "$d" ]] || continue
|
|
1261
|
+
local name
|
|
1262
|
+
name="$(basename "$d")"
|
|
1263
|
+
if [[ -f "$d/SKILL.md" ]]; then
|
|
1264
|
+
echo "- [$name](.agents/skills/$name/SKILL.md)"
|
|
1265
|
+
has_skills="true"
|
|
1266
|
+
fi
|
|
1267
|
+
done
|
|
1268
|
+
# Legacy flat skills: skills/name.md
|
|
942
1269
|
if compgen -G "$agents_dir/skills/*.md" > /dev/null 2>&1; then
|
|
943
1270
|
for f in "$agents_dir/skills/"*.md; do
|
|
944
1271
|
local name
|
|
945
1272
|
name="$(basename "$f" .md)"
|
|
946
1273
|
echo "- [$name](.agents/skills/$name.md)"
|
|
1274
|
+
has_skills="true"
|
|
947
1275
|
done
|
|
948
|
-
|
|
1276
|
+
fi
|
|
1277
|
+
if [[ "$has_skills" == "false" ]]; then
|
|
949
1278
|
echo "_No skills defined yet. Add one with \`sync-agents add skill <name>\`._"
|
|
950
1279
|
fi
|
|
951
1280
|
echo ""
|
|
@@ -1124,6 +1453,9 @@ main() {
|
|
|
1124
1453
|
import)
|
|
1125
1454
|
cmd_import "$@"
|
|
1126
1455
|
;;
|
|
1456
|
+
fix)
|
|
1457
|
+
cmd_fix "$@"
|
|
1458
|
+
;;
|
|
1127
1459
|
hook)
|
|
1128
1460
|
cmd_hook
|
|
1129
1461
|
;;
|