Local Python web server with a tabbed multi-file editor. Any file change triggers:
- Send all files to
/api/analyze - Rewrite all files into the persistent local staging directory shown in the UI
- Copy those files into a fresh disposable analysis directory and run
uv sync - Run the type checkers in that analysis directory:
python -m ty check .- optional:
cargo run --bin ty -- check --project <temp-project-path>in your local Ruff clone - optional:
uv run --frozen --with-editable 'mypy @ <local-mypy-checkout>' mypy --color-output --pretty . - optional:
uv run --frozen --with-editable 'pycroscope @ <local-pycroscope-checkout>' pycroscope --output-format concise . python -m pyright --outputjson .(then normalized to relative paths in UI)python -m pyrefly check .python -m mypy --color-output --pretty .zuban check --pretty .python -m pycroscope --output-format concise .
- Display output from each tool in the UI
The runtime pane is always present and is turned off and collapsed by default. Like
the type-checker panes, its On/Off toggle controls whether it runs independently
of whether its output is collapsed. When enabled, it runs main.py (or the first
Python file when there is no main.py) with the selected Python version and the
project's installed dependencies. The runtime interpreter installs
typing.reveal_type as the built-in reveal_type when available, and provides the
same built-in behavior without modifying typing on Python 3.10.
uv run multiplayThen open http://localhost:8000.
Or, to start the server and automatically open it in your default browser:
./run.shdocker build -t multiplay .
docker run --rm -p 8000:8000 multiplayThen open http://localhost:8000.
Pycroscope imports the code, and enabling the runtime pane executes it. Don't enter code in the playground that you don't want run on your system.
Each type checker run has a 10-second timeout during analyze; if exceeded, that tool returns a timeout error while others still complete.
Each checker card includes:
- an
On/Offtoggle (disabled tools are skipped by the backend) - a
Configurebutton to open/create the tool's config section inpyproject.toml - a
Docsbutton linking to the tool's configuration documentation - a collapse/expand arrow to hide/show that checker's output panel
- a drag grip for reordering panels
Optional local Ruff ty checker:
- provide a local Ruff clone path in the "Local checker directories (optional)" section
- this adds a
ty (/path/to/checkout)checker card for side-by-side comparison - backend runs it from that repo with
cargo run --bin ty -- check --project <temp-project-path> - this local-checkout run is not capped by the 10-second analyze timeout
Optional local Python checker checkouts:
- open the "Local checker directories (optional)" section in the header
- provide local checkout paths for
mypyand/orpycroscope - backend runs those tools via
uv run --frozen --with-editable '<tool> @ <checkout>' <tool> ...instead of the installed PyPI package - checker card titles include the local checkout path so you can confirm which build is active
On startup, the server primes tool installs and detects checker versions. For
each analysis, it copies the submitted files from the persistent staging
directory into a fresh disposable directory, runs uv sync, and executes the
checkers there. The UI shows each detected version in the checker pane header.
Click the Share button in the header to create a public GitHub Gist containing your current files and dependencies. The gist ID is copied to your clipboard.
To load a shared gist, paste the gist ID (or full URL) into the Gist ID or URL input in the header and click Load. This replaces the current files and dependencies with the contents of the gist. Before analyzing the loaded files, multiplay turns off and collapses both the runtime and pycroscope panes; re-enable them only after reviewing the gist contents.
Sharing uses the GitHub Gist API directly. It uses MULTIPLAY_GH_TOKEN if set
(for example: export MULTIPLAY_GH_TOKEN=...), otherwise it falls back to
gh auth token when the GitHub CLI is installed/authenticated.
Loading public gists only requires network access.
The header has a dependency field (comma/newline separated). When non-empty,
dependencies are added to pyproject.toml and installed into that analysis's
venv with uv sync before the type checker tools run. All tools in one analysis
use the same snapshot venv, so they can resolve imports from installed packages
directly.
If dependency install fails, the UI shows a dedicated error panel with command, exit code, requested dependencies, and full installer output.
Dependency installs use a 2-day package cooldown, so newly uploaded package
versions are ignored until they have been available for at least two days. The
advanced options include a package exemption list for dependencies that should
skip the cooldown; it defaults to ty.
Because we are simply running the type checker CLIs, you can add ty.toml,
mypy.ini, pyrightconfig.json etc files and they "just work".
Output panes preserve ANSI terminal color codes when the tool emits them.
- Backend server/API:
app.py - Frontend markup:
static/index.html - Frontend styles:
static/styles.css - Frontend behavior/highlighting:
static/app.js
- Python 3.14+
uvavailable onPATH- GitHub auth for sharing gists: either
MULTIPLAY_GH_TOKENor authenticatedghCLI - Network access on first run so
uvcan fetch tool packages if not already cached