Files
brain/scripts/lib/install-plugins.sh
T
Дмитрий dc71e2338e refactor(brain-install): filter plugins by target ENUM in install-plugins.sh
Closes тех-долг из routing.md v1.1 §4.1 — install-plugins.sh теперь
фильтрует entries по полю `target` относительно режима install'а.

Added флаг `--install-target=user|consumer` (required, с fallback на 'user'
+ warning для backwards-compat прямых вызовов из тестов). Filter jq-выражение:

  user:     target ∈ {"user-level", "user-level+consumer"}
  consumer: target ∈ {"consumer", "user-level+consumer"}

scripts/install.sh теперь передаёт --install-target автоматически на основе
detected $mode (user|project). Regression: текущие 8 entries → 8 plugins при
--install-target=user, 2 plugins (FD + UPM, target=user-level+consumer) при
--install-target=consumer.

Подготовка под Phase 1: добавление 4 consumer-only entries (target=consumer)
и 1 user-level+consumer entry (context7) в plugins-manifest.json — filter
обеспечит, что в brain user-level попадут только нужные.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:00:39 +03:00

98 lines
3.8 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Install Claude Code plugins from brain manifest
# Adds marketplaces, installs plugins, warns on SHA mismatch.
#
# CORRECTION B: real Claude CLI subcommand shape is
# `claude plugin marketplace add <repo>` (NOT `claude marketplace add`)
# `claude plugin marketplace list`
# `claude plugin install <name@marketplace>`
# `claude plugin info <name@marketplace> --json`
# Phase 0 discovery confirmed: `marketplace` is a child of `plugin`, not a
# top-level subcommand. The plan originally had the wrong shape.
#
# Usage: install-plugins.sh --marketplaces=<path> --manifest=<path>
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/common.sh"
marketplaces=""
manifest=""
install_target=""
while [ $# -gt 0 ]; do
case "$1" in
--marketplaces=*) marketplaces="${1#--marketplaces=}" ;;
--manifest=*) manifest="${1#--manifest=}" ;;
--install-target=*) install_target="${1#--install-target=}" ;;
*) log_error "Unknown arg: $1"; exit 1 ;;
esac
shift
done
# Backwards-compat: если флаг не передан, default 'user' с warning
if [ -z "$install_target" ]; then
log_warn "--install-target not specified, defaulting to 'user' (deprecated path)"
install_target="user"
fi
# Validate
case "$install_target" in
user|consumer) ;;
*) log_error "--install-target must be 'user' or 'consumer', got: $install_target"; exit 1 ;;
esac
[ -f "$marketplaces" ] || { log_error "Marketplaces file: $marketplaces not found"; exit 1; }
[ -f "$manifest" ] || { log_error "Manifest file: $manifest not found"; exit 1; }
require_cmd jq || exit 1
# Fallback: if `claude` CLI is not in PATH (common on this Windows machine where
# the VSCode-extension binary lives outside %PATH%), log instructions and exit 0
# so installer can continue with manual JSON edits.
if ! command -v claude >/dev/null 2>&1; then
log_warn "claude CLI not found — fallback: edit JSON configs manually and restart"
log_info "Required edits:"
log_info " 1. Copy $marketplaces -> ~/.claude/plugins/known_marketplaces.json"
log_info " 2. Copy $manifest -> ~/.claude/plugins/installed_plugins.json"
log_info " 3. Update ~/.claude/settings.json:enabledPlugins"
log_info " 4. Restart Claude Code"
exit 0
fi
# Add marketplaces (CORRECTION B: `claude plugin marketplace ...`)
for mp in $(jq -r 'keys[]' "$marketplaces"); do
repo=$(jq -r ".[\"$mp\"].source.repo" "$marketplaces")
if claude plugin marketplace list 2>/dev/null | grep -q "$mp"; then
log_info "Marketplace $mp already added"
else
log_info "Adding marketplace: $repo"
claude plugin marketplace add "$repo" || { log_error "plugin marketplace add failed: $repo"; exit 6; }
fi
done
# Install plugins (filtered by target ENUM per --install-target)
case "$install_target" in
user)
filter='.plugins | to_entries[] | select(.value[0].target == "user-level" or .value[0].target == "user-level+consumer") | .key'
;;
consumer)
filter='.plugins | to_entries[] | select(.value[0].target == "consumer" or .value[0].target == "user-level+consumer") | .key'
;;
esac
for plugin in $(jq -r "$filter" "$manifest"); do
expected_sha=$(jq -r ".plugins[\"$plugin\"][0].gitCommitSha" "$manifest")
expected_ver=$(jq -r ".plugins[\"$plugin\"][0].version" "$manifest")
log_info "Installing $plugin (pinned v$expected_ver, SHA $expected_sha)"
claude plugin install "$plugin" || { log_error "plugin install failed: $plugin"; exit 6; }
actual_sha=$(claude plugin info "$plugin" --json 2>/dev/null | jq -r '.gitCommitSha // "unknown"')
if [ "$actual_sha" = "$expected_sha" ]; then
log_info " SHA match: $actual_sha"
else
log_warn " SHA mismatch (expected $expected_sha, got $actual_sha) — marketplace may have updated"
fi
done