Documentation Index
Fetch the complete documentation index at: https://mintlify.com/RtlZeroMemory/Rezi/llms.txt
Use this file to discover all available pages before exploring further.
The engine emits input as a ZREV event batch—a binary format containing one or more input events. These batches flow from the native Zireael engine to the TypeScript core.
Event Types
ZREV batches contain these event record types:
| Record | Description | Fields |
|---|
| Key | Keyboard input with key code and modifiers | keyCode, mods, text |
| Mouse | Mouse events (move, drag, down, up, wheel) | x, y, mouseKind, buttons, wheelX, wheelY, mods |
| Resize | Terminal size change | cols, rows |
| Tick | Animation timer | deltaNs |
Every ZREV buffer begins with a 24-byte header. All fields are little-endian.
| Offset | Size | Type | Field | Description |
|---|
| 0 | 4 | u32 | magic | 0x5645525A (ASCII ZREV as LE u32) |
| 4 | 4 | u32 | version | Format version (currently 1) |
| 8 | 4 | u32 | header_size | Always 24 |
| 12 | 4 | u32 | total_size | Total byte length of entire buffer |
| 16 | 4 | u32 | record_count | Number of event records |
| 20 | 4 | u32 | reserved0 | Must be 0 |
Event Record Structure
After the header, event records are laid out contiguously. Each record is self-framed with a record header:
| Offset | Size | Type | Field |
|---|
| 0 | 1 | u8 | kind (1=key, 2=text, 3=paste, 4=mouse, 5=resize, 6=tick) |
| 1 | 1 | u8 | flags (reserved, must be 0) |
| 2 | 2 | u16 | size (total bytes including this header) |
Followed by kind-specific payload.
Key Events
Kind: 1
Total size: Variable (minimum 12 bytes)
| Offset | Size | Type | Field |
|---|
| 0 | 1 | u8 | kind = 1 |
| 1 | 1 | u8 | flags = 0 |
| 2 | 2 | u16 | size |
| 4 | 4 | u32 | keyCode (ZR_KEY_* constant) |
| 8 | 4 | u32 | mods (bitmask of ZR_MOD_*) |
| 12+ | variable | UTF-8 | text (optional, when printable) |
Key Codes
Special keys:
| Key | Code |
|---|
ZR_KEY_ESCAPE | 1 |
ZR_KEY_ENTER | 2 |
ZR_KEY_TAB | 3 |
ZR_KEY_BACKSPACE | 4 |
ZR_KEY_INSERT | 10 |
ZR_KEY_DELETE | 11 |
ZR_KEY_HOME | 12 |
ZR_KEY_END | 13 |
ZR_KEY_PAGE_UP | 14 |
ZR_KEY_PAGE_DOWN | 15 |
Arrow keys:
| Key | Code |
|---|
ZR_KEY_UP | 20 |
ZR_KEY_DOWN | 21 |
ZR_KEY_LEFT | 22 |
ZR_KEY_RIGHT | 23 |
Function keys: ZR_KEY_F1 (100) through ZR_KEY_F12 (111)
Printable keys: Use ASCII codepoints (32-126)
Modifier Bitmask
const ZR_MOD_SHIFT = 1 << 0; // 0x01
const ZR_MOD_CTRL = 1 << 1; // 0x02
const ZR_MOD_ALT = 1 << 2; // 0x04
const ZR_MOD_META = 1 << 3; // 0x08
Mouse Events
Kind: 4
Total size: 28 bytes
| Offset | Size | Type | Field |
|---|
| 0 | 1 | u8 | kind = 4 |
| 1 | 1 | u8 | flags = 0 |
| 2 | 2 | u16 | size = 28 |
| 4 | 4 | i32 | x (column, 0-based) |
| 8 | 4 | i32 | y (row, 0-based) |
| 12 | 4 | u32 | mouseKind (1=move, 2=drag, 3=down, 4=up, 5=wheel) |
| 16 | 4 | u32 | mods (modifier bitmask) |
| 20 | 4 | u32 | buttons (button state bitmask) |
| 24 | 2 | i16 | wheelX (horizontal scroll delta) |
| 26 | 2 | i16 | wheelY (vertical scroll delta) |
Mouse Kind Values
| Kind | Value | Description |
|---|
move | 1 | Mouse moved without button pressed |
drag | 2 | Mouse moved with button pressed |
down | 3 | Button pressed |
up | 4 | Button released |
wheel | 5 | Scroll wheel moved |
const BUTTON_LEFT = 1 << 0; // 0x01
const BUTTON_MIDDLE = 1 << 1; // 0x02
const BUTTON_RIGHT = 1 << 2; // 0x04
Resize Events
Kind: 5
Total size: 12 bytes
| Offset | Size | Type | Field |
|---|
| 0 | 1 | u8 | kind = 5 |
| 1 | 1 | u8 | flags = 0 |
| 2 | 2 | u16 | size = 12 |
| 4 | 4 | u32 | cols (new column count) |
| 8 | 4 | u32 | rows (new row count) |
Tick Events
Kind: 6
Total size: 12 bytes
| Offset | Size | Type | Field |
|---|
| 0 | 1 | u8 | kind = 6 |
| 1 | 1 | u8 | flags = 0 |
| 2 | 2 | u16 | size = 12 |
| 4 | 8 | i64 | deltaNs (nanoseconds since last tick) |
Note: Offset 4 is 8 bytes (i64), not 4-byte aligned. Parser must handle this.
Parsing
Rezi parses ZREV deterministically:
function parseZrevBatch(buffer: Uint8Array): ZrevEvent[] {
const reader = new BinaryReader(buffer);
// Read header
const magic = reader.readU32();
if (magic !== ZREV_MAGIC) {
throw new Error("Invalid ZREV magic");
}
const version = reader.readU32();
if (version !== ZR_EVENT_BATCH_VERSION_V1) {
throw new Error(`Unsupported ZREV version: ${version}`);
}
const headerSize = reader.readU32();
const totalSize = reader.readU32();
const recordCount = reader.readU32();
const reserved0 = reader.readU32();
// Read records
const events: ZrevEvent[] = [];
for (let i = 0; i < recordCount; i++) {
const kind = reader.readU8();
const flags = reader.readU8();
const size = reader.readU16();
// Parse kind-specific payload
const event = parseEventRecord(kind, size, reader);
events.push(event);
}
return events;
}
Safety guarantees:
- No reads past buffer end
- No unbounded allocations from untrusted sizes
- Explicit, structured errors (no exceptions into user code)
Location: packages/core/src/events.ts
Event Caps
Event batches have configurable size limits:
const config = {
maxEventBytes: 64 * 1024 // 64 KiB default
};
Enforcement:
- Engine enforces cap when building ZREV batches
- Events exceeding cap are dropped (with warning)
- Prevents unbounded memory allocation
Validation Rules
The parser enforces these constraints:
magic must be 0x5645525A (ZREV)
version must be 1
total_size must be >= header_size (24)
record_count must be >= 0
- Each record’s
kind must be valid (1-6)
- Each record’s
size must be >= 4 (minimum record header)
- Sum of all record sizes must not exceed buffer bounds