upgrade skill

Upgrade the NotFair plugin to the latest version.

by nowork-studio·MIT license·★ 3,853 Stars on the repo·GitHub ↗

Use now

Files of upgrade

nowork-studio/main1 file shown
SKILL.md
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.


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:

  1. Check for dev symlink (see "Dev symlink detection" above). If detected, stop.

  2. 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"
  1. If UPGRADE_AVAILABLE <old> <new>: follow Steps 2–8 above.

  2. If no UPGRADE_AVAILABLE output: tell the user "You're already on the latest version (v{LOCAL})."

1---
2name: upgrade
3argument-hint: "<or just run '/notfair:upgrade'>"
4description: >
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.
9allowed-tools:
10 - Bash
11 - Read
12 - AskUserQuestion
13---
14 
15# /notfair:upgrade
16 
17Upgrade 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 
32This section is used when a skill preamble outputs `UPGRADE_AVAILABLE`.
33 
34### Step 1: Auto-upgrade
35 
36Log "Upgrading NotFair v{old} → v{new}..." and proceed to Step 2.
37 
38---
39 
40### Step 2: Detect current install
41 
42First check for dev symlink (see "Dev symlink detection" section). If detected, stop — do not upgrade.
43 
44```bash
45# Find the currently installed plugin path
46INSTALLED_DIR=$(ls -d ~/.claude/plugins/cache/nowork-studio/notfair/*/ 2>/dev/null | grep -v '.bak' | head -1)
47if [ -z "$INSTALLED_DIR" ]; then
48 echo "ERROR: NotFair plugin not found in cache"; exit 1
49fi
50MARKETPLACE_DIR="$HOME/.claude/plugins/marketplaces/nowork-studio"
51if [ ! -d "$MARKETPLACE_DIR/.git" ]; then
52 echo "ERROR: marketplace repo not found at $MARKETPLACE_DIR"; exit 1
53fi
54echo "Current install: $INSTALLED_DIR"
55echo "Marketplace repo: $MARKETPLACE_DIR"
56```
57 
58### Step 3: Save old version
59 
60```bash
61OLD_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```bash
67cd "$MARKETPLACE_DIR"
68git fetch origin
69git reset --hard origin/main
70NEW_VERSION=$(cat VERSION | tr -d '[:space:]')
71GIT_SHA=$(git rev-parse HEAD)
72 
73# Create new versioned cache directory
74NEW_CACHE_DIR="$HOME/.claude/plugins/cache/nowork-studio/notfair/$NEW_VERSION"
75if [ -d "$NEW_CACHE_DIR" ]; then
76 rm -rf "$NEW_CACHE_DIR"
77fi
78mkdir -p "$NEW_CACHE_DIR"
79 
80# Copy plugin files (exclude .git to save space)
81rsync -a --exclude='.git' "$MARKETPLACE_DIR/" "$NEW_CACHE_DIR/"
82```
83 
84If 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 
88Read `~/.claude/plugins/installed_plugins.json`, then update the `notfair@nowork-studio` entry:
89 
90```bash
91python3 -c "
92import json, os
93from datetime import datetime, timezone
94 
95path = os.path.expanduser('~/.claude/plugins/installed_plugins.json')
96with open(path) as f:
97 data = json.load(f)
98 
99data['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 
108with open(path, 'w') as f:
109 json.dump(data, f, indent=4)
110print('Updated installed_plugins.json: notfair@nowork-studio -> v$NEW_VERSION')
111"
112```
113 
114### Step 6: Clean up old cache versions
115 
116Remove old versioned cache directories (keep only the new one). Never remove a `dev` symlink:
117 
118```bash
119for 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
125done
126```
127 
128### Step 7: Write marker + clear update state
129 
130```bash
131mkdir -p ~/.toprank
132echo "$OLD_VERSION" > ~/.toprank/just-upgraded-from
133rm -f ~/.toprank/last-update-check
134rm -f ~/.toprank/update-snoozed
135```
136 
137### Step 8: Show What's New
138 
139Read `$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 
141Format:
142```
143NotFair v{new} — upgraded from v{old}!
144 
145What's new:
146- [bullet 1]
147- [bullet 2]
148- ...
149 
150The new version will be fully active on your next Claude Code session.
151```
152 
153### Step 9: Continue
154 
155After showing What's New, continue with whatever skill the user originally invoked.
156 
157---
158 
159## Dev symlink detection
160 
161Before upgrading, check if the installed cache directory is a symlink named `dev`:
162 
163```bash
164CACHE_DIR=$(ls -d ~/.claude/plugins/cache/nowork-studio/notfair/*/ 2>/dev/null | head -1)
165if [ -L "${CACHE_DIR%/}" ] && [ "$(basename "$CACHE_DIR")" = "dev" ]; then
166 echo "DEV_SYMLINK"
167fi
168```
169 
170If `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 
176When invoked directly as `/notfair:upgrade`:
177 
1781. Check for dev symlink (see "Dev symlink detection" above). If detected, stop.
179 
1802. Force a fresh update check (bypass cache and snooze):
181```bash
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=""
184echo "$_UPD"
185```
186 
1873. If `UPGRADE_AVAILABLE <old> <new>`: follow Steps 2–8 above.
188 
1894. If no `UPGRADE_AVAILABLE` output: tell the user "You're already on the latest version (v{LOCAL})."
190 

Discussion