AI Code Assistant for Ruby & Rails — Open Source
Refactor controllers, generate idiomatic RSpec, catch N+1 queries, review code for anti-patterns, and build entire features — all context-aware with your schema, routes, and specs. Powered by Claude Opus 4.6, running on your existing Claude subscription.
Rubyn is going open source. The original Rubyn gem provided AI-assisted refactoring, spec generation, and code review through the Rubyn API. Rubyn Code is the next evolution — a complete agentic coding assistant that runs locally, thinks for itself, and learns from every session. No API keys. No separate billing. Just
gem install rubyn-codeand go.
- Why Rubyn?
- Install
- Quick Start
- What Can Rubyn Do?
- VS Code Extension
- 29 Built-in Tools
- MCP — External Tool Servers
- Codebase Indexing
- 112 Best Practice Skills
- Context Architecture
- RUBYN.md — Project Instructions
- PR Review
- Sub-Agents & Teams
- GOLEM — Autonomous Daemon
- Continuous Learning
- Streaming Output
- Search Providers
- User Hooks
- CLI Reference
- Authentication
- Architecture
- Configuration
- Security
- Diagnostics
- Development
- From Rubyn to Rubyn Code
- Contributing
- License
- Rails-native — understands service object extraction, RSpec conventions, ActiveRecord patterns, and Hotwire
- Context-aware — automatically incorporates schema, routes, specs, factories, and models
- Best practices built in — ships with 112 curated Ruby and Rails guidelines that load on demand
- Agentic — doesn't just answer questions. Reads files, writes code, runs specs, commits, reviews PRs, spawns sub-agents, and remembers what it learns
- IDE-ready — works in the terminal and inside VS Code with full bidirectional communication
- Extensible — connect external tool servers via MCP, add custom skills, or wire up your own providers
Requires Ruby 4.0+. Install with your latest Ruby, then pin it so it works in every project:
# Install the gem
gem install rubyn-code
# Pin to this Ruby — bypasses rbenv/rvm version switching
rubyn-code --setupThat's it. rubyn-code now works in any project regardless of .ruby-version.
Using rbenv?
If you manage multiple Rubies with rbenv, install on your latest:
RBENV_VERSION=4.0.2 gem install rubyn-code
RBENV_VERSION=4.0.2 rubyn-code --setupThe --setup command creates a launcher in ~/.local/bin that calls the gem wrapper directly, skipping rbenv's shim. As long as ~/.local/bin is in your PATH before ~/.rbenv/shims, you're good.
Using rvm?
rvm use 4.0.2
gem install rubyn-code
rubyn-code --setupFrom source
git clone https://github.com/MatthewSuttles/rubyn-code.git
cd rubyn-code
bundle install
bundle exec ruby -Ilib exe/rubyn-codeAuthentication: Rubyn Code reads your Claude Code OAuth token from the macOS Keychain automatically. Just make sure you've logged into Claude Code once (claude in your terminal). Also supports ANTHROPIC_API_KEY env var. See Authentication for OpenAI and other providers.
# Interactive REPL
rubyn-code
# YOLO mode — no tool approval prompts
rubyn-code --yolo
# Single prompt
rubyn-code -p "Refactor app/controllers/orders_controller.rb into service objects"
# VS Code IDE mode (used by the extension)
rubyn-code --iderubyn > This orders controller is 300 lines. Break it up.
> read_file: path=app/controllers/orders_controller.rb
> read_file: path=app/models/order.rb
> read_file: path=config/routes.rb
> write_file: path=app/services/orders/create_service.rb
> write_file: path=app/services/orders/cancel_service.rb
> edit_file: path=app/controllers/orders_controller.rb
Done. Extracted CreateService and CancelService. Controller is down to 45 lines.
rubyn > Write specs for the new service objects
> read_file: path=app/services/orders/create_service.rb
> read_file: path=spec/factories/orders.rb
> write_file: path=spec/services/orders/create_service_spec.rb
> run_specs: path=spec/services/orders/
4 examples, 0 failures. All green.
rubyn > /review
> review_pr: base_branch=main
[warning] app/models/user.rb:15 — N+1 query detected
[critical] app/controllers/admin_controller.rb:8 — SQL injection risk
[suggestion] app/services/create_order.rb:22 — Method too long, extract private methods
rubyn > I'm new to this project. Give me the lay of the land.
Spawning explore agent...
[⠹] Agent exploring the codebase... (23 tools)
Agent finished (23 tool calls).
This is a Rails 7.1 e-commerce app with...
Rubyn Code includes a VS Code extension that provides a full IDE experience with bidirectional JSON-RPC communication. The extension runs Rubyn as a subprocess and connects over stdin/stdout.
Capabilities:
- Chat panel with streaming responses and syntax-highlighted code blocks
- Inline diffs — review and accept generated code changes directly in the editor
- Tool approval prompts in the IDE (or skip them in YOLO mode)
- Full session management — resume, list, fork, and reset conversations
- Structured code review feedback with severity ratings
- IDE config get/set for persistent settings
- All 29 tools available, including MCP tools
Permission modes:
| Mode | Behavior |
|---|---|
default |
Per-tool approval required |
bypass |
YOLO — skip all approval prompts |
The extension communicates over 14 RPC methods: initialize, prompt, cancel, review, approveToolUse, acceptEdit, session/*, config/*, models/list, and shutdown.
| Category | Tools |
|---|---|
| File I/O | read_file, write_file, edit_file |
| Search | glob, grep |
| Execution | bash (sandboxed, dangerous commands blocked) |
| Web | web_search, web_fetch |
| Git | git_status, git_diff, git_log, git_commit |
| Rails | rails_generate, db_migrate, run_specs, bundle_install, bundle_add |
| Review | review_pr (diff-based best practice code review) |
| Agents | spawn_agent, spawn_teammate, background_run |
| Context | compact, load_skill, task |
| Memory | memory_search, memory_write |
| Teams | send_message, read_inbox |
| Interactive | ask_user (ask clarifying questions mid-task) |
Connect external tool servers via the Model Context Protocol. MCP tools are dynamically discovered and registered as native Rubyn tools, available in the REPL, IDE, and daemon.
Create .rubyn-code/mcp.json in your project or ~/.rubyn-code/mcp.json globally:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
},
"my-api": {
"url": "http://localhost:3001/mcp",
"timeout": 30
}
}
}- Stdio transport — specify
commandandargsto run a subprocess - SSE transport — specify
urlfor HTTP-based servers - Environment variables are interpolated with
${VAR}syntax
MCP tools appear in the tool palette prefixed with mcp_ and require confirmation before execution. Run /doctor to verify server connectivity.
Rubyn ships with three example MCP servers: database explorer, RubyGems lookup, and Rails routes. See /mcp for documentation.
Rubyn builds a structural index of your codebase on first session and incrementally updates it as files change. The index powers smarter context injection, skill suggestions, and impact analysis.
What it tracks:
- Classes, modules, methods, callbacks, scopes, validations, associations
- Relationships between files (associations, test coverage, caller/callee)
- Rails patterns:
has_many,belongs_to,before_action,validates, etc. - File classification: model, controller, service, concern, spec
How it's used:
- Injects a compact structural summary into the system prompt
- Feeds the dynamic tool schema for smarter tool selection
- Powers
impact_analysis(file)to find affected tests and dependents - Suggests relevant skills based on the code you're working with
Stored at .rubyn-code/codebase_index.json. The /doctor command flags stale indexes (>24 hours).
Rubyn ships with curated best practice documents that load on demand. Only skill names are in memory — full content loads when Rubyn needs it.
| Category | Topics |
|---|---|
| Ruby | Collections, error handling, metaprogramming, concurrency, pattern matching |
| Rails | Controllers, models, views, migrations, ActiveRecord, Hotwire, caching, security |
| RSpec | Matchers, factories, request specs, shared examples, performance |
| Minitest | Assertions, system tests, fixtures, mocking |
| Design Patterns | Observer, strategy, decorator, builder, factory, adapter, and more |
| SOLID | All five principles with Ruby examples |
| Refactoring | Extract method/class, replace conditional, code smells, command-query separation |
| Code Quality | Naming, YAGNI, value objects, null object, technical debt |
| Gems | Sidekiq, Devise, FactoryBot, Pundit, Faraday, Stripe, RuboCop, dry-rb |
| Sinatra | Application structure, middleware, testing |
rubyn > /skill search factory # search by name, description, or tags
rubyn > /skill list rails # filter by category
rubyn > /skill list # show all categories
rubyn > /skill load rspec_matchers # inject a skill into context
Results are relevance-ranked: name matches score highest, then description, then tags.
Override or extend with your own:
# Project-specific
mkdir -p .rubyn-code/skills
echo "# Always use Grape for APIs" > .rubyn-code/skills/api_conventions.md
# Global
mkdir -p ~/.rubyn-code/skills
echo "# Use double quotes for strings" > ~/.rubyn-code/skills/my_style.mdRubyn automatically loads relevant context based on what you're working on:
- Controllers → includes models, routes, request specs, services
- Models → includes schema, associations, specs, factories
- Service objects → includes referenced models and their specs
- Any file → checks for
RUBYN.md,CLAUDE.md, orAGENT.mdinstructions
The codebase index enhances this with structural awareness — Rubyn knows which files depend on each other before it reads them.
Drop a RUBYN.md in your project root and Rubyn follows your conventions:
# My Project
- Always use RSpec, never Minitest
- Use FactoryBot for test data
- Service objects go in app/services/ with a .call interface
- API endpoints use Grape, not Rails controllers
- Run rubocop before committingAlso reads CLAUDE.md and AGENT.md — no migration needed from other tools.
| Location | Scope |
|---|---|
~/.rubyn-code/RUBYN.md |
Global — all projects |
| Parent directories | Monorepo — shared conventions |
./RUBYN.md |
Project root |
./subdir/RUBYN.md |
Subfolder-specific |
Review your branch against best practices before opening a PR:
rubyn > /review # vs main
rubyn > /review develop # vs develop
rubyn > /review main security # security focus only
Focus areas: all, security, performance, style, testing
Severity ratings: [critical] [warning] [suggestion] [nitpick]
rubyn > Explore the app/services directory and summarize the patterns
Spawning explore agent...
[⠹] Dispatching the intern... (18 tools)
Agent finished (18 tool calls).
Two types: explore (read-only) and worker (full write access).
rubyn > /spawn alice tester
Spawned teammate alice as tester
rubyn > Send alice a message to write specs for the User model
Teammates run in background threads with their own agent loop and mailbox.
GOLEM is an always-on autonomous agent that claims tasks from a queue and works through them independently. It runs a full agent loop per task with access to all tools, MCP servers, and memory.
rubyn-code daemon \
--name golem-1 \
--role "Backend Engineer" \
--max-runs 100 \
--max-cost 10.0 \
--poll-interval 5 \
--idle-timeout 60Lifecycle: spawned → working ⇄ idle → shutting_down → stopped
Safety limits:
| Guard | Description |
|---|---|
--max-runs |
Auto-shutdown after N completed tasks |
--max-cost |
Stop when cumulative USD spend exceeds limit |
| Retry backoff | 3 retries per task before marking failed |
| Audit trail | Full conversation saved per task via session persistence |
| Cost tracking | Accurate per-task spend via the observability layer |
Rubyn gets smarter with every session:
- During conversation — saves preferences and patterns to memory
- On session end — extracts reusable "instincts" with confidence scores
- On next startup — injects top instincts into the system prompt
- Over time — reinforced instincts strengthen, unused ones decay and get pruned
Real-time streaming with live syntax highlighting via Rouge/Monokai. Code blocks are buffered and highlighted when complete. No waiting for full responses.
Auto-detects the best available provider:
| Provider | Env Variable | Free Tier |
|---|---|---|
| DuckDuckGo | (none) | Unlimited |
| Tavily | TAVILY_API_KEY |
1,000/mo |
| Brave | BRAVE_API_KEY |
2,000/mo |
| SerpAPI | SERPAPI_API_KEY |
100/mo |
GOOGLE_SEARCH_API_KEY + GOOGLE_SEARCH_CX |
100/day |
Customize behavior via .rubyn-code/hooks.yml:
pre_tool_use:
- tool: bash
match: "rm -rf"
action: deny
reason: "Destructive delete blocked"
- tool: write_file
path: "db/migrate/**"
action: deny
reason: "Use rails generate migration"
post_tool_use:
- tool: write_file
action: logrubyn-code # Interactive REPL
rubyn-code --yolo # Auto-approve all tools
rubyn-code -p "prompt" # Single prompt, exit when done
rubyn-code --ide # IDE server mode (JSON-RPC over stdin/stdout)
rubyn-code --resume [ID] # Resume previous session
rubyn-code --setup # Pin to this Ruby (run once after install)
rubyn-code --debug # Enable debug output
rubyn-code --auth # Authenticate with Claude
rubyn-code --version # Show version
rubyn-code --help # Show help
rubyn-code daemon [OPTIONS] # Run GOLEM autonomous daemon| Command | Purpose |
|---|---|
/help |
Show help |
/quit |
Exit (saves session + extracts learnings) |
/new |
Save session and start a fresh conversation |
/review [base] |
PR review against best practices |
/spawn name role |
Spawn a persistent teammate |
/compact |
Compress conversation context |
/cost |
Show token usage and costs |
/tasks |
List all tasks |
/budget [amt] |
Show or set session budget |
/skill [name] |
Load, search, or list available skills |
/resume [id] |
Resume or list sessions |
/provider |
Add or list providers |
/model |
Show/switch model and provider |
/doctor |
Run environment health checks |
/mcp |
MCP server documentation and status |
| Priority | Source | Setup |
|---|---|---|
| 1 | macOS Keychain | Log into Claude Code once: claude |
| 2 | Token file | ~/.rubyn-code/tokens.yml |
| 3 | Environment | export ANTHROPIC_API_KEY=sk-ant-... |
Works with Claude Pro, Max, Team, and Enterprise. Default model: Claude Opus 4.6.
export OPENAI_API_KEY=sk-...Available models: gpt-5.4, gpt-5.4-mini, gpt-5.4-nano, gpt-4o, gpt-4o-mini, o3, o4-mini
Add a provider and its API key in one command:
/provider add groq https://api.groq.com/openai/v1 --key gsk-xxx --models llama-3.3-70b
# For Anthropic-format proxies (e.g., Bedrock, custom gateways)
/provider add my-proxy https://proxy.example.com/v1 --format anthropic --key sk-xxx --models claude-sonnet-4-6
# Update a key later
/provider set-key groq gsk-new-key
# List configured providers
/provider listAPI keys are encrypted at rest using AES-256-GCM. The encryption key is derived from your machine identity (username, hostname, home directory) via PBKDF2, so keys are only decryptable on the same machine by the same user. Rubyn decrypts them automatically at runtime and re-encrypts on save — no manual steps required.
Keys stored via environment variables (GROQ_API_KEY, TOGETHER_API_KEY, etc.) also work
as a fallback if you prefer that approach.
Or add directly to ~/.rubyn-code/config.yml:
providers:
groq:
base_url: https://api.groq.com/openai/v1
env_key: GROQ_API_KEY
models:
top: llama-3.3-70b
my-proxy:
api_format: anthropic # 'openai' (default) or 'anthropic'
base_url: https://proxy.example.com/v1
env_key: PROXY_API_KEY
models:
top: claude-sonnet-4-6Then switch with /model groq:llama-3.3-70b.
Local providers (Ollama, LM Studio) running on localhost/127.0.0.1 don't require an API key.
16-layer agentic architecture:
┌──────────────────────────────────────────────────────────────┐
│ Layer 16: Continuous Learning (pattern extraction + decay) │
│ Layer 15: MCP (external tool servers via protocol) │
│ Layer 14: Hooks & Events (user-configurable pre/post hooks) │
│ Layer 13: Observability (cost tracking, budget enforcement) │
│ Layer 12: Memory (persistent knowledge across sessions) │
│ Layer 11: Autonomous Operation (GOLEM daemon, task claiming) │
│ Layer 10: Protocols (shutdown handshake, plan approval) │
│ Layer 9: Teams (persistent teammates, mailbox messaging) │
│ Layer 8: Background Execution (async tasks, notifications) │
│ Layer 7: Task System (persistent DAG with dependencies) │
│ Layer 6: Sub-Agents (explore + worker, isolated contexts) │
│ Layer 5: Skills (112 best practice docs, on-demand loading) │
│ Layer 4: Context Management (3-layer compression pipeline) │
│ Layer 3: Permissions (tiered access + deny lists + hooks) │
│ Layer 2: Tool System (29 tools, dispatch map registry) │
│ Layer 1: THE AGENT LOOP (while tool_use → execute → repeat) │
└──────────────────────────────────────────────────────────────┘
The provider and model keys at the top set the default provider and model used at startup.
These must match a provider defined in the providers section (or a built-in like anthropic/openai).
# ~/.rubyn-code/config.yml (global)
provider: anthropic # default provider on startup
model: claude-opus-4-6 # default model on startup
permission_mode: allow_read
session_budget: 5.00
daily_budget: 10.00
# .rubyn-code/config.yml (project — overrides global)
provider: minimax # this project uses MiniMax by default
model: MiniMax-M2.7-highspeed
permission_mode: autonomousRubyn can automatically route tasks to different AI models based on complexity. Simple tasks (file search, git ops) use cheap, fast models. Complex tasks (architecture, security review) use the most capable model. Configure per-provider model tiers in config.yml:
# ~/.rubyn-code/config.yml
provider: anthropic
model: claude-opus-4-6
providers:
anthropic:
env_key: ANTHROPIC_API_KEY
models:
cheap: claude-haiku-4-5 # file search, git ops, formatting
mid: claude-sonnet-4-6 # code gen, specs, refactors, reviews
top: claude-opus-4-6 # architecture, security, complex work
openai:
env_key: OPENAI_API_KEY
models:
cheap: gpt-5.4-nano # lightweight tasks
mid: gpt-5.4-mini # regular coding
top: gpt-5.4 # complex reasoning
groq:
base_url: https://api.groq.com/openai/v1
env_key: GROQ_API_KEY
models:
cheap: llama-3-8b
mid: llama-3-70b
pricing:
llama-3-8b: [0.05, 0.08] # [input_rate, output_rate] per million tokens
llama-3-70b: [0.59, 0.79]
ollama:
base_url: http://localhost:11434/v1
models:
cheap: llama3
mid: llama3
top: llama3How it works: When you ask Rubyn to do something, the Model Router detects the task type and picks the right tier. If you've configured model tiers for a provider, those are used first. Otherwise it falls back to the built-in defaults (Anthropic for all tiers).
| Tier | Task types | Default model |
|---|---|---|
| cheap | File search, git ops, formatting, summaries | claude-haiku-4-5 |
| mid | Code generation, specs, refactors, code review, bug fixes | claude-sonnet-4-6 |
| top | Architecture, security review, complex refactors, planning | claude-opus-4-6 |
You can also set custom pricing per model so /cost reports accurate spending for third-party providers.
All provider API keys are encrypted at rest using AES-256-GCM (authenticated encryption). Keys are never stored as plaintext on disk.
| Layer | Detail |
|---|---|
| Cipher | AES-256-GCM (authenticated — detects tampering) |
| Key derivation | PBKDF2-HMAC-SHA256, 100,000 iterations |
| Machine binding | Key derived from username + hostname + home directory |
| Salt | Random 32-byte salt, generated once, stored in ~/.rubyn-code/.encryption_salt |
| File permissions | tokens.yml and .encryption_salt are 0600 (owner read/write only) |
This means:
- Keys copied to another machine or user account cannot be decrypted
- The encryption key is never stored — it is derived at runtime
- Plaintext keys from older versions are automatically encrypted on first read
| File | Permissions | Contents |
|---|---|---|
~/.rubyn-code/ |
0700 |
Home directory |
~/.rubyn-code/tokens.yml |
0600 |
Encrypted API keys, OAuth tokens |
~/.rubyn-code/.encryption_salt |
0600 |
PBKDF2 salt (not secret alone, but protected) |
~/.rubyn-code/config.yml |
0600 |
Provider config (no secrets) |
Run /doctor to check your environment:
rubyn > /doctor
✓ Ruby version 4.0.2
✓ Bundler installed
✓ Database 12 migrations applied
✓ Authentication valid (keychain)
✓ Skills 112 available
✓ Project detected Rails 7.1
✓ MCP servers 2 connected
✓ Codebase index fresh (2 hours ago)
✓ Skill catalog 112 skills, 0 malformed
Checks Ruby version, bundler, database state, authentication, skills, project type, MCP server connectivity, codebase index freshness, and skill catalog integrity.
Requires Ruby 4.0+.
git clone https://github.com/MatthewSuttles/rubyn-code.git
cd rubyn-code
bundle install
bundle exec rspecQuick rebuild from source:
bin/dev-installIf you used the original Rubyn gem, here's what changed:
| Rubyn (original) | Rubyn Code (open source) |
|---|---|
| Rubyn API required | Runs locally, no external API |
| API key billing | Uses your Claude subscription |
| Refactor, spec, review commands | Full agentic assistant — reads, writes, thinks, learns |
| Static best practices | 112 on-demand skills + custom overrides |
| Single-turn commands | Multi-turn sessions with memory and context |
| Closed source | MIT open source |
PRs welcome. If your team has conventions that should be a skill document, contribute it. If you need a tool we don't have, the tool system is a base class and a registry — add yours.
# Add a new tool
lib/rubyn_code/tools/your_tool.rb # extend Base, register with Registry
# Add a new skill
skills/your_category/your_skill.md # markdown with optional YAML frontmatterMIT License — see LICENSE for details.
