# 37signals Skills Agent skills and a reference guide that teach AI coding assistants to write Rails the 37signals way — extracted from Fizzy, Campfire, and 100+ of DHH's code reviews. > **Unofficial.** This is a community project based on 37signals' public code and discussions — not affiliated with or endorsed by 37signals. Drop the skills into Claude Code or Cursor and your agent starts applying the same patterns 37signals uses: rich domain models over service objects, state as records, CRUD-everything routing, fixtures over factories, vanilla Rails over gems. ## The Skills | Skill | What it covers | Invocation | |---|---|---| | [`rails-best-practices-core`](skills/rails-best-practices-core/SKILL.md) | Architecture, naming, modeling patterns, REST routing, authorization — the baseline for all Rails work | Automatic | | [`rails-hotwire-realtime`](skills/rails-hotwire-realtime/SKILL.md) | Turbo Streams/Frames, morphing, Stimulus, ActionCable, presence, optimistic UI, web push | On demand | | [`rails-jobs`](skills/rails-jobs/SKILL.md) | Active Job design, `_later`/`_now` conventions, Solid Queue, recurring tasks, retry policy | On demand | | [`rails-migrations`](skills/rails-migrations/SKILL.md) | Safe schema changes, staged rollouts, script backfills, multi-DB/multi-adapter setups | On demand | | [`rails-security-multitenancy`](skills/rails-security-multitenancy/SKILL.md) | Path-based tenancy, Identity→Session→User auth, scoped lookups, SSRF, CSRF, rate limiting | On demand | | [`rails-testing`](skills/rails-testing/SKILL.md) | Minitest + fixtures, coverage budget, Turbo/broadcast assertions, multi-tenant test wiring | On demand | | [`rails-webhooks`](skills/rails-webhooks/SKILL.md) | Outbox delivery, failure classification, delinquency circuit breakers, payload signing | On demand | | [`dhh`](skills/dhh/SKILL.md) | Review code like DHH would — direct, opinionated, allergic to over-engineering | `/dhh` | "On demand" skills are marked `disable-model-invocation: true` so they don't bloat every request — invoke them explicitly (e.g. as a slash command) or let the core skill point to them. ## Installation ### Claude Code Copy the skills you want into your personal or project skills directory: ```bash git clone https://github.com/marckohlbrugge/37signals-skills.git # Personal (all projects) cp -R 37signals-skills/skills/* ~/.claude/skills/ # Or per-project cp -R 37signals-skills/skills/* your-app/.claude/skills/ ``` Then ask for a review with `/dhh`, or just write Rails code — the core skill activates automatically. ### Cursor ```bash # Per-project cp -R 37signals-skills/skills/* your-app/.cursor/skills/ ``` ### Codex Copy the skills into your global Codex skills directory: ```bash git clone https://github.com/marckohlbrugge/37signals-skills.git mkdir -p ~/.agents/skills cp -R 37signals-skills/skills/* ~/.agents/skills/ ``` Codex can invoke skills explicitly with `$skill-name` (for example, `$dhh`) or automatically when a task matches the skill description. Restart Codex if the new skills do not appear. ### Other agents Each skill is a plain `SKILL.md` with YAML frontmatter ([Agent Skills format](https://agentskills.io)). Most SKILL.md-compatible tools can load them as-is, or paste the contents into your system prompt / rules file. ### Staying up to date Clone the repo somewhere permanent and symlink instead of copying: ```bash ln -s "$(pwd)/37signals-skills/skills/"* ~/.claude/skills/ ``` For Codex: ```bash mkdir -p ~/.agents/skills ln -s "$(pwd)/37signals-skills/skills/"* ~/.agents/skills/ ``` Then `git pull` to get updates. ## The Guide The skills are distilled from a longer-form reference covering ~35 topics, kept in [`guide/`](guide/). It was extracted from analyzing 265 pull requests in 37signals' Fizzy codebase — not just the final code, but the reviews, trade-offs, and iterations that led to it. **Core Rails:** [Routing](guide/routing.md) · [Controllers](guide/controllers.md) · [Models](guide/models.md) · [Views](guide/views.md) **Frontend:** [Hotwire](guide/hotwire.md) · [Stimulus](guide/stimulus.md) · [CSS](guide/css.md) · [Accessibility](guide/accessibility.md) · [Mobile](guide/mobile.md) **Backend:** [Authentication](guide/authentication.md) · [Multi-Tenancy](guide/multi-tenancy.md) · [Database](guide/database.md) · [Background Jobs](guide/background-jobs.md) · [Caching](guide/caching.md) · [Performance](guide/performance.md) **Real-time & Communication:** [ActionCable](guide/actioncable.md) · [Notifications](guide/notifications.md) · [Email](guide/email.md) **Features:** [Webhooks](guide/webhooks.md) · [Workflows](guide/workflows.md) · [Watching](guide/watching.md) · [Filtering](guide/filtering.md) · [AI/LLM Integration](guide/ai-llm.md) **Rails Components:** [Active Storage](guide/active-storage.md) · [Action Text](guide/action-text.md) **Infrastructure & Testing:** [Security Checklist](guide/security-checklist.md) · [Testing](guide/testing.md) · [Configuration](guide/configuration.md) · [Observability](guide/observability.md) **Philosophy & People:** [Development Philosophy](guide/development-philosophy.md) · [What They Avoid](guide/what-they-avoid.md) · [DHH](guide/dhh.md) · [Jason Zimdars](guide/jason-zimdars.md) · [Jorge Manrubia](guide/jorge-manrubia.md) ## Quick Start: The 37signals Way 1. **Rich domain models** over service objects 2. **CRUD controllers** over custom actions 3. **Concerns** for horizontal code sharing 4. **Records as state** over boolean columns 5. **Database-backed everything** (no Redis) 6. **Build it yourself** before reaching for gems 7. **Ship to learn** - prototype quality is valid 8. **Vanilla Rails is plenty** - maximize what Rails gives you ## Important Caveats **LLM-Generated Content**: This guide and these skills were largely produced by an LLM (Claude) analyzing source code, PR descriptions, and code snippets. There may be hallucinations or inaccuracies. Take everything with a grain of salt and verify against actual implementations. **Code License**: Code examples extracted from Fizzy are licensed under the [O'Saasy License](https://osaasy.dev). Please review that license before using code snippets in your projects. ## Acknowledgements - **[37signals](https://37signals.com)** for open-sourcing their codebases and giving the community a window into how they build software - **[Rob Zolkos](https://www.zolkos.com/2025/12/10/fizzys-pull-requests)** for his work identifying and cataloging the most educational PRs - **[Claude Code](https://claude.com/claude-code)** for creating this guide through iterative deep-dive research sessions ## Further Reading - [Fizzy Source Code](https://github.com/basecamp/fizzy) - The official Fizzy repository with full git history - [Campfire Source Code](https://github.com/basecamp/once-campfire) - 37signals' open-source chat application, another reference implementation - [Fizzy's Pull Requests: Who Built What and How](https://www.zolkos.com/2025/12/10/fizzys-pull-requests) - Curated PR sequences organized by topic - [Fizzy JS Patterns](https://www.driftingruby.com/episodes/fizzy-js-patterns) - Drifting Ruby episode analyzing JavaScript patterns in Fizzy - [Read The Friendly Source Code](https://beautifulruby.com/code/fizzy) - Beautiful Ruby code review covering architecture and security observations - [Writebook by ONCE](https://igor.works/blog/writebook-by-once) - Code walkthrough of another 37signals open-source project - [On Writing Software Well](https://www.youtube.com/playlist?list=PL9wALaIpe0Py6E_oHCgTrD6FvFETwJLlx) - DHH's screencast series on software development practices ## Disclaimer This is an unofficial project created by analyzing publicly available code and discussions. It is not affiliated with or endorsed by 37signals. ## License Code examples extracted from Fizzy are licensed under the [O'Saasy License](https://osaasy.dev). All analysis, commentary, skills, and original content in this repo is licensed under MIT.