Antipattern Prevention
doorkeeper-gem/doorkeeper
Avoid common Ruby and Rails antipatterns that degrade maintainability and performance.
Scaffold a new Rails app with event sourcing, following project conventions (todomvc as reference)
$ npx skills add RailsEventStore/ecommerce --skill new-app -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install RailsEventStore/ecommerce new-app --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/new-app .claude/skills/new-app && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "new-app" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/new-app into .claude/skills/new-app/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "new-app", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/new-appType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add RailsEventStore/ecommerce --skill new-app -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install RailsEventStore/ecommerce new-app --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/new-app .agents/skills/new-app && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "new-app" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/new-app into .agents/skills/new-app/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "new-app", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add RailsEventStore/ecommerce --skill new-app -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install RailsEventStore/ecommerce new-app --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/new-app .cursor/skills/new-app && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "new-app" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/new-app into .cursor/skills/new-app/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "new-app", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/RailsEventStore/ecommerce.git --path .claude/skills/new-app--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add RailsEventStore/ecommerce --skill new-app -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install RailsEventStore/ecommerce new-app --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/new-app .gemini/skills/new-app && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "new-app" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/new-app into .gemini/skills/new-app/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "new-app", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install RailsEventStore/ecommerce new-appInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add RailsEventStore/ecommerce --skill new-app -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/new-app .github/skills/new-app && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "new-app" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/new-app into .github/skills/new-app/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "new-app", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add RailsEventStore/ecommerce --skill new-app -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install RailsEventStore/ecommerce new-app --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/new-app .opencode/skills/new-app && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "new-app" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/new-app into .opencode/skills/new-app/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "new-app", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
new-appScaffold a new Rails app with event sourcing, following project conventions (todomvc as reference)
New App is an agent skill from RailsEventStore/ecommerce. Scaffold a new Rails app with event sourcing, following project conventions (todomvc as reference)
Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs, covering Event-driven systems. It works with Ruby on Rails and Ruby. The repository describes itself as: Application with CQRS and Event Sourcing built on Rails and Rails Event Store. The licence is MIT.
11 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 42c6c23. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
railsbundlegemmakeFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
New App loads about 3.1k tokens when it runs. Until then it costs about 27 tokens; SKILL.md has 1,045 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from RailsEventStore/ecommerce at commit 42c6c23, republished under its MIT licence (© RailsEventStore). 1,045 words, ~3,055 tokens.
.claude/skills/new-app/SKILL.md (or your agent's skills folder).Use this skill when asked to create a new Rails application in the apps/ directory. Each app is a standalone Rails application that uses domain modules from domains/ and the shared infra gem.
apps/todo_mvc is the canonical reference for app structure (initializer, Configuration, test harness, Makefile). For the current RES 3.0 wiring and gem versions, use apps/rails_application and apps/twitter — todo_mvc still pins RES 2.x, which is stale. When the two disagree, follow rails_application.
Always scaffold on the newest Ruby and newest Rails — do not hardcode versions from this doc, they go stale.
gem list rails --remote --exact | head -1 (checks RubyGems, not just what's installed locally). As of this writing: Rails 8.1.3.~/.rbenv/versions/ (ls ~/.rbenv/versions | sort -V | tail). As of this writing: Ruby 4.0.1. Set it in the app's .ruby-version. Ruby 4.0.1 works with Rails 8.1 + RES 3.0 + the infra/domain gems.~/.rbenv/versions/{ruby}/bin/rails -v.Invoke rails/bundle via the full rbenv path for the chosen Ruby, e.g. ~/.rbenv/versions/4.0.1/bin/rails, ~/.rbenv/versions/4.0.1/bin/bundle — the rails shell alias may resolve to a different Ruby.
Commit frequently at natural checkpoints, not once at the end. Commit directly on the current branch — do not create a feature branch. Suggested commits: (1) after generating the app + configuring the Gemfile, (2) after RES wiring is green, (3) after each domain/read model. Per project convention, use the /commit skill and never mention Claude in commit messages.
Before writing any code, clarify:
crm, inventory_tracker)domains/ or new ones to be created)Run from the apps/ directory, using the full rbenv path for the newest Ruby (see Version policy above):
cd apps && ~/.rbenv/versions/{ruby}/bin/rails new {app_name} --database=postgresql --css=tailwind --skip-test--skip-test (not --skip-test-unit, which no longer exists) drops the default test setup so we can install our own minitest + mutant harness.
Important post-generation steps:
echo "{ruby}" > apps/{app_name}/.ruby-version (the generator pins the global default, which may not be the newest).rails new creates a nested .git directory inside the new app. It must be removed so the app is part of the parent repo. rm -rf is blocked by the repo's git-safety hook, so ask the user to run it manually: rm -rf apps/{app_name}/.git. Do not proceed to committing until it's gone.Add these gems to the generated Gemfile (after jbuilder, before the tzinfo/solid gems). Use RES 3.0 to match rails_application:
gem "rails_event_store", ">= 3.0", "< 4.0"
gem "arkency-command_bus"
gem "infra", path: "../../infra"Rails 8.1 with --skip-test does not generate a capybara/selenium test group. Just add a test group:
group :test do
gem "mutant-minitest"
endRun bundle install (via the full rbenv path). Commit the generated app + Gemfile now (checkpoint 1).
Create config/initializers/rails_event_store.rb:
require "rails_event_store"
require "arkency/command_bus"
require_relative "../../lib/configuration"
Rails.configuration.to_prepare do
Rails.configuration.event_store = Infra::EventStore.main
Rails.configuration.command_bus = Arkency::CommandBus.new
Configuration.new.call(Rails.configuration.event_store, Rails.configuration.command_bus)
endCreate lib/configuration.rb. For the initial scaffold there is no domain yet, so call only wires event linking — this keeps the app bootable and tests green before any domain exists:
require_relative "../../../infra/lib/infra"
class Configuration
def call(event_store, command_bus)
enable_res_infra_event_linking(event_store)
end
private
def enable_res_infra_event_linking(event_store)
[
RailsEventStore::LinkByEventType.new,
RailsEventStore::LinkByCorrelationId.new,
RailsEventStore::LinkByCausationId.new
].each { |h| event_store.subscribe_to_all_events(h) }
end
endAs domains and read models are added later, extend call: require_relative the domain, add {DomainModule}::Configuration.new.call(event_store, command_bus), and give each read model its own enable_* private method called from call. Do not add a require_relative to a domain that doesn't exist yet — it will break boot.
In RES 3.0 the generator was renamed — the old rails_event_store_active_record:migration no longer exists. Use the ruby_event_store namespace with a data type (jsonb pairs cleanly with infra's RailsEventStore::JSONClient):
cd apps/{app_name} && ~/.rbenv/versions/{ruby}/bin/bundle exec rails generate ruby_event_store:active_record:migration --data-type=jsonbThen rails db:create && rails db:migrate (via the full rbenv path). The generated migration creates event_store_events and event_store_events_in_streams with uuid event_id and jsonb data/metadata.
Ensure app/controllers/application_controller.rb has:
class ApplicationController < ActionController::Base
allow_browser versions: :modern
def command_bus
Rails.configuration.command_bus
end
def event_store
Rails.configuration.event_store
end
endReplace the generated test/test_helper.rb (which has parallelize and fixtures :all):
ENV["RAILS_ENV"] ||= "test"
require_relative "../config/environment"
require "rails/test_help"
require "mutant/minitest/coverage"
ActiveJob::Base.logger = Logger.new(nil)
class InMemoryRESTestCase < ActiveSupport::TestCase
def before_setup
result = super
@previous_event_store = Rails.configuration.event_store
@previous_command_bus = Rails.configuration.command_bus
Rails.configuration.event_store = Infra::EventStore.in_memory
Rails.configuration.command_bus = Arkency::CommandBus.new
Configuration.new.call(
Rails.configuration.event_store, Rails.configuration.command_bus
)
result
end
def before_teardown
result = super
Rails.configuration.event_store = @previous_event_store
Rails.configuration.command_bus = @previous_command_bus
result
end
def event_store
Rails.configuration.event_store
end
def command_bus
Rails.configuration.command_bus
end
end
class InMemoryRESIntegrationTestCase < ActionDispatch::IntegrationTest
def before_setup
result = super
@previous_event_store = Rails.configuration.event_store
@previous_command_bus = Rails.configuration.command_bus
Rails.configuration.event_store = Infra::EventStore.in_memory_rails
Rails.configuration.command_bus = Arkency::CommandBus.new
Configuration.new.call(Rails.configuration.event_store, Rails.configuration.command_bus)
result
end
def before_teardown
result = super
Rails.configuration.event_store = @previous_event_store
Rails.configuration.command_bus = @previous_command_bus
result
end
def command_bus
Rails.configuration.command_bus
end
endCreate .mutant.yml in the app root. On the initial scaffold there are no subjects yet, so start with empty lists (mutant isn't run until there's domain code to cover):
includes:
- test
requires:
- ./config/environment
integration: minitest
usage: opensource
coverage_criteria:
timeout: true
process_abort: true
matcher:
subjects: []
ignore: []As each read model is added, append its namespace to subjects (e.g. - Tweets*) and its AR model + Configuration#call to ignore. See apps/crm/.mutant.yml for a fully-populated example.
Mutant writes per-run result JSONs to .mutant/results/. These are transient artifacts and must never be committed — add this line to the app's .gitignore now:
/.mutant/results/Add targets to the root Makefile:
install-{app_name}:
@make -C apps/{app_name} install
test-{app_name}:
@make -C apps/{app_name} test
mutate-{app_name}:
@make -C apps/{app_name} mutateAdd install-{app_name} to the install: target, test-{app_name} to test:, and mutate-{app_name} to mutate:.
Create Makefile in the app directory:
install:
@bin/setup
dev:
@make -j 2 web css
test:
@bin/rails test
mutate:
@RAILS_ENV=test bundle exec mutant run
tailwind:
@bin/rails tailwindcss:build
css:
@bin/rails tailwindcss:watch
web:
@bin/rails server -p {port}
.PHONY: install dev test mutate tailwind css webUse a unique port per app (3000 for rails_application, 3001+ for new apps).
Controllers dispatch commands and query read models:
class ResourceController < ApplicationController
def index
@records = ReadModelName.all
end
def create
id = SecureRandom.uuid
ActiveRecord::Base.transaction do
command_bus.call(DomainModule::CreateCommand.new(id: id, ...))
end
redirect_to root_path
end
def update
command_bus.call(DomainModule::UpdateCommand.new(id: params[:id], ...))
redirect_to root_path
end
def destroy
command_bus.call(DomainModule::DeleteCommand.new(id: params[:id]))
redirect_to root_path
end
endBuild the app incrementally, with tests passing at each step:
/domain skill)/read-model skill)make test and mutation testingrails/bundle alias: The shell alias may resolve to the wrong Ruby. Always use the full rbenv path: ~/.rbenv/versions/{ruby}/bin/rails, ~/.rbenv/versions/{ruby}/bin/bundle..git: rails new creates its own git repo. It must be removed before the app can be committed to the parent repo. rm -rf is blocked by the git-safety hook — ask the user to run rm -rf apps/{app_name}/.git manually..ruby-version: The generator pins the rbenv global default, not necessarily the newest — overwrite it with the chosen Ruby.ruby_event_store:active_record:migration, not the old rails_event_store_active_record:migration (see step 6).bin/rails commands (migrations, generators, tests): Must run from apps/{app_name}/ directory, not project root.apps/require_relative "../../../domains/{name}/lib/{name}"gem "infra", path: "../../infra"app/read_models/{name}/configuration.rbevent.data.fetch(:key)command_bus.call(...) for writes, read models for queriesSecureRandom.uuid)© RailsEventStore, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/new-app of RailsEventStore/ecommerce.
Open the folder on GitHubat commit 42c6c23
New App next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| New App this skillRailsEventStore/ecommerce | 507 | — | ~3.1k | Automated safety check: Pass | MIT | |
| Antipattern Preventiondoorkeeper-gem/doorkeeper | 5.5k | — | ~1.1k | Automated safety check: Pass | MIT | |
| Dependency Safetydoorkeeper-gem/doorkeeper | 5.5k | — | ~931 | Automated safety check: Pass | MIT | |
| Rails ExpertJeffallan/claude-skills | 12k | — | ~1.4k | Automated safety check: Pass | MIT | |
| Rails Patternsaffaan-m/ECC | 276k | — | ~4.1k | Automated safety check: Pass | MIT | |
| Ruby Patternssoftspark/ai-toolkit | 179 | — | ~2.3k | Automated safety check: Pass | Apache-2.0 |
doorkeeper-gem/doorkeeper
Avoid common Ruby and Rails antipatterns that degrade maintainability and performance.
doorkeeper-gem/doorkeeper
Ensure gems are safe, necessary, and properly constrained when adding, updating, or reviewing dependencies in Doorkeeper.
Jeffallan/claude-skills
Builds Rails 7+ apps with Hotwire Turbo Frames and Streams, Active Record tuning, Action Cable, Sidekiq jobs and RSpec specs, with migration and N+1 checks.
affaan-m/ECC
Ruby on Rails framework patterns for Rails 7.1+ and 8.x apps.
softspark/ai-toolkit
Ruby/Rails: blocks, metaprogramming, ActiveRecord, Sidekiq, RSpec, Sorbet, Hanami.
ericrisco/rsc-harness
A skill your agent uses when building or maintaining a Ruby on Rails app — models, controllers, views, routes and migrations; ActiveRecord associations, scopes and query performance; Hotwire (Turbo…
RailsEventStore/ecommerce
Create atomic git commits following project conventions. An agent skill from RailsEventStore/ecommerce.
RailsEventStore/ecommerce
Create a controller with commands, read model queries, routes, and integration tests
RailsEventStore/ecommerce
Create a new domain bounded context with aggregates, commands, events, and handlers
RailsEventStore/ecommerce
Plan a new feature end-to-end — impact analysis across all layers, start-from-the-middle slicing into deployable steps, then delegating to /domain, /read-model, /controller skills
RailsEventStore/ecommerce
Build a new read model following project conventions (event handlers, tests, migration, configuration)
RailsEventStore/ecommerce
Upgrade Rails framework to a newer version following the smooth upgrade methodology
Works with
Categories
Scaffold a new Rails app with event sourcing, following project conventions (todomvc as reference). New App is an agent skill from RailsEventStore/ecommerce.
New App fits situations like: tasks that involve Event-driven systems.
Run `npx skills add RailsEventStore/ecommerce --skill new-app -a claude-code`. Or copy the skill folder (.claude/skills/new-app in RailsEventStore/ecommerce) into .claude/skills/new-app in your project. Claude Code loads it when a task matches its description.
Run `npx skills add RailsEventStore/ecommerce --skill new-app -a codex`. Or copy the skill folder (.claude/skills/new-app in RailsEventStore/ecommerce) into .agents/skills/new-app in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add RailsEventStore/ecommerce --skill new-app -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/new-app, .gemini/skills/new-app, .github/skills/new-app and .opencode/skills/new-app in your project.
Going by SKILL.md and its folder, New App needs the command-line tools its instructions call (rails, bundle, gem and make).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
New App is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with New App: Antipattern Prevention (doorkeeper-gem/doorkeeper, 5.5k stars), Dependency Safety (doorkeeper-gem/doorkeeper, 5.5k stars), Rails Expert (Jeffallan/claude-skills, 12k stars) and Rails Patterns (affaan-m/ECC, 276k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
RailsEventStore (a GitHub organization) maintains it in RailsEventStore/ecommerce, which has 507 GitHub stars. The repository holds 8 skills in this directory. The repository was last updated on September 21, 2026.
Source: RailsEventStore/ecommerce on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.