
Blecsd Tui
- 4 installs
- Updated March 7, 2026
- kadajett/blecsd-skill
Helps with ai & agent building tasks.
About
blecsd-tui is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- blecsd-tui
- AI & Agent Building
- AI-coding skill
Blecsd Tui by the numbers
- 4 all-time installs (skills.sh)
- Ranked #13,348 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/kadajett/blecsd-skill --skill blecsd-tuiAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 4 |
|---|---|
| Last updated | March 7, 2026 |
| Repository | kadajett/blecsd-skill ↗ |
What it does
Helps with ai & agent building tasks.
Files
blECSd Core Library Skill
blECSd is a modern, high-performance terminal UI library built on TypeScript and ECS (Entity Component System) architecture using bitecs. It is a ground-up rewrite of the original blessed node library, NOT backwards-compatible. Version: 0.7.0. Node.js >= 22.0.0.
Hard Rules (Non-Negotiable)
1. Purely Functional, No OOP
BANNED: class, this, new (except Map/Set/Error), prototype manipulation, inheritance.
// WRONG
class MyWidget { private x: number; constructor(x: number) { this.x = x; } }
// CORRECT
interface MyWidget { readonly x: number; }
function createMyWidget(x: number): MyWidget { return { x }; }2. No Direct bitecs Imports
Only three files may import from 'bitecs': src/core/ecs.ts, src/core/world.ts, src/core/types.ts. Everything else imports from 'blecsd' (external) or '../core/ecs' (internal).
3. Library-First Design
Users control their own world and update loop. All functions take world as a parameter. Never own a global world.
4. Input Priority
INPUT phase is always first in the update loop. Cannot be reordered. All pending input is processed every frame.
5. Early Returns and Guard Clauses
Handle errors first, happy path last. Max nesting 2-3 levels.
6. File Size Limits
- Component files: max 200 lines
- Widget files: max 300 lines per sub-file
- All other source files: max 500 lines
7. Strict TypeScript
- All functions have explicit return types
- No
any(useunknown+ type guards) - Prefer
readonlyarrays and objects - Branded types for IDs
Architecture
Update Loop Phases (in order)
1. INPUT (always first, immutable position) — keyboard/mouse 2. EARLY_UPDATE — pre-processing, state transitions 3. UPDATE — main game/app logic 4. LATE_UPDATE — post-processing, cleanup 5. ANIMATION — physics, springs, tweens, momentum scrolling 6. LAYOUT — positions, sizes, constraints 7. RENDER — write to screen buffer 8. POST_RENDER — cleanup, telemetry
Where Does Logic Go?
| Question | Module |
|---|---|
| Pure data storage (typed arrays)? | components/ (200 lines max) |
| Queries entities and transforms state? | systems/ |
| Combines components into user-facing API? | widgets/ (300 lines/sub-file) |
| Pure function, no ECS dependency? | utils/ |
| Validates config or input? | schemas/ |
| Handles terminal I/O? | terminal/ |
| ECS primitive (addEntity, etc.)? | core/ |
Rule: Components = data only. Systems = logic. Never put business logic in component files.
API Surface (Three Tiers)
Tier 2: Subpath Imports (Recommended)
Full module access — the default for all applications:
import { position, content, scroll } from 'blecsd/components';
import { animationSystem, collisionSystem } from 'blecsd/systems';
import { box, tabs, modal, flexbox } from 'blecsd/widgets';
import { createDoubleBuffer, createProgram } from 'blecsd/terminal';
import { BoxConfigSchema } from 'blecsd/schemas';
import { renderText, wrapText } from 'blecsd/utils';
import { enableDebugOverlay } from 'blecsd/debug';
import { queueKeyEvent } from 'blecsd/input';
import { createViState, processViKey } from 'blecsd/input';Tier 1: Curated Top-Level ('blecsd')
~80 exports for small scripts and quick prototypes. See API Reference.
Tier 3: Namespace Objects (Preferred for Complex Apps)
Frozen plain objects grouping related functions:
import { position, content, dimensions, border } from 'blecsd/components';
position.set(world, eid, 10, 5);
content.set(world, eid, 'Hello');
dimensions.set(world, eid, 40, 10);
border.set(world, eid, { type: 'line' });Quick Start with createApp()
The recommended way to bootstrap a blECSd application (added in v0.7.0):
import { createApp } from 'blecsd';
import { createBoxEntity, createTextEntity } from 'blecsd/core';
const app = await createApp({ fullscreen: true, fps: 30 });
// app.world — ECS world
// app.program — terminal input handling
// app.cols, app.rows — terminal dimensions
// app.render() — run one frame
// app.shutdown() — clean exit
// app.start() — start render loop (returns stop fn)
const panel = createBoxEntity(app.world, {
x: 2, y: 1, width: 40, height: 12,
border: { type: 1, top: true, bottom: true, left: true, right: true },
});
createTextEntity(app.world, {
x: 4, y: 2, text: 'My Dashboard', parent: panel,
});
app.program.on('key', (e) => { if (e.name === 'q') app.shutdown(); });
app.start();createApp Options
| Option | Type | Default | Description |
|---|---|---|---|
cols | number | auto | Terminal columns |
rows | number | auto | Terminal rows |
fps | number | 0 | Target FPS (0 = manual) |
fullscreen | boolean | true | Use alternate screen |
programOptions | ProgramConfig | — | Additional program config |
Other DX Helpers
| Function | Purpose |
|---|---|
createRenderPipeline(stream, opts?) | Wire output → double-buffer → dirty-tracker pipeline manually |
onShutdown(world, opts?) | Register SIGINT/SIGTERM handlers for clean teardown |
renderToString(world, cols, rows) | Render one frame to a string (testing/snapshots) |
Reference Documents
Detailed API surfaces are split into reference files to keep this skill focused:
- [API Surface Reference](./ref/api-surface.md) — Full Tier 1 exports, component namespaces, widget namespaces, systems list
- [Terminal & Server Reference](./ref/terminal-server.md) — Terminal control, server-side (SSH/Telnet/WebSocket), process utils, custom streams, vi mode
- [Graphics & Media Reference](./ref/graphics-media.md) — Graphics manager, braille canvas, vector-to-pixel bridge, image widgets
Common Patterns
Using the Scheduler
import { createWorld, createScheduler, PhaseType } from 'blecsd';
const world = createWorld();
const scheduler = createScheduler();
scheduler.register(inputSystem, PhaseType.INPUT);
scheduler.register(layoutSystem, PhaseType.LAYOUT);
scheduler.register(renderSystem, PhaseType.RENDER);
scheduler.register(outputSystem, PhaseType.POST_RENDER);
function tick() {
scheduler.run(world);
requestAnimationFrame(tick);
}
tick();Custom System
import { defineQuery, defineSystem, hasComponent } from 'blecsd';
import { Position, Velocity } from 'blecsd/components';
const movingQuery = defineQuery([Position, Velocity]);
function createMovementSystem() {
return defineSystem((world) => {
for (const eid of movingQuery(world)) {
Position.x[eid] += Velocity.x[eid];
Position.y[eid] += Velocity.y[eid];
}
return world;
});
}Widget API Pattern
import { createBox, setBoxContent, isBox } from 'blecsd/widgets';
const box = createBox(world, {
position: { x: 0, y: 0 },
dimensions: { width: '100%', height: '100%' },
border: { type: 'line', fg: 0x00ff00 },
padding: { top: 1, left: 2 },
content: 'Initial content',
});
setBoxContent(world, box, 'Updated content');
if (isBox(world, box)) { /* ... */ }Keyboard Shortcuts
Global: Tab (focus next), Shift+Tab (focus prev), Escape (blur). Lists: Up/k, Down/j, Home/g, End/G, PageUp/Down, Enter (select), / (search). Text input: Ctrl+A (start), Ctrl+E (end), Ctrl+U (delete to start), Ctrl+K (delete to end), Ctrl+W (delete word).
Error Handling
import { ok, err, isOk, isErr, map } from 'blecsd/errors';
function parseConfig(raw: unknown): Result<Config, ValidationError> {
const result = ConfigSchema.safeParse(raw);
if (!result.success) return err(createValidationError(result.error));
return ok(result.data);
}Error categories: validation, terminal, system, entity, component, input, render, config, internal.
Testing
import { describe, it, expect } from 'vitest';
import { createWorld, addEntity, addComponent, hasComponent } from 'blecsd';
describe('movement system', () => {
it('updates position from velocity', () => {
const world = createWorld();
const eid = addEntity(world);
addComponent(world, eid, Position);
addComponent(world, eid, Velocity);
Position.x[eid] = 0;
Velocity.x[eid] = 5;
movementSystem(world);
expect(Position.x[eid]).toBe(5);
});
});⚠️ Critical: renderSystem Does NOT Render Text Content
The base renderSystem only renders borders and backgrounds. The renderContent() function is a no-op placeholder (see src/systems/renderSystem.ts:341). This means:
setContent(world, eid, "text")stores data but nothing appears on screencreateTextEntity(world, { text: "Hello" })creates an invisible text entity
All official examples use raw ANSI rendering via writeRaw() from blecsd/systems. For TUI apps that need visible text, use:
import { writeRaw, cursorHome, enterAlternateScreen, hideCursor, setOutputStream } from "blecsd/systems";
import { clearScreen } from "blecsd";
setOutputStream(process.stdout);
enterAlternateScreen();
hideCursor();
// Render with ANSI escape codes
writeRaw(`\x1b[${row};${col}H\x1b[38;2;${r};${g};${b}mHello blECSd!`);⚠️ Critical: Dev Server Setup for TUI Apps
NEVER use `tsx watch` or `nodemon` for interactive TUI apps. They steal or pipe stdin, breaking process.stdin.setRawMode(true). Symptoms: keypress restarts app, ANSI escape codes echo on screen, arrow keys don't work.
Use this `dev.mjs` pattern instead:
import { spawn } from "node:child_process";
import { watch } from "node:fs";
let child = null, restarting = false;
function start() {
child = spawn("npx", ["tsx", "src/index.ts"], {
stdio: "inherit", // Child gets actual TTY
env: { ...process.env },
});
child.on("exit", (code) => {
child = null;
if (restarting) { restarting = false; start(); }
else process.exit(code || 0);
});
}
let debounce = null;
watch("src", { recursive: true }, (_, f) => {
if (!f?.endsWith(".ts") || debounce) return;
debounce = setTimeout(() => { debounce = null; }, 500);
if (child) { restarting = true; child.kill("SIGTERM"); } else start();
});
start();{ "scripts": { "dev": "node dev.mjs" } }⚠️ Critical: Use Entity Factories, Not addEntity()
addEntity(world) creates a bare entity with zero components — no Renderable, no Position, no Dimensions. It will be completely invisible with no error. Always use createBoxEntity(), createTextEntity(), or other factories from blecsd/core.
Common Anti-Patterns
1. Using classes — All code must be functional. 2. Importing from bitecs directly — Always import from blecsd or ../core/ecs. 3. Putting logic in component files — Components are data only. 4. Deep nesting — Use guard clauses and early returns. 5. Using `any` — Use unknown with type guards. 6. Missing Zod validation at boundaries — All config objects need Zod schemas. 7. Forgetting barrel exports — Update the module's index.ts when adding exports. 8. Processing input outside INPUT phase — All input goes through inputSystem. 9. Using addEntity() for UI elements — Use createBoxEntity() etc. Bare entities lack Renderable and are invisible. 10. Using tsx watch for TUI apps — Use dev.mjs with stdio: "inherit" spawn. See warning above. 11. Expecting renderSystem to show text — It only renders borders/backgrounds. Use writeRaw() for text.
Module Ownership (Ambiguous Names)
| Function | Canonical Module | Notes |
|---|---|---|
moveCursor | components/textInput/cursor | 6+ versions exist |
fillRect | terminal/screen/cell | 3D package has its own |
getText | components/content | Rope utils also have one |
Development Commands
pnpm install # Install dependencies
pnpm dev # Development mode
pnpm build # Build (catches issues tests miss)
pnpm test # Run tests
pnpm test:watch # Watch mode
pnpm lint # Biome linter
pnpm lint:fix # Auto-fix lint
pnpm typecheck # TypeScript type checkPerformance Tips
- Cache queries:
const myQuery = defineQuery([Position, Velocity])once, reuse everywhere. - Batch component reads in one pass per entity.
- Use dirty tracking: only re-render changed entities.
- Virtualize large lists with
createVirtualizedList. - Use double buffering (
createDoubleBuffer) for flicker-free rendering. - Avoid allocations in hot loops.
- Use
frameBudgetSystemto monitor frame times.
Add-on Packages
| Package | Import | Purpose |
|---|---|---|
@blecsd/3d | import { ... } from '@blecsd/3d' | 3D rendering with software rasterizer |
@blecsd/ai | import { ... } from '@blecsd/ai' | AI/LLM interface widgets |
@blecsd/game | import { ... } from '@blecsd/game' | High-level game API |
@blecsd/audio | import { ... } from '@blecsd/audio' | Audio management |
@blecsd/media | import { ... } from '@blecsd/media' | Image/video/GIF rendering |
{
"name": "blecsd-tui-skill",
"description": "Best practices and module map for blECSd, a modern TypeScript terminal UI library built on ECS (bitecs). Use when building, reviewing, or refactoring blECSd apps, widgets, systems, or ECS/game-loop code.",
"version": "2.0.0",
"author": {
"name": "Jeremy Stover",
"email": "jeremy.ryan.stover@gmail.com"
},
"license": "MIT",
"homepage": "https://github.com/Kadajett/blECSd",
"repository": "https://github.com/blecsd/agent-skills",
"keywords": "blecsd, terminal, tui, ecs, bitecs, typescript",
"category": "development"
}
blECSd API Surface Reference
Tier 1: Top-Level Exports ('blecsd')
ECS Core
createWorld(),destroyWorld(world)addEntity(world),removeEntity(world, eid)addComponent(world, eid, Component),hasComponent(world, Component, eid)- Types:
Entity,World,System
App Helpers (DX) — New in v0.7.0
createApp(options?)— Full application bootstrap (world + pipeline + input + shutdown)createRenderPipeline(stream, options?)— Wire render pipeline manuallyonShutdown(world, options?)— Register SIGINT/SIGTERM handlersrenderToString(world, cols, rows)— Render frame to string- Types:
App,AppOptions,RenderPipeline,RenderPipelineOptions,ShutdownOptions
Entity Factories
createScreenEntity(world, config)— Root screen entitycreateBoxEntity(world, config)— Box/container (supportstitleoption as of v0.7.0)createTextEntity(world, config)— Text displaycreateButtonEntity(world, config)— ButtoncreateCheckboxEntity(world, config)— CheckboxcreateInputEntity(world, config)— Text inputcreateSelectEntity(world, config)— Dropdown selectcreateListEntity(world, config)— List
Systems
inputSystem(world)— Process keyboard/mouselayoutSystem(world)— Calculate layoutrenderSystem(world)— Render to bufferoutputSystem(world)— Write buffer to terminalanimationSystem(world)— Update animationsfocusSystem(world)— Manage focuscleanup(),clearScreen()
Component Helpers
getText(world, eid),setText(world, eid, text)getPosition(world, eid),setPosition(world, eid, x, y)getDimensions(world, eid),setDimensions(world, eid, w, h)setZIndex(world, eid, z),getZIndex(world, eid),normalizeZIndices(world)toggle(world, eid)— Toggle visibilityscrollByLines(world, eid, delta),scrollToTop/Bottom/Line(world, eid, ...)focusNext(world),focusPrev(world)prepend(world, parentEid, childEid)hitTest(world, x, y)Position,Velocity,getVelocity(world, eid),setVelocity(world, eid, vx, vy)
Terminal I/O
enableInput/disableInput(world),enableKeys/disableKeys(world),enableMouse/disableMouse(world)stripAnsi(str),createDoubleBuffer(w, h),getBackBuffer(db)getCell(buf, x, y),setCell(buf, x, y, cell),clearBuffer(buf),fillRect(...)createDirtyTracker(cols, rows)— Dirty tracking for render pipelineLogLevel,parseKeyBuffer(buf),isMouseBuffer(buf),parseMouseSequence(buf)- Types:
KeyEvent,CellBuffer,Cell,KeyHandler,MouseHandler,TerminalCapabilities,CursorShape
Schemas
BoxConfigSchema,PositionValueSchema,TextConfigSchema
Utilities
renderText(text, options),wrapText(text, width)getLine(rope, n),getLines(rope),getStats(rope)createCellBuffer(w, h)
Types
DimensionValue,BoxConfig,CleanupCallback,HitTestResult,PositionValue,TextConfig,Unsubscribe,DirtyRect
---
Component Namespaces (blecsd/components)
Each is a frozen object of pure functions. 44 namespaces total:
| Namespace | Purpose | Key Functions |
|---|---|---|
accessibility | ARIA-like roles, labels, announcements | setRole, setLabel, announce |
animation | Animation state | set, get |
behavior | AI/movement behaviors | set, get |
border | Border style | set, get, hasBorder |
button | Button state | set, get |
camera | Camera viewport | set, get, setTarget |
checkbox | Checkbox state | set, get |
collision | Hit detection | set, get, isEnabled |
content | Text content | set, get, setText, getText |
dimensions | width, height | set, get |
focus | Focus management | setFocusable, isFocused |
form | Form state | set, get |
health | Entity health/HP | set, get, damage, heal |
hierarchy | Parent-child tree | setParent, getParent, getChildren, prepend |
interactive | Click/hover | set, isInteractive |
label | Text labels | set, get |
list | List state | set, get |
padding | Inner padding | set, get |
particle | Particle emitter | set, get |
position | x, y, z coordinates | set, get, setZIndex, getZIndex, moveBy |
progressBar | Progress indicator | set, get |
radio | Radio button | set, get |
renderable | Visibility, style | toggle, setVisible, isVisible |
screenComponent | Screen properties | set, get |
scroll | Scroll state | set, get, scrollBy |
select | Select/dropdown | set, get |
shadow | Shadow effects | set, get |
slider | Slider state | set, get |
spinner | Spinner state | set, get |
sprite | Sprite data | set, get, setFrame |
stateMachine | FSM state | set, get, transition |
table | Table data | set, get |
textInput | Text input state | set, get |
tilemap | Tile grid data | set, get |
timer | Countdown/stopwatch | set, get, start, stop |
userData | Custom data store | set, get |
velocity | Movement speed | set, get |
---
Widget Namespaces (blecsd/widgets)
63 widget namespaces. All follow createXxx(world, config) → entity ID pattern:
| Namespace | Purpose | Factory |
|---|---|---|
accordion | Collapsible sections | createAccordion |
ansiImage | ANSI-rendered image display | createANSIImage |
autocomplete | Autocomplete input | createAutocomplete |
barChart | Bar chart | createBarChart |
bigText | Large ASCII text | createBigText |
box | Container with border, padding | createBox |
buttonWidget | Clickable button | createButton |
calendar | Date picker calendar | createCalendar |
canvas | Drawing canvas | createCanvas |
chartUtils | Shared chart utilities | — |
checkboxWidget | Toggle checkbox | createCheckbox |
collapsible | Collapsible panel | createCollapsible |
commandPalette | Command palette (Ctrl+P) | createCommandPalette |
contentManipulation | Content manipulation helpers | — |
contextMenu | Right-click menu | createContextMenu |
devTools | ECS inspector | createDevTools |
fileManager | File browser | createFileManager |
flexbox | Flex layout | createFlexContainer |
fonts | Font management | — |
footer | Footer bar | createFooter |
formWidget | Form with fields | createForm |
gauge | Gauge/meter | createGauge |
grid | Grid layout | createGrid |
header | Header bar | createHeader |
hoverText | Hover tooltip | createHoverText |
image | Image display (overlay/inline) | createImage |
layoutWidget | Layout helpers | — |
line | Horizontal/vertical line | createLine |
lineChart | Line chart | createLineChart |
listbar | List bar | createListbar |
listTable | Tabular list | createListTable |
listWidget | Selectable list | createList |
loading | Loading spinner | createLoading |
log | Log output | createLog |
message | Status message | showInfo/showError/showWarning/showSuccess |
modal | Modal dialog | createModal |
multiSelect | Multi-select with checkboxes | createMultiSelect |
overlayImage | Overlay image (graphics protocol) | createOverlayImage |
panel | Titled panel | createPanel |
progressBarWidget | Progress bar | createProgressBar |
promptWidget | Prompt dialog | createPrompt |
question | Question dialog | createQuestion |
radioWidget | Radio button group | createRadioGroup |
registry | Widget registry | — |
scrollableBox | Scrollable container | createScrollableBox |
scrollableText | Scrollable text | createScrollableText |
searchableList | List with inline filter | createSearchableList |
searchOverlay | Search overlay (regex/plain) | createSearchOverlay |
sparkline | Inline chart | createSparkline |
splitPane | Resizable split view | createSplitPane |
streamingText | Streaming text display | createStreamingText |
switchWidget | Toggle switch | createSwitch |
tableWidget | Data table | createTable |
tabs | Tab container | createTabs |
terminalWidget | Embedded terminal | createTerminal |
text | Static text display | createText |
timerWidget | Timer/stopwatch | createTimer |
toast | Toast notifications | showInfoToast/showErrorToast/... |
tree | Tree view | createTree |
virtualizedList | Performant large list | createVirtualizedList |
---
Systems (blecsd/systems)
| System | Purpose | Phase |
|---|---|---|
inputSystem | Process keyboard/mouse events | INPUT |
focusSystem | Tab navigation, focus management | INPUT |
animationSystem | Tweens, springs, easing | ANIMATION |
layoutSystem | Position/size calculation | LAYOUT |
renderSystem | Write entities to screen buffer | RENDER |
outputSystem | Flush buffer to terminal | POST_RENDER |
collisionSystem | AABB collision detection | UPDATE |
cameraSystem | Camera viewport tracking | UPDATE |
particleSystem | Particle emitter/updater | ANIMATION |
createBehaviorSystem | AI/movement behaviors (factory) | UPDATE |
sceneGraphSystem | Transform hierarchy | EARLY_UPDATE |
stateMachineSystem | FSM transitions | UPDATE |
smoothScrollSystem | Momentum scrolling | ANIMATION |
gameLoopSystem | Fixed timestep physics | UPDATE |
workerPoolSystem | Web worker management | UPDATE |
constraintLayout | Constraint-based layout | LAYOUT |
frameBudgetSystem | Frame time monitoring | POST_RENDER |
dragSystem | Drag-and-drop | UPDATE |
movementSystem | Entity movement | UPDATE |
panelMovementSystem | Panel dragging | UPDATE |
spatialHashSystem | Spatial hash for collision | UPDATE |
tilemapRenderSystem | Tilemap rendering | RENDER |
virtualizedRenderSystem | Virtualized content rendering | RENDER |
visibilityCullingSystem | Off-screen culling | RENDER |
springSystem | Spring physics animations | ANIMATION |
createReactiveSystem | Reactive data binding | varies |
---
Other Subpath Modules
| Module | Key Exports |
|---|---|
blecsd/core | createWorld, addEntity, addComponent, hasComponent, removeEntity, destroyWorld, createScheduler, PhaseType, createGameLoop, entity factories, event bus, serialization, scenes, key bindings, key lock, lazy init, input actions, input state, hit test |
blecsd/schemas | Zod schemas for all config objects |
blecsd/style | Style module for CSS-like stylesheets |
blecsd/debug | enableDebugOverlay, memory profiler, debug overlay |
blecsd/errors | ok, err, isOk, isErr, map, Result types |
blecsd/input | queueKeyEvent, createViState, createViConfig, processViKey (vi mode), input event buffer |
blecsd/text | Text processing utilities |
blecsd/testing | Snapshot testing, visual diff, test helpers |
blecsd/widgets/bigText | Big text widget with fonts |
blecsd/widgets/fonts | Font definitions |
Graphics & Media Reference
Unified Graphics Backend (v0.5.0+)
Auto-detect and use the best terminal graphics protocol:
import {
createAutoGraphicsManager,
createGraphicsManager,
registerBackend,
detectGraphicsSupport,
selectBackend,
refreshBackend,
} from 'blecsd/terminal'; // or 'blecsd/systems' depending on moduleAuto-Detection
const gm = createAutoGraphicsManager();
// Detects: Kitty > iTerm2 > Sixel > ANSI > Braille > ASCIIManual Backend Management
const gm = createGraphicsManager();
registerBackend(gm, kittyBackend);
registerBackend(gm, sixelBackend);
registerBackend(gm, brailleBackend);
selectBackend(gm, 'kitty'); // or let it auto-selectBackend Constants
KITTY_BACKEND_NAME,ITERM2_BACKEND_NAME,SIXEL_BACKEND_NAME,ANSI_BACKEND_NAME,BRAILLE_BACKEND_NAME
Protocol Constants
APC_PREFIX,KITTY_ST,OSC_1337_PREFIX,DCS_START,SIXEL_ST
Schemas (Zod)
GraphicsCapabilitiesSchema,GraphicsManagerConfigSchema,ImageDataSchema,GraphicsRenderOptionsSchema,GraphicsDetectionResultSchema
---
Braille Canvas (Vector Graphics Primitives)
Create a braille dot-coordinate drawing surface (2x4 dots per cell):
import {
createBrailleCanvas,
drawBrailleLine, drawBrailleRect, fillBrailleRect,
drawBrailleCircle, fillBrailleCircle,
drawBrailleArc, drawBrailleBezier, drawBrailleEllipse,
setDot, clearDot, getDot, setCellColor, dotToCell, cellToDot,
brailleCanvasToString, brailleCanvasToCells,
} from 'blecsd/terminal'; // exact subpath may vary
const canvas = createBrailleCanvas(80, 48); // width x height in dot coordinates
drawBrailleLine(canvas, 0, 0, 79, 47);
drawBrailleCircle(canvas, 40, 24, 15);
fillBrailleRect(canvas, 10, 10, 30, 20);
const output = brailleCanvasToString(canvas);---
Vector-to-Pixel Bridge
Render braille canvas through the best available graphics backend:
import { renderVector, canvasToPixelBitmap, hasPixelBackend } from 'blecsd/terminal';
// Renders BrailleCanvas through best backend (pixel or braille fallback)
renderVector(graphicsManager, brailleCanvas, { x: 0, y: 0 });
// Convert vector drawings to RGBA pixel bitmap for Kitty/iTerm2/Sixel
const bitmap = canvasToPixelBitmap(brailleCanvas, width, height);
// Check if a pixel-capable backend is active
if (hasPixelBackend(graphicsManager)) { /* use pixel rendering */ }---
Image Widget Enhancements
Overlay Mode with GraphicsManager
import { createImage, setGraphicsManager } from 'blecsd/widgets';
const img = createImage(world, {
type: 'overlay', // Use graphics protocol overlay
graphicsManager: gm, // Auto-detected manager
});
// Dynamically assign graphics manager
setGraphicsManager(img, gm);ANSIImage and OverlayImage Widgets (v0.7.0)
import { ansiImage, overlayImage } from 'blecsd/widgets';
// ANSI-rendered image (works in all terminals)
const ai = ansiImage.createANSIImage(world, config);
// Overlay image (uses Kitty/iTerm2/Sixel protocol)
const oi = overlayImage.createOverlayImage(world, config);Aspect Ratio & Animation
import { calculateAspectRatioDimensions, setAnimatedImage, startAnimation, stopAnimation, setFrame } from 'blecsd/widgets';
const { width, height } = calculateAspectRatioDimensions(srcW, srcH, targetW, targetH);
setAnimatedImage(eid, gifFrames);
startAnimation(eid);
stopAnimation(eid);
setFrame(eid, 3);Cache Management
import { clearImageCache, clearAllImageCaches } from 'blecsd/widgets';
clearImageCache(eid);
clearAllImageCaches();---
Chart Rendering
Braille Gauge Mode
import { gauge } from 'blecsd/widgets';
const g = gauge.createGauge(world, {
renderMode: 'braille', // 4x vertical resolution
gradientStart: '#00ff00',
gradientEnd: '#ff0000',
});Chart Utilities
brailleFillPattern()— Fill pattern for braille chartsrenderBrailleBar()— Single braille barrenderBrailleGradientBar()— Gradient-colored braille bar
---
Spring Physics Animation System
import { springSystem } from 'blecsd/systems';
// Presets: bouncy, smooth, snappy
// Config: stiffness, damping, precisionSmooth spring-based animations for UI transitions.
---
Constraint Layout System
import { constraintLayout } from 'blecsd/systems';
// Constraint types: fixed, percentage, min, max, ratio
// Functions: layoutHorizontal, layoutVertical---
Accessibility Foundation
import { accessibility } from 'blecsd/components';
// ARIA-like roles: button, checkbox, list, textbox, dialog, menu, tree
accessibility.setRole(world, eid, 'button');
accessibility.setLabel(world, eid, 'Submit');
accessibility.announce('Item selected'); // screen reader notification---
CSS-like Stylesheet System (blecsd/style)
Declarative style rules with selectors by widget tag, class, and entity ID:
import { ... } from 'blecsd/style';
// CSS-like specificity cascading with Zod validation---
Plugin/Module System
Extensible architecture for bundling components, systems, and lifecycle hooks into reusable modules with dependency resolution and priority ordering.
---
Render Backend Abstraction
Pluggable RenderBackend interface with auto-detection:
- AnsiBackend — Standard ANSI escape sequences with optimized cursor movement
- KittyBackend — Kitty graphics protocol with synchronized output and image encoding
Terminal & Server Reference
Terminal Control Functions
All available from blecsd/terminal or blecsd:
Cursor & Screen
cursorHome()— Move cursor to 0,0clearScreen()— Clear terminalenterAlternateScreen()/leaveAlternateScreen()— Alternate bufferhideCursor()/showCursor()— Cursor visibilitymoveTo(x, y)— Move cursor to absolute position (0-indexed)saveCursorPosition()/restoreCursorPosition()— DEC cursor save/restoresetCursorShape(shape)— Set cursor to'block','underline', or'bar'bell()— Ring terminal bellsetWindowTitle(title)— Set terminal window title via OSC 2writeRaw(data)— Write raw data to output
Mouse Tracking
enableMouseTracking(mode)— Enable with'normal','button', or'any'modesdisableMouseTracking()— Disable all mouse tracking
Output Modes
beginSyncOutput()/endSyncOutput()— Synchronized output (DEC 2026) for flicker-free renderingenableBracketedPasteMode()/disableBracketedPasteMode()— Bracketed pasteenableFocusReporting()/disableFocusReporting()— Terminal focus eventssetOutputStream(stream)— Set output targetsetOutputBuffer(db)— Set output double buffersetRenderBuffer(tracker, backBuffer)— Set render buffer
Input Parsing
createProgram(config?)— Create terminal program for input handlingparseKeyBuffer(buf)— Parse raw key buffer to KeyEventisMouseBuffer(buf)/parseMouseSequence(buf)— Mouse input parsingcreateInputHandler(config)— Input stream handler
Screen Buffers
createDoubleBuffer(w, h)— Create double buffer for flicker-free outputgetBackBuffer(db)— Get back buffer referenceclearDirtyRegions(db)— Clear tracked dirty regionsgetCell(buf, x, y)/setCell(buf, x, y, cell)— Cell operationsclearBuffer(buf)/fillRect(buf, x, y, w, h, cell)— Buffer operations
Colors
CSS_COLORS— Named CSS colors mapmatchColor(r, g, b)/matchColorCached(r, g, b)— Find nearest 256-colornameToColor(name)— CSS color name to RGB
Detection
- Terminal capability detection, color support probing
---
Vi Mode (blecsd/input)
Vi-style navigation for scrollable elements:
import { createViState, createViConfig, processViKey } from 'blecsd/input';
const state = createViState();
const config = createViConfig({ enabled: true, viewportHeight: 40 });
const [action, newState] = processViKey(keyEvent, state, config);
// action.type: 'scroll' | 'jump' | 'page' | 'search' | 'searchNext' | 'enterSearch' | 'exitSearch' | 'searchInput' | 'none'Modes: 'normal' | 'search' | 'command'
Key bindings (normal mode):
j/k— Scroll down/uph/l— Scroll left/rightgg/G— Jump to top/bottomH/M/L— Jump to high/middle/low of viewportCtrl+d/Ctrl+u— Half page down/upCtrl+f/Ctrl+b— Full page down/up/— Enter search mode (forward)?— Enter search mode (backward)n/N— Next/prev search match
---
Process Utilities (blecsd/terminal)
Spawn processes with automatic terminal state management:
import { spawn, exec, execSync, readEditor, getDefaultEditor } from 'blecsd/terminal';
// Spawn child process (saves/restores terminal state)
spawn('vim', ['file.txt'], { stdio: 'inherit' });
// Execute command
const result = await exec('ls -la');
// Sync execution
const output = execSync('echo hello');
// Open external editor (respects $EDITOR)
const content = await readEditor({ initialContent: 'Edit me', suffix: '.md' });
// Get default editor
const editor = getDefaultEditor(); // $EDITOR or 'vi'The processUtils namespace groups these:
import { process as proc } from 'blecsd/terminal';
proc.spawn('ls', ['-la']);---
Server-Side (SSH, Telnet, WebSocket, TCP)
Unified Server App
import { createServerApp } from 'blecsd/terminal';
const app = createServerApp({
mode: 'telnet', // 'tcp' | 'telnet' | 'ssh'
port: 2323,
onSession: (session) => {
writeToSession(session, 'Welcome!\r\n');
},
});SSH Server
import { createSSHServer, startSSHServer, stopSSHServer, getSSHClientCount } from 'blecsd/terminal';
const server = createSSHServer({
port: 2222,
hostKey: fs.readFileSync('/path/to/host_key'),
authorizedKeys: [{ key: publicKeyData, username: 'admin' }],
onSession: (session) => { /* StreamSession */ },
});
startSSHServer(server);Features: public key auth, password auth, PTY support with window resize, multi-client. Peer dependency: ssh2.
Telnet Server
import { createTelnetServer, startTelnetServer, stopTelnetServer } from 'blecsd/terminal';
const server = createTelnetServer({
port: 2323,
onSession: (session) => {
writeToSession(session, 'Welcome!\r\n');
session.onData((data) => console.log('Input:', data));
},
});
startTelnetServer(server);Protocol support: NAWS, TTYPE, SGA, ECHO.
WebSocket Server (Browser Rendering)
import { createWebServer, startWebServer, stopWebServer, webBroadcast } from 'blecsd/terminal';
const server = createWebServer({
port: 8080,
title: 'My Terminal App',
authToken: 'secret',
});
startWebServer(server);
webBroadcast(server, '\x1b[2J\x1b[HHello from blECSd!');High-Level serveWeb
import { serveWeb } from 'blecsd/terminal';
const { server, stop } = await serveWeb(world, {
port: 8080,
title: 'My Terminal App',
});
// Open http://localhost:8080 in browserCustom Streams
import { createStreamSession, writeToSession, endSession } from 'blecsd/terminal';
const session = createStreamSession({
input: readableStream,
output: writableStream,
cols: 80,
rows: 24,
onData: (data) => { /* handle input */ },
onResize: (cols, rows) => { /* handle resize */ },
onClose: () => { /* cleanup */ },
});
writeToSession(session, 'Hello!\r\n');
endSession(session);---
Terminal Cleanup
import { cleanup, restoreTerminal } from 'blecsd';
// cleanup() disables ALL terminal modes on exit:
// - Mouse tracking
// - Bracketed paste
// - Focus reporting
// - Synchronized output
// - Kitty keyboard protocol
// - Alternate screen
// - Cursor visibility
// - Style resetOutputState tracks: mouseTracking, mouseMode, syncOutput, bracketedPaste, focusReporting.