A lightweight game engine for your terminal.

cmdfx is a lightweight game engine for your terminal, allowing you to create some pretty wild things. It is designed to be simple and easy to use, while still providing a powerful set of features.
It is written in C and is available cross-platform. It is licensed under the MIT license.
๐ Features
- Cross-platform: cmdfx is available on Windows, macOS, and Linux.
- Curses-backed: renders through (n)curses (PDCurses on Windows) for portable terminal output.
- Lightweight: cmdfx is designed to be lightweight and fast.
- Easy to use: cmdfx is simple to use and easy to learn.
- Powerful: cmdfx provides a powerful set of features for creating terminal-based games.
๐ Highlighted Features
For a full method list, check out the documentation.
- Events API
- Handle window events such as key presses and window resizing.
- Register listeners for key, mouse, and button events.
- Canvas API
- Draw characters and shapes on the terminal.
- Set foreground and background colors.
- Clear the screen.
- Get the size of the terminal and the screen.
- ...and much more!
- Sprites API
- Load and draw sprites on the terminal.
- Set the color of a sprite.
- Create Gradients for a sprite.
- ...and much more!
- Builder API
- Easily build 2D arrays of characters and strings.
- Set the color of the text.
- Create gradients of text and colors!
- ...and much more!
- Physics Engine
- Create and manage physics objects with the Sprite API.
- Set the velocity and acceleration of a sprite.
- Detect collisions between sprites.
- ...and much more!
- Input API
- Receive keyboard and mouse input through the event system.
- React to key presses, mouse clicks, and terminal resizes.
- ..and much more!
- Cross-Platform Exposure
- Expose platform-specific features and utilities such as setting the title of the terminal.
๐ฆ Installation
You can download the latest release of cmdfx from the releases page.
Install via Script
Use the cross-platform Bash installer to clone, build, and install cmdfx with CMake.
Prerequisites
cmdfx renders through a curses library, so a curses development package is required:
- Linux: sudo apt-get install -y libncursesw5-dev (or libncurses-dev)
- macOS: ncurses ships with the system (brew install ncurses is optional)
- Windows (MSYS2/MinGW): pacman -S mingw-w64-x86_64-ncurses, or install PDCurses. If no curses is found at configure time, the build fetches PDCurses automatically.
Linux additionally requires the ALSA sound library for audio:
sudo apt-get update
sudo apt-get install -y libasound2-dev libncursesw5-dev
If ALSA is not installed, sound support will not be built.
Running the Installer
# default install (includes kotlin/native, tests, docs, full clone)
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash
# disable kotlin/native and enable shallow (most common use case with c/c++)
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash -s -- --no-kn --shallow
# include debug statements
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash -s -- --type Debug
# to disable building tests
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash -s -- --no-tests
# to disable including documentation
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash -s -- --no-docs
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh -o install-cmdfx.sh
bash install-cmdfx.sh
- Windows: run from Git Bash (bundled with Git for Windows) or MSYS2 shell:
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh -o install-cmdfx.sh
bash install-cmdfx.sh
Defaults after a no-flags run:
- MacOS: installs to /usr/local
- Linux: installs to /usr
- Windows (Git Bash/MSYS): installs to C:/Program Files/cmdfx
Common options:
- --branch <name>: install a tag/branch (e.g. v0.3.3)
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash -s -- --branch v0.3.3
- --prefix <path>: change install prefix
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash -s -- --prefix /custom/path
- --type <Release|Debug>: CMake build type
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash -s -- --type Release
- --shallow: faster shallow clone
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash -s -- --shallow
- --no-tests, --no-docs, --no-package, --no-kn: toggle optional components
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash -s -- --no-tests --no-docs
Run ./install.sh --help for full options.
Install via Homebrew
A homebrew/core submission is in progress. Until it lands, install from this repository's tap:
brew tap gmitch215/cmdfx https://github.com/gmitch215/cmdfx
brew install gmitch215/cmdfx/cmdfx
This builds cmdfx from source and pulls in ncurses (and alsa-lib on Linux). To build the latest master instead of the most recent release, append --HEAD to the install command.
Use in CMake Projects
cmdfx installs a CMake package with the target cmdfx::cmdfx.
find_package(cmdfx REQUIRED)
add_executable(app main.c)
target_link_libraries(app PRIVATE cmdfx::cmdfx)
If CMake cannot find the package, point it at the install prefix:
cmake -S . -B build -DCMAKE_PREFIX_PATH="/usr/local" # macOS
cmake -S . -B build -DCMAKE_PREFIX_PATH="/usr" # Linux
cmake -S . -B build -DCMAKE_PREFIX_PATH="C:/Program Files/cmdfx" # Windows
GitHub Actions
Install cmdfx via the script, then build your project with CMake using the exported package.
name: Build with cmdfx
on: [push, pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
cmake_prefix: /usr
- os: macos-latest
cmake_prefix: /usr/local
- os: windows-latest
cmake_prefix: 'C:/Program Files/cmdfx'
steps:
- uses: actions/checkout@v6
- name: Install Linux Dependencies
if: startsWith(matrix.os, 'ubuntu')
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y libasound2-dev
- name: Install cmdfx
shell: bash
run: |
curl -fsSL https://raw.githubusercontent.com/gmitch215/cmdfx/master/install.sh | bash
- name: Configure
shell: bash
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="${{ matrix.cmake_prefix }}"
- name: Build
shell: bash
run: cmake --build build
Kotlin/Native
If you are using Kotlin/Native, you can add cmdfx as a dependency in your build.gradle.kts file:
plugins {
kotlin("multiplatform") version "<version>"
}
repositories {
// GitHub Packages requires authentication, even to read.
// Provide a personal access token with the `read:packages` scope.
maven("https://maven.pkg.github.com/gmitch215/cmdfx") {
credentials {
username = providers.gradleProperty("gpr.user").orNull ?: System.getenv("GITHUB_ACTOR")
password = providers.gradleProperty("gpr.key").orNull ?: System.getenv("GITHUB_TOKEN")
}
}
}
kotlin {
// Define your targets here
macosArm64()
mingwX64()
sourceSets {
// for example, if you are using macOS arm64
macosArm64Main.dependencies {
implementation("dev.gmitch215.cmdfx:cmdfx-macosarm64:<version>@klib")
}
// or, if you are using windows
mingwX64Main.dependencies {
implementation("dev.gmitch215.cmdfx:cmdfx-mingwx64:<version>@klib")
}
}
}
๐ Examples
int main() {
}
void Canvas_setChar(int x, int y, char c)
Sets a character at a specific position.
void Canvas_hLine(int x, int y, int width, char c)
Draws a horizontal line.
void Canvas_setForeground(int rgb)
Sets the foreground color at the current cursor position.
void Canvas_fillCircle(int x, int y, int radius, char c)
Fills a circle with a character.
The main header file for CmdFX. Includes the rest of the library.
int main() {
}
@ GRADIENT_ANGLE_45
A 45-degree gradient.
Definition builder.h:497
void Sprite_moveTo(CmdFX_Sprite *sprite, int x, int y)
Moves a sprite to the given position.
int Sprite_setForegroundGradientAll(CmdFX_Sprite *sprite, enum CmdFX_GradientDirection direction, int numColors,...)
Sets a foreground gradient using RGB colors.
CmdFX_Sprite * Sprite_loadFromFile(const char *path, int z)
Creates a new sprite from a file.
int Sprite_draw(int x, int y, CmdFX_Sprite *sprite)
Draws a sprite to the terminal.
CmdFX_Sprite * Sprite_createFilled(int width, int height, char c, char *ansi, int z)
Creates a new sprite with the given dimensions.
int Sprite_setForegroundAll(CmdFX_Sprite *sprite, int rgb)
Sets the foreground color of the sprite at the given position.
Represents a sprite that can be drawn to the terminal.
Definition sprites.h:31
#include <stdio.h>
printf("Terminal resized from %dx%d to %dx%d\n", resizeEvent->prevWidth, resizeEvent->prevHeight, resizeEvent->newWidth, resizeEvent->newHeight);
return 0;
}
int main() {
int r = 0;
while (1) {
}
}
void Canvas_clearScreen()
Clears the screen.
int addCmdFXEventListener(unsigned int id, CmdFX_EventCallback callback)
Adds an event listener.
#define CMDFX_EVENT_RESIZE
Called when the terminal is resized.
Definition events.h:39
The main event structure for CmdFX.
Definition events.h:176
void * data
A pointer to the data associated with the event.
Definition events.h:188
The payload for the CMDFX_EVENT_RESIZE event.
Definition events.h:44
More examples can be found in the samples directory.
๐งช Sanitizers
For development, cmdfx can be built and tested under sanitizers. Pass -DSANITIZE_CMDFX=<list> to CMake (e.g. address,undefined or thread), or use the helper scripts which configure, build, and run the test suite for you:
./asan.sh # AddressSanitizer + UndefinedBehaviorSanitizer
./ubsan.sh # UndefinedBehaviorSanitizer only
./tsan.sh # ThreadSanitizer (physics engine lifecycle / race detection)
ThreadSanitizer cannot be combined with AddressSanitizer, so it uses a separate build directory. These require a Clang or GCC toolchain.
๐ Contributing
If you would like to contribute to cmdfx, please see the contributing guidelines. All contributions are welcome!