Skip to content

rasjonell/chessh

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cheSSH

Play chess in your terminal over SSH. No account, no browser, no install, just:

ssh chessh.org

demo

How it works

cheSSH is an SSH server that drops you into a chess game instead of a shell. It's built with Go using Wish (SSH server), Bubble Tea (TUI framework), and Lip Gloss (styling). Game rules are handled by notnil/chess.

When you connect, you land in a lobby where you can host or join a game. Hosting gives you a 6-character room code to share. Once both players are in, the match starts. White for the host, Black for the joiner. Moves sync in real-time over SSH channels, and there's an in-game chat.

Architecture

SSH connection
  └─ Wish server (main.go)
       └─ Bubble Tea TUI per session
            ├─ Screens: Menu -> Nicname -> Join/Host -> Play
            ├─ Game engine (internal/game/)
            │    └─ notnil/chess wrapper - move validation, check, promotion
            └─ Multiplayer manager (internal/multiplayer/)
                 ├─ Room registry - create/join/leave by code
                 ├─ Room state - White/Black players, turn tracking
                 └─ Event broadcast — moves, chat, disconnects via Go channels

Each SSH session gets its own Bubble Tea model. The multiplayer manager is a shared singleton that coordinates rooms across sessions. Rooms are ephemeral - they exist only while players are connected.

What could be improved

  • No persistence. Games vanish on disconnect. Adding a storage layer (SQLite, Redis) would enable reconnection, game history, and ELO tracking.
  • Single-process, in-memory rooms. The room manager uses Go maps + mutexes. This works for one server but doesn't scale horizontally. A pub/sub backend (Redis, NATS) would allow multiple server instances.
  • No spectators. The room model is hardcoded for two players. The event broadcast system already uses channels, so adding read-only subscribers would be straightforward.
  • No matchmaking. Players must share room codes out-of-band. A queue-based matchmaker could pair strangers automatically.
  • No time controls. There's no clock - games can stall indefinitely. Adding per-move or per-game timers would complete the competitive experience.

Controls

In-game:

Action Keys
Move cursor Arrow keys / h j k l
Select / place piece Enter / Space
Cancel selection Esc
Promote to Q/R/B/N q r b n or arrows + Enter
Toggle chat Tab
Quit q / Ctrl+C

Mouse is also supported - click to select and move pieces.

In the lobby: arrow keys or j/k to navigate, Enter to confirm.

Run locally

go run .

Then in another terminal:

ssh localhost -p 23234

Environment variables:

Variable Default Description
CHESSH_HOST localhost Bind address
CHESSH_PORT 23234 Listen port
CHESSH_HOST_KEY_PATH .ssh/id_ed25519 SSH host key path

Deploy

See deploy/chessh.service for a production systemd unit. The short version:

  1. Build: go build -o chessh .
  2. Create a service user: useradd --system --home /opt/chessh --shell /usr/sbin/nologin chessh
  3. Generate an SSH host key:
    install -d -m 755 /etc/chessh
    ssh-keygen -t ed25519 -f /etc/chessh/host_key -N ''
    chown -R chessh:chessh /opt/chessh /etc/chessh
  4. Install the binary and service file, then:
    systemctl enable --now chessh

To let players connect on port 22, move your admin SSH to another port first.

Requirements

  • Go 1.25+
  • An SSH client

About

SSH into a chess game

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages