Video chat in your terminal
Probably the first command line video chat program (let me know if this isn't true). Initial commits November 20-24, 2013, with @craigpalermo, at some collegiate hackathon (I forget which one).
ascii-chat is a client-server application that operates over TCP/IP. It supports color and audio and crypto and compression and multiple clients and has lots of other little features and options.
The client functions by simply printing text and terminal escape codes to your terminal, so it works EVERYWHERE that terminals work: on rxvt-unicode in OpenBox, in a Putty SSH session, in iTerm and Kitty.app on macOS, and theoretically everywhere else terminals run. You just need a webcam.
ascii-chat even works in an initial UNIX login shell. You know, the shell that runs 'startx' and launches your desktop environment so you can open a GUI terminal app like Konsole or Kitty or Alacritty. You don't need a desktop environment at all to video chat with ascii-chat. (*)
π We support UTF-8 now so it's not just ASCII anymore. However the name is still ascii-chat.
π Now 3+ simultaneous people can connect and the server will render the clients to each other as a grid, like Google Hangouts and Zoom calls do. See the Network Protocol docs.
π Audio is now supported - turn on your microphone and start talking! (TODO: buggy - needs work) See the Audio System docs.
π Read the Documentation - Full API reference, architecture guides, and more.
(*) Testing needed to verify a decent framerate on different systems and environments.
ascii-chat v0 from 2013:
ascii-chat v0.3.5 in 2025. Here are 3 clients connected to a single server, in a call:
- π»πΈ ascii-chat π‘π¬
macOS (Homebrew):
# Add the tap
brew tap zfogg/ascii-chat
# Install runtime binary
brew install ascii-chat
# Install development libraries (headers, static/shared libs, docs)
brew install libasciichatArch Linux (AUR):
# Stable releases
paru -S ascii-chat # Runtime binary
paru -S libasciichat # Development libraries (headers, libs, docs)
# Latest git versions (recommended for development)
paru -S ascii-chat-git # Runtime binary from git
paru -S libasciichat-git # Development libraries from gitAll Platforms:
- Latest release: v0.4.12
- All downloads: GitHub Releases
- Documentation: zfogg.github.io/ascii-chat β API reference and developer guides
- Source installation: see the Dependencies section below, then follow the Build from source steps (or the Build System docs)
ascii-chat uses a unified binary with three modes: server, client, and mirror.
Start a server and wait for client connections:
# NOTE: on Windows the filename is ascii-chat.exe
ascii-chat [binary-options...] server [server-options...]Connect to a server as a client:
ascii-chat [binary-options...] client [<address>] [client-options...]View your local webcam without a network connection (mirror mode):
ascii-chat [binary-options...] mirror [mirror-options...]Get help for any mode:
ascii-chat --help # Top-level help
ascii-chat server --help # Server-specific help
ascii-chat client --help # Client-specific help
ascii-chat mirror --help # Mirror-specific helpMan Page:
ascii-chat includes a man page with comprehensive documentation. When installed via Homebrew or a package manager:
man ascii-chatFrom the build directory (after running cmake --build build --target docs):
man build/docs/ascii-chat.1These options apply to all modes (server, client, mirror) and must be specified before the mode:
Configuration:
--config FILE: Load configuration from TOML file--config-create [PATH]: Create default configuration file and exit
Logging:
-L --log-file FILE: Redirect logs to file (default: server.log/client.log/mirror.log based on mode)--log-level LEVEL: Set log level: dev, debug, info, warn, error, fatal (default: info in release, debug in debug builds)-V --verbose: Increase verbosity (stackable: -V, -VV, -VVV for more detail)-q --quiet: Disable console logging (logs only to file)
Information:
--version: Display version information--help: Show help message
Example:
# Binary options come before the mode
ascii-chat -V --log-level debug --log-file /tmp/debug.log client
ascii-chat --config ~/my-config.toml serverRun ascii-chat client --help to see all client options.
Connection (positional argument):
Client accepts 0-1 positional argument for server address:
[address][:port]: Server address with optional portaddress: IPv4, IPv6, or hostname (default: localhost):port: Optional port suffix (default: 27224)
Examples:
ascii-chat client # Connect to localhost:27224
ascii-chat client 192.168.1.1 # Connect to 192.168.1.1:27224
ascii-chat client example.com:8080 # Connect to example.com:8080
ascii-chat client [::1]:8080 # Connect to IPv6 ::1:8080Connection (flags):
-p --port PORT: TCP port (default: 27224) - conflicts with port in positional argument--reconnect VALUE: Automatic reconnection behavior:off,auto, or number 1-999 (default: auto)
Terminal Dimensions:
-x --width WIDTH: Terminal width in characters (auto-detected by default)-y --height HEIGHT: Terminal height in characters (auto-detected by default)--stretch: Stretch video to fit without preserving aspect ratio
Webcam Options:
-c --webcam-index INDEX: Webcam device index (0-based, default: 0)-f --webcam-flip: Toggle horizontal flip of webcam image (default: flipped)--test-pattern: Use test pattern instead of real webcam (for debugging/testing)--list-webcams: List available webcam devices and exit
Display & Color:
--color-mode MODE: Color modes: auto, none, 16, 256, truecolor (default: auto)-M --render-mode MODE: Render modes: foreground (fg), background (bg), half-block (default: foreground)-P --palette TYPE: ASCII palette: standard, blocks, digital, minimal, cool, custom (default: standard)-C --palette-chars CHARS: Custom palette characters (implies --palette=custom)--show-capabilities: Display detected terminal color capabilities and exit--utf8: Force enable UTF-8/Unicode support
Audio Options:
-A --audio: Enable audio capture and playback--microphone-index INDEX: Microphone device index (-1 for system default)--speakers-index INDEX: Speakers device index (-1 for system default)--list-microphones: List available audio input devices and exit--list-speakers: List available audio output devices and exit--audio-analysis: Enable audio analysis for debugging audio quality issues--no-audio-playback: Disable speaker playback while keeping received audio recording
Performance:
--fps FPS: Desired frame rate, 1-144 (default: 60)--compression-level LEVEL: zstd compression level 1-9 (default: 1, fastest)--no-compress: Disable video frame compression and audio encoding entirely--encode-audio: Force enable Opus audio encoding (overrides --no-compress)--no-encode-audio: Disable Opus audio encoding, send raw audio samples
Snapshot Mode:
-S --snapshot: Capture single frame from server and exit (useful for scripting, CI/CD)-D --snapshot-delay SECONDS: Delay in seconds before capturing snapshot (default: 3.0-4.0 for webcam warmup)--strip-ansi: Remove all ANSI escape codes from output (plain ASCII only)
Encryption:
-E --encrypt: Enable packet encryption (default: enabled if keys are available)-K --key FILE: SSH/GPG key file for authentication (supports /path/to/key, github:user, gitlab:user, or 'ssh' for auto-detect)--password PASSWORD: Password for connection encryption-F --keyfile FILE: Alternative way to specify key file (alias for --key)--no-encrypt: Disable encryption (for local testing)--server-key KEY: Expected server public key for identity verification (prevents MITM attacks)
Run ascii-chat server --help to see all server options.
Network Binding (positional arguments):
Server accepts 0-2 positional arguments for bind addresses:
- 0 arguments: bind to defaults (127.0.0.1 and ::1)
- 1 argument: bind to this IPv4 OR IPv6 address
- 2 arguments: bind to both (must be one IPv4 and one IPv6)
Examples:
ascii-chat server # Bind to 127.0.0.1 and ::1
ascii-chat server 0.0.0.0 # Bind to all IPv4 interfaces
ascii-chat server :: # Bind to all IPv6 interfaces
ascii-chat server 0.0.0.0 :: # Bind to all interfaces (IPv4 and IPv6)
ascii-chat server 127.0.0.1 ::1 # Bind to localhost (IPv4 and IPv6)Network Binding (flags):
-p --port PORT: TCP port to listen on (default: 27224)--max-clients N: Maximum concurrent client connections, 1-32 (default: 10)
Display & Palette:
-P --palette TYPE: ASCII palette: standard, blocks, digital, minimal, cool, custom (default: standard)-C --palette-chars CHARS: Custom palette characters (implies --palette=custom)
Performance:
--compression-level LEVEL: zstd compression level 1-9 (default: 1, fastest)--no-compress: Disable video frame compression entirely--encode-audio: Force enable Opus audio encoding (overrides --no-compress)--no-encode-audio: Disable Opus audio encoding, send raw audio samples--no-audio-mixer: Disable audio mixer, send silence instead of mixing (debug only)
Encryption:
-E --encrypt: Enable packet encryption (default: enabled if keys are available)-K --key FILE: SSH/GPG key file for authentication: /path/to/key, github:user, gitlab:user, or 'ssh' for auto-detect--password PASSWORD: Password for connection encryption-F --keyfile FILE: Alternative way to specify key file (alias for --key)--no-encrypt: Disable encryption (for local testing)--client-keys FILE: File containing allowed client public keys for authentication (whitelist, one per line in authorized_keys format)
Run ascii-chat mirror --help to see all mirror mode options.
Mirror mode displays your local webcam as ASCII art without any network connection - perfect for testing your webcam, palette settings, and terminal rendering.
Terminal Dimensions:
-x --width WIDTH: Terminal width in characters (auto-detected by default)-y --height HEIGHT: Terminal height in characters (auto-detected by default)--stretch: Stretch video to fit without preserving aspect ratio
Webcam Options:
-c --webcam-index INDEX: Webcam device index (0-based, default: 0)-f --webcam-flip: Toggle horizontal flip of webcam image (default: flipped)--test-pattern: Use test pattern instead of real webcam--list-webcams: List available webcam devices and exit
Display & Color:
--color-mode MODE: Color modes: auto, none, 16, 256, truecolor (default: auto)-M --render-mode MODE: Render modes: foreground (fg), background (bg), half-block (default: foreground)-P --palette TYPE: ASCII palette: standard, blocks, digital, minimal, cool, custom (default: standard)-C --palette-chars CHARS: Custom palette characters (implies --palette=custom)--show-capabilities: Display detected terminal color capabilities and exit--utf8: Force enable UTF-8/Unicode support
Performance:
--fps FPS: Desired frame rate, 1-144 (default: 60)
Snapshot Mode:
-S --snapshot: Capture single frame and exit (useful for testing palettes)-D --snapshot-delay SECONDS: Delay in seconds before capturing snapshot (default: 3.0-4.0 for webcam warmup)--strip-ansi: Remove all ANSI escape codes from output (plain ASCII only)
Example:
# View webcam with custom palette
ascii-chat mirror --palette blocks
# Test truecolor rendering with half-block mode
ascii-chat mirror --color-mode truecolor --render-mode half-block
# Capture a single snapshot with debug logging
ascii-chat -V --log-level debug mirror --snapshotπ Protocol details: Cryptographic Handshake Documentation
ascii-chat supports end-to-end encryption using libsodium with Ed25519 key authentication and X25519 key exchange.
ascii-chat's crypto works like your web browser's HTTPS: the client and server perform the Diffie-Hellman exchange to establish secure communication with ephemeral keys every connection. HTTPS depends on certificates tied to DNS names with a certificate authority roots build into the operating system, but ascii-chat is built on TCP so DNS doesn't work for us to secure our servers. ascii-chat users need to verify their server's public keys manually until ACDS (ascii-chat discovery service) is built.
SSH/GPG Key Authentication (--key):
- Use your existing SSH Ed25519 keys for authentication
- Use GPG Ed25519 keys via gpg-agent (no passphrase prompts)
- Supports encrypted SSH keys (prompts for passphrase or uses ssh-agent)
- Supports GitHub public keys with
--client-keys github:usernameand--server-key github:username - GPG key formats:
gpg:KEYIDwhere KEYID is 8, 16, or 40 hex characters (short/long/full fingerprint)
Password-Based Encryption (--password):
- Simple password string for encrypting connections
- Can be combined with
--keyfor dual authentication + encryption
Ephemeral Keys (default):
- When no authentication is provided, generates temporary keypair for the session
# SSH key authentication (prompts for passphrase if encrypted)
ascii-chat client --key ~/.ssh/id_ed25519
# GPG key authentication (uses gpg-agent, no passphrase prompt)
ascii-chat server --key gpg:897607FA43DC66F612710AF97FE90A79F2E80ED3
# Password-based encryption
ascii-chat server --password "hunter2"
# Both SSH key + password (double security)
ascii-chat client --key ~/.ssh/id_ed25519 --password "extra_encryption"
# Disable encryption (for local testing)
ascii-chat server --no-encrypt
# Server key verification with SSH (client verifies server identity)
ascii-chat client --key ~/.ssh/id_ed25519 --server-key ~/.ssh/server1.pub
# This .pub file format is standard OpenSSH public key format (ssh-ed25519).
# Server key verification with GPG (client verifies server identity)
ascii-chat client --server-key gpg:897607FA43DC66F612710AF97FE90A79F2E80ED3
# Server key verification using GitHub GPG keys (fetches server's GPG keys from GitHub)
ascii-chat client --server-key github:zfogg.gpg
# Server key verification using GitLab GPG keys
ascii-chat client --server-key gitlab:username.gpg
# Client key whitelisting (server only accepts specific clients)
ascii-chat server --key ~/.ssh/id_ed25519 --client-keys allowed_clients.txt
# This .txt file contains multiple .pub file contents, 1 per line, where each line is a client key that is allowed to connect to the server.
# GitHub GPG key whitelisting (fetch client's public GPG keys from GitHub)
ascii-chat server --key gpg:MYKEYID --client-keys github:zfogg.gpg
# Server fetches all GPG public keys from https://github.com/zfogg.gpg and whitelists them
# Client must authenticate with their GPG key:
ascii-chat client --key gpg:897607FA43DC66F612710AF97FE90A79F2E80ED3 --server-key gpg:MYKEYID
# GitLab GPG key whitelisting (same but from GitLab)
ascii-chat server --key gpg:MYKEYID --client-keys gitlab:username.gpg
# Combine all three for maximum security!
ascii-chat server --key ~/.ssh/id_ed25519 --client-keys ~/.ssh/client1.pub --password "password123"
# You need to know (1) the server public key and (2) the password before connecting, and the server needs to know (3) your public key and (4) the same password.
# GPG key with password for extra security
ascii-chat server --key gpg:7FE90A79F2E80ED3 --password "password123"ascii-chat is built on a modern, reusable C library called libasciichat that can be embedded in other projects. The library provides production-ready implementations for video processing, networking, cryptography, and cross-platform development. You can install libasciichat as a development dependency and use it in your own applications.
What's in the library:
- Network Protocol: Full implementation of the ascii-chat client/server protocol with encrypted packet exchange, lossless frame compression (zstd), and audio codec integration (Opus). See the protocol reference in the docs.
- Image Processing: The
videomodule converts images to ASCII art with hardware acceleration via SIMD (AVX2, NEON, SSE) for 1-4x performance gains. Includes grid layout algorithms for multi-client rendering. - Platform Abstraction: Write once, run anywhere. Cross-platform abstractions for threads, mutexes, read-write locks, condition variables, sockets, and terminal I/O that work identically on Windows, macOS, and Linux.
- Media Support: Audio capture, mixing, and playback via PortAudio; webcam integration with V4L2 (Linux), AVFoundation (macOS), and Media Foundation (Windows); frame buffering and synchronization.
- Cryptography: End-to-end encryption with libsodium (X25519 key exchange, XSalsa20-Poly1305 AEAD, Ed25519 signatures) and SSH key authentication with agent support.
- Debugging & Profiling: Built-in memory leak detection with source file/line tracking, lock contention analysis, AddressSanitizer integration, and comprehensive logging infrastructure.
- Memory Management: High-performance buffer pooling, lock-free ring buffers, and thread-safe packet queues designed for real-time video/audio applications.
Install libasciichat:
# macOS (Homebrew)
brew install libasciichat
# Arch Linux (AUR)
paru -S libasciichat # Stable release
paru -S libasciichat-git # Latest from gitThe library headers, static and shared libraries, and API documentation are included. Installation also provides CMake config files (asciichatConfig.cmake) and pkg-config metadata (libasciichat.pc) for integration into your own projects.
Using libasciichat in your CMake project:
find_package(asciichat REQUIRED)
target_link_libraries(your_project asciichat::asciichat)Using libasciichat with pkg-config:
pkg-config --cflags --libs libasciichatSee the online API documentation for detailed function references and architecture guides.
ascii-chat is an open source project with an MIT license, meaning you can and should use our code to make cool stuff. Follow through this Open Source section of the README and you'll be compiling against libasciichat in no time.
π‘ For detailed API documentation, see the online docs β includes function references, architecture diagrams, and module documentation generated from source comments.
The first thing you need to do is get the dependencies. Some of them are git submodules of the repo. When you clone the repo get the submodules too.
git submodule init
git submodule update --recursiveNow let's list out and talk about the dependencies before we install them.
π¦ Complete guide: Build System / Dependencies
ascii-chat is built on operating system code and several libraries.
-
musl libc - A small and focused implementation of the C standard library for Linux
- Purpose: This enables us to nicely make static builds that work on any Linux system. This is just for Linux releases - you can build ascii-chat with your system libc if you don't want to use musl (
cmake -B build -DUSE_MUSL=OFF). - License: MIT
- Purpose: This enables us to nicely make static builds that work on any Linux system. This is just for Linux releases - you can build ascii-chat with your system libc if you don't want to use musl (
-
mimalloc - A drop-in replacement for
malloc()- Purpose: Better performing memory allocation. ascii-chat releases are build with mimalloc but you can build without it if you want to use the system default allocator (
cmake -B build -DUSE_MIMALLOC=OFF). - License: MIT
- Purpose: Better performing memory allocation. ascii-chat releases are build with mimalloc but you can build without it if you want to use the system default allocator (
-
PortAudio - Audio I/O Library
- Purpose: So the clients can talk to and hear each other. This library provides audio via the same interface on all three major operating systems, which is really neat because for webcam code I have to work with three different operating system APIs to build ascii-chat.
- License: MIT
-
tomlc17 - TOML File Library
- Purpose: Modern implementation of TOML for config file parsing and editing. For
~/.config/ascii-chat/config.toml. - License: MIT
- Purpose: Modern implementation of TOML for config file parsing and editing. For
-
uthash - Hash Table Library
- Purpose: Gives us fast O(1) lookups for the server's client manager, and persistent memory for caching data
- License: BSD revised
-
libsodium - Cryptographic Library
- Purpose: I use this for the crypto protocol, which you can read more about below. End-to-end encryption and authentication of the protocol's packets, with features like password protection and re-keying.
- License: ISC
-
libsodium-bcrypt-pbkdf - libsodium-Compatible Code
- Purpose: Exports a single function that does the blowfish cipher key derivation needed for decrypting ed25519 keys. This code for bcrypt + BearSSL for aes-ctr and aes-cbc + libsodium crypto algorithms = the ability to decrypt and use password-protected ~/.ssh/id_ed25519 files.
- License: [none]
-
BearSSL - SSL/TLS Library
- Purpose: We need this for our custom HTTPS client, to fetch public keys from GitHub/GitLab for encryption authorization. We also use its aes-ctr and aes-cbc functions with libsodium-bcrypt-pkdf to decrypt ed25519 keys.
- License: MIT
-
zstd - Compression Library
- Purpose: To make the protocol more efficient. Makes all the protocol packets smaller at the cost of some compute time every frame. Check out
lib/compression.c, it's pretty small. - License: BSD/GPLv2
- Purpose: To make the protocol more efficient. Makes all the protocol packets smaller at the cost of some compute time every frame. Check out
-
Opus - Audio Codec Library
- Purpose: Real-time audio compression for low-bandwidth audio transmission. Enables high-quality bidirectional voice and audio communication between clients with minimal latency and bandwidth overhead.
- License: BSD
-
Sokol - Utility Library
- Purpose: Header-only C library providing simple cross-platform APIs (random collection of header-only SDKs for things like timing and audio and async downloads).
- License: zlib/libpng
-
liburcu - Userspace RCU (Read-Copy-Update) Library
- Purpose: Lock-free synchronization for high-performance concurrent data structures in the ACDS (ASCII-Chat Discovery Service). Provides read-side access that scales linearly with CPU cores, achieving 5-10x performance improvement on read-heavy workloads compared to traditional rwlock approaches.
- License: LGPLv2.1
-
SQLite3 - Embedded SQL Database Engine
- Purpose: Persistent storage for the ACDS (ASCII-Chat Discovery Service) session database. Stores active sessions, user identities, and connection metadata for the discovery service.
- License: Public Domain
π Cross-platform details: Platform Abstraction Layer
ascii-chat uses native platform APIs for each platform for webcam access:
- Linux: V4L2 Linux kernel module
- macOS: AVFoundation native macOS API
- Windows: Media Foundation native Windows API
Linux (apt/yum/pacman):
./scripts/install-deps.shmacOS:
brew install make cmake ninja llvm zstd portaudio opus libsodium criterion userspace-rcu sqlite3-
Install Scoop (if not already installed):
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser irm get.scoop.sh | iex
-
Install build tools via Scoop:
scoop install cmake ninja llvm
-
Install Windows SDK:
- Download and install Visual Studio Build Tools
- Or install via Scoop:
scoop install windows-sdk-10-version-2004
-
Install dependencies via vcpkg:
# Install vcpkg (if not already installed) git clone https://github.com/Microsoft/vcpkg.git cd vcpkg .\bootstrap-vcpkg.bat # Install required packages for a development build vcpkg install zstd:x64-windows portaudio:x64-windows opus:x64-windows libsodium:x64-windows liburcu:x64-windows sqlite3:x64-windows # If you want to do a release build vcpkg install zstd:x64-windows-static portaudio:x64-windows-static opus:x64-windows-static libsodium:x64-windows-static liburcu:x64-windows-static sqlite3:x64-windows-static mimalloc:x64-windows
./tests/scripts/run-docker-tests.ps1.
π See also: Build System Documentation β CMake presets, configuration options, and platform-specific build details.
For open source developers who want a working copy:
- Clone this repository:
git clone git@github.com:zfogg/ascii-chat.git; ls ascii-chat && cd ascii-chat. - Install the dependencies for your platform (see Dependencies above or the Build System / Dependencies docs).
- Build an optimized-with-debug build:
make CMAKE_BUILD_TYPE=RelWithDebInfo. - Run
./build/bin/ascii-chat server. - Open a second terminal window, tab, split, or pane. Or go to another computer.
- Run
./build/bin/ascii-chat client. - π― Optional: open more terminals and run more clients! ascii-chat is multiplayer π’. They'll all connect and show in a grid. On macOS you can just open multiple terminals and run
ascii-chat clientin each one. On Windows and Linux computers only one program can use a webcam at a time, so use multiple computers to test connecting multiple clients to the server (call a friend).
make configures CMake for you; if you prefer manual steps, you can still run cmake directly: cmake --preset default && cmake --build build (or choose another --preset).
musl libc: A lightweight, fast, and simple C standard library alternative to glibc. Release builds (cmake --preset release) use musl to create statically linked binaries that have no external dependencies - perfect for deployment as they work on any Linux system without requiring specific libraries to be installed.
mimalloc: Microsoft's high-performance memory allocator. Release builds use mimalloc instead of the system allocator for better performance. It provides:
- Up to 2x faster allocation/deallocation
- Better memory locality and cache performance
- Lower memory fragmentation
- Optimized for multi-threaded workloads
First configure a debug build so the cmake targets we want will be available:
cmake --preset debugNow we can access useful development targets:
cmake --build build --target format- Format all source code using clang-formatcmake --build build --target format-check- Error if the code is not formatted correctlycmake --build build --target clang-tidy- Run clang-tidy across the treecmake --build build --target docs- Generate the Doxygen API reference intobuild/docs/htmlcmake --build build --target docs-open- Build and open the docs in your default browsercmake --build build --target package-productbuild- Build a release and make a.pkginstaller for macOS (analogous targets exist per platform.. try--target package-debfor a.debinstaller on Linux)./build.ps1- PowerShell helper that stops running binaries, cleans, configures, builds, and syncs artifacts intobin/when developing on Windowsctest --test-dir build --output-on-failure --parallel 0- Run all tests with ctest (auto-detects CPU cores)../tests/scripts/run-docker-tests.ps1- Runs tests in a Docker container. Useful on Windows where Criterion tests don't compile../scripts/*- Developer utilities (dependency installers, useful aliases and functions, etc.)
Sanitizers giving you trouble? Here's how to build a Dev build, which is like Debug but with sanitizers disabled:
cmake --preset dev && cmake --build build --target ascii-chatPass these Boolean options via -D<option>=ON|OFF when configuring CMake (for example cmake -B build -DASCIICHAT_ENABLE_ANALYZERS=ON). Defaults reflect the logic in our CMake modules. For complete details, see the Build System Reference.
USE_MUSL(Linux only): defaults toONforRelease/RelWithDebInfobuilds to produce static PIE binaries with musl + mimalloc;OFFfor other build types and on non-Linux hosts.USE_MIMALLOC: defaults toONwhenever we're optimizing for performance (Release/RelWithDebInfo or musl builds), andOFFforDebug/Devconfigurations to keep debugging predictable.BUILD_TESTS: defaults toONso Criterion unit/integration/performance tests are compiled.USE_PRECOMPILED_HEADERS: defaults toON(requires CMake β₯ 3.16 and is disabled automatically for musl builds) to accelerate core library builds.USE_CCACHE: defaults toONto speed up rebuilds withccache(forcedOFFwhen musl is enabled).USE_CPACK: defaults toONto make packaging targets (package,package-productbuild, etc.) available. The release preset turns thisON.ASCIICHAT_RELEASE_ENABLE_FAST_MATH: defaults toOFF; flip toONto allow aggressive fast-math optimizations in Release builds. The release preset turns thisON.ASCIICHAT_RELEASE_KEEP_FRAME_POINTERS: defaults toON; setOFFif you want slightly tighter Release binaries and are okay with poorer stack traces. The release preset turns thisOFF.ASCIICHAT_ENABLE_ANALYZERS: defaults toOFF; enable to wire clang-tidy/cppcheck into the build (respectingASCIICHAT_CLANG_TIDY/ASCIICHAT_CPPCHECKoverrides). The release preset turns thisOFF.ASCIICHAT_ENABLE_UNITY_BUILDS: defaults toOFF, but the presets turn itON; enable to batch-compile sources for faster rebuilds on some toolchains.ASCIICHAT_ENABLE_CTEST_DASHBOARD: defaults toOFF; enable to include CTest dashboard configuration (include(CTest)). All presets except release and release-musl turn thisON.
π Online Documentation: zfogg.github.io/ascii-chat
The documentation is automatically generated from source code comments using Doxygen and published to GitHub Pages on every push to master.
To build documentation locally:
- Install Doxygen (
brew install doxygen,apt-get install doxygen, etc.) to enable the documentation targets. - Configure a build (
cmake --preset default) to let cmake find the doxygen binary. - Run
cmake --build build --target docsto generate HTML + manpage docs inbuild/docs/. - Run
cmake --build build --target docs-opento generate the docs and openbuild/docs/html/index.htmlin your default browser (works on macOS, Linux, and Windows).
π§ͺ Full documentation: Testing Framework
- Framework: libcriterion
- Coverage: Code coverage reports generated in CI
- Performance: SIMD performance tests with aggressive speedup expectations (1-4x)
- Memory Checking: Comprehensive sanitizer support via
-b debugfor detecting memory issues, undefined behavior, and more
Tests are run using CMake's ctest tool, which integrates with Criterion for parallel execution and XML output.
- Have the dependencies installed.
- Choose:
- Linux or macOS: Use ctest directly
- Windows: Use Docker:
./tests/scripts/run-docker-tests.ps1
- Unit Tests: Test individual components in isolation
- Integration Tests: Test component interactions and full workflows
- Performance Tests: Benchmark stuff like SIMD vs scalar implementations
# Build tests first
cmake --build build --target tests
# Run all tests
ctest --test-dir build --output-on-failure --parallel 0
# Run specific test categories using labels
ctest --test-dir build --label-regex "^unit$" --output-on-failure
ctest --test-dir build --label-regex "^integration$" --output-on-failure
ctest --test-dir build --label-regex "^performance$" --output-on-failure
# Run specific tests by name pattern
ctest --test-dir build -R "buffer_pool" --output-on-failure
ctest --test-dir build -R "test_unit_options" --output-on-failure
# Verbose output
ctest --test-dir build --output-on-failure --verbose
# List available tests
ctest --test-dir build -NOn Windows, since Criterion is POSIX-based, tests must be run in a Docker container. Use the PowerShell wrapper script:
# Run all tests
./tests/scripts/run-docker-tests.ps1
# Run specific test category
./tests/scripts/run-docker-tests.ps1 unit
./tests/scripts/run-docker-tests.ps1 integration
./tests/scripts/run-docker-tests.ps1 performance
# Run tests matching a pattern
./tests/scripts/run-docker-tests.ps1 -Filter "buffer"
# This script can also run clang-tidy static analysis
./tests/scripts/run-docker-tests.ps1 clang-tidy
./tests/scripts/run-docker-tests.ps1 clang-tidy lib/common.c
# INFO: powershell doesn't like when you pass -Verbose to a script - use -VerboseOutput
./tests/scripts/run-docker-tests.ps1 unit options -VerboseOutput
The Docker script automatically:
- Builds the test container if needed
- Mounts your source code for live testing
- Handles incremental builds
- Provides the same test interface as the native script
You can also run individual test executables directly:
# Build the project first
cmake --preset debug && cmake --build build
# Run individual tests
build/bin/test_unit_mixer --verbose
build/bin/test_performance_ascii_simd --filter "*monochrome*"ascii-chat uses several environment variables for configuration and security controls. These variables can be set to modify the program's behavior without changing command-line arguments.
-
ASCII_CHAT_INSECURE_NO_HOST_IDENTITY_CHECK- Purpose: Disables host identity verification (known_hosts checking)
- Values:
1(enable), unset or any other value (disable, default) β οΈ DANGER: This completely bypasses security checks and makes connections vulnerable to man-in-the-middle attacks
-
SSH_AUTH_SOCK- Purpose: SSH agent socket for secure key authentication
- Values: Path to SSH agent socket (e.g.,
/tmp/ssh-XXXXXX/agent.12345) - Security: β Secure - uses SSH agent for key management
- When to use: Preferred method for SSH key authentication (automatically detected)
- Used for: SSH key authentication without storing passphrases in environment
-
ASCII_CHAT_KEY_PASSWORD- Purpose: Provides key passphrase for encrypted SSH or GPG keys
- Values: The passphrase string for your encrypted key
- Security:
β οΈ Sensitive data - contains your key passphrase - prefer ssh-agent/gpg-agent over this (we support both) - When to use: When using encrypted keys and you want to avoid interactive passphrase prompts
-
TERM- Purpose: Terminal type detection for display capabilities
- Usage: Automatically set by terminal emulators
- Used for: Determining color support, character encoding, and display features
-
COLORTERM- Purpose: Additional terminal color capability detection
- Usage: Automatically set by modern terminal emulators
- Used for: Enhanced color support detection beyond
TERM
-
LANG,LC_ALL,LC_CTYPE- Purpose: Locale and character encoding detection
- Usage: Automatically set by system locale
- Used for: UTF-8 support detection and character encoding
-
TTY- Purpose: Terminal device detection
- Usage: Automatically set by terminal sessions
- Used for: Determining if running in a real terminal vs. script
-
LINES,COLUMNS- Purpose: Terminal size detection for display dimensions
- Usage: Automatically set by terminal emulators
- Used for: Auto-detecting optimal video dimensions
-
USER- Purpose: Username detection for system identification on POSIX systems
- Usage: Automatically set by POSIX systems
- Used for: System user identification and logging
-
HOME- Purpose: Determines user home directory for configuration files on POSIX systems
- Usage: Automatically detected by the system
- Used for:
- SSH key auto-detection (
~/.ssh/) - Configuration file paths (
~/.ascii-chat/) - Path expansion with
~prefix
- SSH key auto-detection (
-
USERNAME- Purpose: Username detection for system identification on Windows
- Usage: Automatically set by Windows system
- Used for: System user identification and logging
-
USERPROFILE- Purpose: Determines user home directory for configuration files on Windows
- Usage: Automatically detected by the Windows system
- Used for:
- SSH key auto-detection (
~/.ssh/) - Configuration file paths (
~/.ascii-chat/) - Path expansion with
~prefix
- SSH key auto-detection (
-
_NT_SYMBOL_PATH- Purpose: Windows debug symbol path for crash analysis
- Usage: Automatically set by Windows debug tools
- Used for: Enhanced crash reporting and debugging
-
CI- Purpose: Continuous Integration environment detection
- Values: Any non-empty value indicates CI environment
- Used for: Adjusting test behavior and terminal detection in automated environments
-
TESTING,CRITERION_TEST- Purpose: Test environment detection
- Values: Any non-empty value indicates test environment
- Used for: Reducing test data sizes and adjusting performance expectations
-
WEBCAM_DISABLED- Purpose: Automatically enables test pattern mode without requiring
--test-patternflag - Values:
1,true,yes, oron(case-insensitive for string values) - Used for: CI/CD pipelines and testing environments where no physical webcam is available
- Effect: Sets
opt_test_pattern = true, causing the client to use a generated test pattern instead of webcam input
- Purpose: Automatically enables test pattern mode without requiring
- Audio.
- Client should continuously attempt to reconnect
- switch Client "-a/--address" option to "host" and make it accept domains as well as ipv4
- Colorize ASCII output
- Refactor image processing algorithms
- Grid packing algorithm.
- client reconnect logic
- terminal resize events
- A nice protocol for the thing (packets and headers).
- client requests a frame size
- Client should gracefully handle
frame width > term width - Client should gracefully handle
term resizeevent - Compile to WASM/WASI and run in the browser
- Socket multiplexing.
- Edge detection and other things like that to make the image nicer.
- Square packing / grid packing / putting multiple squares into one square efficiently. For the multi-client grid layout system.
- Multiple clients. Grid to display them.
- Snapshot mode for clients with --snapshot to "take a photo" of a call and print it to the terminal or a file, rather than rendering video for a long time.
- Audio mixing for multiple clients with compression and ducking.
- Color filters so you can pick a color for all the ascii so it can look like the matrix when you pick green (Gurpreet suggested).
- Lock-free packet send queues.
- Hardware-accelerated ASCII-conversion via SIMD.
- Windows support.
- Linux support.
- Fix v4l2 usage because the ascii rendered looks corrupted on Linux.
- Crypto.
- GPG key support for crypto (Ed25519 via gpg-agent).
- zalgo text generator
- v4l2 webcam images working.
- make more little todos from the github issues so they're tracked in the readme because i like the changelog (i can check with git when things are checked off)
- submit an ascii-chat internet protocol (ACIP) ietf rfc
- ascii-chat discovery service
- submit an ascii-chat discovery service (ACDS) ietf rfc
- ascii-chat official homebrew bottles
-
Note: Colored frames are many times larger than monochrome frames due to the ANSI color codes.
-
We don't really save bandwidth by sending color ascii video. I did the math with Claude Code.

