- Setup:
bundle install && pnpm install - Run Dev:
pnpm devorovermind start -f ./Procfile.dev - Seed Local Test Data:
bundle exec rails db:seed(quickly populates minimal data for standard feature verification) - Seed Search Test Data:
bundle exec rails search:setup_test_data(bulk fixture generation for search/performance/manual load scenarios) - Seed Account Sample Data (richer test data):
Seeders::AccountSeederis available as an internal utility and is exposed through Super AdminAccounts#seed, but can be used directly in dev workflows too:- UI path: Super Admin → Accounts → Seed (enqueues
Internal::SeedAccountJob). - CLI path:
bundle exec rails runner "Internal::SeedAccountJob.perform_now(Account.find(<id>))"(or callSeeders::AccountSeeder.new(account: Account.find(<id>)).perform!directly).
- UI path: Super Admin → Accounts → Seed (enqueues
- Lint JS/Vue:
pnpm eslint/pnpm eslint:fix - Lint Ruby:
bundle exec rubocop -a - Test JS:
pnpm testorpnpm test:watch - Test Ruby:
bundle exec rspec spec/path/to/file_spec.rb - Single Test:
bundle exec rspec spec/path/to/file_spec.rb:LINE_NUMBER - Run Project:
overmind start -f Procfile.dev - Ruby Version: Manage Ruby via
rbenvand install the version listed in.ruby-version(e.g.,rbenv install $(cat .ruby-version)) - rbenv setup: Before running any
bundleorrspeccommands, init rbenv in your shell (eval "$(rbenv init -)") so the correct Ruby/Bundler versions are used - Always prefer
bundle execfor Ruby CLI tasks (rspec, rake, rubocop, etc.)
- Ruby: Follow RuboCop rules (150 character max line length)
- Vue/JS: Use ESLint (Airbnb base + Vue 3 recommended)
- Vue Components: Use PascalCase
- Events: Use camelCase
- I18n: No bare strings in templates; use i18n
- Error Handling: Use custom exceptions (
lib/custom_exceptions/) - Models: Validate presence/uniqueness, add proper indexes
- Type Safety: Use PropTypes in Vue, strong params in Rails
- Naming: Use clear, descriptive names with consistent casing
- Vue API: Always use Composition API with
<script setup>at the top
- Tailwind Only:
- Do not write custom CSS
- Do not use scoped CSS
- Do not use inline styles
- Always use Tailwind utility classes
- Colors: Refer to
tailwind.config.jsfor color definitions
- MVP focus: Least code change, happy-path only
- No unnecessary defensive programming
- Ship the happy path first: limit guards/fallbacks to what production has proven necessary, then iterate
- Prefer minimal, readable code over elaborate abstractions; clarity beats cleverness
- Break down complex tasks into small, testable units
- Iterate after confirmation
- Avoid writing specs unless explicitly asked
- Remove dead/unreachable/unused code
- Don’t write multiple versions or backups for the same logic — pick the best approach and implement it
- Prefer
with_modified_env(from spec helpers) over stubbingENVdirectly in specs - Specs in parallel/reloading environments: prefer comparing
error.class.nameover constant class equality when asserting raised errors
- Use a separate git worktree + branch per task to keep changes isolated.
- Keep Codex-specific local setup under
.codex/and useProcfile.worktreefor worktree process orchestration. - The setup workflow in
.codex/environments/environment.tomlshould dynamically generate per-worktree DB/port values (Rails, Vite, Redis DB index) to avoid collisions. - Start each worktree with its own Overmind socket/title so multiple instances can run at the same time.
- Prefer Conventional Commits:
type(scope): subject(scope optional) - Example:
feat(auth): add user authentication - Don't reference Claude in commit messages
- Translations:
- Only update
en.ymlanden.json - Other languages are handled by the community
- Backend i18n →
en.yml, Frontend i18n →en.json
- Only update
- Frontend:
- Use
components-next/for message bubbles (the rest is being deprecated)
- Use
- Use compact
module/classdefinitions; avoid nested styles
- Chatwoot has an Enterprise overlay under
enterprise/that extends/overrides OSS code. - When you add or modify core functionality, always check for corresponding files in
enterprise/and keep behavior compatible. - Follow the Enterprise development practices documented here:
Practical checklist for any change impacting core logic or public APIs
- Search for related files in both trees before editing (e.g.,
rg -n "FooService|ControllerName|ModelName" app enterprise). - If adding new endpoints, services, or models, consider whether Enterprise needs:
- An override (e.g.,
enterprise/app/...), or - An extension point (e.g.,
prepend_mod_with, hooks, configuration) to avoid hard forks.
- An override (e.g.,
- Avoid hardcoding instance- or plan-specific behavior in OSS; prefer configuration, feature flags, or extension points consumed by Enterprise.
- Keep request/response contracts stable across OSS and Enterprise; update both sets of routes/controllers when introducing new APIs.
- When renaming/moving shared code, mirror the change in
enterprise/to prevent drift. - Tests: Add Enterprise-specific specs under
spec/enterprise, mirroring OSS spec layout where applicable. - When modifying existing OSS features for Enterprise-only behavior, add an Enterprise module (via
prepend_mod_with/include_mod_with) instead of editing OSS files directly—especially for policies, controllers, and services. For Enterprise-exclusive features, place code directly underenterprise/.
- For user-facing strings that currently contain "Chatwoot" but should adapt to branded/self-hosted installs, prefer applying
replaceInstallationNamefromshared/composables/useBrandingin the UI layer (for example tooltip and suggestion labels) instead of adding hardcoded brand-specific copy.