Skip to main content

textual-tetris

textual-tetris is a minimalist Tetris clone written with Textual, an amazing TUI framework for Python. It focuses on compact components, colorized blocks, and a responsive keyboard feel in the terminal.

Original Blog post: https://mgaitan.github.io/en/posts/textual-tetris/

Running

The easiest way is using uvx (part of uv):

uvx textual-tetris

For local multiplayer:

uvx textual-tetris --2players

Remote games

Start a server as local Player 1, then connect Player 2:

uvx textual-tetris server --name Ada
uvx textual-tetris connect ws://HOST:8765 --name Grace

The server UI connects through the same WebSocket protocol as every other player, so the server remains independent from Player 1. Run uvx textual-tetris connect without a URL to use ws://localhost:8765.

For a server without a local player, use headless mode and connect two clients:

uvx textual-tetris server --headless
uvx textual-tetris connect --name Ada
uvx textual-tetris connect --name Grace

Use watch-only mode to observe without occupying a player slot or joining the challenger queue:

uvx textual-tetris connect ws://HOST:8765 --watch-only --name Observer

For an agent-versus-agent game with a local spectator UI, start the server itself in watch-only mode, then connect both agents to ws://localhost:8765:

uvx textual-tetris server --watch-only

Other spectators wait in a FIFO queue by default. When a player disconnects or loses, the winner stays and the next queued client is promoted. Watch-only clients are never promoted.

Every interactive client uses arrow keys to move and rotate and Space to hard drop. Press N to change your visible name. Press C to open a one-line chat input; Enter sends, Escape cancels, and incoming messages appear as non-blocking notifications. A player who becomes a spectator can press J to join the challenger queue again.

Share over the internet

For a temporary game, a Cloudflare Quick Tunnel can expose the local WebSocket server without opening an inbound port or requiring a Cloudflare account. Install cloudflared, bind the game locally, and start the tunnel in another terminal:

uvx textual-tetris server --host 127.0.0.1 --port 8765 --name Ada
cloudflared tunnel --url http://localhost:8765

cloudflared prints a temporary https://<random>.trycloudflare.com URL. Replace https with wss when connecting:

uvx textual-tetris connect wss://<random>.trycloudflare.com --name Grace

Quick Tunnel URLs change whenever cloudflared restarts and are intended for testing and short-lived games. Use a named Cloudflare Tunnel when a stable hostname is required.

Agentic player

An automated AI (like Codex) player can use the same WebSocket without rendering the terminal UI.

On connection, the server sends a welcome message describing protocol v2, the assigned role and player id, valid messages and events, and the piece catalog. It then sends revisioned state snapshots containing both players and the complete connection roster.

The welcome also includes the complete piece catalog: each rotation code maps to its four relative block coordinates, so the client does not need to know how pieces are encoded internally.

Every message has a monotonically increasing revision; ignore older messages. A piece_locked event identifies the locked piece_id, and an input with an id receives an ack event, so an agent can wait for confirmed state changes. Send actions as JSON, for example:

{"type": "input", "id": 42, "action": "left"}

Agents can also set their name and use chat:

{"type": "name", "name": "Codex"}
{"type": "chat", "message": "good luck"}

The same server supports agent-versus-agent games: launch server --headless for no UI or server --watch-only to watch locally, then connect two automated WebSocket clients. A raw watch-only client can connect with ?role=spectator; it receives state and chat events but can never become a player.

Screenshots

Single-player

Two-player

Gameplay

  • Blocks follow the classic rules: move left/right, rotate, soft drop, and hard drop.
  • Every locked piece awards a small bonus; clearing 1–4 lines follows the traditional scoring table. Levels increase automatically based on the number of cleared lines, and the drop interval accelerates per level.
  • The Next widget previews the upcoming piece so you can plan ahead, and the score widget keeps score/level/lines visible at all times.

Controls

In the default one-player mode, use arrows or W/A/S/D to move and rotate, and Space or Q to hard drop.

In remote mode, use arrows and Space. C opens chat, N changes your player name, and J joins the queue.

With --2players:

Key Action
A / D / S / W (Player 1) Move left/right, soft drop, rotate
Q (Player 1) Hard drop
← / → / ↓ / ↑ (Player 2) Move left/right, soft drop, rotate
Space (Player 2) Hard drop
N / Shift+N Change Player 1 / Player 2 name
Ctrl+Q Quit
R Restart after a game-over

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

textual_tetris-0.5.0.tar.gz (20.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

textual_tetris-0.5.0-py3-none-any.whl (22.1 kB view details)

Uploaded Python 3

File details

Details for the file textual_tetris-0.5.0.tar.gz.

File metadata

  • Download URL: textual_tetris-0.5.0.tar.gz
  • Upload date:
  • Size: 20.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for textual_tetris-0.5.0.tar.gz
Algorithm Hash digest
SHA256 bc1b3afbfa164eedcc130821e9aa61bf4cab188822838b0f877f898dd7f65b45
MD5 5ad19c76e518c0feb880f485a6f7a3c9
BLAKE2b-256 b8476ff0f126b13232fae73def47c13e6d0e8eabc7b14c0782df259edee1e79d

See more details on using hashes here.

Provenance

The following attestation bundles were made for textual_tetris-0.5.0.tar.gz:

Publisher: cd.yml on mgaitan/textual-tetris

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file textual_tetris-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: textual_tetris-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 22.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for textual_tetris-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2a0b8ac683005816baacbbd747e8cfa001bd39fd230574544b0c9b33bc80411d
MD5 5cff1b00b1a8d412e63546a4ab6ee89c
BLAKE2b-256 dff48328d95d1aa7e62401ddaff10cdd4d18320e2f399e9b064b31db4fb728f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for textual_tetris-0.5.0-py3-none-any.whl:

Publisher: cd.yml on mgaitan/textual-tetris

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 files

0.4.0

2 files

0.3.1

2 files

0.3

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page