$npx -y skills add hanamizuki/solopreneur --skill releaseBump versions and tag plugins for release in the solopreneur multi-plugin marketplace. Detects which sub-plugins changed since their last tag, checks whether the root README is stale relative to those changes (offering one proposal at a time), asks the user for per-plugin patch/m
| 1 | # Release |
| 2 | |
| 3 | Manual release flow for the solopreneur multi-plugin marketplace. |
| 4 | Implements the release rule documented in `CLAUDE.md` at the repo root. |
| 5 | |
| 6 | This skill is **interactive**. Confirm each decision with the user. Do not |
| 7 | autopilot version bumps or release publishing. |
| 8 | |
| 9 | ## Pre-flight |
| 10 | |
| 11 | 1. Confirm cwd is the repo root or a worktree of it. Run from the directory |
| 12 | containing `.claude-plugin/marketplace.json` and `plugins/`. |
| 13 | |
| 14 | 2. Confirm working tree is clean: |
| 15 | |
| 16 | ```bash |
| 17 | git status --porcelain |
| 18 | ``` |
| 19 | |
| 20 | If unclean, stop and ask the user to commit or stash first. Don't release |
| 21 | on top of uncommitted work. The new commit's content depends on the |
| 22 | working tree. |
| 23 | |
| 24 | 3. Confirm we're on `main` (the typical release path is "merge → release"): |
| 25 | |
| 26 | ```bash |
| 27 | git branch --show-current |
| 28 | ``` |
| 29 | |
| 30 | If not on main, ask the user to confirm the branch is intentional. |
| 31 | |
| 32 | 4. Pull latest: |
| 33 | |
| 34 | ```bash |
| 35 | git fetch origin && git pull --ff-only |
| 36 | ``` |
| 37 | |
| 38 | If `--ff-only` fails (local has commits), stop and ask the user. |
| 39 | |
| 40 | ## Step 1: Detect per-plugin changes since last tag |
| 41 | |
| 42 | For each sub-plugin, find its last `<plugin>--v*` tag and compare against HEAD. |
| 43 | Plugin directory names match marketplace names 1:1. |
| 44 | |
| 45 | ```bash |
| 46 | PLUGINS=(solopreneur designer marketer ios-dev android-dev ai-engineer neo4j-dev) |
| 47 | for p in "${PLUGINS[@]}"; do |
| 48 | LAST_TAG=$(git tag -l "${p}--v*" --sort=-v:refname | head -1) |
| 49 | # Transitional fallback: the v0.5.x → v0.5.3 rename dropped the `solo-` |
| 50 | # prefix from sub-plugins. The first /release run after that rename has |
| 51 | # no `<bare>--v*` tag yet, so look for the legacy `solo-<bare>--v*` tag |
| 52 | # to avoid a misleading "NO TAG YET" message. Once the new tag exists, |
| 53 | # this fallback never fires again. |
| 54 | if [ -z "$LAST_TAG" ] && [ "$p" != "solopreneur" ]; then |
| 55 | LAST_TAG=$(git tag -l "solo-${p}--v*" --sort=-v:refname | head -1) |
| 56 | fi |
| 57 | if [ -z "$LAST_TAG" ]; then |
| 58 | echo "=== $p: NO TAG YET (first release) ===" |
| 59 | git log --oneline -- "plugins/$p/" |
| 60 | continue |
| 61 | fi |
| 62 | CHANGED=$(git diff --name-only "$LAST_TAG"..HEAD -- "plugins/$p/" | wc -l | tr -d ' ') |
| 63 | if [ "$CHANGED" -gt 0 ]; then |
| 64 | echo "=== $p: $CHANGED files changed since $LAST_TAG ===" |
| 65 | git log --oneline "$LAST_TAG"..HEAD -- "plugins/$p/" |
| 66 | else |
| 67 | echo "=== $p: no changes since $LAST_TAG ===" |
| 68 | fi |
| 69 | done |
| 70 | ``` |
| 71 | |
| 72 | Also check whether `marketplace.json` changed in a way that affects a plugin |
| 73 | entry (per the rule in CLAUDE.md): |
| 74 | |
| 75 | ```bash |
| 76 | git diff "$LAST_RELEASE_BASELINE"..HEAD -- .claude-plugin/marketplace.json |
| 77 | ``` |
| 78 | |
| 79 | Use the most recent tag of any plugin as `$LAST_RELEASE_BASELINE`. If the |
| 80 | diff touches a plugin entry's `name` / `source` / `description` / `license`, |
| 81 | flag those plugins for a bump even if their `plugins/<name>/` directory |
| 82 | didn't change. |
| 83 | |
| 84 | ## Step 1.5: README sync check |
| 85 | |
| 86 | Before asking for version bumps, look at whether the changes since |
| 87 | `$LAST_RELEASE_BASELINE` make the root `README.md` stale. Skip this step |
| 88 | entirely if the diff only touches internals (no surface changes). |
| 89 | |
| 90 | ### What might make README stale |
| 91 | |
| 92 | Apply judgment — these are signals, not rules: |
| 93 | |
| 94 | - A plugin's `description` in `marketplace.json` or `plugins/<p>/.claude-plugin/plugin.json` |
| 95 | changed, and the README's row / paragraph for that plugin still quotes the |
| 96 | old text |
| 97 | - A new plugin directory was added under `plugins/`, and the README's plugin |
| 98 | table doesn't include it |
| 99 | - A new in-house skill landed in a plugin, and the README's "Bundled skills" |
| 100 | section for that plugin enumerates skills explicitly (so an addition is |
| 101 | user-visible) |
| 102 | - A new agent was added under `plugins/<p>/agents/`, and the README mentions |
| 103 | agents per plugin |
| 104 | - Counts mentioned in the README (e.g. "23 vendored skills") drifted |
| 105 | |
| 106 | Examples of cases that don't need a README change: |
| 107 | |
| 108 | - Bug fix or refactor inside a skill with no description change |
| 109 | - Vendored skill re-sync with no upstream content drift |
| 110 | - New skill landed but README only says "ships N+ vendored skills" without |
| 111 | enumerating, and N is still an accurate floor |
| 112 | |
| 113 | ### Workflow |
| 114 | |
| 115 | 1. Pull the changed-files list scoped to surface signals: |
| 116 | ```bash |
| 117 | git diff --name-only "$LAST_RELEASE_BASELINE"..HEAD | grep -E \ |
| 118 | '(\.claude-plugin/(plugin|marketpl |