RubySage
Open source · Rails engine · MIT

Stop paying your
AI to re-read
the same Rails app.

RubySage is a Rails engine that builds a structured, file-level index of your codebase — kept fresh by git fingerprints — and hands it to Claude Code, Cursor, or Codex in a 3K-token retrieval call instead of a 200K-token orientation. Same answers, a fraction of the bill.

~70%
fewer input tokens at session start *
~10×
cheaper follow-ups with prompt caching
zero
prod token spend with pre-baked scans
* Live benchmark coming — Phase F install on a real production Rails codebase (ChangeMaker, ~200K LOC). Number updates the day the run lands.
The problem

Your agent is paying retail for what it learned yesterday.

Every Claude Code or Cursor session on a Rails app burns 50–200K input tokens just orienting itself. Reading models. Grepping routes. Re-deriving conventions. Across a team of five, that’s millions of tokens a day spent re-learning the same codebase before anyone writes a line.

The codebase has not changed that much. Most files are byte-identical to yesterday. What changed is knowable — git already fingerprints every file in the repo. The expensive work of mapping the app should happen once, not on every new chat.

Why not just write a CLAUDE.md

A human-written summary goes stale the day you ship.

CLAUDE.md / .cursorrules / AGENTS.md are useful for taste and conventions. They are also static prose someone wrote on a Tuesday — and they drift the moment you rename a service, split a controller, or swap a gem.

RubySage indexes the actual code. Every public class. Every route. Every service object. Per-file summaries that come from reading the file, not from a human guessing six months ago.

A hand-written CLAUDE.md

  • Static — drifts as the app changes
  • High-level (gems, stack, conventions)
  • Same context for every question
  • Nothing prevents the agent re-reading files anyway
  • Costs nothing, gives the agent prose

RubySage's index

  • +Refreshed on every scan, keyed by git blob hash
  • +Per-file — summaries, public symbols, routes
  • +Retrieval picks the 5–15 files the question actually needs
  • +Replaces the model's instinct to grep through everything
  • +Costs ~$0.10 to build, ~$0.01–0.05 per cached question
Architecture

Three pieces. Nothing clever.

01

Scan

A rake task walks your codebase and produces per-file artifacts — summaries, public symbols, route mappings. Stored in your app's database. Secret values redacted. Files unchanged since the last scan are skipped via digest cache, so incremental runs are cheap.

02

Retrieve

When someone asks a question, RubySage retrieves the most relevant artifacts using keyword + symbol matching, boosted by the current page context. Not vector-only — Rails apps have strong lexical signals (model names, route paths) that BM25 nails.

03

Answer

Relevant artifacts go into a prompt with the question. The LLM answers, citing the specific files and classes it used. Anthropic prompt caching is on by day 1 — subsequent questions within ~5 minutes cost roughly 10× less.

# config/initializers/ruby_sage.rb
RubySage.configure do |config|
  config.provider   = :anthropic
  config.model      = "claude-sonnet-4-6"
  config.api_key    = ENV.fetch("ANTHROPIC_API_KEY", nil)
  config.auth_check = ->(c) { c.current_user&.admin? }
end
The point

A drop-in API for your AI coding agents.

RubySage’s retrieval layer is a Ruby method and a JSON endpoint. Wire it into Claude Code, Cursor, Codex, or whatever agent you use. Instead of dumping the whole codebase into context, the agent pulls the 5–15 files the question actually needs — with summaries, public symbols, and route mappings prebaked.

# From inside your agent — Ruby
result = RubySage.context_for("how does subscription billing work?")

result[:artifacts]   # => relevant Artifact records
result[:citations]   # => [{path:, kind:, score:, snippet:}, ...]
result[:scan_id]     # => Scan id used
# From anywhere else — HTTP
curl -X POST https://your-app.com/ruby_sage/internal/retrieve \
  -H "Content-Type: application/json" \
  -d '{"query":"subscription billing"}'

Onboarding docs, generated

rake ruby_sage:onboard writes docs/ONBOARDING.md for humans and docs/AGENT_PRIMER.mdfor AI agents — under 600 words, fits any agent’s context prefix. Better than a hand-written CLAUDE.md because it actually reflects current code.

Use your agent for the scan itself

rake ruby_sage:scan:plan writes a manifest. Tell Claude Code or Cursor to read INSTRUCTIONS.md. Your existing subscription pays for the summaries — zero API spend, no new key to manage.

Cost

Honest numbers.

All figures USD, Anthropic Sonnet pricing. Your mileage will vary by codebase size and question patterns.

OperationFrequencyCost
Initial full scan (200-file Rails app)Once$0.10 – $0.50
Daily incremental scan (50 changed files)Per day$0.05 – $0.20
Question, with prompt-cache hitPer question$0.01 – $0.05
Question, cache missFirst of session$0.10 – $0.30

Pre-bake scans in CI, ship artifacts to prod with rake ruby_sage:import_artifacts. Production runs zero LLM summarization. The expensive part lives in your CI runner.

Install

Five lines, one rake task.

Add the gem, generate the install, run your first scan. RubySage ships with the migrations and the rake tasks — no separate service, no extra infrastructure.

# Gemfile
gem "ruby_sage"

# Shell
bundle install
rails generate ruby_sage:install
rails db:migrate
bundle exec rake ruby_sage:scan

That’s it. The index is in your database, the retrieval API is live at /ruby_sage/internal/retrieve, and your team gets an optional chat widget if you drop oneruby_sage_widget line into your layout.

<%# app/views/layouts/application.html.erb — optional %>
<body>
  <%= yield %>
  <%= ruby_sage_widget %>
</body>

Less context.
Cheaper answers.
Open under MIT.

Read the source →View on RubyGems