@_hyf0: I wanted to build a toy coding agent. Started by looking into the TUI layer. That rabbit hole turned into a full termin…
Summary
VUE-TUI is a new open-source framework that lets developers build interactive terminal applications using Vue components, with features like flexbox layout, HMR, and a focus system.
View Cached Full Text
Cached at: 05/25/26, 10:35 AM
I wanted to build a toy coding agent. Started by looking into the TUI layer. That rabbit hole turned into a full terminal UI framework.
- Write Vue components for the terminal.
- Develop them with Vite HMR.
Meet VUE-TUI: https://t.co/SOyHgf4zBd https://t.co/IYh6pTuOA0
vuejs-ai/vue-tui
Source: https://github.com/vuejs-ai/vue-tui
vue-tui
Early stage — under active development. Bug reports welcome, but not recommended for production use yet.
Vue for the terminal. Build interactive CLI apps with components, flexbox, and HMR.
- Vue SFC & JSX — write terminal UIs with
<template>, TSX, or both - Flexbox layout — powered by Yoga, the same engine behind React Native
- Focus system — built-in focus management with Tab navigation
- Hot module replacement — instant feedback while developing
- First-class testing — render components, simulate input, assert frames
Packages
@vue-tui/runtime— The core framework. A custom Vue 3 renderer that targets the terminal instead of the DOM. Provides components (Box,Text,Static, etc.), composables (useInput,useFocus,useExit, etc.), and a yoga-based flexbox layout engine.@vue-tui/cli— Development tool. Runvue-tui devto start your app with Vite-powered HMR — edit a.vuefile and see the terminal update instantly.@vue-tui/testing— Test harness. Render components in an isolated fake terminal, simulate keyboard input, and assert on visual output frame by frame.
Quick Example
// src/main.ts
import { createApp } from "@vue-tui/runtime";
import App from "./App.vue";
createApp(App).mount();
<!-- src/App.vue -->
<script setup lang="ts">
import { shallowRef } from "vue";
import { Box, Text, useInput } from "@vue-tui/runtime";
const count = shallowRef(0);
useInput((input) => {
if (input === "+") count.value++;
if (input === "-") count.value--;
});
</script>
<template>
<Box>
<Text>Count: </Text>
<Text bold color="green">{{ count }}</Text>
<!-- try changing this color -->
<Text dimColor> (+/- to change)</Text>
</Box>
</template>
Examples
| Example | Description |
|---|---|
basic-template | Vue SFC with <template> syntax |
basic-jsx | Same app in TSX |
coding-agent | AI coding agent with LLM streaming and interactive UI |
flappy-bird | Physics-based terminal game with reactive state and borders |
Getting Started
npx tiged vuejs-ai/vue-tui-starter my-app
cd my-app
npm install
npm run dev
That’s it — try changing the color or text in App.vue and watch the terminal update instantly while keeping your component state.
To build and run:
npm run preview
Components
| Component | Description |
|---|---|
<Box> | Flexbox container — direction, wrap, align, justify, gap, padding, margin, borders, background |
<Text> | Styled text — color, bold, italic, underline, strikethrough, dimColor, wrap/truncate modes |
<Spacer> | Expands to fill available space (flex-grow: 1) |
<Newline> | Inserts line breaks (configurable count) |
<Static> | Renders a list of items once, above the redrawn region |
<Transform> | Applies a string transform function to each rendered line |
Hooks
| Hook | Description |
|---|---|
useInput(handler, opts?) | Handle keyboard input — receives (input, key) with modifier and arrow key detection |
useFocus(opts?) | Component-level focus — returns { isFocused, focus } |
useFocusManager() | App-level focus control — focusNext(), focusPrevious(), focus(id) |
useExit() | Programmatic app exit — returns exit(error?) |
useTerminalSize() | Reactive terminal dimensions — { columns, rows } |
useStdin() | Access stdin stream and raw mode control |
useStdout() | Write directly to stdout |
useStderr() | Write directly to stderr |
Testing
The @vue-tui/testing package renders components in an isolated environment and lets you simulate input and assert visual output:
npm install -D @vue-tui/testing
import { defineComponent, ref } from "vue";
import { expect, test } from "vitest";
import { render } from "@vue-tui/testing";
import { Box, Text, useInput } from "@vue-tui/runtime";
test("counter responds to + and - keys", async () => {
const Counter = defineComponent(() => {
const count = ref(0);
useInput((input) => {
if (input === "+") count.value++;
if (input === "-") count.value--;
});
return () => (
<Box>
<Text>Count: {count.value}</Text>
</Box>
);
});
const { lastFrame, stdin } = await render(Counter);
expect(lastFrame()).toContain("Count: 0");
await stdin.write("+");
expect(lastFrame()).toContain("Count: 1");
await stdin.write("-");
expect(lastFrame()).toContain("Count: 0");
});
Development
Requires pnpm and Node.js 22+.
pnpm install # install dependencies
vp run ready # lint, typecheck, test, and build (the full check)
vp run -r test # run tests across all packages
vp run -r build # build all packages
vue-tui dev # start an example with HMR
Caveats
- vue-tui enables raw mode by default so the terminal won’t echo keystrokes into your UI.
- Ctrl+C still exits —
exitOnCtrlCdefaults totrue. - For pure-output tools that don’t need input suppression, pass
rawMode: falsetomount().
Credits
vue-tui started as a Vue port of Ink, the library that proved terminal UIs could be built with the same component patterns we use on the web. The component model, yoga-based layout, focus system, rendering pipeline — all of it originates in Ink’s design, adapted to follow Vue’s philosophy and conventions. Thank you to Vadim Demedes, Sindre Sorhus, and the Ink contributors for creating such a solid foundation.
License
MIT
Yunfei He (@_hyf0): Been bored lately, so I’m gonna build a toy coding agent. Kicking off with the TUI layer!
Similar Articles
@_hyf0: Happy to announce [email protected]! What you get: - Vue <script setup> + reactivity, rendered to the terminal - Real Yoga fl…
[email protected] is released, enabling Vue components with reactivity to render in the terminal, featuring Yoga flexbox layout and patterns inspired by React Ink.
@evanyou: 3D in the terminal with Vue?!
Evan You highlights Vue TUI, a library that renders 3D effects in the terminal using Vue.
Stop Making TUIs
Thomas Ptacek advocates for building native graphical user interfaces instead of text-based interfaces, citing that coding agents have reduced development costs. Simon Willison supports this view based on his own experience with vibe-coded macOS apps.
@jakevin7: Here's a hot take: TUI will gradually decline or even become obsolete. I haven't used Claude Code in a long time. I almost exclusively use Slock. For ad-hoc tasks, I now use Codex Desktop more, occasionally Claude Desktop. It makes me rethink TUI…
This article discusses the trend of TUI (Terminal User Interface) gradually declining in AI programming tools. The author argues that as model capabilities improve, TUI will be replaced by CLI+server architectures or Web UI, and shares personal experience switching from Claude Code to Slock, Codex Desktop, and other tools.
Stop Making TUIs
The author advocates for building native user interfaces over terminal user interfaces, demonstrating several AI-assisted apps created with minimal coding effort.