Bug reports, fixes, translations, and small features welcome.
Open an issue. Useful template:
**Version**: v4.0.x (from container env or `/about`)
**Browser / client**: Safari 17 / Chrome 124 / KOReader 2024.04 / Kobo Libra Color
**Reverse proxy**: yes/no, with path prefix?
**Repro steps**:
1. ...
2. ...
**Expected vs actual**: ...
**Container logs (last 50 lines)**: ...
Bug reports without a version + repro are still useful — we'll just ask follow-ups before we can act on them.
- Fork → branch off
main→ commit → push → open PR againstmain. - Keep PRs focused on one logical change. Explain the problem, the approach, the user-visible result, and anything deliberately left out.
- Include verification that traces the real trigger to the observed result. For UI work, name the browser and input modes tested; screenshots are welcome when appearance changed.
- Add or update tests for changed behavior. Python tests live under
tests/; React end-to-end tests live underfrontend/e2e/. - CI must pass, including
validate-author,Fast Tests (Smoke + Unit),Frontend Build (SPA bundle), andTest Suite Summary. Docker integration and browser E2E jobs run when the change requires them. - If touching
cps/translations/, update the relevant.po; CI validates translations.
validate-author checks the committer email on every PR commit, not just the displayed author. Fork-maintained commits must be committed as new-usemame using an allowed noreply address. Genuine outside contributions retain their authorship: a maintainer applies the community-contribution label, which exempts that PR from the committer-identity check without weakening its other CI or review gates.
Don't introduce new dependencies, license changes, or external service URLs without flagging in the PR description and tagging @new-usemame for approval.
The development compose file is a starting point for a live-edit container:
cp docker-compose.yml.dev docker-compose.override.ymlEdit the host paths in docker-compose.override.yml, then add source binds under the service's volumes:
- ./cps:/app/calibre-web-automated/cps
- ./scripts:/app/calibre-web-automated/scriptsStart it with:
docker compose -f docker-compose.override.yml up -d
docker compose -f docker-compose.override.yml logs -fThe React application is compiled into cps/static/app; mounting cps/ alone does not compile frontend changes. Build it on the host whenever files under frontend/ change:
cd frontend
npm ci
npm run build
cd ..The mounted cps/ directory then exposes the new bundle to the running container. Stop the environment with docker compose -f docker-compose.override.yml down.
Install Python development requirements, then run the same fast test class as CI:
python -m pip install -r requirements.txt -r requirements-dev.txt
PYTHONPATH="$PWD:$PWD/scripts" pytest -m "smoke or unit" -n auto --dist=loadfile --maxfail=3 -v --tb=shortFor a focused change, run its test file directly first. Docker integration tests are sequential by design:
pytest tests/docker/ tests/integration/ -v --tb=long --durations=10Build and run the React E2E suite with:
cd frontend
npm ci
npm run build
npx playwright install chromium
E2E_BASE_URL=http://localhost:8083 npm run test:e2eIf you spot a useful PR sitting unmerged on crocodilestick/Calibre-Web-Automated:
git remote add upstream https://github.com/crocodilestick/Calibre-Web-Automated.git && git fetch upstream pull/<N>/head:upstream-pr-<N>git checkout -b merge/upstream-pr-<N>from currentmaingit cherry-pick upstream-pr-<N>(or rebase if it conflicts on refreshedmessages.pot)- Re-author the commit so the author email is yours, not upstream's:
git commit --amend --reset-author - Push, open PR, mention the upstream PR number + author in the PR title/body. Release notes will credit
@upstream-author.
The autopilot script does this automatically (scripts/draft-cherry-pick.sh <N>), so check notes/merge/ first to see if it's already in flight.
Useful work from an upstream or community PR may be adopted even when the original PR cannot merge cleanly. Preserve the contributor's authorship when cherry-picking their commit. If the change must be reimplemented, credit the original author and link the source PR in the new commit and PR description; record the credit in CHANGES-vs-upstream.md when the change creates or updates a fork divergence. Never use a Co-Authored-By trailer for someone who did not author the resulting commit.
safe-tier-1 (translations / docs only) auto-merge once CI is green.
safe-tier-2 (≤50 LOC isolated single-file code, no security-adjacent paths) auto-merge after a 7-day clean tier-1 history.
needs-review (everything else) waits for project lead.
Full tier definitions in CLAUDE.md.
Follow the existing code style of the file you're editing. CWA is mostly Flask + SQLAlchemy + jQuery + Bootstrap; we're not doing a rewrite. New code that fits the existing patterns merges; new code that introduces a new framework or paradigm gets bounced.
See GOVERNANCE.md. Short version: ~3 quality merged PRs + ask.
Every backported upstream PR credits the original author by handle in the release notes. Direct contributions are credited the same way. We don't squash credit out.