Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.allthingslinux.org/llms.txt

Use this file to discover all available pages before exploring further.

This guide covers everything you need to contribute code, docs, or configuration to atl.chat — from branching to merge.

PR workflow

atl.chat uses a fork-and-PR model against the main branch. Every merge into main triggers semantic-release which reads commit messages to determine the next version, generate changelogs, and publish a GitHub release.

Branch naming

Use a descriptive prefix that matches the work type:
PrefixUse caseExample
feat/New feature or enhancementfeat/xmpp-muc-bridging
fix/Bug fixfix/cloak-key-fallback
docs/Documentation onlydocs/add-atheme-ops-guide
chore/Tooling, CI, dependency updateschore/bump-unrealircd-image
refactor/Code restructuring (no behaviour change)refactor/bridge-event-bus
test/Test additions or fixestest/irc-integration-suite

Step-by-step

  1. Fork the repository on GitHub and clone your fork locally.
  2. Create a branch from main:
    git checkout main && git pull origin main
    git checkout -b feat/my-feature
    
  3. Make your changes. Run tests and linting before committing:
    just test          # run root pytest suite
    just lint          # run all pre-commit hooks
    
  4. Commit using Conventional Commits format.
  5. Push your branch and open a pull request against main.
  6. Address review feedback. Push additional commits — the PR will be squash-merged.

Code review expectations

  • Every PR requires at least one approving review before merge.
  • Reviewers check for correctness, test coverage, style compliance, and documentation updates.
  • Keep PRs focused. If a change touches multiple services, consider splitting into separate PRs.
  • CI must pass (lint, unit tests, type checks) before merge is allowed.
  • PRs are squash-merged into main to keep a linear history.

Commit style

atl.chat enforces Conventional Commits via commitlint (run as a pre-commit hook on the commit-msg stage). Semantic-release parses these messages to determine version bumps and generate release notes.

Format

<type>(<scope>): <description>

[optional body]

[optional footer(s)]

Types

TypeVersion bumpPurpose
featminorNew feature or user-facing enhancement
fixpatchBug fix
docsDocumentation only
choreTooling, CI, dependencies
refactorCode restructuring without behaviour change
testAdding or updating tests
ciCI/CD pipeline changes
styleFormatting, whitespace (no logic change)
perfpatchPerformance improvement
A commit with BREAKING CHANGE: in the footer (or ! after the type) triggers a major version bump.

Scopes

Use the app or area name as scope: irc, atheme, xmpp, bridge, web, lounge, webpanel, docs, infra, ops, ci.

Examples

# Feature with scope
feat(bridge): add XMPP MUC room join/part relay

# Bug fix
fix(irc): correct cloak key fallback in prepare-config.sh

# Documentation
docs(ops): add SSL certificate renewal runbook

# Breaking change (major version bump)
feat(bridge)!: switch event bus from polling to WebSocket

BREAKING CHANGE: bridge config.yaml now requires a `ws_url` field.

# Chore with body
chore(deps): bump UnrealIRCd image to 6.1.8

Updated base image tag in infra/compose/irc.yaml.
Tested locally with `just dev` all services start cleanly.

Interactive commits

The repo includes Commitizen for guided commit message creation. Run it interactively:
pnpm exec cz
This walks you through type, scope, description, body, and breaking change prompts.

Pre-commit hooks

atl.chat uses pre-commit to enforce code quality on every commit. The just lint command runs all hooks against the entire repo.

Setup

  1. Install pre-commit (included in the Python dev dependencies):
    uv sync          # installs pre-commit into the venv
    
  2. If your environment sets core.hooksPath (some editors and CI systems do this), unset it first — otherwise pre-commit install will silently fail to register hooks:
    git config --unset-all core.hooksPath
    
  3. Install the git hooks:
    uv run pre-commit install
    uv run pre-commit install --hook-type commit-msg   # enables commitlint
    
  4. Verify hooks are active:
    uv run pre-commit run --all-files
    
    This is equivalent to just lint.

Hook reference

