NotFair Upgrade Tool

upgrade

by nowork-studio · MIT license · ★ 3,853 on GitHub · updated Sep 24

upgrade cover

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)
Claude Codenpx skills add nowork-studio/notfair-plugin --skill upgrade -g -a claude-code
Claude Code (degit)npx degit nowork-studio/notfair-plugin/notfair-upgrade-skill#main ~/.claude/skills/upgrade-nowork-studio
Claude.ai / desktopZip the folder and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md5.6 KB
Read SKILL.md here
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 
View all files on GitHub →

Details

Updated
Sep 24, 2026
License
MIT
Stars on the repo
★ 3,853
Checked
Source
nowork-studio/notfair-plugin ↗
Creator
nowork-studio · 55 listings
View creator

Similar skills

See all →

More from nowork-studio

SkillCMS Configuration Helpernowork-studio/notfair-plugin · by nowork-studioConnect a CMS to notfair SEO tools. Guides users through configuring WordPress, Strapi, Contentful, or Ghost — tests the connection, and writes credentials to .env.local. Once set up, seo-analysis automatically cross- references CMS content against Google Search Console data. Use whenever the user says "connect my CMS", "set up WordPress", "configure Strapi", "add Contentful", "connect Ghost", or "CMS setup". Also trigger if the user asks why no CMS data appears in a seo-analysis report.★ 3.9k GitHub starsSkillAds Copy Generatornowork-studio/notfair-plugin · by nowork-studioGenerate and A/B test Google Ads copy. Use when asked to write ad copy, headlines, descriptions, create ad variants, test ad messaging, improve CTR, or generate RSA (Responsive Search Ad) components. Trigger on "ad copy", "write ads", "headlines", "descriptions", "RSA", "responsive search ad", "ad text", "ad creative", "improve CTR", "ad A/B test", "ad variants", "write me an ad", "ad variation experiment", or when the user wants to improve click-through rate on existing ads.★ 3.9k GitHub starsSkillAmazon Ads Optimizernowork-studio/notfair-plugin · by nowork-studioPlan and review Amazon Ads with margin-aware ACoS, product, and search-term guardrails. Use for Amazon advertising, Sponsored Products, Sponsored Brands, Sponsored Display, ASIN targeting, Amazon ACoS, or Amazon Ads performance exports.★ 3.9k GitHub starsSkillOff-Page SEO Auditornowork-studio/notfair-plugin · by nowork-studioBacklink / off-page SEO audit. Works WITHOUT a paid tool by default — it uses the Google Search Console Links report (your top linking sites, most-linked pages, and anchor text) plus any backlink export the user provides (Ahrefs / Semrush / Majestic / DataForSEO CSV). Analyzes referring-domain profile, anchor-text distribution (over-optimized / spammy patterns), most-linked pages vs. money pages (internal-linking opportunity), toxic/spam link signals, and link-building priorities. Use this skill when the user asks about backlinks, link building, off-page SEO, referring domains, anchor text, toxic/spam links, disavow, or their link profile. Trigger on: "backlinks", "backlink audit", "link building", "off- page SEO", "referring domains", "anchor text", "toxic links", "spam links", disavow file", "who links to me", "link profile", "domain authority". NOTE: rich third-party metrics (DR/DA, full link index) require a paid data source; this skill is explicit about what it can and can't see without one.★ 3.9k GitHub starsSkillLink Checkernowork-studio/notfair-plugin · by nowork-studioScans a website to find broken links (404s, 500s). Crawls internal pages, identifies broken outbound links, and reports source pages for easy fixing. Use this when the user asks to "check for broken links", "find 404s", audit my links", or "is my site healthy".★ 3.9k GitHub starsSkillChatGPT Ads Optimizernowork-studio/notfair-plugin · by nowork-studioPlan and review ChatGPT Ads experiments without assuming ad inventory, account access, or platform capabilities. Use for ChatGPT advertising, OpenAI ads, conversational ad concepts, ChatGPT campaign plans, or performance reviews from a verified export.★ 3.9k GitHub stars