aidevops 3.13.95 → 3.14.1

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.
@@ -1,697 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
3
- # SPDX-FileCopyrightText: 2025-2026 Marcus Quinn
4
- # =============================================================================
5
- # aidevops Skills and Plugin Library
6
- # =============================================================================
7
- # Skill and plugin management functions extracted from aidevops.sh to keep
8
- # the orchestrator under the 2000-line file-size threshold.
9
- #
10
- # Covers:
11
- # 1. Skills: _skill_help, _skill_add_usage, cmd_skill, cmd_skills
12
- # 2. Plugins: _plugin_validate_ns, _plugin_field, _plugin_add, _plugin_list,
13
- # _plugin_update, _plugin_toggle, _plugin_remove, _plugin_scaffold,
14
- # _plugin_help, cmd_plugin
15
- #
16
- # Usage: source "${SCRIPT_DIR}/aidevops-skills-plugin-lib.sh"
17
- #
18
- # Dependencies:
19
- # - INSTALL_DIR, AGENTS_DIR, CONFIG_DIR (set by aidevops.sh)
20
- # - print_* helpers and utility functions (defined in aidevops.sh before sourcing)
21
- #
22
- # Part of aidevops framework: https://aidevops.sh
23
-
24
- # Apply strict mode only when executed directly (not when sourced)
25
- [[ "${BASH_SOURCE[0]}" == "${0}" ]] && set -euo pipefail
26
-
27
- # Include guard
28
- [[ -n "${_AIDEVOPS_SKILLS_PLUGIN_LIB_LOADED:-}" ]] && return 0
29
- _AIDEVOPS_SKILLS_PLUGIN_LIB_LOADED=1
30
-
31
- # Skill help text (extracted for complexity reduction)
32
- _skill_help() {
33
- print_header "Agent Skills Management"
34
- echo ""
35
- echo "Import and manage reusable AI agent skills from the community."
36
- echo "Skills are converted to aidevops format with upstream tracking."
37
- echo "Telemetry is disabled - no data sent to third parties."
38
- echo ""
39
- echo "Usage: aidevops skill <command> [options]"
40
- echo ""
41
- echo "Commands:"
42
- echo " add <source> Import a skill from GitHub (saved as *-skill.md)"
43
- echo " list List all imported skills"
44
- echo " check Check for upstream updates"
45
- echo " update [name] Update specific or all skills"
46
- echo " remove <name> Remove an imported skill"
47
- echo " scan [name] Security scan imported skills (Cisco Skill Scanner)"
48
- echo " status Show detailed skill status"
49
- echo " generate Generate SKILL.md stubs for cross-tool discovery"
50
- echo " clean Remove generated SKILL.md stubs"
51
- echo ""
52
- echo "Source formats:"
53
- echo " owner/repo GitHub shorthand"
54
- echo " owner/repo/path/to/skill Specific skill in multi-skill repo"
55
- echo " https://github.com/owner/repo Full URL"
56
- echo ""
57
- echo "Examples:"
58
- echo " aidevops skill add vercel-labs/agent-skills"
59
- echo " aidevops skill add anthropics/skills/pdf"
60
- echo " aidevops skill add expo/skills --name expo-dev"
61
- echo " aidevops skill check"
62
- echo " aidevops skill update"
63
- echo " aidevops skill scan"
64
- echo " aidevops skill scan cloudflare-platform"
65
- echo " aidevops skill generate --dry-run"
66
- echo ""
67
- echo "Imported skills are saved with a -skill suffix to distinguish"
68
- echo "from native aidevops subagents (e.g., playwright-skill.md vs playwright.md)."
69
- echo ""
70
- echo "Browse community skills: https://skills.sh"
71
- echo "Agent Skills specification: https://agentskills.io"
72
- return 0
73
- }
74
-
75
- _skill_add_usage() {
76
- print_error "Source required (owner/repo or URL)"
77
- echo ""
78
- echo "Usage: aidevops skill add <source> [options]"
79
- echo ""
80
- echo "Examples:"
81
- echo " aidevops skill add vercel-labs/agent-skills"
82
- echo " aidevops skill add anthropics/skills/pdf"
83
- echo " aidevops skill add https://github.com/owner/repo"
84
- echo ""
85
- echo "Options:"
86
- echo " --name <name> Override the skill name"
87
- echo " --force Overwrite existing skill"
88
- echo " --dry-run Preview without making changes"
89
- echo ""
90
- echo "Browse skills: https://skills.sh"
91
- return 0
92
- }
93
-
94
- # Skill management command
95
- cmd_skill() {
96
- local action="${1:-help}"
97
- shift || true
98
- export DISABLE_TELEMETRY=1 DO_NOT_TRACK=1 SKILLS_NO_TELEMETRY=1
99
- local add_skill_script="$AGENTS_DIR/scripts/add-skill-helper.sh"
100
- local update_skill_script="$AGENTS_DIR/scripts/skill-update-helper.sh"
101
- case "$action" in
102
- add | a)
103
- if [[ $# -lt 1 ]]; then
104
- _skill_add_usage
105
- return 1
106
- fi
107
- [[ ! -f "$add_skill_script" ]] && {
108
- print_error "add-skill-helper.sh not found"
109
- print_info "Run 'aidevops update' to get the latest scripts"
110
- return 1
111
- }
112
- bash "$add_skill_script" add "$@"
113
- ;;
114
- list | ls | l)
115
- [[ ! -f "$add_skill_script" ]] && {
116
- print_error "add-skill-helper.sh not found"
117
- return 1
118
- }
119
- bash "$add_skill_script" list
120
- ;;
121
- check | c)
122
- [[ ! -f "$update_skill_script" ]] && {
123
- print_error "skill-update-helper.sh not found"
124
- return 1
125
- }
126
- bash "$update_skill_script" check "$@"
127
- ;;
128
- update | u)
129
- [[ ! -f "$update_skill_script" ]] && {
130
- print_error "skill-update-helper.sh not found"
131
- return 1
132
- }
133
- bash "$update_skill_script" update "$@"
134
- ;;
135
- remove | rm)
136
- [[ $# -lt 1 ]] && {
137
- print_error "Skill name required"
138
- echo "Usage: aidevops skill remove <name>"
139
- return 1
140
- }
141
- [[ ! -f "$add_skill_script" ]] && {
142
- print_error "add-skill-helper.sh not found"
143
- return 1
144
- }
145
- bash "$add_skill_script" remove "$@"
146
- ;;
147
- status | s)
148
- [[ ! -f "$update_skill_script" ]] && {
149
- print_error "skill-update-helper.sh not found"
150
- return 1
151
- }
152
- bash "$update_skill_script" status "$@"
153
- ;;
154
- generate | gen | g)
155
- local gs="$AGENTS_DIR/scripts/generate-skills.sh"
156
- [[ ! -f "$gs" ]] && {
157
- print_error "generate-skills.sh not found"
158
- print_info "Run 'aidevops update' to get the latest scripts"
159
- return 1
160
- }
161
- print_info "Generating SKILL.md stubs for cross-tool discovery..."
162
- bash "$gs" "$@"
163
- ;;
164
- scan)
165
- local ss="$AGENTS_DIR/scripts/security-helper.sh"
166
- [[ ! -f "$ss" ]] && {
167
- print_error "security-helper.sh not found"
168
- print_info "Run 'aidevops update' to get the latest scripts"
169
- return 1
170
- }
171
- bash "$ss" skill-scan "$@"
172
- ;;
173
- clean)
174
- local gs="$AGENTS_DIR/scripts/generate-skills.sh"
175
- [[ ! -f "$gs" ]] && {
176
- print_error "generate-skills.sh not found"
177
- return 1
178
- }
179
- bash "$gs" --clean "$@"
180
- ;;
181
- help | --help | -h) _skill_help ;;
182
- *)
183
- print_error "Unknown skill command: $action"
184
- echo "Run 'aidevops skill help' for usage information."
185
- return 1
186
- ;;
187
- esac
188
- }
189
-
190
- # Plugin management helpers (extracted for complexity reduction)
191
- _PLUGIN_RESERVED="custom draft scripts tools services workflows templates memory plugins seo wordpress aidevops"
192
-
193
- _plugin_validate_ns() {
194
- local ns="$1"
195
- if [[ ! "$ns" =~ ^[a-z][a-z0-9-]*$ ]]; then
196
- print_error "Invalid namespace '$ns': must be lowercase alphanumeric with hyphens, starting with a letter"
197
- return 1
198
- fi
199
- local r
200
- for r in $_PLUGIN_RESERVED; do [[ "$ns" == "$r" ]] && {
201
- print_error "Namespace '$ns' is reserved."
202
- return 1
203
- }; done
204
- return 0
205
- }
206
-
207
- _plugin_field() {
208
- local pf="$1" n="$2" f="$3"
209
- jq -r --arg n "$n" --arg f "$f" '.plugins[] | select(.name == $n) | .[$f] // empty' "$pf" 2>/dev/null || echo ""
210
- return 0
211
- }
212
-
213
- _plugin_regenerate_discovery_index() {
214
- local ad="$1"
215
- local runtime_generator="$ad/scripts/generate-runtime-config.sh"
216
- local index_helper="$ad/scripts/subagent-index-helper.sh"
217
-
218
- if [[ -x "$runtime_generator" ]]; then
219
- if bash "$runtime_generator" all >/dev/null 2>&1; then
220
- print_success "Runtime config and subagent index regenerated"
221
- return 0
222
- fi
223
- print_warning "Runtime config regeneration encountered issues; trying subagent index only"
224
- fi
225
-
226
- if [[ -x "$index_helper" ]]; then
227
- if bash "$index_helper" generate >/dev/null 2>&1; then
228
- print_success "Subagent index regenerated"
229
- return 0
230
- fi
231
- print_warning "Subagent index regeneration encountered issues"
232
- return 1
233
- fi
234
-
235
- print_warning "Subagent index helper not found; run 'aidevops update' to regenerate discovery"
236
- return 1
237
- }
238
-
239
- _plugin_add() {
240
- local pf="$1" ad="$2"
241
- shift 2
242
- if [[ $# -lt 1 ]]; then
243
- print_error "Repository URL required"
244
- echo ""
245
- echo "Usage: aidevops plugin add <repo-url> [options]"
246
- echo ""
247
- echo "Options:"
248
- echo " --namespace <name> Namespace directory (default: derived from repo name)"
249
- echo " --branch <branch> Branch to track (default: main)"
250
- echo " --name <name> Human-readable name (default: derived from repo)"
251
- echo ""
252
- echo "Examples:"
253
- echo " aidevops plugin add https://github.com/marcusquinn/aidevops-pro.git --namespace pro"
254
- echo " aidevops plugin add https://github.com/marcusquinn/aidevops-anon.git --namespace anon"
255
- return 1
256
- fi
257
- local repo_url="$1"
258
- shift
259
- local namespace="" branch="main" plugin_name=""
260
- while [[ $# -gt 0 ]]; do
261
- local _opt="$1" _val="${2:-}"
262
- case "$_opt" in
263
- --namespace | --ns)
264
- namespace="$_val"
265
- shift 2
266
- ;;
267
- --branch | -b)
268
- branch="$_val"
269
- shift 2
270
- ;;
271
- --name | -n)
272
- plugin_name="$_val"
273
- shift 2
274
- ;;
275
- *)
276
- print_error "Unknown option: $_opt"
277
- return 1
278
- ;;
279
- esac
280
- done
281
- [[ -z "$namespace" ]] && {
282
- namespace=$(basename "$repo_url" .git | sed 's/^aidevops-//')
283
- namespace=$(echo "$namespace" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g')
284
- }
285
- [[ -z "$plugin_name" ]] && plugin_name="$namespace"
286
- _plugin_validate_ns "$namespace" || return 1
287
- local existing
288
- existing=$(jq -r --arg n "$plugin_name" '.plugins[] | select(.name == $n) | .name' "$pf" 2>/dev/null || echo "")
289
- [[ -n "$existing" ]] && {
290
- print_error "Plugin '$plugin_name' already exists. Use 'aidevops plugin update $plugin_name' to update."
291
- return 1
292
- }
293
- if [[ -d "$ad/$namespace" ]]; then
294
- local ns_owner
295
- ns_owner=$(jq -r --arg ns "$namespace" '.plugins[] | select(.namespace == $ns) | .name' "$pf" 2>/dev/null || echo "")
296
- [[ -n "$ns_owner" ]] && print_error "Namespace '$namespace' is already used by plugin '$ns_owner'" || {
297
- print_error "Directory '$ad/$namespace/' already exists"
298
- echo " Choose a different namespace with --namespace <name>"
299
- }
300
- return 1
301
- fi
302
- print_info "Adding plugin '$plugin_name' from $repo_url..."
303
- print_info " Namespace: $namespace"
304
- print_info " Branch: $branch"
305
- local clone_dir="$ad/$namespace"
306
- if ! git clone --branch "$branch" --depth 1 "$repo_url" "$clone_dir" 2>&1; then
307
- print_error "Failed to clone repository"
308
- rm -rf "$clone_dir" 2>/dev/null || true
309
- return 1
310
- fi
311
- rm -rf "$clone_dir/.git"
312
- local tmp="${pf}.tmp"
313
- jq --arg name "$plugin_name" --arg repo "$repo_url" --arg branch "$branch" --arg ns "$namespace" \
314
- '.plugins += [{"name": $name, "repo": $repo, "branch": $branch, "namespace": $ns, "enabled": true}]' "$pf" >"$tmp" && mv "$tmp" "$pf"
315
- local loader="$ad/scripts/plugin-loader-helper.sh"
316
- [[ -f "$loader" ]] && bash "$loader" hooks "$namespace" init 2>/dev/null || true
317
- _plugin_regenerate_discovery_index "$ad" || true
318
- print_success "Plugin '$plugin_name' installed to $clone_dir"
319
- echo ""
320
- echo " Agents available at: ~/.aidevops/agents/$namespace/"
321
- echo " Update: aidevops plugin update $plugin_name"
322
- echo " Remove: aidevops plugin remove $plugin_name"
323
- return 0
324
- }
325
-
326
- _plugin_list() {
327
- local pf="$1"
328
- local count
329
- count=$(jq '.plugins | length' "$pf" 2>/dev/null || echo "0")
330
- if [[ "$count" == "0" ]]; then
331
- echo "No plugins installed."
332
- echo ""
333
- echo "Add a plugin: aidevops plugin add <repo-url> --namespace <name>"
334
- return 0
335
- fi
336
- echo "Installed plugins ($count):"
337
- echo ""
338
- printf " %-15s %-10s %-8s %s\n" "NAME" "NAMESPACE" "ENABLED" "REPO"
339
- printf " %-15s %-10s %-8s %s\n" "----" "---------" "-------" "----"
340
- jq -r '.plugins[] | " \(.name)\t\(.namespace)\t\(.enabled // true)\t\(.repo)"' "$pf" 2>/dev/null |
341
- while IFS=$'\t' read -r name ns enabled repo; do
342
- local si="yes"
343
- [[ "$enabled" == "false" ]] && si="no"
344
- printf " %-15s %-10s %-8s %s\n" "$name" "$ns" "$si" "$repo"
345
- done
346
- return 0
347
- }
348
-
349
- _plugin_update() {
350
- local pf="$1" ad="$2" target="${3:-}"
351
- if [[ -n "$target" ]]; then
352
- local repo ns bn
353
- repo=$(_plugin_field "$pf" "$target" "repo")
354
- ns=$(_plugin_field "$pf" "$target" "namespace")
355
- bn=$(_plugin_field "$pf" "$target" "branch")
356
- bn="${bn:-main}"
357
- [[ -z "$repo" ]] && {
358
- print_error "Plugin '$target' not found"
359
- return 1
360
- }
361
- print_info "Updating plugin '$target'..."
362
- local cd2="$ad/$ns"
363
- rm -rf "$cd2"
364
- if git clone --branch "$bn" --depth 1 "$repo" "$cd2" 2>&1; then
365
- rm -rf "$cd2/.git"
366
- print_success "Plugin '$target' updated"
367
- _plugin_regenerate_discovery_index "$ad" || true
368
- else
369
- print_error "Failed to update plugin '$target'"
370
- return 1
371
- fi
372
- else
373
- local names
374
- names=$(jq -r '.plugins[] | select(.enabled != false) | .name' "$pf" 2>/dev/null || echo "")
375
- [[ -z "$names" ]] && {
376
- echo "No enabled plugins to update."
377
- return 0
378
- }
379
- local failed=0
380
- while IFS= read -r pn; do
381
- [[ -z "$pn" ]] && continue
382
- local pr pns pb
383
- pr=$(_plugin_field "$pf" "$pn" "repo")
384
- pns=$(_plugin_field "$pf" "$pn" "namespace")
385
- pb=$(_plugin_field "$pf" "$pn" "branch")
386
- pb="${pb:-main}"
387
- print_info "Updating '$pn'..."
388
- local pd="$ad/$pns"
389
- rm -rf "$pd"
390
- if git clone --branch "$pb" --depth 1 "$pr" "$pd" 2>/dev/null; then
391
- rm -rf "$pd/.git"
392
- print_success " '$pn' updated"
393
- else
394
- print_error " '$pn' failed to update"
395
- failed=$((failed + 1))
396
- fi
397
- done <<<"$names"
398
- [[ "$failed" -gt 0 ]] && {
399
- print_warning "$failed plugin(s) failed to update"
400
- return 1
401
- }
402
- print_success "All plugins updated"
403
- _plugin_regenerate_discovery_index "$ad" || true
404
- fi
405
- return 0
406
- }
407
-
408
- _plugin_toggle() {
409
- local pf="$1" ad="$2" tn="$3" action="$4"
410
- if [[ "$action" == "enable" ]]; then
411
- local tr
412
- tr=$(_plugin_field "$pf" "$tn" "repo")
413
- [[ -z "$tr" ]] && {
414
- print_error "Plugin '$tn' not found"
415
- return 1
416
- }
417
- local tns
418
- tns=$(_plugin_field "$pf" "$tn" "namespace")
419
- local tb
420
- tb=$(_plugin_field "$pf" "$tn" "branch")
421
- tb="${tb:-main}"
422
- local tmp="${pf}.tmp"
423
- jq --arg n "$tn" '(.plugins[] | select(.name == $n)).enabled = true' "$pf" >"$tmp" && mv "$tmp" "$pf"
424
- [[ ! -d "$ad/$tns" ]] && {
425
- print_info "Deploying plugin '$tn'..."
426
- git clone --branch "$tb" --depth 1 "$tr" "$ad/$tns" 2>/dev/null && rm -rf "$ad/$tns/.git"
427
- }
428
- local loader="$ad/scripts/plugin-loader-helper.sh"
429
- [[ -f "$loader" ]] && bash "$loader" hooks "$tns" init 2>/dev/null || true
430
- _plugin_regenerate_discovery_index "$ad" || true
431
- print_success "Plugin '$tn' enabled"
432
- else
433
- local tns
434
- tns=$(_plugin_field "$pf" "$tn" "namespace")
435
- [[ -z "$tns" ]] && {
436
- print_error "Plugin '$tn' not found"
437
- return 1
438
- }
439
- local loader="$ad/scripts/plugin-loader-helper.sh"
440
- [[ -f "$loader" && -d "$ad/$tns" ]] && bash "$loader" hooks "$tns" unload 2>/dev/null || true
441
- local tmp="${pf}.tmp"
442
- jq --arg n "$tn" '(.plugins[] | select(.name == $n)).enabled = false' "$pf" >"$tmp" && mv "$tmp" "$pf"
443
- [[ -d "$ad/${tns:?}" ]] && rm -rf "$ad/${tns:?}"
444
- _plugin_regenerate_discovery_index "$ad" || true
445
- print_success "Plugin '$tn' disabled (config preserved)"
446
- fi
447
- return 0
448
- }
449
-
450
- _plugin_remove() {
451
- local pf="$1" ad="$2" tn="$3"
452
- local tns
453
- tns=$(_plugin_field "$pf" "$tn" "namespace")
454
- [[ -z "$tns" ]] && {
455
- print_error "Plugin '$tn' not found"
456
- return 1
457
- }
458
- local loader="$ad/scripts/plugin-loader-helper.sh"
459
- [[ -f "$loader" && -d "$ad/$tns" ]] && bash "$loader" hooks "$tns" unload 2>/dev/null || true
460
- [[ -d "$ad/${tns:?}" ]] && {
461
- rm -rf "$ad/${tns:?}"
462
- print_info "Removed $ad/$tns/"
463
- }
464
- local tmp="${pf}.tmp"
465
- jq --arg n "$tn" '.plugins = [.plugins[] | select(.name != $n)]' "$pf" >"$tmp" && mv "$tmp" "$pf"
466
- print_success "Plugin '$tn' removed"
467
- return 0
468
- }
469
-
470
- _plugin_scaffold() {
471
- local ad="$1" td="${2:-.}" pn="${3:-my-plugin}"
472
- local ns="${4:-$pn}"
473
- if [[ "$td" != "." && -d "$td" ]]; then
474
- local ec
475
- ec=$(find "$td" -maxdepth 1 -type f | wc -l | tr -d ' ')
476
- [[ "$ec" -gt 0 ]] && {
477
- print_error "Directory '$td' already has files. Use an empty directory."
478
- return 1
479
- }
480
- fi
481
- mkdir -p "$td"
482
- local tpl="$ad/templates/plugin-template"
483
- [[ ! -d "$tpl" ]] && {
484
- print_error "Plugin template not found at $tpl"
485
- print_info "Run 'aidevops update' to get the latest templates."
486
- return 1
487
- }
488
- local pnu
489
- pnu=$(echo "$pn" | tr '[:lower:]' '[:upper:]' | tr '-' '_')
490
- sed -e "s|{{PLUGIN_NAME}}|$pn|g" -e "s|{{PLUGIN_NAME_UPPER}}|$pnu|g" -e "s|{{NAMESPACE}}|$ns|g" -e "s|{{REPO_URL}}|https://github.com/user/aidevops-$ns.git|g" "$tpl/AGENTS.md" >"$td/AGENTS.md"
491
- sed -e "s|{{PLUGIN_NAME}}|$pn|g" -e "s|{{PLUGIN_DESCRIPTION}}|$pn plugin for aidevops|g" -e "s|{{NAMESPACE}}|$ns|g" "$tpl/main-agent.md" >"$td/$ns.md"
492
- mkdir -p "$td/$ns"
493
- sed -e "s|{{PLUGIN_NAME}}|$pn|g" -e "s|{{NAMESPACE}}|$ns|g" "$tpl/example-subagent.md" >"$td/$ns/example.md"
494
- mkdir -p "$td/scripts"
495
- if [[ -d "$tpl/scripts" ]]; then
496
- for hf in "$tpl/scripts"/on-*.sh; do
497
- [[ -f "$hf" ]] || continue
498
- local hb
499
- hb=$(basename "$hf")
500
- sed -e "s|{{PLUGIN_NAME}}|$pn|g" -e "s|{{NAMESPACE}}|$ns|g" "$hf" >"$td/scripts/$hb"
501
- chmod +x "$td/scripts/$hb"
502
- done
503
- fi
504
- [[ -f "$tpl/plugin.json" ]] && sed -e "s|{{PLUGIN_NAME}}|$pn|g" -e "s|{{PLUGIN_DESCRIPTION}}|$pn plugin for aidevops|g" -e "s|{{NAMESPACE}}|$ns|g" "$tpl/plugin.json" >"$td/plugin.json"
505
- print_success "Plugin scaffolded in $td/"
506
- echo ""
507
- echo "Structure:"
508
- echo " $td/"
509
- echo " ├── AGENTS.md # Plugin documentation"
510
- echo " ├── plugin.json # Plugin manifest"
511
- echo " ├── $ns.md # Main agent"
512
- echo " ├── $ns/"
513
- echo " │ └── example.md # Example subagent"
514
- echo " └── scripts/"
515
- echo " ├── on-init.sh # Init lifecycle hook"
516
- echo " ├── on-load.sh # Load lifecycle hook"
517
- echo " └── on-unload.sh # Unload lifecycle hook"
518
- echo ""
519
- echo "Next steps:"
520
- echo " 1. Edit plugin.json with your plugin metadata"
521
- echo " 2. Edit $ns.md with your agent instructions"
522
- echo " 3. Add subagents to $ns/"
523
- echo " 4. Push to a git repo"
524
- echo " 5. Install: aidevops plugin add <repo-url> --namespace $ns"
525
- return 0
526
- }
527
-
528
- _plugin_help() {
529
- print_header "Plugin Management"
530
- echo ""
531
- echo "Manage third-party agent plugins that extend aidevops."
532
- echo "Plugins deploy to ~/.aidevops/agents/<namespace>/ (isolated from core)."
533
- echo ""
534
- echo "Usage: aidevops plugin <command> [options]"
535
- echo ""
536
- echo "Commands:"
537
- echo " add <repo-url> Install a plugin from a git repository"
538
- echo " list List installed plugins"
539
- echo " update [name] Update specific or all plugins"
540
- echo " enable <name> Enable a disabled plugin (redeploys files)"
541
- echo " disable <name> Disable a plugin (removes files, keeps config)"
542
- echo " remove <name> Remove a plugin entirely"
543
- echo " init [dir] [name] [namespace] Scaffold a new plugin from template"
544
- echo ""
545
- echo "Options for 'add':"
546
- echo " --namespace <name> Directory name under ~/.aidevops/agents/"
547
- echo " --branch <branch> Branch to track (default: main)"
548
- echo " --name <name> Human-readable plugin name"
549
- echo ""
550
- echo "Examples:"
551
- echo " aidevops plugin add https://github.com/marcusquinn/aidevops-pro.git --namespace pro"
552
- echo " aidevops plugin add https://github.com/marcusquinn/aidevops-anon.git --namespace anon"
553
- echo " aidevops plugin list"
554
- echo " aidevops plugin update"
555
- echo " aidevops plugin update pro"
556
- echo " aidevops plugin disable pro"
557
- echo " aidevops plugin enable pro"
558
- echo " aidevops plugin remove pro"
559
- echo " aidevops plugin init ./my-plugin my-plugin my-plugin"
560
- echo ""
561
- echo "Plugin docs: ~/.aidevops/agents/aidevops/plugins.md"
562
- return 0
563
- }
564
-
565
- # Plugin management command
566
- cmd_plugin() {
567
- local action="${1:-help}"
568
- shift || true
569
- local pf="$CONFIG_DIR/plugins.json" ad="$AGENTS_DIR"
570
- mkdir -p "$CONFIG_DIR"
571
- [[ ! -f "$pf" ]] && echo '{"plugins":[]}' >"$pf"
572
- case "$action" in
573
- add | a) _plugin_add "$pf" "$ad" "$@" ;;
574
- list | ls | l) _plugin_list "$pf" ;;
575
- update | u) _plugin_update "$pf" "$ad" "$@" ;;
576
- enable)
577
- [[ $# -lt 1 ]] && {
578
- print_error "Plugin name required"
579
- echo "Usage: aidevops plugin enable <name>"
580
- return 1
581
- }
582
- local _enable_name="$1"
583
- _plugin_toggle "$pf" "$ad" "$_enable_name" enable
584
- ;;
585
- disable)
586
- [[ $# -lt 1 ]] && {
587
- print_error "Plugin name required"
588
- echo "Usage: aidevops plugin disable <name>"
589
- return 1
590
- }
591
- local _disable_name="$1"
592
- _plugin_toggle "$pf" "$ad" "$_disable_name" disable
593
- ;;
594
- remove | rm)
595
- [[ $# -lt 1 ]] && {
596
- print_error "Plugin name required"
597
- echo "Usage: aidevops plugin remove <name>"
598
- return 1
599
- }
600
- local _remove_name="$1"
601
- _plugin_remove "$pf" "$ad" "$_remove_name"
602
- ;;
603
- init) _plugin_scaffold "$ad" "$@" ;;
604
- help | --help | -h) _plugin_help ;;
605
- *)
606
- print_error "Unknown plugin command: $action"
607
- echo "Run 'aidevops plugin help' for usage information."
608
- return 1
609
- ;;
610
- esac
611
- return 0
612
- }
613
-
614
- # Skills discovery command - search, browse, describe installed skills
615
- cmd_skills() {
616
- local action="${1:-help}"
617
- shift || true
618
-
619
- local skills_helper="$AGENTS_DIR/scripts/skills-helper.sh"
620
-
621
- if [[ ! -f "$skills_helper" ]]; then
622
- print_error "skills-helper.sh not found"
623
- print_info "Run 'aidevops update' to get the latest scripts"
624
- return 1
625
- fi
626
-
627
- case "$action" in
628
- search | s | find | f)
629
- bash "$skills_helper" search "$@"
630
- ;;
631
- browse | b)
632
- bash "$skills_helper" browse "$@"
633
- ;;
634
- describe | desc | d | show)
635
- bash "$skills_helper" describe "$@"
636
- ;;
637
- info | i | meta)
638
- bash "$skills_helper" info "$@"
639
- ;;
640
- list | ls | l)
641
- bash "$skills_helper" list "$@"
642
- ;;
643
- categories | cats | cat)
644
- bash "$skills_helper" categories "$@"
645
- ;;
646
- recommend | rec | suggest)
647
- bash "$skills_helper" recommend "$@"
648
- ;;
649
- install | add)
650
- bash "$skills_helper" install "$@"
651
- ;;
652
- registry | online)
653
- bash "$skills_helper" registry "$@"
654
- ;;
655
- help | --help | -h)
656
- print_header "Skill Discovery & Exploration"
657
- echo ""
658
- echo "Discover, explore, and get recommendations for installed skills."
659
- echo "For importing/managing skills, use: aidevops skill <cmd>"
660
- echo ""
661
- echo "Usage: aidevops skills <command> [options]"
662
- echo ""
663
- echo "Commands:"
664
- echo " search <query> Search installed skills by keyword"
665
- echo " search --registry <q> Search the public skills.sh registry (online)"
666
- echo " browse [category] Browse skills by category"
667
- echo " describe <name> Show detailed skill description"
668
- echo " info <name> Show skill metadata (path, source, model tier)"
669
- echo " list [filter] List skills (--imported, --native, --all)"
670
- echo " categories List all categories with skill counts"
671
- echo " recommend <task> Suggest skills for a task description"
672
- echo " install <owner/repo@s> Install a skill from the public registry"
673
- echo ""
674
- echo "Options:"
675
- echo " --json Output in JSON format (for scripting)"
676
- echo " --registry, --online Search the public skills.sh registry"
677
- echo ""
678
- echo "Examples:"
679
- echo " aidevops skills search \"browser automation\""
680
- echo " aidevops skills search --registry \"seo\""
681
- echo " aidevops skills browse tools"
682
- echo " aidevops skills browse tools/browser"
683
- echo " aidevops skills describe playwright"
684
- echo " aidevops skills info seo-audit-skill"
685
- echo " aidevops skills list --imported"
686
- echo " aidevops skills categories"
687
- echo " aidevops skills recommend \"deploy a Next.js app\""
688
- echo " aidevops skills install vercel-labs/agent-browser@agent-browser"
689
- echo ""
690
- echo "See also: aidevops skill help (import/manage skills)"
691
- ;;
692
- *)
693
- # Treat unknown action as a search query
694
- bash "$skills_helper" search "$action $*"
695
- ;;
696
- esac
697
- }