@brickhouse-tech/sync-agents 0.1.10 → 0.1.12
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 +55 -2
- package/package.json +6 -2
- package/src/sh/sync-agents.sh +218 -8
package/README.md
CHANGED
|
@@ -31,13 +31,16 @@ chmod +x /usr/local/bin/sync-agents
|
|
|
31
31
|
|
|
32
32
|
```
|
|
33
33
|
.agents/
|
|
34
|
+
├── config # sync targets (claude, windsurf, cursor, copilot)
|
|
34
35
|
├── rules/
|
|
35
36
|
│ ├── rule1.md
|
|
36
37
|
│ ├── rule2.md
|
|
37
38
|
│ └── ...
|
|
38
39
|
├── skills/
|
|
39
|
-
│ ├── skill1
|
|
40
|
-
│
|
|
40
|
+
│ ├── skill1/
|
|
41
|
+
│ │ └── SKILL.md
|
|
42
|
+
│ ├── skill2/
|
|
43
|
+
│ │ └── SKILL.md
|
|
41
44
|
│ └── ...
|
|
42
45
|
├── workflows/
|
|
43
46
|
│ ├── workflow1.md
|
|
@@ -46,6 +49,8 @@ chmod +x /usr/local/bin/sync-agents
|
|
|
46
49
|
└── STATE.md
|
|
47
50
|
```
|
|
48
51
|
|
|
52
|
+
> **Note:** Skills use a directory layout (`skills/name/SKILL.md`) rather than flat files. This allows skills to include supporting files alongside their definition. The `fix` command can convert legacy flat skill files to the directory layout automatically.
|
|
53
|
+
|
|
49
54
|
Running `sync-agents sync` creates symlinks from `.agents/` subdirectories into `.claude/`, `.windsurf/`, `.cursor/`, and `.github/copilot/`. Any changes to `.agents/` are automatically reflected in the target directories because they are symlinks, not copies.
|
|
50
55
|
|
|
51
56
|
AGENTS.md is also symlinked to CLAUDE.md so that Claude reads the index natively.
|
|
@@ -70,6 +75,7 @@ AGENTS.md is also symlinked to CLAUDE.md so that Claude reads the index natively
|
|
|
70
75
|
| `add <type> <name>` | Add a new rule, skill, or workflow from a template (type is `rule`, `skill`, or `workflow`) |
|
|
71
76
|
| `index` | Regenerate `AGENTS.md` by scanning the contents of `.agents/` |
|
|
72
77
|
| `clean` | Remove all synced symlinks and empty target directories (does not remove `.agents/`) |
|
|
78
|
+
| `fix [type]` | Migrate legacy dirs into `.agents/`, convert flat skill files to directory layout, and repair broken symlinks. Type: `skills`, `rules`, `workflows`, or `all` (default) |
|
|
73
79
|
|
|
74
80
|
## Options
|
|
75
81
|
|
|
@@ -81,6 +87,47 @@ AGENTS.md is also symlinked to CLAUDE.md so that Claude reads the index natively
|
|
|
81
87
|
| `--targets <list>` | Comma-separated list of sync targets (default: `claude,windsurf,cursor,copilot`) |
|
|
82
88
|
| `--dry-run` | Show what would be done without making changes |
|
|
83
89
|
| `--force` | Overwrite existing files and symlinks |
|
|
90
|
+
| `--no-clobber` | (fix only) Skip items that already exist in `.agents/` instead of merging |
|
|
91
|
+
|
|
92
|
+
## Configuration
|
|
93
|
+
|
|
94
|
+
`sync-agents init` creates `.agents/config` with default sync targets:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
# sync-agents configuration
|
|
98
|
+
# Comma-separated list of sync targets (available: claude, windsurf, cursor, copilot)
|
|
99
|
+
targets = claude,windsurf,cursor,copilot
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Edit this file to limit which targets `sync` writes to by default. The `--targets` flag on any command overrides the config.
|
|
103
|
+
|
|
104
|
+
## Fix
|
|
105
|
+
|
|
106
|
+
The `fix` command handles three scenarios:
|
|
107
|
+
|
|
108
|
+
1. **Legacy directory migration** — Moves top-level `skills/`, `rules/`, or `workflows/` directories into `.agents/` and replaces them with symlinks.
|
|
109
|
+
2. **Flat skill conversion** — Converts `.agents/skills/name.md` flat files to the directory layout `.agents/skills/name/SKILL.md`.
|
|
110
|
+
3. **Symlink repair** — Recreates missing or broken symlinks in target directories (`.claude/`, `.windsurf/`, etc.) and the `CLAUDE.md` symlink.
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Fix everything (all types)
|
|
114
|
+
sync-agents fix
|
|
115
|
+
|
|
116
|
+
# Fix only skills
|
|
117
|
+
sync-agents fix skills
|
|
118
|
+
|
|
119
|
+
# Preview without changing anything
|
|
120
|
+
sync-agents fix --dry-run
|
|
121
|
+
|
|
122
|
+
# Don't overwrite items already in .agents/
|
|
123
|
+
sync-agents fix --no-clobber skills
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
A reproducible demo is available in [`examples/fix/`](examples/fix/):
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
bash examples/fix/run-demo.sh
|
|
130
|
+
```
|
|
84
131
|
|
|
85
132
|
## Inheritance
|
|
86
133
|
|
|
@@ -262,6 +309,12 @@ sync-agents index
|
|
|
262
309
|
# Remove all synced symlinks
|
|
263
310
|
sync-agents clean
|
|
264
311
|
|
|
312
|
+
# Fix legacy layouts and broken symlinks
|
|
313
|
+
sync-agents fix
|
|
314
|
+
|
|
315
|
+
# Fix only skills (migrate + convert flat files + repair symlinks)
|
|
316
|
+
sync-agents fix skills
|
|
317
|
+
|
|
265
318
|
# Work in a different directory
|
|
266
319
|
sync-agents sync --dir /path/to/project
|
|
267
320
|
```
|
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.12",
|
|
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,10 +75,13 @@ ${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
|
|
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/
|
|
79
81
|
inherit <label> <path> Add an inheritance link to AGENTS.md (convention-based)
|
|
80
82
|
inherit --list List current inheritance links
|
|
81
83
|
inherit --remove <label> Remove an inheritance link by label
|
|
84
|
+
version Show version (same as --version)
|
|
82
85
|
|
|
83
86
|
${BOLD}OPTIONS${RESET}
|
|
84
87
|
-h, --help Show this help message
|
|
@@ -301,7 +304,17 @@ TMPL_EOF
|
|
|
301
304
|
cmd_fix() {
|
|
302
305
|
ensure_agents_dir
|
|
303
306
|
|
|
304
|
-
|
|
307
|
+
# Parse fix-specific flags
|
|
308
|
+
local no_clobber="false"
|
|
309
|
+
local fix_args=()
|
|
310
|
+
for arg in "$@"; do
|
|
311
|
+
case "$arg" in
|
|
312
|
+
--no-clobber) no_clobber="true" ;;
|
|
313
|
+
*) fix_args+=("$arg") ;;
|
|
314
|
+
esac
|
|
315
|
+
done
|
|
316
|
+
|
|
317
|
+
local fix_type="${fix_args[0]:-all}"
|
|
305
318
|
local subdirs=()
|
|
306
319
|
|
|
307
320
|
case "$fix_type" in
|
|
@@ -320,13 +333,50 @@ cmd_fix() {
|
|
|
320
333
|
local agents_abs
|
|
321
334
|
agents_abs="$(cd "$PROJECT_ROOT/$AGENTS_DIR" && pwd)"
|
|
322
335
|
local fixed=0
|
|
336
|
+
local skipped=0
|
|
337
|
+
local merged=0
|
|
338
|
+
|
|
339
|
+
# Helper: compare inodes of two directories (portable across macOS/Linux)
|
|
340
|
+
same_inode() {
|
|
341
|
+
local inode_a inode_b
|
|
342
|
+
if stat --version >/dev/null 2>&1; then
|
|
343
|
+
# GNU stat (Linux)
|
|
344
|
+
inode_a="$(stat -c '%i' "$1" 2>/dev/null)"
|
|
345
|
+
inode_b="$(stat -c '%i' "$2" 2>/dev/null)"
|
|
346
|
+
else
|
|
347
|
+
# BSD stat (macOS)
|
|
348
|
+
inode_a="$(stat -f '%i' "$1" 2>/dev/null)"
|
|
349
|
+
inode_b="$(stat -f '%i' "$2" 2>/dev/null)"
|
|
350
|
+
fi
|
|
351
|
+
[[ -n "$inode_a" ]] && [[ "$inode_a" == "$inode_b" ]]
|
|
352
|
+
}
|
|
323
353
|
|
|
324
354
|
for subdir in "${subdirs[@]}"; do
|
|
325
355
|
local legacy_dir="$PROJECT_ROOT/$subdir"
|
|
326
356
|
local agents_subdir="$agents_abs/$subdir"
|
|
327
357
|
|
|
328
358
|
# Skip if legacy dir doesn't exist or is already a symlink
|
|
329
|
-
if [[ ! -d "$legacy_dir" ]]
|
|
359
|
+
if [[ ! -d "$legacy_dir" ]]; then
|
|
360
|
+
continue
|
|
361
|
+
fi
|
|
362
|
+
if [[ -L "$legacy_dir" ]]; then
|
|
363
|
+
info "$subdir/ is already a symlink — nothing to do."
|
|
364
|
+
continue
|
|
365
|
+
fi
|
|
366
|
+
|
|
367
|
+
# Detect same-inode (legacy dir IS .agents/subdir — e.g. hardlink or bind mount)
|
|
368
|
+
if [[ -d "$agents_subdir" ]] && same_inode "$legacy_dir" "$agents_subdir"; then
|
|
369
|
+
warn "$subdir/ and $AGENTS_DIR/$subdir/ are the same directory (same inode)."
|
|
370
|
+
warn "Replacing $subdir/ with a symlink to $AGENTS_DIR/$subdir/."
|
|
371
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
372
|
+
echo " would remove $subdir/ (same inode as $AGENTS_DIR/$subdir/)"
|
|
373
|
+
echo " would create symlink $subdir/ -> $AGENTS_DIR/$subdir"
|
|
374
|
+
else
|
|
375
|
+
rm -rf "$legacy_dir"
|
|
376
|
+
ln -s "$AGENTS_DIR/$subdir" "$legacy_dir"
|
|
377
|
+
info "Replaced $subdir/ with symlink -> $AGENTS_DIR/$subdir"
|
|
378
|
+
fi
|
|
379
|
+
fixed=$((fixed + 1))
|
|
330
380
|
continue
|
|
331
381
|
fi
|
|
332
382
|
|
|
@@ -340,7 +390,21 @@ cmd_fix() {
|
|
|
340
390
|
name="$(basename "$item")"
|
|
341
391
|
|
|
342
392
|
if [[ -d "$agents_subdir/$name" ]]; then
|
|
343
|
-
|
|
393
|
+
if [[ "$no_clobber" == "true" ]]; then
|
|
394
|
+
warn "Skipping $subdir/$name — already exists in $AGENTS_DIR/$subdir/ (--no-clobber)"
|
|
395
|
+
skipped=$((skipped + 1))
|
|
396
|
+
continue
|
|
397
|
+
fi
|
|
398
|
+
# Merge: legacy content wins (overwrite into .agents/)
|
|
399
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
400
|
+
echo " would merge: $subdir/$name -> $AGENTS_DIR/$subdir/$name (overwrite)"
|
|
401
|
+
else
|
|
402
|
+
rm -rf "${agents_subdir:?}/${name:?}"
|
|
403
|
+
mv "$item" "$agents_subdir/$name"
|
|
404
|
+
info "Merged: $subdir/$name -> $AGENTS_DIR/$subdir/$name (overwrote existing)"
|
|
405
|
+
fi
|
|
406
|
+
merged=$((merged + 1))
|
|
407
|
+
fixed=$((fixed + 1))
|
|
344
408
|
continue
|
|
345
409
|
fi
|
|
346
410
|
|
|
@@ -360,7 +424,20 @@ cmd_fix() {
|
|
|
360
424
|
name="$(basename "$item")"
|
|
361
425
|
|
|
362
426
|
if [[ -f "$agents_subdir/$name" ]]; then
|
|
363
|
-
|
|
427
|
+
if [[ "$no_clobber" == "true" ]]; then
|
|
428
|
+
warn "Skipping $subdir/$name — already exists in $AGENTS_DIR/$subdir/ (--no-clobber)"
|
|
429
|
+
skipped=$((skipped + 1))
|
|
430
|
+
continue
|
|
431
|
+
fi
|
|
432
|
+
# Merge: legacy content wins
|
|
433
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
434
|
+
echo " would merge: $subdir/$name -> $AGENTS_DIR/$subdir/$name (overwrite)"
|
|
435
|
+
else
|
|
436
|
+
mv "$item" "$agents_subdir/$name"
|
|
437
|
+
info "Merged: $subdir/$name -> $AGENTS_DIR/$subdir/$name (overwrote existing)"
|
|
438
|
+
fi
|
|
439
|
+
merged=$((merged + 1))
|
|
440
|
+
fixed=$((fixed + 1))
|
|
364
441
|
continue
|
|
365
442
|
fi
|
|
366
443
|
|
|
@@ -390,10 +467,139 @@ cmd_fix() {
|
|
|
390
467
|
fi
|
|
391
468
|
done
|
|
392
469
|
|
|
393
|
-
|
|
394
|
-
|
|
470
|
+
# --- Phase 1b: Convert flat skill files to directory layout ---
|
|
471
|
+
# e.g. .agents/skills/foo.md -> .agents/skills/foo/SKILL.md
|
|
472
|
+
for subdir in "${subdirs[@]}"; do
|
|
473
|
+
[[ "$subdir" == "skills" ]] || continue
|
|
474
|
+
local skills_dir="$agents_abs/skills"
|
|
475
|
+
[[ -d "$skills_dir" ]] || continue
|
|
476
|
+
|
|
477
|
+
for flat_file in "$skills_dir"/*.md; do
|
|
478
|
+
[[ -f "$flat_file" ]] || continue
|
|
479
|
+
local name
|
|
480
|
+
name="$(basename "$flat_file" .md)"
|
|
481
|
+
local target_dir="$skills_dir/$name"
|
|
482
|
+
local target_file="$target_dir/SKILL.md"
|
|
483
|
+
|
|
484
|
+
if [[ -d "$target_dir" ]] && [[ -f "$target_file" ]]; then
|
|
485
|
+
if [[ "$no_clobber" == "true" ]]; then
|
|
486
|
+
warn "Skipping flat skill $name.md — $name/SKILL.md already exists (--no-clobber)"
|
|
487
|
+
skipped=$((skipped + 1))
|
|
488
|
+
continue
|
|
489
|
+
fi
|
|
490
|
+
# Flat file wins (same merge behavior as legacy migration)
|
|
491
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
492
|
+
echo " would convert: skills/$name.md -> skills/$name/SKILL.md (overwrite)"
|
|
493
|
+
else
|
|
494
|
+
mv "$flat_file" "$target_file"
|
|
495
|
+
info "Converted: skills/$name.md -> skills/$name/SKILL.md (overwrote existing)"
|
|
496
|
+
fi
|
|
497
|
+
merged=$((merged + 1))
|
|
498
|
+
fixed=$((fixed + 1))
|
|
499
|
+
continue
|
|
500
|
+
fi
|
|
501
|
+
|
|
502
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
503
|
+
echo " would convert: skills/$name.md -> skills/$name/SKILL.md"
|
|
504
|
+
else
|
|
505
|
+
mkdir -p "$target_dir"
|
|
506
|
+
mv "$flat_file" "$target_file"
|
|
507
|
+
info "Converted: skills/$name.md -> skills/$name/SKILL.md"
|
|
508
|
+
fi
|
|
509
|
+
fixed=$((fixed + 1))
|
|
510
|
+
done
|
|
511
|
+
done
|
|
512
|
+
|
|
513
|
+
# --- Phase 2: Repair broken/missing symlinks ---
|
|
514
|
+
local repaired=0
|
|
515
|
+
|
|
516
|
+
for target in "${ACTIVE_TARGETS[@]}"; do
|
|
517
|
+
local target_dir
|
|
518
|
+
target_dir="$(resolve_target_dir "$target" "$PROJECT_ROOT")"
|
|
519
|
+
local agents_rel
|
|
520
|
+
agents_rel="$(resolve_agents_rel "$target")"
|
|
521
|
+
|
|
522
|
+
for subdir in "${subdirs[@]}"; do
|
|
523
|
+
if [[ ! -d "$agents_abs/$subdir" ]]; then
|
|
524
|
+
continue
|
|
525
|
+
fi
|
|
526
|
+
local expected_link="$target_dir/$subdir"
|
|
527
|
+
local expected_source="$agents_rel/$subdir"
|
|
528
|
+
|
|
529
|
+
if [[ -L "$expected_link" ]]; then
|
|
530
|
+
local current_target
|
|
531
|
+
current_target="$(readlink "$expected_link")"
|
|
532
|
+
if [[ "$current_target" == "$expected_source" ]]; then
|
|
533
|
+
continue # Already correct
|
|
534
|
+
fi
|
|
535
|
+
# Symlink exists but points to wrong target
|
|
536
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
537
|
+
echo " would relink: $expected_link -> $expected_source (was $current_target)"
|
|
538
|
+
else
|
|
539
|
+
rm "$expected_link"
|
|
540
|
+
create_symlink "$expected_source" "$expected_link" "false"
|
|
541
|
+
info "Repaired: $expected_link -> $expected_source (was $current_target)"
|
|
542
|
+
fi
|
|
543
|
+
repaired=$((repaired + 1))
|
|
544
|
+
elif [[ -e "$expected_link" ]]; then
|
|
545
|
+
# Something exists but isn't a symlink — skip unless --force
|
|
546
|
+
if [[ "$FORCE" == "true" ]]; then
|
|
547
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
548
|
+
echo " would replace: $expected_link with symlink -> $expected_source"
|
|
549
|
+
else
|
|
550
|
+
rm -rf "$expected_link"
|
|
551
|
+
create_symlink "$expected_source" "$expected_link" "false"
|
|
552
|
+
info "Repaired: replaced $expected_link with symlink -> $expected_source"
|
|
553
|
+
fi
|
|
554
|
+
repaired=$((repaired + 1))
|
|
555
|
+
else
|
|
556
|
+
warn "$expected_link exists but is not a symlink (use --force to replace)"
|
|
557
|
+
fi
|
|
558
|
+
else
|
|
559
|
+
# Missing entirely
|
|
560
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
561
|
+
echo " would create: $expected_link -> $expected_source"
|
|
562
|
+
else
|
|
563
|
+
create_symlink "$expected_source" "$expected_link" "false"
|
|
564
|
+
fi
|
|
565
|
+
repaired=$((repaired + 1))
|
|
566
|
+
fi
|
|
567
|
+
done
|
|
568
|
+
done
|
|
569
|
+
|
|
570
|
+
# Repair CLAUDE.md symlink
|
|
571
|
+
if [[ -f "$PROJECT_ROOT/$AGENTS_MD" ]]; then
|
|
572
|
+
if [[ -L "$PROJECT_ROOT/CLAUDE.md" ]]; then
|
|
573
|
+
local current_target
|
|
574
|
+
current_target="$(readlink "$PROJECT_ROOT/CLAUDE.md")"
|
|
575
|
+
if [[ "$current_target" != "$AGENTS_MD" ]]; then
|
|
576
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
577
|
+
echo " would relink: CLAUDE.md -> $AGENTS_MD (was $current_target)"
|
|
578
|
+
else
|
|
579
|
+
rm "$PROJECT_ROOT/CLAUDE.md"
|
|
580
|
+
create_symlink "$AGENTS_MD" "$PROJECT_ROOT/CLAUDE.md" "false"
|
|
581
|
+
fi
|
|
582
|
+
repaired=$((repaired + 1))
|
|
583
|
+
fi
|
|
584
|
+
elif [[ ! -e "$PROJECT_ROOT/CLAUDE.md" ]]; then
|
|
585
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
586
|
+
echo " would create: CLAUDE.md -> $AGENTS_MD"
|
|
587
|
+
else
|
|
588
|
+
create_symlink "$AGENTS_MD" "$PROJECT_ROOT/CLAUDE.md" "false"
|
|
589
|
+
fi
|
|
590
|
+
repaired=$((repaired + 1))
|
|
591
|
+
fi
|
|
592
|
+
fi
|
|
593
|
+
|
|
594
|
+
# Summary
|
|
595
|
+
if [[ "$fixed" -eq 0 ]] && [[ "$skipped" -eq 0 ]] && [[ "$repaired" -eq 0 ]]; then
|
|
596
|
+
info "Nothing to fix — all directories and symlinks are correct."
|
|
395
597
|
else
|
|
396
|
-
info "Fixed $fixed item(s).
|
|
598
|
+
if [[ "$fixed" -gt 0 ]]; then info "Fixed $fixed item(s)."; fi
|
|
599
|
+
if [[ "$merged" -gt 0 ]]; then info "Merged $merged item(s) (legacy overwrote existing)."; fi
|
|
600
|
+
if [[ "$skipped" -gt 0 ]]; then warn "Skipped $skipped item(s) (use without --no-clobber to merge)."; fi
|
|
601
|
+
if [[ "$repaired" -gt 0 ]]; then info "Repaired $repaired symlink(s)."; fi
|
|
602
|
+
if [[ "$fixed" -gt 0 ]]; then info "Run 'sync-agents sync' to update agent target symlinks."; fi
|
|
397
603
|
fi
|
|
398
604
|
}
|
|
399
605
|
|
|
@@ -1257,6 +1463,10 @@ main() {
|
|
|
1257
1463
|
inherit)
|
|
1258
1464
|
cmd_inherit "$@"
|
|
1259
1465
|
;;
|
|
1466
|
+
version)
|
|
1467
|
+
echo "sync-agents v${VERSION}"
|
|
1468
|
+
exit 0
|
|
1469
|
+
;;
|
|
1260
1470
|
"")
|
|
1261
1471
|
usage
|
|
1262
1472
|
exit 0
|