Skip to content

Setup

Contributor requirements

Mitup is a Python project, managed with uv and deployed as containers on AWS. To work on it you need:

  • uv, which manages the Python version, the virtual environment, and every dependency
  • A Docker installation (Docker Desktop works well if you don't have one), used for local Postgres and for running the bot in a container
  • gettext, which compiles the translation catalogs
  • A GitLab account
  • Working knowledge of modern Python, including type annotations

uv installs the right Python version for you the first time you sync, so you don't need to install a specific distribution yourself. gettext is the one system dependency uv can't provide; install it with your package manager (brew install gettext on macOS, apt install gettext on Debian/Ubuntu). You don't need any PostgreSQL client libraries.

No PostgreSQL client libraries needed

Mitup talks to PostgreSQL through psycopg, pinned with the binary extra in pyproject.toml. The binary wheels bundle libpq, so you don't need a C compiler or a separate PostgreSQL installation.

Clone and bootstrap

External contributors work from a fork. Fork the repository into your own namespace on GitLab, then clone the fork:

git clone git@gitlab.com:<your-namespace>/mitup-telegram-bot.git
cd mitup-telegram-bot

The rest of this page is the same whether you cloned a fork or the main repository.

Create the environment and install the git hooks in one step:

uv sync
uv run mb setup

uv sync reads uv.lock and builds a .venv at the repo root with every workspace member and dependency. uv run mb setup bootstraps the rest of the checkout: it runs uv sync again (so it's safe to run on its own), installs the pre-commit hooks, and copies any local-only config from your main checkout when you're in a worktree. The command is idempotent, so you can re-run it any time your setup drifts.

mb is the developer CLI for this repository. Every task below runs through it. See the mb CLI for the full command surface, or run uv run mb --help.

Type hints in your editor

Point your editor's interpreter at the workspace virtual environment (.venv/bin/python at the repo root). It carries boto3-stubs and the project's type checker, so autocompletion and inline type checking match what CI runs. To generate a shared VS Code (or Cursor) config with the right interpreter and formatter wired up, run uv run mb setup --vscode.

Configure your development bot

To drive your changes through Telegram, link a bot to Mitup. Open BotFather and register one:

  • Run the /newbot command
  • Choose a name, e.g. Mitup-<yourname>-dev
  • Choose a username, e.g. mitup_yourname_dev_bot
  • Copy the token BotFather gives you

Write that token into your local development config:

uv run mb setup --bot-token <token>

This generates a dev.toml config file that Mitup reads when running locally. If it already exists, the command asks before overwriting; pass --force to skip the prompt. Rerun uv run mb setup without --bot-token whenever the project gains required config options: it adds any option your dev.toml is missing, with a sample value, and leaves every value you already set untouched. Passing --admin-id sets up the admin-only broadcast feature. The full catalogue of config options lives on the config models in config.py.

Set up your database

Local runs use a Postgres container. Start it and apply the schema:

uv run mb db up
uv run mb db migrate up

mb db up starts the Postgres container and waits until it reports healthy. mb db migrate up runs every pending migration. The container keeps its data in a local ./postgres-data volume, so the schema and rows survive restarts.

Launch Mitup

Start the bot:

uv run mb run bot

That runs the bot on your host against the local Postgres. To run it inside docker compose instead, add --docker. The recurrent-events worker runs the same way with uv run mb run events. Open your bot in Telegram and start a conversation.

Once the bot is running, the mb CLI covers the rest of the day-to-day workflow: tests, migrations, locales, and the local container lifecycle.