From smurf
Pattern for calling OpenRouter from a Bash tool to keep Claude token cost low on tier-3 work (release notes, support summaries). Loaded by marketing, sales-feedback.
How this skill is triggered — by the user, by Claude, or both
Slash command
/smurf:openrouter-curlThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This pattern lets a Claude Code subagent generate content using a cheap
This pattern lets a Claude Code subagent generate content using a cheap OpenRouter model without routing through Claude. The subagent stays in Claude (cheap orchestration tokens); the actual generation happens at Gemini-Flash / Haiku-4.5 prices (~10× cheaper).
OPENROUTER_API_KEY exported in the agent's environment.tools includes Bash restricted to
Bash(curl https://openrouter.ai/api/v1/*).curl and jq.| Use case | Model id | Why |
|---|---|---|
| short-form copy (tweet, release-note) | google/gemini-2.5-flash | cheapest, decent voice |
| longer reasoning under 2k tokens | anthropic/claude-haiku-4.5 | reliable, no jailbreak guardrails to fight |
| code-adjacent prose, technical | deepseek/deepseek-v4-pro | strong on technical tone |
Always pin a specific model id — :latest aliases drift.
RESPONSE=$(curl -sS https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-H "HTTP-Referer: https://github.com/<owner>/<repo>" \
-H "X-Title: smurf-orchestrator" \
-d @- <<'JSON'
{
"model": "google/gemini-2.5-flash",
"messages": [
{"role": "system", "content": "You are a developer-relations writer. Tone: technical, accessible. No marketese."},
{"role": "user", "content": "Write 3 release-note variants for the change described below.\n\n<feature summary>"}
],
"temperature": 0.5,
"max_tokens": 600
}
JSON
)
echo "$RESPONSE" | jq -r '.choices[0].message.content' > docs/marketing/<date>-<slug>/release-notes.md
COST=$(echo "$RESPONSE" | jq -r '.usage.total_cost // 0')
echo "openrouter cost: \$$COST"
If the response shape is unexpected (rate limit, auth fail), jq returns
null — handle by inspecting the raw response:
if [ "$(echo "$RESPONSE" | jq -r '.choices[0].message.content // empty')" = "" ]; then
echo "openrouter call failed:" >&2
echo "$RESPONSE" | jq . >&2
exit 1
fi
OpenRouter free tier: ~50 req/day across all models. Paid: per-key cap configurable. If hit:
# TODO: regenerate when rate-limit resets header and exit 0 (don't fail the whole run for a
tier-3 task).| Agent | Calls per run | Tokens per call | Cost on Gemini Flash |
|---|---|---|---|
| marketing | 5 (release notes×3, tweet, linkedin, changelog, demo script) | ~600 out / 800 in | <$0.01 total |
| sales-feedback | 1–3 (theme summarization) | ~1500 out / 3000 in | <$0.05 total |
If you see a single curl above $0.10, something is wrong — likely
unbounded max_tokens or a recursion. Check the request body.
Authorization.npx claudepluginhub abaddon/smurf --plugin smurfProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.