You ask Claude a complex question about the data your Rails app already holds. Claude answers with the SQL. Rails runs it.
Your data never travels. Claude is shown the schema and writes one SELECT; Rails runs it
read-only and draws the answer -- encrypted columns included -- for whoever asked. Nothing that
statement returned is ever sent back.
In your Gemfile, pinned to the current minor while this is still below 1.0:
gem 'omen', '~> 0.4.0'Then four commands:
bin/rails g omen:install # three migrations and an initializer you may delete
bin/rails db:migrate # omen_readings, omen_questions, omen_answers
bin/rails db:omen:grant # the read-only role a statement runs as, and three functions
bin/rails g omen:pages # a model, a controller, three views and a route, all yoursbin/rails s, then /inquiries. Type a question and the answer arrives under it, with the
statement Claude wrote and the rows it found.
None of it is Omen's to create, and each is checked rather than assumed:
- PostgreSQL, and a
db/schema.rbrather than astructure.sql. Both are raised on at boot. - A read-only connection role:
connects_to database: { writing: :primary, reading: :reader }onApplicationRecord, wherereaderlogs in as a Postgres role grantedSELECTand nothing else. Omen raises rather than falling back to a role that could write, which is the point. ANTHROPIC_API_KEY, or a key named in the initializer.- Active Record Encryption keys, without which an encrypted column reads back as a placeholder rather than as its value, quietly.
- An
ApplicationJob, since a reading is answered outside the request.
Omen::Reading.create! question: 'Where are the homes we serve?' is the whole of asking, and
reading.ask '...' is a follow-up. Each question is answered in a job, and the answer carries
the statement Claude wrote, the rows it found, and which of their headers held an encrypted
column. rails g omen:pages writes the pages that draw all of that, into your app, for you to
keep or replace.
INSTRUCTIONS.md has the reasoning: why Postgres and no other adapter, what
db:omen:grant creates and what to do on a managed database that forbids it, every setting and
its default, what the generated pages get right and why, and what a host can build on top.
MIT, see LICENSE.txt.