monol-plugin-scout 2.1.3 → 4.1.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.
Files changed (87) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +244 -0
  3. package/monol-plugin-scout-pkg/CLAUDE.md +125 -8
  4. package/monol-plugin-scout-pkg/api/mock/categories.json +81 -0
  5. package/monol-plugin-scout-pkg/api/mock/insights.json +111 -0
  6. package/monol-plugin-scout-pkg/api/mock/marketplace.json +501 -0
  7. package/monol-plugin-scout-pkg/api/mock/trending.json +96 -0
  8. package/monol-plugin-scout-pkg/commands/console.md +79 -0
  9. package/monol-plugin-scout-pkg/commands/frequency.md +32 -0
  10. package/monol-plugin-scout-pkg/commands/install.md +32 -0
  11. package/monol-plugin-scout-pkg/commands/priority.md +30 -0
  12. package/monol-plugin-scout-pkg/commands/quiet.md +32 -0
  13. package/monol-plugin-scout-pkg/commands/schedule.md +32 -0
  14. package/monol-plugin-scout-pkg/commands/scout.md +8 -5
  15. package/monol-plugin-scout-pkg/commands/skills.md +160 -0
  16. package/monol-plugin-scout-pkg/commands/team.md +32 -0
  17. package/monol-plugin-scout-pkg/commands/timing.md +32 -0
  18. package/monol-plugin-scout-pkg/commands/trust.md +85 -0
  19. package/monol-plugin-scout-pkg/commands/trusted-install.md +98 -0
  20. package/monol-plugin-scout-pkg/commands/uninstall.md +31 -0
  21. package/monol-plugin-scout-pkg/config.yaml +57 -0
  22. package/monol-plugin-scout-pkg/data/.cache/676d5ab664292155e5f509c69d4edae1 +10 -0
  23. package/monol-plugin-scout-pkg/data/.session +8 -0
  24. package/monol-plugin-scout-pkg/data/analytics.json +102 -0
  25. package/monol-plugin-scout-pkg/data/history.json +67 -11
  26. package/monol-plugin-scout-pkg/data/logs/scout.log +1 -0
  27. package/monol-plugin-scout-pkg/data/schedules.json +17 -0
  28. package/monol-plugin-scout-pkg/data/team.json +53 -0
  29. package/monol-plugin-scout-pkg/data/usage.json +100 -7
  30. package/monol-plugin-scout-pkg/docs/ARCHITECTURE.md +201 -0
  31. package/monol-plugin-scout-pkg/hooks/generate-insights.sh +102 -0
  32. package/monol-plugin-scout-pkg/hooks/hooks.json +36 -1
  33. package/monol-plugin-scout-pkg/hooks/on-session-end.sh +136 -0
  34. package/monol-plugin-scout-pkg/hooks/on-session-start.sh +43 -0
  35. package/monol-plugin-scout-pkg/hooks/on-stop.md +79 -0
  36. package/monol-plugin-scout-pkg/hooks/open-console.sh +111 -0
  37. package/monol-plugin-scout-pkg/hooks/open-dashboard.sh +61 -0
  38. package/monol-plugin-scout-pkg/hooks/track-usage.sh +59 -0
  39. package/monol-plugin-scout-pkg/lib/ai-recommender.sh +505 -0
  40. package/monol-plugin-scout-pkg/lib/cache.sh +194 -0
  41. package/monol-plugin-scout-pkg/lib/data-validator.sh +360 -0
  42. package/monol-plugin-scout-pkg/lib/error-handler.sh +296 -0
  43. package/monol-plugin-scout-pkg/lib/logger.sh +263 -0
  44. package/monol-plugin-scout-pkg/lib/plugin-manager.sh +239 -0
  45. package/monol-plugin-scout-pkg/lib/priority-scorer.sh +262 -0
  46. package/monol-plugin-scout-pkg/lib/profile-learner.sh +339 -0
  47. package/monol-plugin-scout-pkg/lib/project-analyzer.sh +281 -0
  48. package/monol-plugin-scout-pkg/lib/recommendation-controller.sh +290 -0
  49. package/monol-plugin-scout-pkg/lib/rejection-learner.sh +232 -0
  50. package/monol-plugin-scout-pkg/lib/scheduler.sh +275 -0
  51. package/monol-plugin-scout-pkg/lib/skill-scout.sh +729 -0
  52. package/monol-plugin-scout-pkg/lib/sync.sh +221 -0
  53. package/monol-plugin-scout-pkg/lib/team-learner.sh +450 -0
  54. package/monol-plugin-scout-pkg/lib/team-manager.sh +369 -0
  55. package/monol-plugin-scout-pkg/lib/trend-learner.sh +428 -0
  56. package/monol-plugin-scout-pkg/lib/trust-manager.sh +261 -0
  57. package/monol-plugin-scout-pkg/lib/trusted-installer.sh +738 -0
  58. package/monol-plugin-scout-pkg/plugin.json +3 -2
  59. package/monol-plugin-scout-pkg/skills/audit.md +6 -0
  60. package/monol-plugin-scout-pkg/skills/cleanup.md +6 -0
  61. package/monol-plugin-scout-pkg/skills/compare.md +6 -0
  62. package/monol-plugin-scout-pkg/skills/console.md +315 -0
  63. package/monol-plugin-scout-pkg/skills/explore.md +6 -0
  64. package/monol-plugin-scout-pkg/skills/fork.md +6 -0
  65. package/monol-plugin-scout-pkg/skills/frequency.md +93 -0
  66. package/monol-plugin-scout-pkg/skills/install.md +127 -0
  67. package/monol-plugin-scout-pkg/skills/priority.md +77 -0
  68. package/monol-plugin-scout-pkg/skills/quiet.md +73 -0
  69. package/monol-plugin-scout-pkg/skills/schedule.md +95 -0
  70. package/monol-plugin-scout-pkg/skills/scout.md +27 -17
  71. package/monol-plugin-scout-pkg/skills/skills.md +230 -0
  72. package/monol-plugin-scout-pkg/skills/team.md +117 -0
  73. package/monol-plugin-scout-pkg/skills/timing.md +97 -0
  74. package/monol-plugin-scout-pkg/skills/trust.md +120 -0
  75. package/monol-plugin-scout-pkg/skills/trusted-install.md +264 -0
  76. package/monol-plugin-scout-pkg/skills/uninstall.md +100 -0
  77. package/monol-plugin-scout-pkg/web/components/activity-chart.js +208 -0
  78. package/monol-plugin-scout-pkg/web/components/index.js +27 -0
  79. package/monol-plugin-scout-pkg/web/components/insight-card.js +365 -0
  80. package/monol-plugin-scout-pkg/web/components/overview.js +154 -0
  81. package/monol-plugin-scout-pkg/web/components/plugin-list.js +242 -0
  82. package/monol-plugin-scout-pkg/web/components/stats-card.js +126 -0
  83. package/monol-plugin-scout-pkg/web/components/team-list.js +346 -0
  84. package/monol-plugin-scout-pkg/web/console.html +2098 -0
  85. package/monol-plugin-scout-pkg/web/dashboard.html +2106 -0
  86. package/monol-plugin-scout-pkg/web/manifest.json +29 -0
  87. package/package.json +1 -1
