veil

v1.2.0 Status: stable by viewerofall GitHub

Nested Wayland compositor that encodes any GUI app — browser, file manager, game — into your terminal via Kitty graphics, Unicode halfblocks, or ASCII. The app has no idea what's below it. It just runs.

one-line install
curl -fsSL https://viewerofall.pages.dev/install/veil/install.sh | sh

Contents

  1. Install
  2. Usage
  3. Render Modes
  4. Config
  5. Architecture
  6. App Compatibility
  7. Roadmap

Install

Curl (recommended)

curl -fsSL https://viewerofall.pages.dev/install/veil/install.sh | sh

Detects your architecture, downloads the right binary, installs to ~/.local/bin. Supports x86_64 and aarch64.

AUR

yay -S veil-host-bin

Manual

Download from GitHub Releases and place the binary in your PATH.

Build from source

git clone https://github.com/viewerofall/veilTDC
cd veilTDC
cargo build --release
sudo cp target/release/veil-host /usr/local/bin/

Requires Rust 1.78+, Vulkan drivers (for GPU mode), and a running Wayland session.

Usage

veil-host run <command> [args...]

Examples:

veil-host run helium-browser
veil-host run firefox
veil-host run thunar
veil-host run niri
veil-host run steam

Flags

FlagDescription
-m, --mode <mode>Force render mode (kitty, halfblock, ascii, ascii-edge)
-d, --debugLog to /tmp/veil.log
--statsShow fps / compositor dimensions in status bar
-w, --width <px>Override compositor width
-h, --height <px>Override compositor height
-s, --socket <name>Wayland socket name (default: wayland-veil-0)

Other subcommands

veil-host probe        # show terminal caps, resolved config, compositor size
veil-host list-modes   # list render modes and which one auto-selected

Render Modes

kitty
Native pixel images via Kitty Graphics Protocol. Best quality. Requires kitty terminal or WezTerm.
halfblock
Unicode ▀ with 24-bit truecolor. 2× vertical resolution. Requires truecolor terminal.
ascii
Luma-mapped ASCII characters. Works in any terminal.
ascii-edge
Luma with hysteresis edge detection. Sharper than ascii.

Mode is auto-detected from $TERM / $COLORTERM. Override with -m <mode> or set in config.

Config

Place config.lua at ./config.lua or ~/.config/veil/config.lua:

quality    = "kitty"    -- auto | kitty | pixel | ascii | ascii_edge
fps        = 30         -- compositor frame rate cap
gpu_render = true       -- GPU compute shaders for halfblock/luma encoding

quality = "auto" detects based on terminal capabilities. gpu_render = false forces CPU-only encoding.

Architecture

Your terminal
    ↑ Kitty / halfblock / ASCII frames
veil-host
    ├── Smithay compositor (nested Wayland socket)
    ├── veil-gpu  — wgpu Vulkan compute shaders (halfblock + luma encoding)
    ├── veil-render — CPU fallback encoders
    └── veil-config — Lua config (mlua)
    ↑ frames via wl_surface commit
Hosted app (Chromium, GTK4, Qt, XWayland, anything)

How it works

  1. veil-host opens a Wayland socket (wayland-veil-0 by default)
  2. The hosted app connects to that socket and renders normally
  3. veil-host composites the app's frames (shm or dmabuf) into RGBA
  4. RGBA is encoded to the configured terminal format and written to stdout
  5. Input (keyboard, mouse, scroll) is forwarded from crossterm → Wayland seat

GPU encoding

When gpu_render = true (default), halfblock and ASCII modes use wgpu Vulkan compute shaders to sample and encode frames on the GPU. On a weak CPU + strong GPU this makes a meaningful difference. Kitty mode always runs on CPU since it's just raw RGBA passthrough.

App Compatibility

veil-host exposes the full Wayland protocol set required by modern apps:

ProtocolPurpose
xdg-shellWindow management
zwp_linux_dmabuf_v1 v4GPU buffer sharing (Chromium, Electron)
xwaylandX11 app support
zwp_text_input_manager_v3IME / text input for browsers
zwp_primary_selectionMiddle-click paste
wp_cursor_shape_manager_v1Cursor shape requests
zwp_pointer_constraints_v1Pointer lock (games)
zwp_relative_pointer_manager_v1Relative pointer (games)
zwp_idle_inhibitIdle prevention (video)
zwp_keyboard_shortcuts_inhibitApp keyboard capture
zwp_tablet_manager_v2Tablet / drawing input
wl_data_deviceBidirectional clipboard

Tested with: helium-browser (Chromium), Firefox, Thunar, Nautilus, weston-terminal, foot, kitty terminal.

Roadmap

v1 — done

v2 — planned

by viewerofallgithub · releases