2025-06-20 16:39:04 +10:00
# AI Coding Agent Guide
2025-08-11 10:08:41 +10:00
Project-specific instructions for AI agents. MUST be loaded at conversation start.
2025-06-20 16:39:04 +10:00
## Default Mode
2025-08-11 10:08:41 +10:00
- Architect mode enabled by default: detailed analysis, patterns, trade-offs, architectural guidance
- Stop and ask for context if unable to write code meeting guidelines
2025-06-20 16:39:04 +10:00
2025-08-11 10:08:41 +10:00
## Development Rules
Discourse is large with long history. Understand context before changes.
2025-06-20 16:39:04 +10:00
2025-08-11 10:08:41 +10:00
### Toolset
- Use `pnpm` for JavaScript, `bundle` for Ruby
2026-03-18 08:08:48 +10:00
- Use helpers in bin over bundle exec (bin/rspec, bin/rake, bin/lint)
2025-06-20 16:39:04 +10:00
2026-03-18 08:08:48 +10:00
### JavaScript and UI
2025-08-11 10:08:41 +10:00
- No empty backing classes for template-only components unless requested
2026-08-31 14:33:29 -03:00
- Build UI from the ui-kit primitives (`frontend/discourse/app/ui-kit` : `d-*` components, `helpers/` , `modifiers/` ) rather than hand-rolling controls, layout, or behaviour; new shared, domain-free primitives go there. See ./docs/developer-guides/docs/03-code-internals/02-ui-kit.md
2026-08-31 14:04:01 -03:00
- Use the skill at `.skills/discourse-frontend-conventions` when writing or reviewing JS/TS/Glimmer classes and templates (private members, member ordering, comments, invocation ordering)
2026-08-31 14:33:29 -03:00
- Use FormKit for forms, see ./docs/developer-guides/docs/03-code-internals/22-form-kit.md (`frontend/discourse/app/form-kit` )
- Use BEM for CSS, see ./docs/developer-guides/docs/03-code-internals/26-css-guidelines-bem.md
2026-03-18 08:08:48 +10:00
- Make display strings translatable (use placeholders, not split strings)
- Use "Sentence case" for strings, not "Proper Case" or "lower case"
2026-07-16 10:58:56 +10:00
- Plugins/themes can't import npm modules directly; add the dependency to core and expose a `frontend/discourse/app/lib/load-*.js` wrapper that does the `import()` (see `load-morphlex.js` ).
2026-09-03 08:57:28 +02:00
- Use the skill at `.skills/discourse-warpdrive-models` when creating or changing WarpDrive-backed models (`frontend/discourse/app/data` )
2025-08-11 10:08:41 +10:00
2026-07-15 09:36:42 +01:00
### Comments & Types
- Prefer self-documenting code. Comments should only be added when future misunderstanding is likely. They should be terse, and should describe 'why', not 'what'. They should not be used to describe history.
- In the frontend, typescript is typically used for platform-level code, javascript for business-logic
- Platform-level frontend code should include accurate types & tsdoc descriptions for public APIs
2026-08-31 14:05:00 -03:00
- Use the skill at `.skills/discourse-writing-typescript` when authoring .ts/.gts or converting .js/.gjs to TypeScript
2026-07-15 09:36:42 +01:00
- Simple JSDoc/TSDoc comments can be used in other code for editor intellisense, but this is not essential
2026-07-22 15:50:36 +01:00
- In core, never name plugin features or specific libraries in comments/docs — describe by mechanism
2025-08-11 10:08:41 +10:00
## Testing
2026-05-22 15:39:26 +08:00
- Use the skill at `.skills/discourse-writing-rspec-tests` when writing RSpec tests
2025-08-11 10:08:41 +10:00
2026-05-22 15:39:26 +08:00
## Commands
2025-12-22 11:49:14 +08:00
```bash
2025-11-15 07:29:18 +11:00
# JavaScript tests - bin/qunit
bin/qunit --help # detailed help
bin/qunit path/to/test-file.js # Run all tests in file
bin/qunit path/to/tests/directory # Run all tests in directory
2026-07-22 15:50:36 +01:00
bin/qunit --filter "Some text" # Case-insensitive substring match on "module: test name"
bin/qunit --filter "/Foo|Bar/i" # Slash-wrapped value is a regex (include the "i" flag); use for alternation
2025-08-11 10:08:41 +10:00
# Linting
bin/lint --fix path/to/file path/to/another/file
bin/lint --fix --recent # Lint all recently changed files
2025-06-20 16:39:04 +10:00
```
2026-07-29 13:25:30 +08:00
Run `bin/lint --fix` once after implementation is complete and before handing
off completed changes, committing, or pushing. During iterative edits, only run
lint when it helps diagnose an issue. Prefer passing the specific changed files;
use `bin/lint --fix --recent` only when appropriate.
2025-06-20 16:39:04 +10:00
## Site Settings
2025-08-11 10:08:41 +10:00
- Configured in `config/site_settings.yml` or `config/settings.yml` for plugins
- Functionality in `lib/site_setting_extension.rb`
- Access: `SiteSetting.setting_name` (Ruby), `siteSettings.setting_name` (JS with `@service siteSettings` )
2025-06-20 16:39:04 +10:00
2025-08-11 10:08:41 +10:00
## Services
- Extract business logic (validation, models, permissions) from controllers
2026-08-31 14:33:29 -03:00
- docs/developer-guides/docs/03-code-internals/20-service-objects.md
2026-03-18 08:08:48 +10:00
- Use the skill at .skills/discourse-service-authoring
2025-08-11 10:08:41 +10:00
- Examples: `app/services` (only classes with `Service::Base` )
2025-06-20 16:39:04 +10:00
## Database & Performance
2025-08-11 10:08:41 +10:00
- ActiveRecord: use `includes()` /`preload()` (N+1), `find_each()` /`in_batches()` (large sets), `update_all` /`delete_all` (bulk), `exists?` over `present?`
- Queries: use `explain` , specify columns, strategic indexing, `counter_cache` for counts
2026-05-22 15:39:26 +08:00
## Migrations
- Use the skill at `.skills/discourse-migration` before writing or reviewing any migration
2025-10-21 11:43:10 +11:00
## HTTP Response Codes
- **204 No Content**: Use `head :no_content` for successful operations that don't return data
- DELETE operations that successfully remove a resource
- UPDATE/PUT operations that succeed but don't need to return modified data
- POST operations that perform an action without creating/returning resources (mark as read, clear notifications)
- **200 OK**: Use `render json: success_json` when returning confirmation data or when clients expect a response body
- **201 Created**: Use when creating resources, include location header or resource data
- **Do NOT use 204 when**:
- Creating resources (use 201 with data)
- Returning modified/useful data to the client
- Clients expect confirmation data beyond success/failure
2025-08-11 10:08:41 +10:00
## Security
- XSS: use `{{}}` (escaped) not `{{{ }}}` , sanitize with `sanitize` /`cook` , no `innerHTML` , careful with `@html`
- Auth: Guardian classes (`lib/guardian.rb` ), POST/PUT/DELETE for state changes, CSRF tokens, `protect_from_forgery`
- Input: validate client+server, strong parameters, length limits, don't trust client-only validation
2026-05-05 12:02:08 +10:00
- Authorization: Guardian classes, route+action permissions, scope limiting, `can_see?` /`can_edit?` patterns. Use user.guardian shorthand not Guardian.new(user)
2025-08-11 10:08:41 +10:00
## Knowledge Sharing
- ALWAYS persist information for ALL developers (no conversational-only memory)
- Follow project conventions, prevent knowledge silos
- Recommend storage locations by info type
- Inform when this file changes and reloads