Skip to content
Back to skills

Update

ASecurity

Use when asked to update little-loops, the plugin, or the pip package.

  • 6 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 6, 2026
ai-agentspythonbash

Works with

  • claude code

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned October 6, 2026

npx -y skills add BrennonTWilliams/little-loops --skill update --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Update?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Update
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/brennontwilliams-update/badge)](https://www.skillsdirectory.com/skills/brennontwilliams-update)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: update
description: Use when asked to update little-loops, the plugin, or the pip package.
disable-model-invocation: true
argument-hint: "[flags]"
allowed-tools:
  - Bash(python3:*)
  - Bash(pip:*)
  - Bash(pip3:*)
  - Bash(claude:*)
arguments:
  - name: flags
    description: "Optional flags: --plugin, --package, --all, --dry-run"
    required: false
metadata:
  short-description: Use when asked to update little-loops, the plugin, or the pip package.
---

# Update little-loops

<!-- PLUGIN_VERSION: 1.106.0 -->

Update the little-loops Claude Code plugin and pip package to the latest version.

## Arguments

$ARGUMENTS

- **flags** (optional): Command flags
  - `--plugin` - Update only the little-loops Claude Code plugin (`claude plugin update ll@little-loops`)
  - `--package` - Update only the little-loops pip package (`pip install`)
  - `--all` - Update both components (same as providing no flag)
  - `--dry-run` - Show what would be updated without making any changes

**Default behavior**: If no component flag (`--plugin`, `--package`, `--all`) is given, both components are updated.

## Process

### 1. Parse Flags

```bash
FLAGS="${flags:-}"
DO_PLUGIN=false
DO_PACKAGE=false
DRY_RUN=false

if [[ "$FLAGS" == *"--dry-run"* ]]; then DRY_RUN=true; fi
if [[ "$FLAGS" == *"--plugin"* ]]; then DO_PLUGIN=true; fi
if [[ "$FLAGS" == *"--package"* ]]; then DO_PACKAGE=true; fi
if [[ "$FLAGS" == *"--all"* ]]; then DO_PLUGIN=true; DO_PACKAGE=true; fi

# Default: update both if no component flag given
if [[ "$DO_PLUGIN" == false ]] && [[ "$DO_PACKAGE" == false ]]; then
    DO_PLUGIN=true
    DO_PACKAGE=true
fi
```

Track results for the summary report:
```
PLUGIN_RESULT="SKIP"
PACKAGE_RESULT="SKIP"
```

### 2. Read Current Versions

```bash
# Installed pip package version
PKG_VERSION=$(python3 -c "import importlib.metadata; print(importlib.metadata.version('little-loops'))" 2>/dev/null || echo "not installed")

# Installed plugin version
INSTALLED_PLUGIN_VERSION=$(claude plugin list 2>/dev/null | grep -A1 "ll@little-loops" | grep "Version:" | awk '{print $2}')
```

Print current state:
```
Current versions:
  Plugin (installed):   $INSTALLED_PLUGIN_VERSION
  Package (installed):  $PKG_VERSION
```

---

### 3. Update Plugin (Step A — --plugin)

**Skip this entire step if** `$DO_PLUGIN == false`. Set `PLUGIN_RESULT="SKIP"` and proceed to Step 4.

```bash
echo "========================================"
echo "PLUGIN UPDATE"
echo "========================================"
```

- If `$DRY_RUN == true`:
  - Print `[DRY-RUN] Would run: claude plugin update ll@little-loops`
  - Set `PLUGIN_RESULT="DRY-RUN"`
  - Proceed to Step 4

- If `$DRY_RUN == false`:
  - Run: `claude plugin update ll@little-loops`
  - On success (exit code 0):
    - Read updated version: `UPDATED_PLUGIN_VERSION=$(claude plugin list 2>/dev/null | grep -A1 "ll@little-loops" | grep "Version:" | awk '{print $2}')`
    - Print `[PASS] Plugin updated: $INSTALLED_PLUGIN_VERSION → $UPDATED_PLUGIN_VERSION`
    - Set `PLUGIN_RESULT="PASS ($INSTALLED_PLUGIN_VERSION → $UPDATED_PLUGIN_VERSION)"`
  - On failure:
    - Print `[FAIL] Plugin update failed — try reinstalling: claude plugin install ll@little-loops`
    - Set `PLUGIN_RESULT="FAIL"`

Continue to Step 4 regardless.

---

### 4. Update Package (Step B — --package)

**Skip this entire step if** `$DO_PACKAGE == false`. Set `PACKAGE_RESULT="SKIP"` and proceed to Step 5.

```bash
echo "========================================"
echo "PACKAGE UPDATE"
echo "========================================"
```

Detect install command based on whether little-loops is installed in editable mode:
```bash
EDITABLE_INSTALL=$(pip show little-loops 2>/dev/null | grep -E "^Editable project location:")
if [ -n "$EDITABLE_INSTALL" ]; then
    EDITABLE_PATH=$(echo "$EDITABLE_INSTALL" | sed 's/^Editable project location: //')
    INSTALL_CMD="pip install -e '$EDITABLE_PATH'"  # ll-audience-ok: reinstalls an existing editable install in place
else
    INSTALL_CMD="pip install --upgrade little-loops"
fi
```

Read version before update:
```bash
PKG_BEFORE=$(python3 -c "import importlib.metadata; print(importlib.metadata.version('little-loops'))" 2>/dev/null || echo "not installed")
```

- If `$DRY_RUN == true`:
  - Print `[DRY-RUN] Would run: $INSTALL_CMD`
  - Set `PACKAGE_RESULT="DRY-RUN"`
  - Proceed to Step 5

- If `$DRY_RUN == false`:
  - Run `$INSTALL_CMD`
  - On success:
    - Read new version: `PKG_AFTER=$(python3 -c "import importlib.metadata; print(importlib.metadata.version('little-loops'))" 2>/dev/null || echo "unknown")`
    - Print `[PASS] Package updated: $PKG_BEFORE → $PKG_AFTER`
    - Set `PACKAGE_RESULT="PASS ($PKG_BEFORE → $PKG_AFTER)"`
  - On failure:
    - Print `[FAIL] Package update failed — run manually: $INSTALL_CMD`
    - Set `PACKAGE_RESULT="FAIL"`

Continue to Step 5 regardless.

---

### 5. Summary Report

```
================================================================================
UPDATE COMPLETE
================================================================================

Dry-run: $DRY_RUN

Results:
  Plugin:   $PLUGIN_RESULT
  Package:  $PACKAGE_RESULT

Status key:
  PASS      — Updated successfully
  SKIP      — Step not selected
  FAIL      — Update failed (see errors above for manual steps)
  DRY-RUN   — Would have updated (re-run without --dry-run to apply)
  WARN      — Config has unknown keys (check ll-config.json)

================================================================================
```

---

### Step 6: Config Health Check

If either `$PLUGIN_RESULT` or `$PACKAGE_RESULT` starts with `"PASS"`:

```bash
if [[ "$PLUGIN_RESULT" == PASS* ]] || [[ "$PACKAGE_RESULT" == PASS* ]]; then
python3 -c "
import json, pathlib, sys

config_path = pathlib.Path('.ll/ll-config.json')
if not config_path.exists():
    sys.exit(0)

# Locate config-schema.json via plugin installation registry
plugins_file = pathlib.Path.home() / '.claude' / 'plugins' / 'installed_plugins.json'
if not plugins_file.exists():
    sys.exit(0)
plugins = json.loads(plugins_file.read_text()).get('plugins', {})
entry = plugins.get('ll@little-loops', [])
if not entry:
    sys.exit(0)
schema_path = pathlib.Path(entry[0]['installPath']) / 'config-schema.json'
if not schema_path.exists():
    sys.exit(0)

config = json.loads(config_path.read_text())
schema = json.loads(schema_path.read_text())
known = set(schema.get('properties', {}).keys())
unknown = sorted(set(config.keys()) - known)
if unknown:
    print('[WARN] Config issues detected: unknown keys: ' + ', '.join(unknown))
else:
    print('[PASS] ll-config.json is valid')
" 2>/dev/null || true
fi
```

Non-blocking — does not fail the update. Silent skip if `.ll/ll-config.json` or the schema is absent.

---

## Examples

```bash
# Update both plugin and package
/ll:update

# Update only the pip package
/ll:update --package

# Update only the Claude Code plugin
/ll:update --plugin

# Preview what would be updated
/ll:update --dry-run
```

Files in this skill

  • SKILL.md6.9 KB
  • agents/openai.yaml130 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…