coplay
MIT · githubPlay while Claude works. The game freezes the instant Claude needs you, and resumes when it gets back to work.
install
Three steps. The first is a one-off, and you may have it already. Or ask Claude to do it.
1. Install tmux. The games run in a tmux pane, so this is a hard requirement rather than a nicety.
macOS
brew install tmux
Debian / Ubuntu
sudo apt install tmux
Windows — tmux doesn't exist on native Windows, so run Claude Code inside WSL. Once you're in an Ubuntu shell, the line above is the one you want.
wsl --install
2. Install the plugin, from inside Claude Code:
/plugin marketplace add zumiko/claudecoplay /plugin install coplay@coplay
Restart Claude Code so the hooks load.
3. Start Claude inside tmux. In your terminal, that's just:
tmux claude
Then type /snake, /tetris or /asteroids.
Already deep in a conversation outside tmux? It can't be moved into one — but this reopens that same conversation in tmux, so you lose nothing:
tmux new -s coplay 'claude --continue'
Needs Node 16+ too. No npm dependencies — the games use only fs, os and path. Nothing is ever written to your settings.json: the hooks ship inside the plugin, so uninstalling removes them completely. Unsure what's wired up? /coplay tells you.
or ask Claude to do it
Paste this into Claude Code and it'll do all three steps for you. It asks before running anything, so you can see each command first:
Install coplay for me: https://github.com/zumiko/claudecoplay Check whether tmux is installed and install it if not, then run claude plugin marketplace add zumiko/claudecoplay claude plugin install coplay@coplay and then tell me exactly what to type to start playing, including how to start Claude inside tmux, since the games need a tmux pane.
The bundled bin/coplay script does the same job from a terminal: it works out the right install command for your platform and offers to run it, then starts Claude inside tmux.
the games
/snake — arrows to steer
/tetris — arrows, space drops
/asteroids — turn, thrust, fire
/coplay shows status, which game is running, and your local high scores.
how it works
The whole thing is one word in a file. Claude Code hooks write it; the game polls it every tick.
| hook event | writes |
|---|---|
SessionStart | WORKING |
UserPromptSubmit | WORKING |
PreToolUse | WORKING |
PostToolUse | WORKING |
Notification | PAUSED |
Stop | PAUSED |
SessionEnd | deletes the file |
Each hook is a plain echo, so nothing starts an interpreter and the cost is a couple of bytes per event.
- Focus follows the work. Submit a prompt and the keyboard moves to the game; the moment Claude needs you it moves back. Press
fto turn that off. - Death is free. Press
r, or just send Claude a new prompt — the game restarts on the same edge that resumes it. - The pane cleans itself up.
SessionEnddeletes the state file, the game notices and closes, so panes never linger. - Concurrent sessions don't collide. The state file is keyed by
$CLAUDE_CODE_SESSION_ID, so two Claudes never stomp on each other.
notes
- Claude has to already be running inside tmux — the game needs a pane to split into.
- One game at a time. Starting a different one closes the old pane, so there's never a question about which game has the keyboard.
- Resizing never disturbs a run. If the pane gets too small the game waits behind a notice instead of drawing a broken frame.
- High scores live in
~/.claude-coplay/scores.json. - Uninstall:
/plugin uninstall coplay. It leaves nothing behind but that scores file.
add your own game
The engine owns the terminal, the pane sizing, the pause/resume and the chrome. A game is one file:
engine.run({
id: 'pong', title: 'PONG', tickMs: 60,
controls: 'arrows to move',
minCols: 20, minRows: 10,
dims: (w, h) => ({ w, h }),
create: (w, h) => ({ score, dead, step(), key(k), rows() }),
});Drop it in games/, add a matching command file, and /coplay picks it up automatically.
contact
A little project by Claire Jellison and Drew Devero.
| Claire Jellison | clairejellison@yahoo.com |
| Drew Devero | deverobelfon@gmail.com |
Bugs and ideas are also welcome as issues on GitHub.