NotFair Upgrade Tool
upgrade

Upgrade the NotFair plugin to the latest version. Updates the marketplace repo, installs the new version to the plugin cache, and updates installed_plugins.json.
--- name: upgrade argument-hint: "<or just run '/notfair:upgrade'>" description: > Upgrade the NotFair plugin to the latest version. Updates the marketplace repo, installs the new version to the plugin cache, and updates installed_plugins.json. Use when asked to "upgrade notfair", "update notfair", or "get latest version". Also handles inline upgrade prompts when a skill detects UPGRADE_AVAILABLE at startup. allowed-tools: - Bash - Read - AskUserQuestion --- # /notfair:upgrade Upgrade the NotFair plugin to the latest version and show what's new.
Overview
Upgrade the NotFair plugin to the latest version and show what's new.
Manual install (npx, ZIP)
npx skills add nowork-studio/notfair-plugin --skill upgrade -g -a claude-codenpx degit nowork-studio/notfair-plugin/notfair-upgrade-skill#main ~/.claude/skills/upgrade-nowork-studioConnects with Agent Alley MCP · agentalley.io/mcp
Files included
SKILL.md5.6 KB
Read SKILL.md here
Show the full text190 lines
/notfair:upgrade
Upgrade the NotFair plugin to the latest version and show what's new.
Key paths
| What | Path |
|---|---|
| Marketplace repo | ~/.claude/plugins/marketplaces/nowork-studio/ |
| Plugin cache | ~/.claude/plugins/cache/nowork-studio/notfair/<version>/ |
| Installed plugins | ~/.claude/plugins/installed_plugins.json |
| Update state | ~/.toprank/ (intentionally preserved — see CHANGELOG 0.24.0) |
Inline upgrade flow
This section is used when a skill preamble outputs UPGRADE_AVAILABLE.
Step 1: Auto-upgrade
Log "Upgrading NotFair v{old} → v{new}..." and proceed to Step 2.
Step 2: Detect current install
First check for dev symlink (see "Dev symlink detection" section). If detected, stop — do not upgrade.
# Find the currently installed plugin path
INSTALLED_DIR=$(ls -d ~/.claude/plugins/cache/nowork-studio/notfair/*/ 2>/dev/null | grep -v '.bak' | head -1)
if [ -z "$INSTALLED_DIR" ]; then
echo "ERROR: NotFair plugin not found in cache"; exit 1
fi
MARKETPLACE_DIR="$HOME/.claude/plugins/marketplaces/nowork-studio"
if [ ! -d "$MARKETPLACE_DIR/.git" ]; then
echo "ERROR: marketplace repo not found at $MARKETPLACE_DIR"; exit 1
fi
echo "Current install: $INSTALLED_DIR"
echo "Marketplace repo: $MARKETPLACE_DIR"
Step 3: Save old version
OLD_VERSION=$(cat "$INSTALLED_DIR/VERSION" 2>/dev/null | tr -d '[:space:]' || echo "unknown")
Step 4: Update marketplace repo and install
cd "$MARKETPLACE_DIR"
git fetch origin
git reset --hard origin/main
NEW_VERSION=$(cat VERSION | tr -d '[:space:]')
GIT_SHA=$(git rev-parse HEAD)
# Create new versioned cache directory
NEW_CACHE_DIR="$HOME/.claude/plugins/cache/nowork-studio/notfair/$NEW_VERSION"
if [ -d "$NEW_CACHE_DIR" ]; then
rm -rf "$NEW_CACHE_DIR"
fi
mkdir -p "$NEW_CACHE_DIR"
# Copy plugin files (exclude .git to save space)
rsync -a --exclude='.git' "$MARKETPLACE_DIR/" "$NEW_CACHE_DIR/"
If the copy fails, warn: "Upgrade failed — the old version is still active. Run /notfair:upgrade manually." and stop.
Step 5: Update installed_plugins.json
Read ~/.claude/plugins/installed_plugins.json, then update the notfair@nowork-studio entry:
python3 -c "
import json, os
from datetime import datetime, timezone
path = os.path.expanduser('~/.claude/plugins/installed_plugins.json')
with open(path) as f:
data = json.load(f)
data['plugins']['notfair@nowork-studio'] = [{
'scope': 'user',
'installPath': os.path.expanduser('~/.claude/plugins/cache/nowork-studio/notfair/$NEW_VERSION'),
'version': '$NEW_VERSION',
'installedAt': data['plugins'].get('notfair@nowork-studio', [{}])[0].get('installedAt', datetime.now(timezone.utc).isoformat()),
'lastUpdated': datetime.now(timezone.utc).isoformat(),
'gitCommitSha': '$GIT_SHA'
}]
with open(path, 'w') as f:
json.dump(data, f, indent=4)
print('Updated installed_plugins.json: notfair@nowork-studio -> v$NEW_VERSION')
"
Step 6: Clean up old cache versions
Remove old versioned cache directories (keep only the new one). Never remove a dev symlink:
for dir in ~/.claude/plugins/cache/nowork-studio/notfair/*/; do
ver=$(basename "$dir")
if [ "$ver" != "$NEW_VERSION" ] && [ "$ver" != "dev" ]; then
rm -rf "$dir"
echo "Removed old cache: $ver"
fi
done
Step 7: Write marker + clear update state
mkdir -p ~/.toprank
echo "$OLD_VERSION" > ~/.toprank/just-upgraded-from
rm -f ~/.toprank/last-update-check
rm -f ~/.toprank/update-snoozed
Step 8: Show What's New
Read $NEW_CACHE_DIR/CHANGELOG.md. Find all version entries between the old version and the new version. Summarize as 3-7 bullets grouped by theme — focus on user-facing changes, skip internal refactors.
Format:
NotFair v{new} — upgraded from v{old}!
What's new:
- [bullet 1]
- [bullet 2]
- ...
The new version will be fully active on your next Claude Code session.
Step 9: Continue
After showing What's New, continue with whatever skill the user originally invoked.
Dev symlink detection
Before upgrading, check if the installed cache directory is a symlink named dev:
CACHE_DIR=$(ls -d ~/.claude/plugins/cache/nowork-studio/notfair/*/ 2>/dev/null | head -1)
if [ -L "${CACHE_DIR%/}" ] && [ "$(basename "$CACHE_DIR")" = "dev" ]; then
echo "DEV_SYMLINK"
fi
If DEV_SYMLINK: tell the user "NotFair is installed as a dev symlink — it always points to your local source (v$(cat "$CACHE_DIR/VERSION" 2>/dev/null | tr -d '[:space:]')). No upgrade needed." and stop. Do not proceed with Steps 2–8.
Standalone usage
When invoked directly as /notfair:upgrade:
Check for dev symlink (see "Dev symlink detection" above). If detected, stop.
Force a fresh update check (bypass cache and snooze):
_UPD_BIN=$(ls ~/.claude/plugins/cache/nowork-studio/notfair/*/bin/notfair-update-check 2>/dev/null | head -1)
[ -n "$_UPD_BIN" ] && _UPD=$("$_UPD_BIN" --force 2>/dev/null || true) || _UPD=""
echo "$_UPD"
If
UPGRADE_AVAILABLE <old> <new>: follow Steps 2–8 above.If no
UPGRADE_AVAILABLEoutput: tell the user "You're already on the latest version (v{LOCAL})."
| 1 | |
| 2 | name upgrade |
| 3 | argument-hint "<or just run '/notfair:upgrade'>" |
| 4 | description > |
| 5 | Upgrade the NotFair plugin to the latest version. Updates the marketplace repo, |
| 6 | installs the new version to the plugin cache, and updates installed_plugins.json. |
| 7 | Use when asked to "upgrade notfair", "update notfair", or "get latest version". |
| 8 | Also handles inline upgrade prompts when a skill detects UPGRADE_AVAILABLE at startup. |
| 9 | allowed-tools |
| 10 | - Bash |
| 11 | - Read |
| 12 | - AskUserQuestion |
| 13 | |
| 14 | |
| 15 | # /notfair:upgrade |
| 16 | |
| 17 | Upgrade the NotFair plugin to the latest version and show what's new. |
| 18 | |
| 19 | ## Key paths |
| 20 | |
| 21 | | What | Path | |
| 22 | |------|------| |
| 23 | | Marketplace repo | `~/.claude/plugins/marketplaces/nowork-studio/` | |
| 24 | | Plugin cache | `~/.claude/plugins/cache/nowork-studio/notfair/<version>/` | |
| 25 | | Installed plugins | `~/.claude/plugins/installed_plugins.json` | |
| 26 | | Update state | `~/.toprank/` (intentionally preserved — see CHANGELOG 0.24.0) | |
| 27 | |
| 28 | |
| 29 | |
| 30 | ## Inline upgrade flow |
| 31 | |
| 32 | This section is used when a skill preamble outputs `UPGRADE_AVAILABLE`. |
| 33 | |
| 34 | ### Step 1: Auto-upgrade |
| 35 | |
| 36 | Log "Upgrading NotFair v{old} → v{new}..." and proceed to Step 2. |
| 37 | |
| 38 | |
| 39 | |
| 40 | ### Step 2: Detect current install |
| 41 | |
| 42 | First check for dev symlink (see "Dev symlink detection" section). If detected, stop — do not upgrade. |
| 43 | |
| 44 | |
| 45 | # Find the currently installed plugin path |
| 46 | INSTALLED_DIR=$(ls -d ~/.claude/plugins/cache/nowork-studio/notfair/*/ 2>/dev/null | grep -v '.bak' | head -1) |
| 47 | if [ -z "$INSTALLED_DIR" ]; then |
| 48 | echo "ERROR: NotFair plugin not found in cache"; exit 1 |
| 49 | fi |
| 50 | MARKETPLACE_DIR="$HOME/.claude/plugins/marketplaces/nowork-studio" |
| 51 | if [ ! -d "$MARKETPLACE_DIR/.git" ]; then |
| 52 | echo "ERROR: marketplace repo not found at $MARKETPLACE_DIR"; exit 1 |
| 53 | fi |
| 54 | echo "Current install: $INSTALLED_DIR" |
| 55 | echo "Marketplace repo: $MARKETPLACE_DIR" |
| 56 | |
| 57 | |
| 58 | ### Step 3: Save old version |
| 59 | |
| 60 | |
| 61 | OLD_VERSION=$(cat "$INSTALLED_DIR/VERSION" 2>/dev/null | tr -d '[:space:]' || echo "unknown") |
| 62 | |
| 63 | |
| 64 | ### Step 4: Update marketplace repo and install |
| 65 | |
| 66 | |
| 67 | cd "$MARKETPLACE_DIR" |
| 68 | git fetch origin |
| 69 | git reset --hard origin/main |
| 70 | NEW_VERSION=$(cat VERSION | tr -d '[:space:]') |
| 71 | GIT_SHA=$(git rev-parse HEAD) |
| 72 | |
| 73 | # Create new versioned cache directory |
| 74 | NEW_CACHE_DIR="$HOME/.claude/plugins/cache/nowork-studio/notfair/$NEW_VERSION" |
| 75 | if [ -d "$NEW_CACHE_DIR" ]; then |
| 76 | rm -rf "$NEW_CACHE_DIR" |
| 77 | fi |
| 78 | mkdir -p "$NEW_CACHE_DIR" |
| 79 | |
| 80 | # Copy plugin files (exclude .git to save space) |
| 81 | rsync -a --exclude='.git' "$MARKETPLACE_DIR/" "$NEW_CACHE_DIR/" |
| 82 | |
| 83 | |
| 84 | If the copy fails, warn: "Upgrade failed — the old version is still active. Run `/notfair:upgrade` manually." and stop. |
| 85 | |
| 86 | ### Step 5: Update installed_plugins.json |
| 87 | |
| 88 | Read `~/.claude/plugins/installed_plugins.json`, then update the `notfair@nowork-studio` entry: |
| 89 | |
| 90 | |
| 91 | python3 -c " |
| 92 | import json, os |
| 93 | from datetime import datetime, timezone |
| 94 | |
| 95 | path = os.path.expanduser('~/.claude/plugins/installed_plugins.json') |
| 96 | with open(path) as f: |
| 97 | data = json.load(f) |
| 98 | |
| 99 | data['plugins']['notfair@nowork-studio'] = [{ |
| 100 | 'scope': 'user', |
| 101 | 'installPath': os.path.expanduser('~/.claude/plugins/cache/nowork-studio/notfair/$NEW_VERSION'), |
| 102 | 'version': '$NEW_VERSION', |
| 103 | 'installedAt': data['plugins'].get('notfair@nowork-studio', [{}])[0].get('installedAt', datetime.now(timezone.utc).isoformat()), |
| 104 | 'lastUpdated': datetime.now(timezone.utc).isoformat(), |
| 105 | 'gitCommitSha': '$GIT_SHA' |
| 106 | }] |
| 107 | |
| 108 | with open(path, 'w') as f: |
| 109 | json.dump(data, f, indent=4) |
| 110 | print('Updated installed_plugins.json: notfair@nowork-studio -> v$NEW_VERSION') |
| 111 | " |
| 112 | |
| 113 | |
| 114 | ### Step 6: Clean up old cache versions |
| 115 | |
| 116 | Remove old versioned cache directories (keep only the new one). Never remove a `dev` symlink: |
| 117 | |
| 118 | |
| 119 | for dir in ~/.claude/plugins/cache/nowork-studio/notfair/*/; do |
| 120 | ver=$(basename "$dir") |
| 121 | if [ "$ver" != "$NEW_VERSION" ] && [ "$ver" != "dev" ]; then |
| 122 | rm -rf "$dir" |
| 123 | echo "Removed old cache: $ver" |
| 124 | fi |
| 125 | done |
| 126 | |
| 127 | |
| 128 | ### Step 7: Write marker + clear update state |
| 129 | |
| 130 | |
| 131 | mkdir -p ~/.toprank |
| 132 | echo "$OLD_VERSION" > ~/.toprank/just-upgraded-from |
| 133 | rm -f ~/.toprank/last-update-check |
| 134 | rm -f ~/.toprank/update-snoozed |
| 135 | |
| 136 | |
| 137 | ### Step 8: Show What's New |
| 138 | |
| 139 | Read `$NEW_CACHE_DIR/CHANGELOG.md`. Find all version entries between the old version and the new version. Summarize as 3-7 bullets grouped by theme — focus on user-facing changes, skip internal refactors. |
| 140 | |
| 141 | Format: |
| 142 | |
| 143 | NotFair v{new} — upgraded from v{old}! |
| 144 | |
| 145 | What's new: |
| 146 | - [bullet 1] |
| 147 | - [bullet 2] |
| 148 | - ... |
| 149 | |
| 150 | The new version will be fully active on your next Claude Code session. |
| 151 | |
| 152 | |
| 153 | ### Step 9: Continue |
| 154 | |
| 155 | After showing What's New, continue with whatever skill the user originally invoked. |
| 156 | |
| 157 | |
| 158 | |
| 159 | ## Dev symlink detection |
| 160 | |
| 161 | Before upgrading, check if the installed cache directory is a symlink named `dev`: |
| 162 | |
| 163 | |
| 164 | CACHE_DIR=$(ls -d ~/.claude/plugins/cache/nowork-studio/notfair/*/ 2>/dev/null | head -1) |
| 165 | if [ -L "${CACHE_DIR%/}" ] && [ "$(basename "$CACHE_DIR")" = "dev" ]; then |
| 166 | echo "DEV_SYMLINK" |
| 167 | fi |
| 168 | |
| 169 | |
| 170 | If `DEV_SYMLINK`: tell the user "NotFair is installed as a dev symlink — it always points to your local source (v$(cat "$CACHE_DIR/VERSION" 2>/dev/null | tr -d '[:space:]')). No upgrade needed." and **stop**. Do not proceed with Steps 2–8. |
| 171 | |
| 172 | |
| 173 | |
| 174 | ## Standalone usage |
| 175 | |
| 176 | When invoked directly as `/notfair:upgrade`: |
| 177 | |
| 178 | Check for dev symlink (see "Dev symlink detection" above). If detected, stop. |
| 179 | |
| 180 | Force a fresh update check (bypass cache and snooze): |
| 181 | |
| 182 | _UPD_BIN=$(ls ~/.claude/plugins/cache/nowork-studio/notfair/*/bin/notfair-update-check 2>/dev/null | head -1) |
| 183 | [ -n "$_UPD_BIN" ] && _UPD=$("$_UPD_BIN" --force 2>/dev/null || true) || _UPD="" |
| 184 | echo "$_UPD" |
| 185 | |
| 186 | |
| 187 | If `UPGRADE_AVAILABLE <old> <new>`: follow Steps 2–8 above. |
| 188 | |
| 189 | If no `UPGRADE_AVAILABLE` output: tell the user "You're already on the latest version (v{LOCAL})." |
| 190 |
Details
- Updated
- Sep 24, 2026
- License
- MIT
- Stars on the repo
- ★ 3,853
- Checked
- Source
- nowork-studio/notfair-plugin ↗
- Creator
- nowork-studio · 55 listings
Similar skills
See all →
SkillCross-Platform Reverse Engineer
SkillBrainstorm Ideas
SkillCode Review Feedback Analyzer
SkillBug Diagnosis Framework
SkillImplement Spec
SkillPR Description WriterMore from nowork-studio
SkillCMS Configuration Helper
SkillAds Copy Generator
SkillAmazon Ads Optimizer
SkillOff-Page SEO Auditor
SkillLink Checker
SkillChatGPT Ads Optimizer