๐ŸŽฎ Copilot Fun Mode

March 6, 2026 ยท View on GitHub

A TUI wrapper around GitHub Copilot CLI that lets you play terminal games while your AI codes.

Press Ctrl-G to toggle between Copilot and a game menu with 13 games. Switch back anytime โ€” both your Copilot session and game progress are preserved. Enable Ctrl-S auto-switch mode to automatically toggle screens based on AI activity.

Copilot Fun Mode

Features

  • Seamless screen switching โ€” toggle between Copilot and games with Ctrl-G, like a terminal multiplexer
  • Auto-switch mode โ€” press Ctrl-S to automatically switch to games when AI is working, back to Copilot when it needs input
  • Game state preservation โ€” pause mid-game, check Copilot, resume exactly where you left off
  • Copilot status tracking โ€” status bar shows whether AI is working, waiting for input, or idle (via Copilot Hooks)
  • 13 turn-based games โ€” 10 WASM games compiled from nbsdgames, plus 3 built-in JS games (2048, Cookie Clicker, Tic-Tac-Toe)
  • Custom games support โ€” add your own games as single-file Node.js scripts in ~/.copilot-fun/games/
  • Cross-platform โ€” no tmux, no native binaries, just Node.js

Installation

Prerequisites

  • Node.js 18+ (tested with v23.4.0)
  • GitHub Copilot CLI installed:
    npm install -g @github/copilot-cli
    
  • Platform note: Works best on Linux or WSL. macOS should work but is untested. Windows has limited support (no auto-switch, manual closing required). See Compatibility & Known Issues for details.

Option 1: npx (Quickest)

Run directly without installation:

npx copilot-fun

Pass Copilot CLI arguments:

npx copilot-fun --model claude-sonnet-4.5

Install globally for easier access:

npm install -g copilot-fun
copilot-fun

Option 3: Manual Installation (For Development)

# Clone the repository
git clone https://github.com/sirluky/copilot-fun.git
cd copilot-fun
npm install

# Link globally
npm link

# Run
copilot-fun

Controls

Global

KeyAction
Ctrl-GToggle between Copilot and Game Menu
Ctrl-SToggle auto-switch mode (auto-switch between Copilot and games based on AI activity)

Game Menu

KeyAction
โ†‘โ†“ / W/S / J/KNavigate game list
EnterLaunch game (or resume paused game)
NStart new game (replaces any paused game)
QReturn to Copilot

In-Game

KeyAction
Arrow keys / WASD / HJKLMove cursor
EnterConfirm / act
Ctrl-GPause game, return to menu
QQuit game

See GAMES.md for per-game controls and rules.

Games

All games are turn-based โ€” perfect for playing while waiting for Copilot responses.

Built-in Games

GameDescriptionSimilar to
Fifteen PuzzleSlide tiles into order15-Puzzle
MinesClassic minesweeperMinesweeper
SudokuNumber placement puzzleSudoku
ReversiDisc-flipping strategyOthello
CheckersDiagonal capture gameDraughts
SOSLetter placement strategyTic-Tac-Toe (ext.)
BattleshipNaval combat guessingBattleship
MemoblocksMemory matching cardsConcentration
Rabbit HoleMaze navigationMaze Runner
RevengeBlock-pushing puzzlesSokoban
2048Slide tiles to create 20482048 (Gabriele Cirulli)
Cookie ClickerClick cookies, buy upgradesCookie Clicker
Tic-Tac-ToeClassic 3x3 gameTic-Tac-Toe

Custom Games

You can add your own games as single-file Node.js scripts. Create a ~/.copilot-fun/games/ directory and add .js files with metadata headers.

Custom games will automatically appear in the game menu.

Creating a Custom Game

  1. Create the games directory:

    mkdir -p ~/.copilot-fun/games
    
  2. Add a game file (e.g., ~/.copilot-fun/games/my-game.js) with metadata:

    // @game.id my-game
    // @game.name My Game
    // @game.desc A short description
    // @game.controls Arrow keys to move
    // @game.goal Win the game
    
    // Your game code here...
    
  3. Requirements:

    • Must be a single .js file (Node.js).
    • Use process.env.LINES and process.env.COLS for terminal size.
    • Use raw ANSI escape codes for rendering.
    • Do not handle q or ESC (the wrapper intercepts these).

See the Custom Games section in GAMES.md for a full template and detailed guide.

How It Works

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Your Terminal                          โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚  index.js (wrapper)               โ”‚  โ”‚
โ”‚  โ”‚                                   โ”‚  โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚  โ”‚
โ”‚  โ”‚  โ”‚ Copilot PTY โ”‚  โ”‚ Game PTY  โ”‚   โ”‚  โ”‚
โ”‚  โ”‚  โ”‚ + VTerminal โ”‚  โ”‚ + VTerm   โ”‚   โ”‚  โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚  โ”‚
โ”‚  โ”‚                                   โ”‚  โ”‚
โ”‚  โ”‚  [Status Bar: AI working/idle]    โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  1. Copilot CLI runs inside a pseudo-terminal (node-pty)
  2. @xterm/headless virtual terminals track screen state for both Copilot and games (like tmux does internally)
  3. Ctrl-G switches which screen is rendered โ€” the inactive process keeps running and its VTerminal keeps recording output
  4. Ctrl-S enables auto-switch mode โ€” automatically switches to games when AI is working autonomously, back to Copilot when it needs input
  5. Copilot Hooks write status to a file, polled every second by the wrapper to update the status bar and drive auto-switch
  6. WASM games run in their own PTY via Node.js โ€” compiled from C with a custom ncurses shim
  7. JS games run as Node.js child processes with raw terminal I/O

