Case is dual-licensed (AGPL for the box, MIT for the clients) and is also offered under a commercial license. That second license only works if the project can sublicense every line it ships, so contributions come in under a Contributor License Agreement.
You keep your copyright. It is a license with the right to sublicense, not
an assignment. To sign, add your GitHub username to CLA-SIGNERS
in the same pull request as your first contribution:
echo "your-github-username" >> CLA-SIGNERSThat edit records your agreement and covers everything you contribute after it. No bot, external service, or separate paperwork.
New files take the SPDX-License-Identifier of their directory (see
LICENSE.md); CI fails a file without one.
Use Python 3.12 and Node 22, matching CI.
python3 -m venv .venv
.venv/bin/pip install -r requirements-dev.txt
for f in tests/test_*.py; do
case "$f" in tests/test_acceptance.py) continue ;; esac
.venv/bin/python "$f" || exit 1
done
npm --prefix web ci
npm --prefix web testdocker build -t case-desk:acceptance image
CASE_ACCEPTANCE_IMAGE=case-desk:acceptance .venv/bin/python -m pytest -q tests/test_acceptance.pyThe suite starts its own cased on a random loopback port, with a temporary vault
and token. It removes only computers created by that run. Failed runs retain
logs and screenshots in the printed scratch directory. CASE_KEEP=1 also keeps
the primary test computer and its volume for inspection.
A7 needs ntfy and a phone. A8 is skipped unless CASE_A8=1 is set,
because it restarts the Docker VM and interrupts every container using it.
Run that check only on a dedicated test machine.
control-plane/: REST API (composition root:cased.py)image/: desktop containermcp/case_mcp.py: MCP wrapperweb/web-ui/: Drive UIcompose.yaml: self-host stack
Be decent to people: CODE_OF_CONDUCT.md.
PRs that touch credential injection (image/deskd.py login/inject, store.py,
links.py) need maintainer review. SECURITY.md is the bar.