🔥🔥 A Claude Skill that teaches Claude Code how to write LLM features
SaferSkills independently audited rails-llm-integration (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.
Teaches Claude to write LLM integrations the Rails Way -- treating LLM calls like first-class Rails citizens alongside ActionMailer (email), ActiveJob (background work), and ActionController (HTTP). Instead of scattered API calls, you get conventions.
app/
services/
llm/
base_service.rb # All LLM calls inherit from this
concerns/ # Traceable, Retryable, CostTrackable
product_description_service.rb
ticket_triage_service.rb
errors.rb # Typed error hierarchy
result.rb # Result monad
jobs/
llm/
base_job.rb # Async LLM calls inherit from this
generate_description_job.rb
prompts/ # Prompts as views (ERB templates)
product_descriptions/
generate.text.erb
generate.system.erb
ticket_triage/
classify.text.erb
config/
llm.yml # Model config like database.yml
initializers/
llm.rb # Boot-time config validation
lib/
llm/
client.rb # Client factory: LLM::Client.for(model)
clients/
openai_client.rb # Wraps ruby-openai gem
anthropic_client.rb # Wraps anthropic-rb gem
ruby_llm_client.rb # Wraps ruby_llm gem (multi-provider)
langchain_client.rb # Wraps langchain-rb gem
proxy_client.rb # LiteLLM/Portkey via Faraday
stub_client.rb # Test double
config.rb # Loads config/llm.yml
router.rb # Task-based model routing
cost_tracker.rb # Redis-backed cost tracking
prompt_renderer.rb # ERB-based prompt rendering
db/
migrate/
create_llm_batches.rb # Batch job tracking
create_llm_dead_letters.rb # Permanent failure tracking
create_llm_eval_cases.rb # Eval dataset storage
create_llm_experiment_logs.rb # Shadow experiment resultsrails generate llm:install # Sets up everything above
rails generate llm:service ProductDescription generation # Scaffold a new service| File | Read When You Need To... |
|---|---|
references/client-setup.md | Wire up ruby_llm, langchain-rb, ruby-openai, anthropic-rb, or proxy clients (start here) |
references/service-patterns.md | Build LLM service objects with Result, tracing, retries |
references/job-patterns.md | Make LLM calls async with ActiveJob + Sidekiq |
references/proxy-routing.md | Route between models, optimize costs, set budgets |
references/eval-pipeline.md | Set up Braintrust evals and quality scoring |
references/prompt-management.md | Manage prompts as ERB templates (prompts-as-views) |
references/testing-guide.md | Test LLM features with stubs, VCR, and CI strategy |
references/generators.md | Rails generators for llm:install and llm:service |
templates/migrations/ | Database schemas for batches, dead letters, eval cases |
scripts/audit_llm_usage.rb | Scan a Rails app for LLM anti-patterns |
Rails patterns are the chassis. Use service objects, ActiveJob, ERB templates, and YAML config. The gem handles the API; the convention handles everything else.
actively waiting (streaming). Never block a web request on a 3-second API call.
cheap models. Set daily budgets. Alert before you hit them.
from production traces. Score quality automatically. Gate deployments on eval regressions.
app/prompts/ as ERB templates, versionedin git, rendered with locals, tested independently from API calls.
BudgetExceededError. Each has its own retry and alerting strategy.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.