kitsune
CLAUDE.md1.7k starsChanged 14 days agoBSD-3-ClauseView on GitHub
Guidance for Claude Code (claude.ai/code) working in this repository. Kitsune is the Django platform behind SuMo (support.mozilla.org). Development is Docker-based. This file holds cross-cutting, non-obvious knowledge. Discoverable detail is intentionally not duplicated here — read the source of truth instead: - Commands → Makefile · services → docker-compose.yml · env vars → .env-dist · frontend build → package.json · dev scripts → bin/. - Versions (Python, Django, Elasticsearch, …) → pyproject.toml and package.json. Don't hardcode version numbers in docs —…
- Reads credentials
We split this CLAUDE.md into the rules it gives an agent
5 rules. About 0 are common, 3 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 29
Cache / Celery: run on Redis; use app-specific cache-key prefixes.
- Very specific: line 33
Prefer concise, verb-based names that read naturally when chained — GroupProfile.objects.visible(user), Article.objects.active().
- Distinctive: line 53
Always: use the visibility-aware paths:
- Very specific: line 63
Run tests through Docker, not uv run: targeted — docker compose run --rm web ./manage.py test <dotted.path> --keepdb -v 2.
- Distinctive: line 74
Don't add trailing whitespace or trailing blank lines at end of files.
≈ “Common” is an estimate: at least 1 in 5 of the 25,680 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CLAUDE.md
Guidance for Claude Code (claude.ai/code) working in this repository.
Kitsune is the Django platform behind SuMo (support.mozilla.org). Development is Docker-based.
This file holds cross-cutting, non-obvious knowledge. Discoverable detail is intentionally not duplicated here — read the source of truth instead:
- Commands →
Makefile· services →docker-compose.yml· env vars →.env-dist· frontend build →package.json· dev scripts →bin/. - Versions (Python, Django, Elasticsearch, …) →
pyproject.tomlandpackage.json. Don't hardcode version numbers in docs — they drift. - App-specific guidance lives in per-app
CLAUDE.mdfiles (see Per-app guides); they load on demand when you work in that app.
Stack (orientation — versions live in pyproject.toml / package.json)
Django + Python · PostgreSQL · Elasticsearch · Redis (cache + Celery broker) · Webpack / SCSS / vanilla JS + jQuery · uv (Python packaging) · ruff (lint + format) · Django TestCase + Playwright (E2E).
App map
Primary: wiki (KB articles) · questions (Q&A / AAQ) · forums · users (profiles, auth) · search (Elasticsearch) · gallery (media) · products (products & topics) · kpi (metrics).
Supporting: sumo (core: ModelBase, base templates, middleware, jinja helpers) · customercare (Zendesk) · flagit (moderation) · inproduct (Firefox in-product redirects) · llm (AI: moderation / categorization / translation) · messages · notifications · tidings (email subscriptions) · kbadge · groups · dashboards.
Conventions
- Models inherit
kitsune.sumo.models.ModelBase. UseLocaleFieldfor locale fields. Celery tasks intasks.py; REST inapi.py; routes inurls.py/urls_api.py. - Imports at the top of the file, always — the only exception is breaking a genuine circular import, with a one-line note naming the cycle. Applies to test files too.
- No environment-specific IDs in code, comments, or migrations — DB primary keys differ per environment. Reference rows by slug / name.
- Test factories live in each app's
tests/__init__.py(e.g.kitsune/questions/tests/__init__.py) — there are nofactories.pyfiles. - All user-facing strings are translated with
_()/_lazy(). - Templating is Django-Jinja (not stock Django templates); helpers in
kitsune.sumo.templatetags.jinja_helpers; mobile via themobile_template()decorator. - Cache / Celery run on Redis; use app-specific cache-key prefixes.
Manager-method naming
Prefer concise, verb-based names that read naturally when chained — GroupProfile.objects.visible(user), Article.objects.active(). Use a more verbose descriptive name only when concision would be unclear.
Routing
i18n URL patterns. KB /kb/ · questions /questions/ · forums /forums/ · gallery /gallery/ · groups /groups/; users / products at root (/users/, /firefox/). APIs: v1 /api/1/{app}/ (legacy), v2 /api/2/{app}/ (current); GraphQL at /graphql. In-product integration under /1/ (see the inproduct guide). Feature-flag JS at /wafflejs.
Frontend
Webpack entrypoints are referenced by name from Jinja templates (base.html includes entrypoints/{name}.html). When removing an entry from webpack/entrypoints.js, grep templates for its name (grep -rn '<name>' kitsune --include='*.html') and remove every reference — a missed one fails the build with TemplateNotFound.
Security — GroupProfile visibility (CRITICAL)
GroupProfile has three visibility levels (PUBLIC, PRIVATE, MODERATED). Django's User.groups returns all groups, ignoring visibility — so bypassing the visibility layer leaks PRIVATE group membership into profiles, search indexing, and API responses.
Never:
user.groups.all() # leaks PRIVATE groups
profile.user.groups.all() # leaks PRIVATE groups
Group.objects.filter(user=some_user) # bypasses visibilityAlways use the visibility-aware paths:
profile.visible_group_profiles(viewer=request.user)
GroupProfile.objects.visible(viewer).filter(group__user=some_user)
group_profile.can_view(request.user)This applies equally in views, templates, API serializers, and search indexing.
Testing
- Run tests through Docker, not
uv run: targeted —docker compose run --rm web ./manage.py test <dotted.path> --keepdb -v 2; full suite —make test. - Factories from
factory_boy(intests/__init__.py). Mock Elasticsearch on code paths that don't need a live index. E2E inplaywright_tests/. Tests run withTESTING=True. - Elasticsearch round-trip and index tests have real gotchas — see the
searchguide.
Development practices
- Format with
ruff format; lint withruff check; runmake lint(pre-commit) before committing. - Be specific with exception types — catch
Model.DoesNotExist,KeyError, etc., not bareException, so unexpected errors still surface. - Preserve functional parity in dependency upgrades and cleanups — don't drop features to shrink a diff; a dropped feature is a regression.
- No AI-planning references in code — never leave
# per Plan 3, step numbers, or ticket-scaffolding comments. An issue/PR reference that captures a real why is fine. - This repo targets Python 3.14 (ruff
target-version = py314). Noteexcept A, B:(unparenthesized multi-exception) is valid 3.14 syntax — don't flag it as an error. - Don't add trailing whitespace or trailing blank lines at end of files.
.envgotcha:bin/dc_ci.sh(and.env-build) overwrite.env— back up any local.envbefore running CI setup scripts.
Localization
100+ locales. Locale definitions in kitsune/lib/sumo_locales.py; translations in locale/; per-language ES synonyms in kitsune/search/dictionaries/synonyms/.
Per-app guides (load on demand)
Deeper, app-specific notes live in kitsune/<app>/CLAUDE.md and load only when you work in that app: search, wiki, llm, retrieval, questions, users, customercare, inproduct.
Trending
Quiet since September.about the whole repository
Who's talking about mozilla/kitsune
- mozmeao/infra“SUMO static media CDN”GitHub · Jan 16, 2018 · 3 reactions
- dslm4515/CMLFS“llvmtools: Failed to build Cmake under Glibc #19”GitHub · Jul 8, 2021 · 2 reactions
- mozilla/sumo“Add an option to modify username”GitHub · Sep 17, 2019 · 2 reactions
- mozilla/sumo“Product titles for the "SUMO needs your help" are not translated”GitHub · Sep 7, 2026 · 1 reactions
- mozilla/sumo“Translation stats are incorrect”GitHub · Aug 25, 2026 · 1 reactions
The biggest 5 of 30 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 30
Talked about on GitHub (30 times).
On GitHub · 30
- Jan 16, 2018SUMO static media CDN — mozmeao/infra3 reactions · 4 comments
- Jul 8, 2021llvmtools: Failed to build Cmake under Glibc #19 — dslm4515/CMLFS2 reactions · 4 comments
- Sep 17, 2019Add an option to modify username — mozilla/sumo2 reactions · 2 comments
- Sep 7, 2026Product titles for the "SUMO needs your help" are not translated — mozilla/sumo1 reaction · 2 comments
- Aug 25, 2026Translation stats are incorrect — mozilla/sumo1 reaction · 6 comments
25 more on GitHub
- Aug 10, 2026tag pill regression — mozilla/sumo1 reaction · 1 comment
- Jul 19, 2026🐦 — johansebastianbach444-lgtm/SnailsOnDeck-1 reaction
- Mar 22, 2024Address the Mozilla Location Service (MLS) sunset — mozilla/sumo1 reaction · 3 comments
- Jun 13, 2021ŹródłoAniołaŻyciaAllsHearts — electron/electron1 reaction · 1 comment
- Nov 11, 2019tests: Install openssl 1.1 in the docker image. — mozilla/sccache1 reaction · 2 comments
- Sep 10, 2026"Menu title" literal string shown for filtering disclosure — mozilla/sumo0 reactions
- Sep 4, 2026Drop l10n of urgency strings — escattone/kitsune0 reactions · 1 comment
- Sep 4, 2026Plurals are not used in custom error messages when referring to chars — mozilla/sumo0 reactions · 1 comment
- Sep 4, 2026Some common responses are automatically flagged for moderation — mozilla/sumo0 reactions · 4 comments
- Aug 20, 2026better alert on invalid record errors when sending Zendesk tickets — mozilla/sumo0 reactions
- Aug 20, 2026External images are blocked by CSP but survive in the e-mail notification — mozilla/sumo0 reactions
- Aug 20, 2026Messaging system bulk_action returns 500 ValueError on mark_read and mark_unread actions — mozilla/sumo0 reactions
- Aug 19, 2026Some sidebar elements become unreachable at a certain viewport width without a reachable alternative — mozilla/sumo0 reactions · 3 comments
- Aug 1, 2026Product logos displayed at the top of KB articles are missing alt text — mozilla/sumo0 reactions · 1 comment
- Aug 1, 2026The Mozilla Support logo alt text is not exposed for l10n — mozilla/sumo0 reactions · 1 comment
- Jun 9, 2026Don't count deleted contributions when awarding badges — mozilla/sumo0 reactions · 7 comments
- Jul 19, 2024Some SUMO strings are not marked as localizable — mozilla/sumo0 reactions · 9 comments
- Nov 7, 2022remove duplicate messages — mozilla-l10n/sumo-l10n0 reactions · 1 comment
- Nov 5, 2022fix sources of compilation errors — mozilla-l10n/sumo-l10n0 reactions · 1 comment
- Dec 4, 2021> > https://github.com/mozilla/kitsune/issues/4949 — h5bp/Front-end-Developer-Interview-Questions0 reactions · 2 comments
- Nov 9, 2021Circleci s3 user — mozilla-it/sumo-infra0 reactions
- Nov 7, 2019Fix for KItsune API timezone — mozilla-it/sumo0 reactions
- May 3, 2019Features/user mobile designs — lincolnloop/kitsune0 reactions
- Oct 26, 2017initial infra project structure for SUMO, S3 + Cloudfront distributions — mozmeao/infra0 reactions · 6 comments
- Feb 26, 2016Deactivate project and add note to README — mozilla/sumo-tests0 reactions · 3 comments
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