The full hook set defined in .pre-commit-config.yaml:
HookSourceWhat it does
check-jsonpre-commit-hooksValidates JSON syntax
check-tomlpre-commit-hooksValidates TOML syntax
end-of-file-fixerpre-commit-hooksEnsures files end with a newline
trailing-whitespacepre-commit-hooksRemoves trailing whitespace (excludes .md)
validate-pyprojectvalidate-pyprojectValidates pyproject.toml schema
yamlfixyamlfixAuto-formats YAML files
yamllintyamllintLints YAML files
actionlintactionlintLints GitHub Actions workflows
markdownlint-fixmarkdownlint-cliAuto-fixes Markdown style issues
ruff-checkruff-pre-commitPython linting with auto-fix (--fix)
ruff-formatruff-pre-commitPython formatting
shellcheckshellcheck-pyShell script static analysis
shfmtpre-commit-shfmtShell script formatting
gitleaksgitleaksScans for accidentally committed secrets
commitlintcommitlint-pre-commit-hookValidates commit message format (commit-msg stage)
luachecklocal (Docker)Lua static analysis (runs via Docker image)
lint-weblocalRuns Biome/ultracite on apps/web/ TypeScript/JSX files

Running hooks manually

# Run all hooks on all files
just lint

# Run a specific hook
uv run pre-commit run ruff-check --all-files
uv run pre-commit run shellcheck --all-files

# Run hooks only on staged files (default git hook behaviour)
uv run pre-commit run

Code style

Each language in the monorepo has its own linter and formatter. The pre-commit hooks enforce these automatically, but you can also run them standalone during development.

Python — ruff

All Python code (bridge, tests, scripts) is linted and formatted by ruff. Configuration lives in the root pyproject.toml.
SettingValue
Target versionPython 3.11
Line length120
Quote styleDouble quotes
Indent styleSpaces
Line endingLF
Enabled rule sets: E (pycodestyle), F (pyflakes), I (isort), N (pep8-naming), UP (pyupgrade), B (flake8-bugbear), SIM (flake8-simplify), PL (pylint), RUF (ruff-specific).
# Lint with auto-fix
uv run ruff check --fix .

# Format
uv run ruff format .

# Check without modifying files
uv run ruff check .
uv run ruff format --check .
Per-file ignores are configured for test directories and the bridge source (see [tool.ruff.lint.per-file-ignores] in pyproject.toml).

TypeScript / JSX — Biome (ultracite)

The Next.js web app (apps/web/) uses ultracite, a wrapper around Biome, for linting and formatting. Ultracite ships a pre-configured Biome profile for Next.js projects.
# Check for issues
cd apps/web && pnpm run check

# Auto-fix
cd apps/web && pnpm run fix

# Or via the pre-commit hook (runs automatically on apps/web/ JS/TSX files)
uv run pre-commit run lint-web --all-files
Note: The ultracite check command currently has a known issue where it expects a .gitignore in apps/web/. This does not affect builds (pnpm run build works fine).

Lua — luacheck

Prosody configuration and any Lua scripts are checked by luacheck. The pre-commit hook runs luacheck via a Docker image, so no local Lua installation is needed. Configuration lives in .luacheckrc at the repo root:
SettingValue
Standardmin (minimal standard globals)
Max line length300
Prosody globalsDeclared in the globals table (VirtualHost, Component, modules_enabled, etc.)
# Run via pre-commit
uv run pre-commit run luacheck --all-files

# Run directly with Docker (same as the hook)
docker run --rm -v "$PWD":/data ghcr.io/lunarmodules/luacheck:latest .
Known warning: apps/prosody/config/prosody.cfg.lua may emit unused-variable warnings because Prosody config files declare variables consumed by the Prosody runtime. The .luacheckrc sets unused = false for this file.

Shell — shellcheck and shfmt

Shell scripts (scripts/, infra/) are analysed by shellcheck for correctness and formatted by shfmt for consistency. shfmt settings (from .pre-commit-config.yaml):
SettingValue
Languagebash
Indent2 spaces
Binary opsNewline after
Switch casesIndented
Keep paddingYes
SimplifyYes
# Run shellcheck
uv run pre-commit run shellcheck --all-files

# Run shfmt
uv run pre-commit run shfmt --all-files

# Run shellcheck directly
shellcheck scripts/*.sh
Known warning: infra/nginx/docker-entrypoint.sh triggers shellcheck SC2016 (unexpanded variable in single quotes) — this is intentional and can be ignored.
  • Testing — test directory layout, running tests, fixtures
  • Adding a Service — checklist for adding a new service to the monorepo
  • Security — secret management and Gitleaks configuration