A Rails engine · MIT · Ruby 3.3+, Rails 8.1+
Your users' agents already know what they want built.
Give them somewhere to say it.
feature_machine adds feature requests, bug reports, a triage queue and a public roadmap to your Rails app. People file from a form. Their agents file over MCP. A judge groups the duplicates and ranks what's left, and you decide what ships.
From a wish to a pull request
Follow one request through the engine. From the draft on, the tags are the work item's real statuses. Press Play all, or step through and choose at the draft. Press a step out of turn and the chart tells you why not.
-
01
Filed
A request lands from
/feature-requestsor fromrequest_featureover MCP. Same table, same status, same note back to the person who asked. -
02
Grouped
Embeddings cluster the five people asking for dark mode into one pile. Name no embedding model and requests still file; they just stay ungrouped.
-
03
Judged
A structured-judgment model ranks the piles.
jev-latestheld 18 of 18 on the bundled calibration run, where paraphrases must not move an answer and real changes must. -
04
Built, if you say so
Triage forms a work item with a drafted spec. Only you can plan it. Your own coding agent picks it up over MCP and attaches a PR. Nothing ships until you merge.
MCP is a front door, not a back door
Mount feature_machine_routes :mcp and any agent with a bearer token can file requests, report bugs and read the roadmap for the person it works for. It sees that person's requests and nobody else's.
Maintainer tools (list_work_items, update_work_item) only show up for tokens whose user passes your admin check, and the engine re-checks that on every call. An agent can move an item along and attach a PR. It can't rewrite the spec, approve a draft or decline the work. A browser cookie never counts as an MCP credential.
# what a user's agent sees
list_feature_requests
request_feature
list_bug_reports
report_bug
read_roadmap
# and a maintainer's, on top
list_work_items
get_work_item
update_work_item
Every model is optional
Embeddings, the spec drafter and the judge each stay off until you name a RubyLLM model. If a provider key goes missing, that step steps aside and the rest keeps working.
Markup, your styles
Pages ship cn-* class hooks and inherit your ApplicationController and layout. A small default stylesheet sits in a low cascade layer, so your rules win.
Bring your own board
Already have a roadmap page or bug tracker? Point roadmap_path at it and the engine links there instead.
Three commands and an initializer
# Gemfile
gem "feature_machine"
bin/rails g feature_machine:install
bin/rails feature_machine:install:migrations
bin/rails db:migrate
Then tell it who's signed in, who may triage, and how a bearer token becomes a credential:
FeatureMachine.configure do |config|
config.current_user = ->(request) { Session.find_by(id: request.cookie_jar.signed[:session_id])&.user }
config.admin = ->(user) { user.admin? }
config.authenticate_api = ->(token) { ApiToken.authenticate(token) }
end
Needs Postgres with pgvector. Full reference in the README.