Files
Modus/CONTRIBUTING.md
2026-07-21 16:42:40 +05:45

8.0 KiB

Contributing to Modus

Thanks for your interest in contributing to Modus! This guide covers everything you need to get started.

Table of Contents

Prerequisites

  • Arch Linux with Hyprland (Wayland compositor)
  • Python 3.13+
  • uv package manager
  • Meson + Ninja (for C backends)
  • GCC (for Global Menu shim)

Install all dependencies:

paru -S uv fabric-cli-git cliphist gnome-bluetooth-3.0 slurp ffmpeg hypridle hyprsunset hyprpicker hyprshot grim libnotify matugen-bin playerctl gtk-session-lock awww apple-fonts swappy wl-clipboard webp-pixbuf-loader wf-recorder acpi brightnessctl power-profiles-daemon uwsm cinnamon-desktop ddcutil at-spi2-core gcc make pkgconf appmenu-gtk-module libdbusmenu-gtk3 libdbusmenu-qt5 meson ninja wayland-protocols --needed

Setup

# Fork and clone
git clone https://github.com/<your-username>/Modus.git ~/.config/Modus
cd ~/.config/Modus

# Install dependencies
uv sync

# Compile App Switcher C backend
cd src/window/switcher/app-capture
meson setup builddir
meson compile -C builddir
cd ../../../..

# Compile Global Menu shim
cd src/window/globalmenu
gcc -shared -fPIC -O2 -o libmenu_button_shim.so libmenu_button_shim.c $(pkg-config --cflags --libs gtk+-3.0) -ldl
cd ../../..

# Run
uv run start

Project Structure

Modus/
├── src/
│   ├── main.py                    # App bootstrap
│   ├── services/                  # System service monitors (DBus, signals)
│   ├── shared/                    # Reusable widgets and base window classes
│   ├── utils/                     # Utility modules
│   ├── window/                    # All UI windows
│   │   ├── panel/                 # Top bar
│   │   ├── dock/                  # macOS-style dock
│   │   ├── controlcenter/         # Quick settings panel
│   │   ├── notification/          # Notification system
│   │   ├── switcher/              # Alt-Tab app switcher (C backend)
│   │   ├── spotlight/             # Super+D search (plugin system)
│   │   ├── osd/                   # Volume/brightness on-screen display
│   │   ├── screencapture/         # Screen capture/recording
│   │   ├── desktop/               # Desktop widgets
│   │   ├── settings/              # Settings window
│   │   ├── globalmenu/            # macOS global menu bar
│   │   └── lock.py                # Session lock screen
│   └── styles/                    # GTK CSS stylesheets
├── config/                        # User-facing config (TOML)
│   ├── config.toml                # Main settings
│   ├── mods.toml                  # Custom panel buttons
│   ├── dock.toml                  # Pinned dock apps
│   └── plugins/                   # User-installed spotlight plugins
├── examples/                      # Example plugins
├── docs/                          # Documentation
├── pyproject.toml                 # Project config + Ruff linting
└── start.py                       # Entry point

Development Workflow

  1. Create a branch from dev:

    git checkout dev
    git checkout -b feat/my-feature
    
  2. Make your changes and ensure they pass linting:

    # Lint
    .venv/bin/ruff check
    
    # Auto-fix lint issues
    .venv/bin/ruff check --fix
    
    # Format
    .venv/bin/ruff format
    
    # Check formatting without changing files
    .venv/bin/ruff format --check
    
  3. Test your changes by running the app:

    uv run start
    
  4. Commit with a descriptive message (see Commit Messages).

  5. Push and open a Pull Request against dev.

Code Style

Modus uses Ruff for both linting and formatting. The full config is in pyproject.toml.

Key Rules

  • Formatter: Double quotes, 4-space indentation, 88 char line length
  • Import sorting: Grouped as stdlib / third-party / first-party, alphabetical within groups
  • Type hints: Use Optional[X] and typing.List, typing.Dict style (not PEP 604 unions)
  • Logging: Use logger from fabric.utils, not print() (except in CLI entry points)
  • Docstrings: Not enforced, but encouraged for public APIs

Enforced via Ruff

Rule What it catches
E, W Pycodestyle style errors
F Pyflakes (unused imports, undefined names)
I Import sorting (isort)
UP Python upgrade suggestions
B Bugbear (common bugs)
SIM Simplification suggestions
C4 Unnecessary comprehensions
RET Return statement issues
RUF Ruff-specific rules
T20 print() detection

Running Ruff

# Check for issues
.venv/bin/ruff check

# Auto-fix safe issues
.venv/bin/ruff check --fix

# Auto-fix including unsafe changes
.venv/bin/ruff check --fix --unsafe-fixes

# Format all files
.venv/bin/ruff format

# Check formatting (CI-friendly)
.venv/bin/ruff format --check

Commit Messages

Follow Conventional Commits:

<type>(<scope>): <summary>

Types

Type Use for
feat New feature
fix Bug fix
refactor Code restructuring without behavior change
perf Performance improvement
docs Documentation changes
style Code style changes (formatting, no logic change)
chore Build, CI, tooling, dependencies
test Adding or updating tests

Scopes

Use the module name: services, window, dock, panel, spotlight, notification, switcher, osd, config, docs, etc.

Examples

feat(dock): add magnifier hover effect
fix(notification): prevent crash on empty body
refactor(services): extract battery polling to separate thread
docs: update installation guide for Arch Linux
style: enforce consistent codestyle via ruff config

Rules

  • Use imperative mood: "add" not "added" or "adds"
  • Keep subject line under 72 characters
  • Reference issues when applicable: Closes #42
  • Body is optional — use it only to explain why, not what

Pull Requests

Before Submitting

  • Code passes ruff check with no errors
  • Code passes ruff format --check
  • Changes are tested on a live Hyprland session
  • Commit messages follow Conventional Commits

PR Guidelines

  • Target the dev branch (not main)
  • Keep PRs focused — one feature or fix per PR
  • Write a clear description of what changed and why
  • Include screenshots or screen recordings for UI changes
  • Reference related issues

Reporting Bugs

Open an issue with:

  1. Description: What happened vs. what you expected
  2. Steps to reproduce: Exact commands or actions
  3. Environment: OS, Hyprland version, Python version
  4. Logs: Relevant output from terminal or journal

Requesting Features

Open an issue with:

  1. Use case: What problem does this solve?
  2. Proposed solution: How should it work?
  3. Alternatives considered: Other approaches you thought about