
Brewtools:Plugin Update
- 6 installs
- 29 repo stars
- Updated August 2, 2026
- kochetkov-ma/claude-brewcode
Helps with ai & agent building tasks.
About
brewtools:plugin-update is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- brewtools:plugin-update
- AI & Agent Building
- AI-coding skill
Brewtools:Plugin Update by the numbers
- 6 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #12,825 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/kochetkov-ma/claude-brewcode --skill brewtoolsplugin-updateAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 6 |
|---|---|
| repo stars | ★ 29 |
| Last updated | August 2, 2026 |
| Repository | kochetkov-ma/claude-brewcode ↗ |
What it does
Helps with ai & agent building tasks.
Files
Brewcode Plugin Update
Check, install, and update the brewcode plugin suite (brewcode, brewdoc, brewtools, brewui). Execute all commands in the current session — never give "you should run" instructions.
Argument Handling
Skill arguments received: $ARGUMENTS
| Arg | Behavior |
|---|---|
| (empty) | Interactive — all 6 phases with AskUserQuestion gates |
check | Phases 0-2 only (status table), no prompts |
update | Phases 0-4, non-interactive "Update all" |
all | Phases 0-6 non-interactive |
Parse first token of $ARGUMENTS. Unknown or empty → interactive.
Critical Rules
- EXECUTE every
claude plugin ...command via Bash tool. Show full output. - NEVER suggest
--plugin-dirfor end users (dev-only). - ALWAYS print the reload notice at the end, even on no-op runs.
- AskUserQuestion: options lists only, no free-text fields.
---
Phase 0 — Discover Installed Plugins
PRIMARY (CC 2.1.163+) — EXECUTE using Bash tool:
unset CLAUDECODE && claude plugin list --json && echo "✅ list OK" || echo "❌ list FAILED"If the command succeeds and returns a non-empty JSON array, parse it directly. Each object has fields: id (<plugin>@<marketplace>), version (string, may be "unknown"), scope, enabled (boolean), installPath, installedAt, lastUpdated, optional mcpServers.
FALLBACK (CC < 2.1.163 or empty/error output from above) — EXECUTE using Bash tool:
bash "${CLAUDE_SKILL_DIR}/scripts/discover-plugins.sh" && echo "✅ discover OK" || echo "❌ discover FAILED"STOP if both fail — report to user and continue without installed data (treat everything as missing).
Partition results into: suite = {brewcode, brewdoc, brewtools, brewui}, other = everything else.
Read references/discovery.md for details on both discovery paths.
Phase 1 — Fetch Latest Versions
EXECUTE using Bash tool:
bash "${CLAUDE_SKILL_DIR}/scripts/fetch-latest-versions.sh" && echo "✅ fetch OK" || echo "❌ fetch FAILED"STOP if ❌ — report network issue, mark latest versions as "unknown", continue.
Merge with Phase 0 data.
Phase 2 — Status Table
Render markdown table to the user:
| Plugin | Installed | Latest | Status |
|---|---|---|---|
| brewcode | 3.4.51 | 3.4.52 | ⬇️ update |
| brewdoc | 3.4.51 | 3.4.51 | ✅ current |
| brewtools | — | 3.4.51 | ❌ missing |
| brewui | 3.4.51 | 3.4.51 | ✅ current |
Status legend: ✅ current, ⬇️ update available, ❌ missing, ❓ unknown.
Also list other plugins below with their versions (informational).
If arg = `check` → STOP here. Skip to Phase 6.
Phase 2b — Token-Cost Table (Optional)
Precheck:
claude plugin details --help >/dev/null 2>&1 && echo "available" || echo "skip"If unavailable → SKIP (proceed to Phase 3).
If available, for each installed suite plugin run claude plugin details <plugin>@claude-brewcode and render:
| Plugin | Base Tokens | With Skills | Hooks | Total |
|---|---|---|---|---|
| brewcode | ... | ... | ... | ... |
| brewdoc | ... | ... | ... | ... |
| brewtools | ... | ... | ... | ... |
| brewui | ... | ... | ... | ... |
Adapt column names to actual output fields. Missing field → —. Command failure for a plugin → ❓ for that row, continue.
Phase is informational only; do not block on errors.
Phase 3 — Install Missing
For each missing suite plugin, ask via AskUserQuestion (unless arg ∈ {update, all} — all auto-installs, update skips install).
AskUserQuestion (interactive only, if missing plugins exist):
Question: "Install missing brewcode plugins?" Options: "Install all missing" / "Install selected" / "Skip install"
If "Install selected" — ask per plugin with options ["Install", "Skip"].
EXECUTE (idempotent):
claude plugin marketplace add https://github.com/kochetkov-ma/claude-brewcode && echo "✅ marketplace add OK" || echo "⚠️ marketplace add warning (may already exist)"Then per plugin:
claude plugin install <plugin>@claude-brewcode && echo "✅ install <plugin> OK" || echo "❌ install <plugin> FAILED"Show full output of each command.
Reference: references/install-prompt.md.
Phase 4 — Update Outdated
AskUserQuestion (interactive only; update and all auto-pick "Update all"):
Question: "Update brewcode plugin suite?" Options: "Update all" / "Update suite only" / "Update selected" / "Skip updates"
EXECUTE full chain in order:
claude plugin marketplace update claude-brewcode && echo "✅ marketplace update OK" || echo "❌ marketplace update FAILED"claude plugin update brewcode@claude-brewcode && echo "✅ brewcode update OK" || echo "❌ brewcode update FAILED"claude plugin update brewdoc@claude-brewcode && echo "✅ brewdoc update OK" || echo "❌ brewdoc update FAILED"claude plugin update brewtools@claude-brewcode && echo "✅ brewtools update OK" || echo "❌ brewtools update FAILED"claude plugin update brewui@claude-brewcode && echo "✅ brewui update OK" || echo "❌ brewui update FAILED"On failure: report exact error and continue. Reference: references/update-commands.md, references/update-prompt.md.
Phase 5 — Auto-Update Toggle (Optional)
Skip for arg ∈ {`check`, `update`}. Interactive or all only.
Auto-update for third-party marketplaces is OFF by default. Toggle per-marketplace via /plugin UI → Marketplaces → claude-brewcode. Exact settings.json key unverified — see references/autoupdate-research.md.
AskUserQuestion (interactive only):
Question: "Enable auto-update for claude-brewcode marketplace?" Options: "Enable via /plugin UI" / "Skip"
Do NOT patch settings.json blindly. Instruct user to toggle via /plugin UI.
Phase 5b — Prune Stale Plugin Caches
EXECUTE using Bash tool:
claude plugin prune --help >/dev/null 2>&1 && claude plugin prune || echo "skipped: claude plugin prune unavailable"Non-fatal: if CLI lacks prune, prints skip notice and continues.
Phase 6 — Reload Notice & Final Report
ALWAYS print the contents of references/reload-notice.md:
⚠️ Reload plugins to activate updates.
Preferred: run /reload-plugins in this session.Fallback: typeexit, then runclaudeagain.
Final summary:
- Plugins installed this run: [...]
- Plugins updated this run: [...]
- Plugins skipped: [...]
- Errors encountered: [...]
<!-- W3-T8 research note: Marketplace auto-update settings.json key not confirmed in CC docs as of 2026-05-12. Continue using UI guidance. Re-investigate when CC adds documented marketplace.autoUpdate setting. -->
Plugin Update
Checks installed brewcode plugins (brewcode, brewdoc, brewtools, brewui) by reading the filesystem and settings.json, fetches the latest versions from the marketplace, installs any missing plugins, updates outdated ones, and always prints a reload notice at the end. All commands execute directly in the current Claude Code session — no "run this yourself" instructions.
Quick Start
/brewtools:plugin-updateModes
| Mode | How to trigger | What it does |
|---|---|---|
| Interactive | /brewtools:plugin-update | Runs all phases with AskUserQuestion gates before installing or updating |
| Check only | /brewtools:plugin-update check | Status table only — no prompts, no changes |
| Update all | /brewtools:plugin-update update | Discover, fetch, table, then update outdated (non-interactive) |
| Full non-interactive | /brewtools:plugin-update all | All phases including install and update without any prompts |
Examples
Good Usage
# Check which plugins are current vs outdated vs missing
/brewtools:plugin-update check
# Install missing plugins and update outdated ones interactively
/brewtools:plugin-update
# Update the full brewcode suite without prompts (CI or scripted sessions)
/brewtools:plugin-update all
# Non-interactive update of outdated plugins, skip installs
/brewtools:plugin-update updateCommon Mistakes
# Forgetting the unset prefix when running claude plugin list inside a session
unset CLAUDECODE && claude plugin list --json # correct
claude plugin list --json # may fail inside a session
# Using --plugin-dir for end users -- this is a dev-only flag
claude --plugin-dir ./brewtools
# End users should install via the marketplace, not --plugin-dir
# Forgetting to reload after updates -- plugins are NOT active until reloaded
/brewtools:plugin-update
# -> plugins updated, but skills still show old behavior until /reload-pluginsWhat It Does
| Phase | Name | Description |
|---|---|---|
| 0 | Discover | Primary: unset CLAUDECODE && claude plugin list --json (CC 2.1.163+). Fallback: scripts/discover-plugins.sh reads settings.json and the plugin cache |
| 1 | Fetch latest | Runs scripts/fetch-latest-versions.sh to get the current published versions from the marketplace |
| 2 | Status table | Renders a markdown table: plugin name, installed version, latest version, and status (✅ current / ⬇️ update / ❌ missing / ❓ unknown) |
| 3 | Install missing | For each missing suite plugin, prompts (interactive) or auto-installs (all); runs claude plugin marketplace add then claude plugin install <plugin>@claude-brewcode |
| 4 | Update outdated | Runs the full update chain: marketplace update then claude plugin update for each outdated plugin |
| 5 | Auto-update toggle | Interactive and all modes only; instructs the user to toggle auto-update via /plugin UI — does NOT patch settings.json directly |
| 6 | Final report | Prints reload notice plus a summary of what was installed, updated, skipped, and any errors |
Discovery Method
Phase 0 uses two paths:
Primary (CC 2.1.163+): unset CLAUDECODE && claude plugin list --json returns a JSON array. Each entry has id, version (may be "unknown"), scope, enabled (boolean), installPath, installedAt, lastUpdated, and optional mcpServers.
Fallback (CC < 2.1.163 or command fails): scripts/discover-plugins.sh reads two sources: 1. ~/.claude/settings.json (and ./.claude/settings.json if present) — the enabledPlugins map where keys are <plugin>@<marketplace>. 2. Plugin cache walk — ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/ — the highest version directory per plugin is the installed version.
The script outputs a JSON object with marketplaces, installed versions, and the cache_dir path.
Output
The status table rendered in Phase 2 looks like this:
| Plugin | Installed | Latest | Status |
|---|---|---|---|
| brewcode | 3.4.51 | 3.4.52 | ⬇️ update |
| brewdoc | 3.4.51 | 3.4.51 | ✅ current |
| brewtools | — | 3.4.51 | ❌ missing |
| brewui | 3.4.51 | 3.4.51 | ✅ current |
Non-suite plugins found in the cache are listed below the main table as informational entries. The final report lists everything installed or updated during the run plus any errors encountered.
Tips
- Run this skill after major Claude Code version updates — plugins sometimes need a fresh install after core upgrades.
- Pair with
/reload-pluginsimmediately after updates; skills do not activate until the session reloads plugin state. - Do NOT use
--plugin-dirfor end-user installations — that flag is for local plugin development only. - The
checkmode is safe to run at any time with no side effects; use it to audit the current state before a project session. - If
discover-plugins.shfails, the skill treats all suite plugins as missing and continues — it will not silently skip the install phase.
Documentation
Full docs: plugin-update
Plugin Auto-Update Research
Current State (verified 2026-04-10)
- Default: Third-party marketplace auto-update is OFF.
- Toggle UI:
/plugin→ Marketplaces → select marketplace → toggle auto-update. - Scope: Auto-update is per-marketplace, not per-plugin.
- Env vars:
DISABLE_AUTOUPDATER=1— disables Claude Code self-updaterFORCE_AUTOUPDATE_PLUGINS=1— force plugin update on next start
Unknown
The exact settings.json key that stores the per-marketplace auto-update flag is NOT verified. Candidates observed in the wild (all unconfirmed):
marketplaces.<name>.autoUpdatepluginMarketplaces.<name>.autoUpdateenabledMarketplaces.<name>.autoUpdate
Recommended Discovery Procedure
To discover the real key:
1. Snapshot ~/.claude/settings.json before toggling. 2. Open /plugin → Marketplaces → claude-brewcode → enable auto-update. 3. Diff ~/.claude/settings.json — the new/changed key is the answer. 4. Document the key here and update the skill to patch settings.json directly.
Rule for This Skill
Do NOT patch settings.json blindly. The skill instructs the user to use /plugin UI until the key is confirmed.
Links
- https://code.claude.com/docs/en/discover-plugins
- https://code.claude.com/docs/en/plugin-marketplaces
- https://code.claude.com/docs/en/plugins-reference
Plugin Discovery
Primary path:claude plugin list --json(CC 2.1.163+). Fallback:scripts/discover-plugins.shfilesystem scan.
Primary — claude plugin list (CC 2.1.163+)
EXECUTE (prefix with unset CLAUDECODE && when running inside a Claude session):
unset CLAUDECODE && claude plugin list --jsonPlain-text format (no --json):
Installed plugins:
> brewcode@claude-brewcode
Version: 3.9.2
Scope: user
Status: enabledJSON format — array of objects:
[
{
"id": "brewcode@claude-brewcode",
"version": "3.9.2",
"scope": "user",
"enabled": true,
"installPath": "/Users/x/.claude/plugins/cache/claude-brewcode/brewcode/3.9.2",
"installedAt": "2026-01-01T00:00:00.000Z",
"lastUpdated": "2026-01-01T00:00:00.000Z"
}
]JSON Schema
| Field | Type | Notes |
|---|---|---|
id | string | <plugin>@<marketplace> |
version | string | May be "unknown" |
scope | string | "user" or "project" |
enabled | boolean | true / false |
installPath | string | Absolute path to plugin cache dir |
installedAt | string | ISO 8601 timestamp |
lastUpdated | string | ISO 8601 timestamp |
mcpServers | object | Optional — present only if plugin registers MCP servers |
"unknown" version means installed but version undetectable — fall back to cache walk for the version.
Fall back to scripts/discover-plugins.sh when:
claude plugin listnot recognized (CC < 2.1.163)- Command exits non-zero
- Output is empty or not valid JSON
Fallback — scripts/discover-plugins.sh (filesystem scan)
| Source | Path | Parser |
|---|---|---|
| Global settings | ~/.claude/settings.json -> enabledPlugins | jq or python3 -c "import json" |
| Project settings | ./.claude/settings.json -> enabledPlugins (if exists) | same |
| Plugin cache | ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/.claude-plugin/plugin.json | walk + parse version field |
| Marketplace list | claude plugin marketplace list | line parsing |
enabledPlugins Format
{
"enabledPlugins": {
"brewcode@claude-brewcode": true,
"brewdoc@claude-brewcode": true
}
}Keys are <plugin>@<marketplace>. Truthy value means enabled.
Cache Walk
Plugin binaries live in ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/. Pick the highest <version> directory per plugin — that is the installed version.
Output JSON
{
"marketplaces": ["claude-brewcode"],
"installed": {
"brewcode": {"version": "3.4.51", "marketplace": "claude-brewcode"},
"brewdoc": {"version": "3.4.51", "marketplace": "claude-brewcode"}
},
"cache_dir": "/Users/x/.claude/plugins/cache"
}Execute these commands in this Claude Code session, one by one, show full output for each, do not skip any, do not summarize:
1. claude plugin marketplace add https://github.com/kochetkov-ma/claude-brewcode
2. claude plugin install brewcode@claude-brewcode
3. claude plugin install brewdoc@claude-brewcode
4. claude plugin install brewtools@claude-brewcode
5. claude plugin install brewui@claude-brewcode
After all commands succeed, run `/reload-plugins`. If `/reload-plugins` is unavailable, tell me to type `exit` and run `claude` again. Run the commands now.⚠️ Reload plugins to activate updates.
>
Preferred: run /reload-plugins in this session.>
Fallback: typeexit, then runclaudeagain.
Canonical Update Command Chain
Run in this exact order. Show full output for each step.
Full Chain
claude plugin marketplace update claude-brewcode
claude plugin update brewcode@claude-brewcode
claude plugin update brewdoc@claude-brewcode
claude plugin update brewtools@claude-brewcode
claude plugin update brewui@claude-brewcodeReload (MANDATORY after updates)
Preferred: /reload-plugins (in-session slash command) Fallback: type exit, then run claude again
Valid CLI Subcommands
| Command | Purpose |
|---|---|
claude plugin list | List installed plugins (CC 2.1.163+) |
claude plugin list --json | List installed plugins as JSON array (CC 2.1.163+) |
claude plugin install <plugin>@<marketplace> | Install |
claude plugin update <plugin>@<marketplace> | Update one plugin |
claude plugin uninstall <plugin>@<marketplace> | Remove |
claude plugin marketplace add <url> | Add marketplace |
claude plugin marketplace update <name> | Refresh marketplace metadata |
claude plugin marketplace list | List marketplaces |
claude plugin marketplace remove <name> | Remove marketplace |
When running inside a Claude session, prefix claude plugin list with unset CLAUDECODE &&.
Verification After Update
unset CLAUDECODE && claude plugin list --jsonConfirm expected versions appear. If CC < 2.1.163, inspect cache directly or run scripts/discover-plugins.sh.
Environment Variables
| Var | Effect |
|---|---|
DISABLE_AUTOUPDATER=1 | Disable Claude Code auto-updater entirely |
FORCE_AUTOUPDATE_PLUGINS=1 | Force plugin auto-update on next start |
Notes
- ❌
--plugin-dirfor end users — dev-only flag
Execute these commands in this Claude Code session, one by one, show full output for each, do not skip any, do not summarize:
1. claude plugin marketplace update claude-brewcode
2. claude plugin update brewcode@claude-brewcode
3. claude plugin update brewdoc@claude-brewcode
4. claude plugin update brewtools@claude-brewcode
5. claude plugin update brewui@claude-brewcode
After all commands succeed, run `/reload-plugins`. If `/reload-plugins` is unavailable, tell me to type `exit` and run `claude` again. Run the commands now.#!/usr/bin/env bash
# discover-plugins.sh
# Emits JSON describing installed Claude Code plugins.
# Discovery sources:
# 1. ~/.claude/settings.json -> enabledPlugins
# 2. ./.claude/settings.json -> enabledPlugins (if present)
# 3. ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/.claude-plugin/plugin.json
# 4. `claude plugin marketplace list` (best-effort)
#
# NEVER uses `claude plugin list` — that subcommand does not exist.
# Requires: jq. Falls back to python3 only for enabledPlugins/version reads.
set -uo pipefail
log() { printf '%s\n' "$*" >&2; }
CACHE_DIR="${HOME}/.claude/plugins/cache"
GLOBAL_SETTINGS="${HOME}/.claude/settings.json"
PROJECT_SETTINGS="./.claude/settings.json"
if ! command -v jq >/dev/null 2>&1; then
log "ERROR: jq is required"
printf '{"error":"jq-missing","marketplaces":[],"enabledPlugins":[],"installed":{},"cache_dir":"%s"}\n' "$CACHE_DIR"
exit 1
fi
# ---------- helpers ----------
read_enabled_plugins() {
local file="$1"
[ -f "$file" ] || return 0
jq -r '.enabledPlugins // {} | to_entries[] | select(.value != false and .value != null) | .key' "$file" 2>/dev/null || true
}
max_version() {
local a="$1" b="$2"
if [ -z "$a" ]; then printf '%s' "$b"; return; fi
if [ -z "$b" ]; then printf '%s' "$a"; return; fi
local ax="${a#v}" bx="${b#v}" bigger
bigger=$(printf '%s\n%s\n' "$ax" "$bx" | sort -V | tail -n1)
if [ "$bigger" = "$ax" ]; then printf '%s' "$a"; else printf '%s' "$b"; fi
}
read_plugin_version() {
local file="$1"
[ -f "$file" ] || { printf ''; return; }
jq -r '.version // ""' "$file" 2>/dev/null || printf ''
}
# ---------- enabled plugin keys ----------
enabled_keys=""
if [ -f "$GLOBAL_SETTINGS" ]; then
enabled_keys+=$'\n'"$(read_enabled_plugins "$GLOBAL_SETTINGS")"
fi
if [ -f "$PROJECT_SETTINGS" ]; then
enabled_keys+=$'\n'"$(read_enabled_plugins "$PROJECT_SETTINGS")"
fi
enabled_keys=$(printf '%s\n' "$enabled_keys" | awk 'NF' | sort -u)
# ---------- walk cache ----------
# Use temp file for portability (macOS bash 3.2 has no associative arrays)
TMP_ROWS=$(mktemp 2>/dev/null || mktemp -t plugins)
trap 'rm -f "$TMP_ROWS" "$TMP_ROWS.final"' EXIT
if [ -d "$CACHE_DIR" ]; then
while IFS= read -r pj; do
[ -n "$pj" ] || continue
rel="${pj#"$CACHE_DIR/"}"
market="${rel%%/*}"
rest="${rel#*/}"
plugin="${rest%%/*}"
rest2="${rest#*/}"
version="${rest2%%/*}"
[ -n "$market" ] && [ -n "$plugin" ] && [ -n "$version" ] || continue
[ "$version" = ".claude-plugin" ] && continue
printf '%s\t%s\t%s\n' "$plugin" "$version" "$market" >> "$TMP_ROWS"
done < <(find "$CACHE_DIR" -mindepth 5 -maxdepth 5 -type f -name plugin.json -path '*/.claude-plugin/plugin.json' 2>/dev/null || true)
fi
# Reduce to highest version per plugin
: > "$TMP_ROWS.final"
if [ -s "$TMP_ROWS" ]; then
plugins_uniq=$(awk -F'\t' '{print $1}' "$TMP_ROWS" | sort -u)
for p in $plugins_uniq; do
# pick highest version for this plugin
best_line=$(awk -F'\t' -v p="$p" '$1==p' "$TMP_ROWS" \
| sort -t $'\t' -k2,2V \
| tail -n1)
printf '%s\n' "$best_line" >> "$TMP_ROWS.final"
done
fi
# ---------- marketplaces ----------
marketplaces_json="[]"
if command -v claude >/dev/null 2>&1; then
# Derive marketplace names from cache dirs (reliable) and also try CLI output.
if [ -d "$CACHE_DIR" ]; then
cache_markets=$(find "$CACHE_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null \
| awk -F/ '{print $NF}' \
| sort -u)
if [ -n "$cache_markets" ]; then
marketplaces_json=$(printf '%s\n' "$cache_markets" | jq -R . | jq -s 'unique')
fi
fi
fi
# ---------- build installed JSON ----------
installed_json="{}"
if [ -s "$TMP_ROWS.final" ]; then
tmp_entries=""
while IFS=$'\t' read -r p v m; do
[ -n "$p" ] || continue
entry=$(jq -nc --arg p "$p" --arg v "$v" --arg m "$m" \
'{($p): {version:$v, marketplace:$m}}')
tmp_entries+="${entry}"$'\n'
done < "$TMP_ROWS.final"
if [ -n "$tmp_entries" ]; then
installed_json=$(printf '%s' "$tmp_entries" | jq -s 'add // {}')
fi
fi
# ---------- enabled JSON ----------
if [ -z "$enabled_keys" ]; then
enabled_json="[]"
else
enabled_json=$(printf '%s\n' "$enabled_keys" | jq -R . | jq -s .)
fi
# ---------- emit ----------
jq -n \
--argjson marketplaces "$marketplaces_json" \
--argjson enabled "$enabled_json" \
--argjson installed "$installed_json" \
--arg cache_dir "$CACHE_DIR" \
'{marketplaces:$marketplaces, enabledPlugins:$enabled, installed:$installed, cache_dir:$cache_dir}'
#!/usr/bin/env bash
# fetch-latest-versions.sh
# Fetches latest versions of brewcode plugin suite from GitHub.
# Primary: raw plugin.json from main branch.
# Fallback: gh api release tag_name.
#
# Output: JSON {"brewcode":"X.Y.Z","brewdoc":"X.Y.Z","brewtools":"X.Y.Z","brewui":"X.Y.Z"}
# On failure for a plugin, value = "unknown".
set -uo pipefail
log() { printf '%s\n' "$*" >&2; }
PLUGINS=(brewcode brewdoc brewtools brewui)
REPO="kochetkov-ma/claude-brewcode"
RAW_BASE="https://raw.githubusercontent.com/${REPO}/main"
if ! command -v jq >/dev/null 2>&1; then
log "ERROR: jq required"
printf '{"error":"jq-missing"}\n'
exit 1
fi
fetch_release_tag() {
command -v gh >/dev/null 2>&1 || { printf ''; return; }
gh api "repos/${REPO}/releases/latest" --jq '.tag_name // ""' 2>/dev/null | sed 's/^v//'
}
RELEASE_FALLBACK=""
fetch_version() {
local plugin="$1"
local url="${RAW_BASE}/${plugin}/.claude-plugin/plugin.json"
local body ver
body=$(curl -sSL --max-time 10 "$url" 2>/dev/null || true)
if [ -n "$body" ]; then
ver=$(printf '%s' "$body" | jq -r '.version // ""' 2>/dev/null || true)
if [ -n "$ver" ] && [ "$ver" != "null" ]; then
printf '%s' "$ver"
return
fi
fi
# fallback: release tag (shared across all 4 plugins in this repo)
if [ -z "$RELEASE_FALLBACK" ]; then
RELEASE_FALLBACK=$(fetch_release_tag)
fi
if [ -n "$RELEASE_FALLBACK" ]; then
printf '%s' "$RELEASE_FALLBACK"
return
fi
printf 'unknown'
}
# Build JSON directly (no associative array — macOS bash 3.2 compat)
entries=""
for p in "${PLUGINS[@]}"; do
v=$(fetch_version "$p")
entries+=$(jq -nc --arg p "$p" --arg v "$v" '{($p): $v}')
entries+=$'\n'
done
printf '%s' "$entries" | jq -s 'add // {}'