|
1 | | -# CLAUDE.md |
2 | | - |
3 | | -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
4 | | - |
5 | | -## Project Overview |
6 | | - |
7 | | -Modmail v5 is a complete rewrite of the Modmail Discord bot (alpha/WIP). It manages support tickets between users and Discord server staff via DM-based modmail. Requires Python 3.14+, uses `uv` as the package manager. |
8 | | - |
9 | | -## Commands |
10 | | - |
11 | | -### Setup |
12 | | -```bash |
13 | | -# Install with SQLite backend |
14 | | -uv sync --locked --compile-bytecode --no-default-groups --extra speed --extra sqlite |
15 | | - |
16 | | -# Install with MongoDB backend |
17 | | -uv sync --locked --compile-bytecode --no-default-groups --extra speed --extra mongodb |
18 | | -``` |
19 | | - |
20 | | -### Run |
21 | | -```bash |
22 | | -uv run python start.py |
23 | | -# or |
24 | | -python -m modmail |
25 | | -``` |
26 | | - |
27 | | -### Lint & Format |
28 | | -```bash |
29 | | -uv run pre-commit run --all-files # Run all pre-commit hooks |
30 | | -uv run ruff check --fix modmail tests |
31 | | -uv run ruff format modmail tests |
32 | | -uv run isort modmail tests |
33 | | -``` |
34 | | - |
35 | | -### Type Check |
36 | | -```bash |
37 | | -uv run pyright |
38 | | -``` |
39 | | - |
40 | | -### Tests (Not Yet Implemented) |
41 | | -```bash |
42 | | -uv run pytest |
43 | | -uv run pytest tests/test_utils.py # Run a single test file |
44 | | -uv run pytest -k "test_name" # Run a specific test |
45 | | -uv run pytest --cov=modmail --cov-report html |
46 | | -uv run tox # Run all tox environments (lint, type, py3.14) |
47 | | -``` |
48 | | - |
49 | | -## Architecture |
50 | | - |
51 | | -### Module Structure |
52 | | -``` |
53 | | -modmail/ |
54 | | -├── backends/ # Database abstraction layer |
55 | | -│ ├── common/ # Abstract base class & shared models |
56 | | -│ ├── mongodb/ # Beanie ODM implementation |
57 | | -│ └── sql/ # SQLAlchemy + aiosqlite implementation |
58 | | -├── config/ # Pydantic config models + YAML loader |
59 | | -├── core/ # Bot class, translator, permissions |
60 | | -│ └── internals/ # Cog base, command types, UI views, embeds |
61 | | -├── cogs/ |
62 | | -│ ├── modmail/ # Core ticket logic (commands + listeners) |
63 | | -│ └── utility/ # about, status, profile commands |
64 | | -└── locales/ # Fluent FTL translation files (en, de) |
65 | | -``` |
66 | | - |
67 | | -### Key Design Patterns |
68 | | - |
69 | | -**Database Abstraction**: `DBClientBase` in `backends/common/client_base.py` defines the interface. Both SQL and MongoDB clients implement this. The active backend is selected via `config.yaml`. |
70 | | - |
71 | | -**Ticket Flow**: |
72 | | -1. User DMs bot → `cogs/modmail/listeners/dm_receive.py` intercepts |
73 | | -2. `core/internals/staff_guild.py` creates a channel or forum thread in the staff server |
74 | | -3. Database stores ticket state via the active backend client |
75 | | -4. Staff reply via commands in `cogs/modmail/commands/` |
76 | | - |
77 | | -**Localization**: Fluent FTL format (`locales/en/main.ftl`). All user-facing strings go through `core/translator.py`. Commands use `LazyHybridCommand` (`core/internals/command.py`) supporting both prefix and slash commands. |
78 | | - |
79 | | -**Cog Base**: Custom `Cog` class in `core/internals/cog.py` with enhanced send/reply helpers and access to the translator. |
80 | | - |
81 | | -### Config |
82 | | -Copy `config.yaml.example` → `config.yaml`. Required fields: `bot.token`, `bot.staff_server_id`, `log_url`. Database backend is configured under the `database` key. |
83 | | - |
84 | | -### Testing Notes |
85 | | -Tests are currently undergoing a rewrite. Pyright runs in strict mode but excludes the `tests/` directory. Pre-commit hooks enforce isort + ruff formatting on every commit. |
| 1 | +## Overview |
| 2 | + |
| 3 | +Modmail is a Discord DM-based support ticket bot. It routes user DMs into staff channels/threads and supports interchangeable MongoDB and SQL backends. The codebase is async-first and structured as a Python package under `modmail/`. |
| 4 | + |
| 5 | +## Structure |
| 6 | + |
| 7 | +- Core runtime and Discord integration live in `modmail/core/` (bot, permissions, translator, internal helpers). |
| 8 | +- Persistence is abstracted behind `modmail/backends/common/` (`DBBackend`, `DBClient`, shared models) with concrete implementations in `modmail/backends/mongodb/` and `modmail/backends/sql/`. |
| 9 | +- Configuration models and loading logic live in `modmail/config/`. |
| 10 | +- Discord-facing behavior is in `modmail/cogs/modmail/` (modmail flows) and `modmail/cogs/utility/` (utility commands). |
| 11 | +- Localization resources are in `modmail/locales/<lang>/main.ftl`, wired via `modmail/core/translator.py`. |
| 12 | +- Support modules: `modmail/logging.py`, `modmail/utils.py`, `modmail/errors.py`, `modmail/enum.py`, and `modmail/__main__.py` as entrypoint. |
| 13 | + |
| 14 | +## Tickets and Data |
| 15 | + |
| 16 | +- DMs are received by listeners in `modmail/cogs/modmail/listeners/`, which create or look up tickets via `StaffGuild` and the database client. |
| 17 | +- Staff interact through commands in `modmail/cogs/modmail/commands/` (e.g. setup, reply, close). |
| 18 | +- Ticket, message, user/profile, settings, activity, and instance-lock models are defined in `modmail/backends/common/models/` and mirrored in both backends. When changing persistence, update **both** Mongo and SQL implementations and keep `DBBackend` the single interface. |
| 19 | + |
| 20 | +## Configuration and Environment |
| 21 | + |
| 22 | +- Configuration is loaded from YAML via `modmail/config/loader.py` into Pydantic models under `modmail/config/models/`. |
| 23 | +- Use configuration (not hardcoded values) for bot token, DB URIs, guild/channel IDs, and locale. Never commit real secrets; only example configs belong in VCS. |
| 24 | + |
| 25 | +## Docs and Docstrings |
| 26 | + |
| 27 | +Docs are built with **Zensical** + **mkdocstrings-python** (griffe). Config: `zensical.toml`. The `docs/` directory contains `:::` stubs — source docstrings are the API reference. Use **Google style**. |
| 28 | + |
| 29 | +Attribute descriptions — write for the *user*, not the implementer: |
| 30 | +- No trivial descriptions: `bot_id: The bot ID.` is bad; `bot_id: Discord application ID.` is the minimum. |
| 31 | +- No implementation details (ORM internals, storage format, index notes, loading strategy) — these belong in the class docstring, not per-attribute. |
| 32 | +- No semicolons; use parenthetical style e.g. `(``None`` if unset)`. |
| 33 | +- Stay within the 115-char line limit. |
| 34 | + |
| 35 | +Cross-references — use `[Name][]` (**not** RST `:class:`Name`` — griffe renders it as literal text): |
| 36 | +- `` [`ClassName`][] ``, `` [`DBBackend`][modmail.backends.common.db_backend.DBBackend] ``, `` [`discord.Guild`][] `` |
| 37 | + |
| 38 | +Unrecognized section names become admonition boxes: `Note:`, `Warning:`, `Tip:`, `Danger:`, etc. |
| 39 | + |
| 40 | +## General Behaviour |
| 41 | + |
| 42 | +- Be conservative with tokens and tool calls: read only what's needed, don't re-read files already in context, avoid unnecessary exploration. |
| 43 | +- Use web search freely — it's cheap and preferred over guessing at external API behaviour. |
| 44 | + |
| 45 | +## Workflows for Claude Code |
| 46 | + |
| 47 | +When working in this repo: |
| 48 | + |
| 49 | +1. Restate the goal and identify relevant modules using the structure above. |
| 50 | +2. Consult the corresponding code/docstrings; for external packages or unfamiliar problems, search public API docs or the web before coding. |
| 51 | +3. Propose a short plan listing affected files, then implement in small, reviewable changes. |
| 52 | +4. Use the existing patterns: |
| 53 | + - Go through `DBClient` for persistence. |
| 54 | + - Use enums from `modmail/enum.py` and errors from `modmail/errors.py`. |
| 55 | + - Keep async I/O non-blocking and follow existing cog patterns. |
| 56 | + - Use Python **3.14+ syntax** in line with the existing code. |
| 57 | +5. Run tools before considering work done: |
| 58 | + - `uv run ruff check --fix && uv run ruff format` |
| 59 | + - `uv run pyright` |
| 60 | + |
| 61 | +## Quirks and Warnings |
| 62 | + |
| 63 | +- Tests in this project are currently **obsolete**; do not use them as a source of truth. |
| 64 | +- Treat migrations and instance-lock logic with care; avoid destructive schema or data changes without explicit human confirmation and a migration plan. |
| 65 | +- No suppression comments: never add `# noqa`, `# type: ignore`, or `# pyright: ignore`; leave errors for a human to decide. |
0 commit comments