@@ -0,0 +1,263 @@
1
+ #!/bin/bash
2
+ # Plugin Scout - 로깅 시스템
3
+ # 구조화된 로그 기록 및 분석
4
+
5
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$0")/..}"
6
+ DATA_DIR="$PLUGIN_ROOT/data"
7
+ LOG_DIR="$DATA_DIR/logs"
8
+ LOG_FILE="$LOG_DIR/scout.log"
9
+ LOG_LEVEL="${SCOUT_LOG_LEVEL:-INFO}" # DEBUG, INFO, WARN, ERROR
10
+
11
+ # 로그 디렉토리 생성
12
+ mkdir -p "$LOG_DIR"
13
+
14
+ # 로그 레벨 숫자 변환
15
+ get_level_num() {
16
+ case "$1" in
17
+ DEBUG) echo 0 ;;
18
+ INFO) echo 1 ;;
19
+ WARN) echo 2 ;;
20
+ ERROR) echo 3 ;;
21
+ *) echo 1 ;;
22
+ esac
23
+ }
24
+
25
+ # 현재 로그 레벨 확인
26
+ should_log() {
27
+ local msg_level="$1"
28
+ local current_level_num=$(get_level_num "$LOG_LEVEL")
29
+ local msg_level_num=$(get_level_num "$msg_level")
30
+
31
+ [ "$msg_level_num" -ge "$current_level_num" ]
32
+ }
33
+
34
+ # 로그 기록
35
+ log() {
36
+ local level="$1"
37
+ local message="$2"
38
+ local context="$3"
39
+ local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
40
+
41
+ # 로그 레벨 필터링
42
+ if ! should_log "$level"; then
43
+ return 0
44
+ fi
45
+
46
+ # 로그 포맷: [timestamp] [level] message | context
47
+ local log_line="[$timestamp] [$level] $message"
48
+ if [ -n "$context" ]; then
49
+ log_line="$log_line | $context"
50
+ fi
51
+
52
+ # 파일에 기록
53
+ echo "$log_line" >> "$LOG_FILE"
54
+
55
+ # DEBUG 모드면 stdout에도 출력
56
+ if [ "$SCOUT_DEBUG" = "true" ]; then
57
+ echo "$log_line"
58
+ fi
59
+ }
60
+
61
+ # 편의 함수들
62
+ log_debug() { log "DEBUG" "$1" "$2"; }
63
+ log_info() { log "INFO" "$1" "$2"; }
64
+ log_warn() { log "WARN" "$1" "$2"; }
65
+ log_error() { log "ERROR" "$1" "$2"; }
66
+
67
+ # 이벤트 로깅 (구조화된 JSON)
68
+ log_event() {
69
+ local event_type="$1"
70
+ local event_data="$2"
71
+ local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
72
+ local user="${USER:-unknown}"
73
+ local session_id=""
74
+
75
+ # 세션 ID 가져오기
76
+ if [ -f "$DATA_DIR/.session" ] && command -v jq &> /dev/null; then
77
+ session_id=$(jq -r '.sessionId // ""' "$DATA_DIR/.session" 2>/dev/null)
78
+ fi
79
+
80
+ # JSON 이벤트 로그
81
+ local event_log="$LOG_DIR/events.jsonl"
82
+ echo "{\"timestamp\":\"$timestamp\",\"type\":\"$event_type\",\"user\":\"$user\",\"session\":\"$session_id\",\"data\":$event_data}" >> "$event_log"
83
+ }
84
+
85
+ # 로그 조회
86
+ view_logs() {
87
+ local lines="${1:-50}"
88
+ local level="${2:-}"
89
+
90
+ if [ ! -f "$LOG_FILE" ]; then
91
+ echo "No logs found"
92
+ return
93
+ fi
94
+
95
+ if [ -n "$level" ]; then
96
+ grep "\[$level\]" "$LOG_FILE" | tail -n "$lines"
97
+ else
98
+ tail -n "$lines" "$LOG_FILE"
99
+ fi
100
+ }
101
+
102
+ # 로그 검색
103
+ search_logs() {
104
+ local pattern="$1"
105
+ local lines="${2:-20}"
106
+
107
+ if [ ! -f "$LOG_FILE" ]; then
108
+ echo "No logs found"
109
+ return
110
+ fi
111
+
112
+ grep -i "$pattern" "$LOG_FILE" | tail -n "$lines"
113
+ }
114
+
115
+ # 이벤트 조회
116
+ view_events() {
117
+ local count="${1:-20}"
118
+ local event_type="$2"
119
+ local event_log="$LOG_DIR/events.jsonl"
120
+
121
+ if [ ! -f "$event_log" ]; then
122
+ echo "No events found"
123
+ return
124
+ fi
125
+
126
+ if [ -n "$event_type" ]; then
127
+ grep "\"type\":\"$event_type\"" "$event_log" | tail -n "$count" | jq -r '"\(.timestamp) [\(.type)] \(.data)"'
128
+ else
129
+ tail -n "$count" "$event_log" | jq -r '"\(.timestamp) [\(.type)] \(.data)"'
130
+ fi
131
+ }
132
+
133
+ # 로그 통계
134
+ log_stats() {
135
+ echo "=== Log Statistics ==="
136
+ echo ""
137
+
138
+ if [ -f "$LOG_FILE" ]; then
139
+ echo "Log File: $LOG_FILE"
140
+ echo "Log Level: $LOG_LEVEL"
141
+ echo ""
142
+ echo "By Level:"
143
+ for level in DEBUG INFO WARN ERROR; do
144
+ local count=$(grep -c "\[$level\]" "$LOG_FILE" 2>/dev/null || echo "0")
145
+ echo " $level: $count"
146
+ done
147
+ echo ""
148
+ echo "Total Lines: $(wc -l < "$LOG_FILE" | tr -d ' ')"
149
+ echo "File Size: $(du -h "$LOG_FILE" | cut -f1)"
150
+ else
151
+ echo "No log file found"
152
+ fi
153
+
154
+ echo ""
155
+ local event_log="$LOG_DIR/events.jsonl"
156
+ if [ -f "$event_log" ]; then
157
+ echo "Events:"
158
+ echo " Total: $(wc -l < "$event_log" | tr -d ' ')"
159
+ if command -v jq &> /dev/null; then
160
+ echo " By Type:"
161
+ jq -r '.type' "$event_log" 2>/dev/null | sort | uniq -c | sort -rn | head -5 | while read count type; do
162
+ echo " $type: $count"
163
+ done
164
+ fi
165
+ fi
166
+ }
167
+
168
+ # 로그 정리 (오래된 로그 삭제)
169
+ cleanup_logs() {
170
+ local days="${1:-30}"
171
+
172
+ echo "Cleaning logs older than $days days..."
173
+
174
+ # 메인 로그 로테이션
175
+ if [ -f "$LOG_FILE" ]; then
176
+ local cutoff_date=$(date -v-${days}d +"%Y-%m-%d" 2>/dev/null || date -d "$days days ago" +"%Y-%m-%d" 2>/dev/null)
177
+ if [ -n "$cutoff_date" ]; then
178
+ # 백업 후 정리
179
+ cp "$LOG_FILE" "$LOG_FILE.bak"
180
+ grep -E "^\[${cutoff_date}|^\[$(date +%Y-)" "$LOG_FILE.bak" > "$LOG_FILE" 2>/dev/null || true
181
+ rm -f "$LOG_FILE.bak"
182
+ echo "Main log cleaned"
183
+ fi
184
+ fi
185
+
186
+ # 이벤트 로그 정리
187
+ local event_log="$LOG_DIR/events.jsonl"
188
+ if [ -f "$event_log" ] && command -v jq &> /dev/null; then
189
+ local cutoff_ts=$(date -v-${days}d -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -d "$days days ago" -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null)
190
+ if [ -n "$cutoff_ts" ]; then
191
+ cp "$event_log" "$event_log.bak"
192
+ jq -c --arg ts "$cutoff_ts" 'select(.timestamp >= $ts)' "$event_log.bak" > "$event_log" 2>/dev/null || true
193
+ rm -f "$event_log.bak"
194
+ echo "Event log cleaned"
195
+ fi
196
+ fi
197
+
198
+ echo "Done"
199
+ }
200
+
201
+ # 로그 파일 초기화
202
+ clear_logs() {
203
+ rm -f "$LOG_FILE"
204
+ rm -f "$LOG_DIR/events.jsonl"
205
+ echo "Logs cleared"
206
+ }
207
+
208
+ # CLI 인터페이스
209
+ case "$1" in
210
+ debug)
211
+ log_debug "$2" "$3"
212
+ ;;
213
+ info)
214
+ log_info "$2" "$3"
215
+ ;;
216
+ warn)
217
+ log_warn "$2" "$3"
218
+ ;;
219
+ error)
220
+ log_error "$2" "$3"
221
+ ;;
222
+ event)
223
+ log_event "$2" "$3"
224
+ ;;
225
+ view)
226
+ view_logs "$2" "$3"
227
+ ;;
228
+ search)
229
+ search_logs "$2" "$3"
230
+ ;;
231
+ events)
232
+ view_events "$2" "$3"
233
+ ;;
234
+ stats)
235
+ log_stats
236
+ ;;
237
+ cleanup)
238
+ cleanup_logs "$2"
239
+ ;;
240
+ clear)
241
+ clear_logs
242
+ ;;
243
+ *)
244
+ echo "Usage: $0 {debug|info|warn|error|event|view|search|events|stats|cleanup|clear}"
245
+ echo ""
246
+ echo "Commands:"
247
+ echo " debug <msg> [ctx] - Log debug message"
248
+ echo " info <msg> [ctx] - Log info message"
249
+ echo " warn <msg> [ctx] - Log warning message"
250
+ echo " error <msg> [ctx] - Log error message"
251
+ echo " event <type> <json> - Log structured event"
252
+ echo " view [lines] [level] - View recent logs"
253
+ echo " search <pattern> - Search logs"
254
+ echo " events [count] [type] - View events"
255
+ echo " stats - Show log statistics"
256
+ echo " cleanup [days] - Clean old logs"
257
+ echo " clear - Clear all logs"
258
+ echo ""
259
+ echo "Environment:"
260
+ echo " SCOUT_LOG_LEVEL - Set log level (DEBUG, INFO, WARN, ERROR)"
261
+ echo " SCOUT_DEBUG - Enable debug output to stdout"
262
+ ;;
263
+ esac
@@ -0,0 +1,239 @@
1
+ #!/bin/bash
2
+ # Plugin Scout - 플러그인 매니저
3
+ # 플러그인 설치/제거/업데이트 자동화
4
+
5
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$0")/..}"
6
+ DATA_DIR="$PLUGIN_ROOT/data"
7
+ HISTORY_FILE="$DATA_DIR/history.json"
8
+ USAGE_FILE="$DATA_DIR/usage.json"
9
+
10
+ CLAUDE_SETTINGS="$HOME/.claude/settings.json"
11
+ CLAUDE_PLUGINS_DIR="$HOME/.claude/plugins"
12
+
13
+ # 플러그인 설치
14
+ install_plugin() {
15
+ local plugin_spec="$1" # format: plugin-name@marketplace or plugin-name
16
+ local source="${2:-recommendation}"
17
+
18
+ # 플러그인명과 마켓플레이스 분리
19
+ local plugin_name="${plugin_spec%@*}"
20
+ local marketplace="${plugin_spec#*@}"
21
+
22
+ if [ "$marketplace" = "$plugin_spec" ]; then
23
+ marketplace=""
24
+ fi
25
+
26
+ echo "Installing plugin: $plugin_name"
27
+
28
+ # settings.json 백업
29
+ if [ -f "$CLAUDE_SETTINGS" ]; then
30
+ cp "$CLAUDE_SETTINGS" "$CLAUDE_SETTINGS.bak"
31
+ fi
32
+
33
+ # enabledPlugins에 추가
34
+ if command -v jq &> /dev/null && [ -f "$CLAUDE_SETTINGS" ]; then
35
+ local plugin_key="$plugin_name"
36
+ if [ -n "$marketplace" ]; then
37
+ plugin_key="${plugin_name}@${marketplace}"
38
+ fi
39
+
40
+ jq --arg key "$plugin_key" '.enabledPlugins[$key] = true' "$CLAUDE_SETTINGS" > "$CLAUDE_SETTINGS.tmp" && mv "$CLAUDE_SETTINGS.tmp" "$CLAUDE_SETTINGS"
41
+
42
+ # history.json에 설치 기록
43
+ local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
44
+ local date_only=$(date +"%Y-%m-%d")
45
+
46
+ if [ -f "$HISTORY_FILE" ]; then
47
+ jq --arg plugin "$plugin_name" \
48
+ --arg date "$date_only" \
49
+ --arg source "$source" \
50
+ --arg ts "$timestamp" \
51
+ '
52
+ .lastUpdated = $ts |
53
+ .installed[$plugin] = {
54
+ date: $date,
55
+ source: $source,
56
+ installedAt: $ts
57
+ }
58
+ ' "$HISTORY_FILE" > "$HISTORY_FILE.tmp" && mv "$HISTORY_FILE.tmp" "$HISTORY_FILE"
59
+ fi
60
+
61
+ # usage.json에 추가
62
+ if [ -f "$USAGE_FILE" ]; then
63
+ jq --arg plugin "$plugin_name" \
64
+ --arg date "$date_only" \
65
+ --arg ts "$timestamp" \
66
+ '
67
+ .lastUpdated = $ts |
68
+ .plugins[$plugin] = (.plugins[$plugin] // {
69
+ installed: $date,
70
+ usageCount: 0,
71
+ lastUsed: null
72
+ })
73
+ ' "$USAGE_FILE" > "$USAGE_FILE.tmp" && mv "$USAGE_FILE.tmp" "$USAGE_FILE"
74
+ fi
75
+
76
+ echo "Installed: $plugin_key"
77
+ echo "Restart Claude Code to activate the plugin."
78
+ return 0
79
+ else
80
+ echo "Error: jq required or settings.json not found"
81
+ return 1
82
+ fi
83
+ }
84
+
85
+ # 플러그인 제거
86
+ uninstall_plugin() {
87
+ local plugin_name="$1"
88
+
89
+ echo "Uninstalling plugin: $plugin_name"
90
+
91
+ if command -v jq &> /dev/null && [ -f "$CLAUDE_SETTINGS" ]; then
92
+ # settings.json 백업
93
+ cp "$CLAUDE_SETTINGS" "$CLAUDE_SETTINGS.bak"
94
+
95
+ # enabledPlugins에서 제거 (정확한 키 또는 @가 포함된 키)
96
+ jq --arg plugin "$plugin_name" '
97
+ .enabledPlugins |= with_entries(
98
+ select(
99
+ .key != $plugin and
100
+ (.key | startswith($plugin + "@") | not)
101
+ )
102
+ )
103
+ ' "$CLAUDE_SETTINGS" > "$CLAUDE_SETTINGS.tmp" && mv "$CLAUDE_SETTINGS.tmp" "$CLAUDE_SETTINGS"
104
+
105
+ # history.json에서 installed 제거
106
+ if [ -f "$HISTORY_FILE" ]; then
107
+ local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
108
+ jq --arg plugin "$plugin_name" --arg ts "$timestamp" '
109
+ .lastUpdated = $ts |
110
+ del(.installed[$plugin])
111
+ ' "$HISTORY_FILE" > "$HISTORY_FILE.tmp" && mv "$HISTORY_FILE.tmp" "$HISTORY_FILE"
112
+ fi
113
+
114
+ echo "Uninstalled: $plugin_name"
115
+ echo "Restart Claude Code to complete removal."
116
+ return 0
117
+ else
118
+ echo "Error: jq required or settings.json not found"
119
+ return 1
120
+ fi
121
+ }
122
+
123
+ # 설치된 플러그인 목록
124
+ list_installed() {
125
+ if command -v jq &> /dev/null && [ -f "$CLAUDE_SETTINGS" ]; then
126
+ echo "Installed Plugins:"
127
+ jq -r '.enabledPlugins | to_entries | .[] | select(.value == true) | " - \(.key)"' "$CLAUDE_SETTINGS"
128
+ else
129
+ echo "Error: jq required or settings.json not found"
130
+ fi
131
+ }
132
+
133
+ # 플러그인 상태 확인
134
+ check_status() {
135
+ local plugin_name="$1"
136
+
137
+ if command -v jq &> /dev/null && [ -f "$CLAUDE_SETTINGS" ]; then
138
+ local enabled=$(jq -r --arg plugin "$plugin_name" '
139
+ .enabledPlugins | to_entries | .[] |
140
+ select(.key == $plugin or (.key | startswith($plugin + "@"))) |
141
+ .value
142
+ ' "$CLAUDE_SETTINGS")
143
+
144
+ if [ "$enabled" = "true" ]; then
145
+ echo "enabled"
146
+ else
147
+ echo "disabled"
148
+ fi
149
+ else
150
+ echo "unknown"
151
+ fi
152
+ }
153
+
154
+ # 플러그인 활성화/비활성화
155
+ toggle_plugin() {
156
+ local plugin_name="$1"
157
+ local action="$2" # enable or disable
158
+
159
+ if command -v jq &> /dev/null && [ -f "$CLAUDE_SETTINGS" ]; then
160
+ local value="true"
161
+ [ "$action" = "disable" ] && value="false"
162
+
163
+ jq --arg plugin "$plugin_name" --argjson val "$value" '
164
+ .enabledPlugins |= with_entries(
165
+ if .key == $plugin or (.key | startswith($plugin + "@"))
166
+ then .value = $val
167
+ else .
168
+ end
169
+ )
170
+ ' "$CLAUDE_SETTINGS" > "$CLAUDE_SETTINGS.tmp" && mv "$CLAUDE_SETTINGS.tmp" "$CLAUDE_SETTINGS"
171
+
172
+ echo "Plugin $plugin_name: $action"
173
+ else
174
+ echo "Error: jq required or settings.json not found"
175
+ fi
176
+ }
177
+
178
+ # 설치 명령 생성 (dry-run)
179
+ generate_install_command() {
180
+ local plugin_name="$1"
181
+ local marketplace="$2"
182
+
183
+ if [ -n "$marketplace" ]; then
184
+ echo "/plugin install ${plugin_name}@${marketplace}"
185
+ else
186
+ echo "/plugin install ${plugin_name}"
187
+ fi
188
+ }
189
+
190
+ # 복원 (백업에서)
191
+ restore_backup() {
192
+ if [ -f "$CLAUDE_SETTINGS.bak" ]; then
193
+ cp "$CLAUDE_SETTINGS.bak" "$CLAUDE_SETTINGS"
194
+ echo "Restored from backup"
195
+ else
196
+ echo "No backup found"
197
+ fi
198
+ }
199
+
200
+ # CLI 인터페이스
201
+ case "$1" in
202
+ install)
203
+ install_plugin "$2" "$3"
204
+ ;;
205
+ uninstall|remove)
206
+ uninstall_plugin "$2"
207
+ ;;
208
+ list)
209
+ list_installed
210
+ ;;
211
+ status)
212
+ check_status "$2"
213
+ ;;
214
+ enable)
215
+ toggle_plugin "$2" "enable"
216
+ ;;
217
+ disable)
218
+ toggle_plugin "$2" "disable"
219
+ ;;
220
+ command)
221
+ generate_install_command "$2" "$3"
222
+ ;;
223
+ restore)
224
+ restore_backup
225
+ ;;
226
+ *)
227
+ echo "Usage: $0 {install|uninstall|list|status|enable|disable|command|restore}"
228
+ echo ""
229
+ echo "Commands:"
230
+ echo " install <plugin[@marketplace]> [source] - Install a plugin"
231
+ echo " uninstall <plugin> - Uninstall a plugin"
232
+ echo " list - List installed plugins"
233
+ echo " status <plugin> - Check plugin status"
234
+ echo " enable <plugin> - Enable a plugin"
235
+ echo " disable <plugin> - Disable a plugin"
236
+ echo " command <plugin> [marketplace] - Generate install command"
237
+ echo " restore - Restore from backup"
238
+ ;;
239
+ esac