Compiling WASM Games

Pre-compiled .js + .wasm files are included in wasm/. If you want to recompile:

First clone the original C source code for the games:

git clone https://github.com/abakh/nbsdgames.git nbsdgames
docker build -t copilot-fun-build .
docker run --rm -v $(pwd)/wasm:/build/wasm copilot-fun-build

Manually (requires Emscripten)

# Install Emscripten SDK
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk && ./emsdk install latest && ./emsdk activate latest
source emsdk_env.sh
cd ..

# Build all games
./build-wasm.sh

Build a single game

source /path/to/emsdk/emsdk_env.sh

emcc -O2 -I wasm -I nbsdgames \
  -DNO_MOUSE -DNO_VLA -D__unix__ \
  -s ASYNCIFY=1 -s 'ASYNCIFY_IMPORTS=["em_getch"]' \
  -s ENVIRONMENT=node -s EXIT_RUNTIME=1 \
  -s FORCE_FILESYSTEM=1 -s NODERAWFS=1 \
  --js-library wasm/term_input.js \
  -lm -o wasm/mines.js nbsdgames/mines.c

WASM Compilation Notes

  • ASYNCIFY is required โ€” getch() in C blocks, but JS stdin is async. Asyncify bridges the gap.
  • FORCE_FILESYSTEM=1 NODERAWFS=1 โ€” without these, Emscripten's printChar only flushes on newline, breaking ANSI escape code output.
  • wasm/curses.h โ€” a ~370-line ncurses shim mapping all curses calls to ANSI escape codes.
  • wasm/term_input.js โ€” Emscripten JS library providing em_getch() with raw terminal input, CRโ†’LF translation, and arrow key parsing.
  • trsr is excluded โ€” has a source bug (variables declared inside #ifndef NO_VLA but used outside it).

Project Structure

copilot-fun/
โ”œโ”€โ”€ index.js           # Main TUI wrapper (~918 lines)
โ”œโ”€โ”€ package.json       # node-pty + @xterm/headless deps
โ”œโ”€โ”€ Dockerfile         # Docker-based WASM compilation
โ”œโ”€โ”€ build-wasm.sh      # Build script for all games
โ”œโ”€โ”€ wasm/
โ”‚   โ”œโ”€โ”€ curses.h       # ncurses โ†’ ANSI shim for Emscripten
โ”‚   โ”œโ”€โ”€ term_input.js  # Emscripten JS library for terminal input
โ”‚   โ”œโ”€โ”€ mines.js       # Compiled game (JS loader)
โ”‚   โ”œโ”€โ”€ mines.wasm     # Compiled game (WASM binary)
โ”‚   โ””โ”€โ”€ ...            # Other compiled games
โ”œโ”€โ”€ games/             # Built-in JS games
โ”‚   โ”œโ”€โ”€ 2048.js        # 2048 game implementation
โ”‚   โ”œโ”€โ”€ 2048.json      # 2048 game metadata
โ”‚   โ”œโ”€โ”€ cookie-clicker.js
โ”‚   โ”œโ”€โ”€ cookie-clicker.json
โ”‚   โ”œโ”€โ”€ tictactoe.js
โ”‚   โ”œโ”€โ”€ tictactoe.json
โ”‚   โ””โ”€โ”€ README.md      # Guide for adding JS games
โ”œโ”€โ”€ .github/
โ”‚   โ””โ”€โ”€ prompts/       # Agent prompts
โ”‚       โ””โ”€โ”€ copilot-fun-add-game.md  # Custom game creation guide
โ”œโ”€โ”€ nbsdgames/         # Original C source (git submodule / clone)
โ”œโ”€โ”€ GAMES.md           # Per-game controls and rules
โ”œโ”€โ”€ LICENSE            # MIT + CC0 (for nbsdgames)
โ””โ”€โ”€ POST.md            # dev.to blog post

User Data Directory

The wrapper creates a ~/.copilot-fun/ directory for runtime data:

~/.copilot-fun/
โ”œโ”€โ”€ games/             # Custom user games (single .js files)
โ”œโ”€โ”€ status             # Copilot status file (idle/working/waiting)
โ””โ”€โ”€ hooks-debug.log    # Hook debugging output

Hook configuration is installed to ~/.copilot/hooks/copilot-fun.json and is automatically removed on exit.

Configuration

Environment VariableDefaultDescription
COPILOT_BINcopilotPath to Copilot CLI binary

Compatibility & Known Issues

Platform Support

PlatformStatusNotes
Linuxโœ… Fully supportedBest experience, auto-switch works perfectly
WSL (Windows Subsystem for Linux)โœ… Fully supportedWorks as well as native Linux
macOSโš ๏ธ Not testedShould work, but untested โ€” feedback welcome
Windows (native)โš ๏ธ LimitedWorks but with caveats (see below)

Windows-Specific Issues

  • No auto-switch mode โ€” Copilot Hooks don't work natively on Windows, so status tracking (and Ctrl-S auto-switching) is unavailable
  • Manual screen switching only โ€” Use Ctrl-G to toggle between Copilot and games
  • Window closing issues โ€” The terminal may hang on exit; you may need to kill the window manually

Workaround for Windows

Use WSL 2 (Windows Subsystem for Linux) โ€” provides full Linux compatibility and fixes all the above issues.

Built With

Built entirely using Copilot CLI & Me โ€” an AI building its own entertainment system.

License

MIT โ€” see LICENSE. Games from nbsdgames are CC0 public domain.