ops-rotate — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ops-rotate (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Manage the optional multi-account Claude Max rotator. Off by default — flip account_rotation_enabled in plugin settings to use it.
$ARGUMENTS | Action |
|---|---|
(none) or status | Show current account, 5h%/7d%, total rotations, daemon health |
rotate-now | Force rotation to the most-cooled candidate (or --to <email>) |
list | List every configured account with token state + last util |
add-account | Interactive wizard: collect email, OAuth into rotator vault |
crs | Show the CRS relay-pool schedulable state + priority-daemon health |
crs-tick | Run one CRS priority tick now (append --dry-run to preview, no writes) |
This skill manages two complementary account-management systems:
status/rotate-now/list/add-account) — for direct-authsessions. One active claude.ai OAuth token in the keychain at a time; the daemon swaps to the coolest account when the active one heats up.
crs/crs-tick) — for a claude-relay-service pool, whichload-balances across _many_ accounts simultaneously. Instead of swapping one token, it toggles each account's schedulable flag from live utilization so the relay avoids near-maxed accounts and re-enables them on recovery. Off by default; see ops-rotate-setup to configure + install.
account_rotation_enabled from plugin preferences. If false, tell the user how to enable and exit.ROT_DIR=${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops}/account-rotationROT_SRC=${CLAUDE_PLUGIN_ROOT}/scripts/account-rotation$ROT_DIR doesn't exist yet, mirror the runtime layout: mkdir -p "$ROT_DIR"
cp "$ROT_SRC/config.example.json" "$ROT_DIR/config.json" # only if missingnode --version. If missing, fail fast with install hint.Run:
node "$ROT_SRC/rotate.mjs" --status
node "$ROT_SRC/rotate.mjs" --utilization 2>/dev/null | head -40
launchctl list 2>/dev/null | grep com.claude-ops.account-rotation || echo "daemon: not loaded"Render a compact panel:
ROTATOR STATUS
Active account : <email>
5h utilization : 42% (resets in 1h 23m)
7d utilization : 18%
Total rotations: 14
Daemon : ✓ running (PID 12345) | ✗ not loaded
Configured : 4 accounts (3 with valid tokens, 1 expired)If user passed an explicit target email (/ops:rotate rotate-now [email protected]), pass --to "<email>". Otherwise let rotate.mjs pick the most-cooled.
bash "$ROT_SRC/force-rotate.sh" "${TARGET_EMAIL:-}"Show the trailing status output. Remind the user that running Claude Code sessions hold their own access token until next /login or until they exit and re-enter.
node "$ROT_SRC/rotate.mjs" --status 2>/dev/nullThen for each account in $ROT_DIR/config.json, render one row:
[✓] [email protected] 5h 12% token valid 6.4h (active)
[✓] [email protected] 5h 87% token valid 3.1h
[✗] [email protected] ── ── token expired 2d ago
[○] [email protected] ── ── no token capturedIf any row is [○] or [✗], suggest running /ops:rotate add-account for that email.
This is the only mutating subcommand. Walk the user through:
AskUserQuestion: "Email of the Claude Max account to add?" (free text via Edit to config — the skill must NOT capture sensitive data through chat options; just ask for the email).AskUserQuestion: [Personal], [Workspace], [Skip]). If Workspace, prompt for orgName (free text) — orgUuid is auto-discovered later.$ROT_DIR/config.json, append the new account entry to accounts[], write back. Use the schema from config.example.json._account_schema_example.AskUserQuestion:[Use current Claude Code login] — runs node "$ROT_SRC/rotate.mjs" --capture --to <email> to copy the live Claude Code-credentials token into the rotator vault.[Run OAuth in browser now] — runs node "$ROT_SRC/rotate.mjs" --setup --only=<email> (background-friendly; opens Chrome).[Skip — I'll capture later].com.claude-ops.account-rotation, ask [Install + start daemon] / [Skip]. On install: sed "s|\${HOME}|$HOME|g" "${CLAUDE_PLUGIN_ROOT}/templates/com.claude-ops.account-rotation.plist" > ~/Library/LaunchAgents/com.claude-ops.account-rotation.plist
launchctl load ~/Library/LaunchAgents/com.claude-ops.account-rotation.plistMirror daemon.mjs + friends to $ROT_DIR if not already symlinked:
for f in rotate.mjs daemon.mjs ai-brain.mjs force-rotate.sh; do
[ -e "$ROT_DIR/$f" ] || ln -s "$ROT_SRC/$f" "$ROT_DIR/$f"
donestatus subcommand inline.Show the claude-relay-service pool's per-account schedulable state + the priority daemon's health. Read-only.
WRAP="$ROT_SRC/crs-priority-daemon.sh"
bash "$WRAP" --status 2>&1 | head -40 # prints "● name sched=true 5h=NN% <status>"
launchctl list 2>/dev/null | grep com.claude-ops.crs-priority || echo "crs-priority daemon: not loaded"
tail -n 5 "${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/logs/crs-priority.log" 2>/dev/nullRender a compact panel:
CRS POOL (http://127.0.0.1:3000)
schedulable : 7 / 10
off : canary-sponsors (rate-limited), pool-chairman (warning), pool-foundation (warning)
daemon : ✓ running (every 120s) | ✗ not loaded — run /ops:rotate-setupIf CRS /health is unreachable, say so and point to ops-rotate-setup. If the daemon isn't loaded but crs.enabled is true, suggest /ops:rotate-setup.
Apply (or, with --dry-run, preview) one prioritization pass immediately — useful right after changing thresholds or to confirm the policy.
bash "$ROT_SRC/crs-priority-daemon.sh" ${ARGS:-} # ARGS="--dry-run" to previewThis is the same code the launchd timer runs; the daemon only ever toggles schedulable (fully reversible) and never deletes or mutates account credentials.
rotate.mjs uses Playwright only for the browser fallback. It is declared as an optional dep in the plugin's package.json. If a browser fallback is needed and Playwright is missing, the skill should offer:
npm install --prefix "$CLAUDE_PLUGIN_ROOT" --no-save playwright
npx --prefix "$CLAUDE_PLUGIN_ROOT" playwright install chromiumadd-account mutates config.json, and only after the user explicitly confirmed the email.config.json outside add-account — token rotation is the daemon's job, not the skill's.account_rotation_enabled is false, refuse to run subcommands and instead explain the toggle.CLAUDE_ROTATOR_KEYCHAIN_ACCOUNT as the override env var.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.