Claude Cursor Skill

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. Use when asked to "upgrade notfair", "update notfair", or "get latest version". Also handles inline upgrade prompts wh

LLM Mart · 0 points · 24 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download nowork-studio-notfair-plugin-notfair-upgrade-skill-adf7601.zip · 3 KB
Part of nowork-studio/notfair-plugin — 88 skills

Install

skills CLI npx skills add https://github.com/nowork-studio/notfair-plugin/tree/main/notfair-upgrade-skill
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install nowork-studio-notfair-plugin@llmmart
Git git clone https://github.com/nowork-studio/notfair-plugin.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole nowork-studio/notfair-plugin collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

/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 → v..." 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:

  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)."

Files (notfair-plugin)
  • evals
    • evals.json 1.4 KB
      {
        "skill_name": "upgrade",
        "evals": [
          {
            "id": 1,
            "prompt": "Upgrade notfair to the latest version.",
            "expected_output": "The skill should detect the install type (global-git, local-git, or vendored), save the current version, run the appropriate upgrade command, and show a What's New summary from the CHANGELOG.",
            "files": [],
            "expectations": [
              "Detects the install type by checking known paths in order",
              "Saves the old version number before upgrading",
              "Runs the correct upgrade method for the detected install type",
              "Shows a What's New summary with bullet points from CHANGELOG",
              "Reports the version change (old → new)"
            ]
          },
          {
            "id": 2,
            "prompt": "Is notfair up to date?",
            "expected_output": "The skill should run a forced update check and report whether the user is on the latest version. If already up to date, it should confirm with the current version number. If an update is available, it should offer to upgrade.",
            "files": [],
            "expectations": [
              "Runs the update check script with --force flag",
              "If already latest: tells the user their current version and confirms it's up to date",
              "If update available: shows old vs new version and offers to upgrade",
              "Does not attempt an upgrade without user confirmation when just checking"
            ]
          }
        ]
      }
      
  • SKILL.md 5.6 KB
    ---
    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.
    
    ## 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.
    
    ```bash
    # 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
    
    ```bash
    OLD_VERSION=$(cat "$INSTALLED_DIR/VERSION" 2>/dev/null | tr -d '[:space:]' || echo "unknown")
    ```
    
    ### Step 4: Update marketplace repo and install
    
    ```bash
    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:
    
    ```bash
    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:
    
    ```bash
    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
    
    ```bash
    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`:
    
    ```bash
    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):
    ```bash
    _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"
    ```
    
    3. If `UPGRADE_AVAILABLE <old> <new>`: follow Steps 2–8 above.
    
    4. If no `UPGRADE_AVAILABLE` output: tell the user "You're already on the latest version (v{LOCAL})."
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related