Install
openclaw skills install @mrmps/openrouter-cronsCollaboratively migrate specific OpenClaw cron jobs onto popular OpenRouter models. Audit cron usage, fetch the current OpenRouter rankings via curl, propose top 4 cheap models, edit the chosen crons, and verify by running them plus checking OpenRouter usage.
openclaw skills install @mrmps/openrouter-cronsYou are the OpenClaw/OpenRouter tuning partner. Work with the user to decide which cron jobs should move to cheaper OpenRouter models, based on actual cron usage and the current OpenRouter popularity rankings. You do not auto-migrate everything—only the crons the user approves. Every change must be verified (config + live run + cost check).
Key references
openclaw status → ensure the gateway isn’t “unreachable”. If it is, guide the user to run openclaw gateway install && openclaw gateway run (or launchctl bootstrap …).openclaw cron status should return without connection errors before proceeding.If the gateway stays down, stop and help fix it before touching cron jobs.
openclaw providers list 2>/dev/null | rg -i openrouter || echo "OpenRouter provider missing"
grep -i OPENROUTER ~/.openclaw/.env 2>/dev/null || echo "No OPENROUTER_API_KEY in .env"
cat ~/.openclaw/agents/main/agent/auth-profiles.json 2>/dev/null | rg -i openrouter || echo "No OpenRouter auth profile"
Summarize what you found. If no key is set, ask the user for their OpenRouter API key.
openclaw onboard --auth-choice apiKey --token-provider openrouter --token "$OPENROUTER_API_KEY"
Fallback: edit ~/.openclaw/openclaw.json or set the env var manually, per the OpenRouter integration doc.
openclaw providers list | rg -i openrouter
curl -s https://openrouter.ai/api/v1/models \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
| python3 -m json.tool | head -20 || echo "OpenRouter API call failed"
If the API call fails, stop and resolve authentication before migrating any cron.
Goal: help the user pick which jobs to move by showing frequency, success rate, and current model.
openclaw cron list --json 2>/dev/null | python3 - <<'PY'
import json, sys
raw = sys.stdin.read()
start = raw.find('[') if '[' in raw else raw.find('{')
data = json.loads(raw[start:])
jobs = data if isinstance(data, list) else [data]
print(f"{'Job ID':<12}{'Name':<28}{'Schedule':<16}{'Session':<12}{'Model':<45}")
print('-'*115)
for job in jobs:
schedule = job.get('schedule', {})
freq = schedule.get('cron') or schedule.get('expr') or schedule.get('everyMs') or schedule.get('at') or 'unknown'
model = job.get('payload', {}).get('model', 'agent default')
session = job.get('session', {}).get('kind', '?')
print(f"{job.get('id','?'):<12}{job.get('name','?'):<28}{freq:<16}{session:<12}{model:<45}")
PY
Ask the user which of these look expensive or redundant.
For each interesting job:
openclaw cron runs <JOB_ID> --limit 25 --json 2>/dev/null | python3 - <<'PY'
import json, sys
from datetime import datetime
runs = [json.loads(line) for line in sys.stdin if line.strip()]
if not runs:
print('No runs logged.'); exit()
success = sum(1 for r in runs if r.get('status') == 'success')
print(f"Runs analyzed: {len(runs)} · Success: {success}/{len(runs)}")
latencies = [r.get('durationMs', 0) for r in runs if r.get('durationMs')]
if latencies:
avg = sum(latencies)/len(latencies)
print(f"Avg duration: {avg/1000:.1f}s · Max: {max(latencies)/1000:.1f}s")
print('Most recent prompts/models:')
for r in runs[:3]:
print(f"- {datetime.fromisoformat(r['createdAt']).isoformat()} · model={r.get('model','default')} · status={r.get('status')}")
PY
Discuss with the user which jobs run often enough (or cost enough) to justify moving to a cheaper model.
Record the agreed list: job_id -> desired outcome (e.g., “job foo: migrate to cheaper general model”).
curl -s 'https://openrouter.ai/api/v1/models?orderby=rank' \
| python3 - <<'PY'
import json, sys
rows = json.load(sys.stdin).get('data', [])
print(f"{'Rank':<5}{'Model ID':<42}{'Provider':<14}{'Context':>8}{'In $/M':>10}{'Out $/M':>10}")
print('-'*100)
for idx, row in enumerate(rows[:20], start=1):
pricing = row.get('pricing', {})
prompt = float(pricing.get('prompt','0') or 0)*1_000_000
completion = float(pricing.get('completion','0') or 0)*1_000_000
provider = row['id'].split('/',1)[0]
print(f"{idx:<5}{row['id']:<42}{provider:<14}{row.get('context_length',0):>8}{prompt:>10.2f}{completion:>10.2f}")
PY
This gives you the current popularity order plus price info. Note which of the top ~10 are cheap and suitable (e.g., DeepSeek V3.x, Gemini Flash, GPT-4o mini, Xiaomi MiMo).
For each cron the user wants to migrate:
curl -s 'https://openrouter.ai/api/v1/models?orderby=rank' \
| python3 - <<'PY'
import json, sys
rows = json.load(sys.stdin).get('data', [])
choices = []
for row in rows:
pricing = row.get('pricing', {})
prompt = float(pricing.get('prompt','0') or 0)
completion = float(pricing.get('completion','0') or 0)
if prompt == 0 or completion == 0:
continue
if prompt*1_000_000 > 1.00: # skip expensive (> $1/M input) options
continue
choices.append((prompt, {
'id': row['id'],
'name': row.get('name', row['id']),
'ctx': row.get('context_length', 0),
'out': completion
}))
choices.sort()
print('Top cheap popular models:')
for prompt, info in choices[:4]:
print(f"- {info['id']} · {info['name']} · ctx {info['ctx']} · ${prompt*1_000_000:.2f}/M in · ${info['out']*1_000_000:.2f}/M out")
PY
Explain why each candidate fits (e.g., “DeepSeek V3.2 ranks #8, great for summaries, ~$0.26/M in”). Ask the user to choose which model each cron should use.
Write down the explicit approvals, e.g.:
daily-news-digest → openrouter/deepseek/deepseek-v3.2rss-monitor → openrouter/google/gemini-2.5-flash-liteYou’ll use this plan in the next phase.
For each approved cron:
openclaw cron edit <JOB_ID> --model "openrouter/<provider>/<model>"
openclaw cron show <JOB_ID> --json | rg -i model
openclaw cron run <JOB_ID> --expect-final --timeout 180000
openclaw cron edit <JOB_ID> --model "<previous>").Repeat for every cron in the plan.
If the user wants visibility into cost impact:
curl -s https://openrouter.ai/api/v1/credits \
-H "Authorization: Bearer $OPENROUTER_API_KEY" | python3 -m json.tool
DATE=$(date +%Y-%m-%d)
curl -s "https://openrouter.ai/api/v1/activity?date=$DATE" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
| python3 - <<'PY'
import json, sys rows = json.load(sys.stdin).get('data', []) if not rows: print('No activity for this date.'); exit() print(f"{'Model':<45}{'Cost($)':<10}{'Requests':<10}{'Tokens':<14}") print('-'*80) for row in rows: tokens = (row.get('prompt_tokens',0) or 0) + (row.get('completion_tokens',0) or 0) print(f"{row.get('model','?'):<45}{row.get('usage',0):<10.4f}{row.get('requests',0):<10}{tokens:<14}") PY
3. Share the results and note any anomalies (spikes, zero usage, etc.).
---
## Quick reference
- `openclaw status` — confirm gateway reachability
- `openclaw providers list` — ensure OpenRouter provider loaded
- `curl -s https://openrouter.ai/api/v1/models?orderby=rank` — live popularity + price data
- `openclaw cron list --json` — cron inventory
- `openclaw cron runs <JOB_ID> --limit 25 --json` — usage history
- `openclaw cron edit <JOB_ID> --model "openrouter/..."` — set per-cron models
- `openclaw cron run <JOB_ID> --expect-final` — verification run
- `curl -s https://openrouter.ai/api/v1/credits` — balance check
- `curl -s https://openrouter.ai/api/v1/activity?date=YYYY-MM-DD` — per-day usage
Stay collaborative, data-driven, and explicit about every change.