Quick Start · Packages · Components · Styling · Architecture · Development
[!IMPORTANT] What this installs:
- Native
.nodebindings for the Taffy layout engine (Rust → Node via napi-rs, not WASM)- Prebuilt for Linux (x64/arm64), macOS (Intel/Apple Silicon), Windows
- No network calls, no telemetry, no files written outside your project
Uninstall:
npm remove @wolf-tui/react @wolf-tui/plugin(substitute your adapter)
Building terminal UIs means choosing between raw ANSI escape codes or framework-specific tools locked to one ecosystem. If you know React, you can use Ink — but there's nothing for Vue, Angular, Solid, or Svelte. And Ink's layout engine (Yoga) only supports Flexbox.
wolf-tui started as a fork of Ink, then expanded: five framework adapters sharing one layout engine (Taffy — Flexbox + CSS Grid), one component library, and one styling pipeline (Tailwind, SCSS, CSS Modules). Write a component once, render it in any adapter.
npm create wolf-tui
The CLI walks you through framework, bundler, and styling choices — generates a ready-to-run project. See create-wolf-tui for flags and options.
Pick your framework:
npm install @wolf-tui/react && npm install -D @wolf-tui/plugin
import { render, Box, Text } from '@wolf-tui/react'
function App() {
return (
<Box style={{ flexDirection: 'column', padding: 1 }}>
<Text style={{ color: 'green' }}>Hello from wolf-tui!</Text>
</Box>
)
}
render(<App />)
npm install @wolf-tui/vue && npm install -D @wolf-tui/plugin
<script setup>
import { Box, Text } from '@wolf-tui/vue'
</script>
<template>
<Box :style="{ flexDirection: 'column', padding: 1 }">
<Text :style="{ color: 'green' }">Hello from wolf-tui!</Text>
</Box>
</template>
import { render } from '@wolf-tui/vue'
import App from './App.vue'
render(App)
npm install @wolf-tui/angular && npm install -D @wolf-tui/plugin
import { Component } from '@angular/core'
import { BoxComponent, TextComponent } from '@wolf-tui/angular'
@Component({
standalone: true,
imports: [BoxComponent, TextComponent],
template: `
<w-box [style]="{ flexDirection: 'column', padding: 1 }">
<w-text [style]="{ color: 'green' }">Hello from wolf-tui!</w-text>
</w-box>
`,
})
export class AppComponent {}
import { renderWolfie } from '@wolf-tui/angular'
import { AppComponent } from './app.component'
renderWolfie(AppComponent)
npm install @wolf-tui/solid && npm install -D @wolf-tui/plugin
import { render, Box, Text } from '@wolf-tui/solid'
function App() {
return (
<Box style={{ flexDirection: 'column' }}>
<Text style={{ color: 'green' }}>Hello from wolf-tui!</Text>
</Box>
)
}
render(App, { stdout: process.stdout, stdin: process.stdin })
npm install @wolf-tui/svelte && npm install -D @wolf-tui/plugin
<!-- App.svelte -->
<script>
import { Box, Text } from '@wolf-tui/svelte'
</script>
<Box style={{ flexDirection: 'column', padding: 1 }}>
<Text style={{ color: 'green', fontWeight: 'bold' }}>Hello from wolf-tui!</Text>
</Box>
import { render } from '@wolf-tui/svelte'
import App from './App.svelte'
render(App)
Svelte requires --conditions=browser at runtime and a build step. See the Svelte adapter README for full setup.
Each adapter has a detailed README with full API docs, Vite/esbuild/webpack configuration, and component reference.
| Package | Description | Docs |
|---|---|---|
| create-wolf-tui | Project scaffolding CLI | README |
| @wolf-tui/core | Layout engine, DOM, renderer | Core |
| @wolf-tui/react | React 19+ adapter | README |
| @wolf-tui/vue | Vue 3.5+ adapter | README |
| @wolf-tui/angular | Angular 17+ adapter | README |
| @wolf-tui/solid | SolidJS 1.9+ adapter | README |
| @wolf-tui/svelte | Svelte 5+ adapter | README |
| @wolf-tui/plugin | Build plugin (Vite/esbuild/webpack/Rollup) | README |
| @wolf-tui/typescript-plugin | TypeScript plugin for CSS module types | README |
| @wolf-tui/css-parser | CSS/SCSS/LESS/Stylus parser | Internal |
All adapters share the same component set — same visual output across all 5 frameworks via the shared WNode render architecture.
| Category | Components |
|---|---|
| Layout | Box, Text, Newline, Spacer, Static, Transform, ScrollView, Table |
| Display | Alert, Badge, Spinner, ProgressBar, StatusMessage, ErrorOverview, Gradient, BigText, Timer, TreeView, JsonViewer, FilePicker |
| Input | TextInput, PasswordInput, EmailInput, ConfirmInput, Select, MultiSelect, Combobox |
| Lists | OrderedList, UnorderedList |
Plus composables/hooks: useInput, useFocus, useFocusManager, stream access, screen reader detection.
Adapted (where applicable) from the ink-* community ecosystem (Gradient from ink-gradient, BigText from ink-big-text). Available in all 5 adapters with identical APIs.
Layout
| Component | Description | Key features |
|---|---|---|
Box |
Flexbox/Grid layout container | All CSS-like flex props, style object, className |
Text |
Styled inline text | Color, bold/italic/underline, wrap modes |
Newline |
Empty lines | count prop |
Spacer |
Fills remaining flex space | Pushes siblings apart in flex containers |
Static |
Renders items once, skips re-renders | Append-only logs, scroll-back history |
Transform |
Transforms rendered text of children | transform: (line, idx) => string |
ScrollView |
Fixed-height viewport with clipped overflow | Built-in arrow / PageUp / PageDown / Home / End navigation |
Table |
Box-drawing table for tabular data | ink-table parity, themable borders/cells, column subset |
Display
| Component | Description | Key features |
|---|---|---|
Alert |
Boxed alert message | variant: success / error / warning / info + title |
Badge |
Inline coloured label | color prop |
Spinner |
Animated loading spinner | 80+ types (dots, line, arc, …), optional label |
ProgressBar |
Horizontal progress bar | value 0–100, custom characters, themable colors |
StatusMessage |
One-line status with icon | variant: success / error / warning / info |
ErrorOverview |
Formatted error display | Pretty stack trace, source frame highlight |
Gradient |
Coloured text gradient | 13 presets or custom hex stops, per-character interpolation |
BigText |
ASCII-art figlet-style banner | cfonts engine, multiple fonts, gradients, alignment |
Timer |
Count-up, countdown, or stopwatch | Lap recording, configurable format, drift-resistant |
TreeView |
Hierarchical tree with expand/collapse | Single/multi-select, async lazy loading, virtual scroll |
JsonViewer |
Interactive JSON tree viewer | 16 value types, syntax colouring, circular-reference detection |
FilePicker |
Filesystem browser with filter mode | Multi-select, symlinks, directory navigation |
Input
| Component | Description | Key features |
|---|---|---|
TextInput |
Single-line text field | onChange / onSubmit, placeholder, mask, suggestions |
PasswordInput |
Masked text input | Configurable mask character |
EmailInput |
Email field with domain suggestions | Auto-completes top-100 email domains |
ConfirmInput |
Yes / No prompt | y / n keys, customizable defaults |
Select |
Single-selection picker | Keyboard nav, themed indicator, options array |
MultiSelect |
Multi-selection picker | Toggle with space, submit with enter |
Combobox |
Fuzzy-search autocomplete dropdown | Two-pass fzf-style matching, cursor nav, autofill |
Lists
| Component | Description | Key features |
|---|---|---|
OrderedList |
Numbered list | OrderedListItem children |
UnorderedList |
Bulleted list | UnorderedListItem children |
// React example
import { Timer, JsonViewer, FilePicker, Table, Gradient, BigText } from '@wolf-tui/react'
// Timer with countdown
<Timer variant="countdown" durationMs={60000} format="human" />
// Interactive JSON viewer
<JsonViewer data={{ users: [{ name: 'Alice' }] }} defaultExpandDepth={2} />
// File picker with multi-select
<FilePicker initialPath="." multiSelect onSelect={(paths) => console.log(paths)} />
// Table with box-drawing borders
<Table data={[{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]} />
// Gradient text — by preset name, or custom stops
<Gradient name="rainbow">wolf-tui in color</Gradient>
<Gradient colors={['#ff3366', '#ffd700']}>Hand-picked stops</Gradient>
// BigText figlet-style banner
<BigText text="WOLF" font="block" gradient="rainbow" />
See individual adapter READMEs for API details and prop reference.
// Inline styles
<Box style={{ flexDirection: 'column', padding: 1, gap: 1 }}>
<Text style={{ color: 'green', fontWeight: 'bold' }}>Styled text</Text>
</Box>
// Tailwind CSS (v3.4 / v4.1)
<Box className="flex-col p-4 gap-2">
<Text className="text-green-500 font-bold">Styled with Tailwind</Text>
</Box>
| Method | Setup |
|---|---|
| Inline styles | Works out of the box |
| Tailwind CSS | PostCSS + @wolf-tui/plugin |
| CSS Modules | *.module.css imports |
| SCSS/LESS/Stylus | Preprocessor + @wolf-tui/plugin |
All CSS approaches resolve to terminal styles at build time — no runtime CSS engine.
Relative units:
| Unit | Terminal conversion |
|---|---|
px |
value / 4 cells |
rem |
value × 4 cells (1rem = 16px = 4 cells) |
% |
Dynamic (parent-based) |
vw / vh |
Terminal columns / rows |
ch |
1 cell per ch |
Color support:
#fff, #ffffffrgb(255 0 0), rgba(255, 0, 0, 0.5)text-[cyan], bg-[#ff0]┌──────────────────┐
│ @wolf-tui/core │ Taffy layout, virtual DOM, ANSI renderer
│ (napi-rs) │ native .node bindings
└────────┬─────────┘
│
┌────────┴─────────┐
│ @wolf-tui/shared │ render scheduler, shared render functions,
│ │ input parsing, theme system
└────────┬─────────┘
│
┌─────┼─────┬─────────┬──────────┐
│ │ │ │ │
React Vue Angular SolidJS Svelte
Each adapter maps its framework's component model to the shared virtual DOM. Taffy computes layout, the core renderer produces ANSI output. A visual bug either affects all adapters (render function issue) or one adapter (integration issue) — two-step debug path.
wolf-tui uses Taffy for layout computation. Taffy supports both Flexbox and CSS Grid — Yoga (used by Ink and React Native) only supports Flexbox.
Integration details:
calc() valuesIncremental rendering: All adapters render only changed terminal lines per frame, not the full screen. Disable for headless testing:
render(<App />, { incrementalRendering: false })
React Compiler: @wolf-tui/react ships pre-compiled with the React Compiler — all library components skip re-renders when props haven't changed. To apply to your own components:
npm install -D babel-plugin-react-compiler
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { wolfie } from '@wolf-tui/plugin/vite'
export default defineConfig({
plugins: [
react({
babel: {
plugins: [['babel-plugin-react-compiler', {}]],
},
}),
wolfie('react'),
],
})
Requires React 19+.
git clone <repo-url>
cd wolf-tui
pnpm install
pnpm dev
| Command | Description |
|---|---|
pnpm dev |
Watch mode for all packages |
pnpm build |
Build all packages |
pnpm test |
Run all unit tests |
pnpm test:e2e |
E2E screenshot tests (20 tests, ~38s) |
pnpm lint |
ESLint check |
pnpm typecheck |
TypeScript type checking |
See CONTRIBUTING.md for development guidelines.
This project started as a fork of Ink by Vadim Demedes. The React package (@wolf-tui/react) builds upon Ink's foundation and includes components from the ink-* ecosystem.
MIT