Files
upstream-zulip/AGENTS.md
upstream-mirror 64898b2c79
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
2026-09-15 15:05:30 +05:00

384 lines
15 KiB
Markdown

# AGENTS.md - Guidelines for AI Contributions to Zulip
This file provides guidance to AI coding agents for contributing to
the Zulip codebase. These guidelines are designed to produce
contributions that meet the same high standards we expect from human
contributors.
When doing any work with AI assistants, it is crucial to follow our
AI use policy and guidelines (the "AI use policy and guidelines"
section in `CONTRIBUTING.md`). In particular:
> **Do not submit an AI-generated PR you haven't personally
> understood and tested**, as this wastes maintainers' time. PRs that
> appear to violate this guideline will be closed without review.
> **Do not post AI-generated messages** in the [Zulip development
> community](https://zulip.com/development-community/) -- we want to
> read your own genuine expression of your thoughts.
Claude Code automatically uses `.claude/rules/` and `.claude/skills/`.
If you are a different agent, read the files in these folders to see
the rest of the agent instructions and when they're relevant. Rules
are relevant for files listed in `paths:` at the top of the rule
file. Skills explain when they're relevant in their `description`.
## Philosophy
Zulip is a team chat application used by thousands of organizations,
built to last for many years. It is developed by a vibrant open-source
community, with maintainers who have consistently emphasized **high
standards for codebase readability, code review, commit discipline,
debuggability, automated testing, tooling, documentation, and all the
other subtle details that together determine whether software is easy
to understand, operate, and modify**.
Zulip's engineering strategy is to **"move quickly without breaking
things"**. This is possible because the project has invested years in
testing, tooling, code structure, documentation, and development
practices that catch bugs systematically rather than relying on
individual vigilance. Maintainers spend most of their review time on
product decisions and code structure/readability, not on chasing
correctness issues — because the process is designed to prevent them.
This means Zulip's coding philosophy is to **focus relentlessly on
making the codebase easy to understand and difficult to make dangerous
mistakes**. This applies equally to AI-generated contributions. Every
change should make the codebase more maintainable and easier to read.
### No detail is too small
There is no category of "minor issue" that is acceptable to ship —
if something is broken in any state, size, theme, or language where
a user would encounter it, it must be fixed before merging. If a fix
would require a design decision, raise it as a question rather than
shipping the broken state. See `.claude/rules/ui-testing.md` for
what to test for UI changes (the file loads automatically when you
work on frontend files).
The right attitude is: "What could go wrong, and how do I verify that
it doesn't?" not "It looks fine to me." **What isn't tested probably
doesn't work** — this applies to visual changes just as much as to
backend logic.
### Understand before coding
Before writing any code, you must understand:
1. What the existing code does and why, including the relevant help center or
developer-facing documentation.
2. What problem you're solving, in its full scope.
3. Why your approach is the right solution, and available alternatives.
4. How you will verify that your work is correct, and avoid regressions
that are plausible for the type of work you're doing.
The answer to "Why is X an improvement?" should never be "I'm not sure."
## Workflow
Follow this workflow for every task: **understand → propose → implement → verify**.
### 1. Understand Before Coding
Before making any changes:
```bash
# Read relevant documentation
cat docs/*/<relevant-area>.md
cat starlight_help/src/content/docs/<topic>.md
cat api_docs/<topic>.md and read the relevant part of zerver/openapi/zulip.yaml
# Look at existing code patterns
git grep "similar_function_name"
git log --oneline -20 -- path/to/file.py
# Check for related issues on GitHub
```
### 2. Propose an Approach
Before writing code, explain the plan:
- Explain your understanding of the problem and all relevant design decisions
- What changes are needed and why
- How the changes fit with existing patterns
- What could break and how to prevent regressions
### 3. Implement in Minimal, Coherent Commits
Structure changes as clean commits:
- Backend and API changes, with tests and API doc changes documented
fully using our double-entry changelog system. Instructions for
documentation can be found in `.claude/rules/api-changelog.md`
(loaded automatically when you edit `zerver/openapi/zulip.yaml`).
- Frontend UI changes (with tests and user-facing documentation
updates). Remember to plan to use your visual test skill
(`.claude/skills/visual-test/SKILL.md`) to check your work whenever
you change web app code (HTML, CSS, JS).
Each commit should be self-contained, highly readable and reviewable
using `git show --color-moved`, and pass lint/tests independently. If
extracting new files or moving code, always do that in a separate
commit from other changes.
### 4. Verify Before Finalizing
Run the linter and the relevant tests before making each commit; see
"Testing Requirements" below for instructions.
Run through the `/self-review` skill's checklist before suggesting opening
a PR (`.claude/skills/self-review/SKILL.md`).
## Before You Start
### Read the Relevant Documentation
Zulip has over 185,000 words of developer documentation. Before working on any area:
- Read documentation from docs/, starlight_help/src/content/docs/, and api_docs/.
`docs/subsystems/directory-structure.md` explains where code lives.
- Read existing code in the area you're modifying.
- Use `git grep` to find similar patterns in the codebase and read those.
### Understand the Code Style
- **Be consistent with existing code.** Look at surrounding code and follow
the same patterns, as this is a thoughtfully crafted codebase.
- **Use clear, greppable names** for functions, arguments, variables, and
tests. Future developers will `git grep` for relevant terms when
researching a problem, so names should communicate purpose clearly.
- Keep everything well factored for maintainability. Avoid duplicating
code, especially where access control or subtle correctness is involved.
- Run `./tools/lint` to catch style issues before committing, including mypy issues.
- Prefer writing code that is readable without explanation over heavily
commented code using clever tricks.
- Don't reference line numbers (e.g., `filter.ts:493`) in comments, commit
messages, or PR descriptions; they get stale when files are edited.
Reference symbol names instead.
**Comments**
- Comments should explain "why" when the reason isn't obvious, not
narrate "what" the code does.
- Comments should have a line to themself except for CSS px math.
- Comments should never describe the change being made or a bug
being fixed. They should read as if they were there all along.
Descriptions of the diff belong in the commit message instead.
- Match comment density of nearby code and similar functions.
If similar code doesn't comment on something, don't comment
on it in new code.
- Avoid metaphors in favor of clear descriptive language. Match
existing idioms verbatim for comments describing specific
situations (e.g., `/* Override bootstrap defaults */`) rather
than writing a new or longer explanation.
**Further rules**
Frontend rules can be found in `.claude/rules/frontend.md` (loaded
automatically when you work on frontend JS/TS and template files).
CSS rules can be found in `.claude/rules/css.md` (loaded
automatically when you work on CSS files).
Python rules can be found in `.claude/rules/python.md` (loaded
automatically when you work on .py files).
See: `docs/contributing/code-style.md`
## Commit Discipline
Zulip follows the Git project's practice of **"Each commit is a minimal
coherent idea."** This is non-negotiable.
### Each Commit Must:
1. **Be coherent**: Implement one logical change completely and atomically.
2. **Pass tests**: Include test updates in the same commit as code changes.
3. **Not make Zulip worse**: Work is ordered so no commit has regressions.
4. **Be safe to deploy individually**: Or explain in detail why not.
5. **Be minimal** and **reviewable**: Don't combine moving code with changing
it in the same commit; make liberal use of small prep commits for
no-op refactoring that are easy to verify.
### Never:
- Mix multiple separable changes in a single commit.
- Create a commit that "fixes" a mistake from an earlier commit in the same PR;
always edit Git to fix the original commit.
- Add content in one commit only to remove or move it in the next;
plan upfront what belongs where and do it right the first time.
- Include debugging code, commented-out code, or temporary TODOs.
- Leave commits that break if a later commit in the PR is dropped.
When a commit is flagged as potentially droppable, verify all
earlier commits work correctly without it.
### Open Independently Useful Fixes as Separate PRs
If, while building a feature, you find and fix a pre-existing bug or
make a refactor that would be worth merging even if the feature never
lands, split this into its own PR. A small isolated PR gets more
scrutiny than the same change as part of a large PR. Prep commits
that mainly make sense in the context of the feature PR should stay
in the feature's PR.
### Commit Message Format
Use the `/commit-message` skill whenever you write or reword a
commit message (`.claude/skills/commit-message/SKILL.md`).
## Testing Requirements
Zulip server takes pride in its ~98% test coverage. All server changes
must include nice tests that follow our testing philosophy.
When writing tests, follow our testing philosophy in
`.claude/rules/testing.md` (loaded automatically when you work on
test files).
Manage your time by running specific backend test collections, not
the entire suite; the node suite is fast enough to run in full.
```bash
# Includes mypy and typescript checkers
./tools/lint path/to/changed/files.py
./tools/test-backend zerver.tests.test_relevant_module
./tools/test-js-with-node
```
### Manual Testing for UI Changes
If a PR makes frontend changes, manually verify the affected UI
using the checklist in `.claude/rules/ui-testing.md` (loaded
automatically when you work on frontend files).
## What Not To Do
- Always check if you're working on top of the latest upstream/main, and
fetch + rebase when starting a project so you're not using a stale branch.
If you're continuing a project, start by rebasing, resolving merge
conflicts carefully.
- Don't make design or UX decisions silently. When a technical
constraint forces a tradeoff, present the constraint and options
to the user rather than picking one. Never remove features, hide
UI elements, or change interaction patterns without asking.
- Don't submit code you haven't tested
- Don't skip becoming familiar with the code you're modifying
- Don't make claims about code behavior without verification, and
cite your sources.
- Don't generate PR descriptions that just describe what files changed
- Always do a pre-mortem: Think about how to avoid a bug recurring,
how it might break something that already works, or imagine under
what circumstances your changes might need to be reverted.
## Pull Request Guidelines
When opening a pull request, prefix the PR title with `[ai]` (e.g.,
`[ai] compose: Fix cursor position after emoji insertion.`). Use
`upstream/main` as the base branch. Use the `/pr-description` skill
to write the PR description
(`.claude/skills/pr-description/SKILL.md`).
## When to Pause and Discuss
Recommend pausing for discussion when:
- The approach involves security-sensitive code
- Database migrations are needed (See `docs/subsystems/schema-migrations.md`).
- The change alters behavior in several subsystems at once (renames
and type annotation changes that touch many files do not count)
- Performance implications are unclear
- The feature design isn't fully specified
- The API or data model design isn't fully specified
- An API change may not be compatible (See `docs/processes/api-design.md`).
- Existing tests are failing for unclear reasons
## Task-Specific Approaches
### For Bug Fixes
1. Look at the relevant code and brainstorm theories for
how the bug might be possible
2. Provide a clear explanation for the bug, and ideally
provide steps for reproducing the bug on `main` in the
dev environment. Verify the cause of the bug before
suggesting a fix, unless a bug is very difficult to verify,
in which case say so and explain a hypothesis instead.
3. Analyze and propose a fix with a clear explanation
4. Write tests that would have caught this bug if possible
5. Audit for whether the bug may exist elsewhere or might be
re-introduced and propose appropriate changes to address if so.
### For New Features
1. Read the relevant documentation in docs/
2. Show similar existing features in the codebase
3. Propose an implementation approach before coding
4. Implement, following "Commit Discipline" above
### For Refactoring
1. Show the current implementation
2. Explain what makes it problematic
3. Propose the refactoring approach
4. Implement in commits that each leave the codebase working
5. No behavior changes unless explicitly discussed
6. Verify completeness: use `git grep` to find all occurrences and
confirm nothing was missed
## Key Documentation Links
- Contributing guide: `docs/contributing/contributing.md`
- Code style: `docs/contributing/code-style.md`
- Commit discipline: `docs/contributing/commit-discipline.md`
- Testing overview: `docs/testing/testing.md`
- Backend tests: `docs/testing/testing-with-django.md`
- Code review: `docs/contributing/code-reviewing.md`
- mypy guide: `docs/testing/mypy.md`
## Help Center Documentation
When making any user-facing change, **read
`docs/documentation/helpcenter.md`** in full and review the relevant
help center articles under `starlight_help/src/content/docs/` for any
updates that should be made. The writing guide there is the source
of truth for help center conventions, components, and structure.
## Zulip Chat Links
When you encounter a Zulip narrow URL (e.g., from `chat.zulip.org` in a
GitHub issue, PR, or user message), use the `/fetch-zulip-messages`
skill (`.claude/skills/fetch-zulip-messages/SKILL.md`) to read the
conversation. Do not use `WebFetch` — it cannot access Zulip message
content.
## Common Commands
```bash
./tools/provision # Set up development environment
./tools/run-dev # Start development server
./tools/lint # Run all linters
./tools/test-backend # Run Python tests
./tools/test-js-with-node # Run JavaScript tests
./tools/run-mypy # Run type checker
git grep "pattern" # Search codebase (use extensively!)
```
Most of these commands take minutes, so run them in the background.
If a tool complains that provision is outdated, run `./tools/provision`
to fix it. Do not use `--skip-provision-check` to work around the
error; the check exists because tests and linters depend on provisioned
dependencies being current.
If the development environment runs in a container (Vagrant/Docker),
run `./tools/` commands inside it. Files and new screenshots will be
accessible on both sides.
```bash
vagrant ssh -c 'cd ~/zulip && ./tools/lint path/to/changed/files.py'
```
If `vagrant ssh` fails with a Docker daemon error, Docker Desktop isn't
running; ask the user to start it.