vue-tui

agent
Security Audit
Warn
Health Warn
  • No license — Repository has no license file
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Community trust — 56 GitHub stars
Code Pass
  • Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

Terminal UI framework built on Vue and Vite. Components, layout, focus, HMR, and testing out of the box.

README.md

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. Run vue-tui dev to start your app with Vite-powered HMR — edit a .vue file 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 — exitOnCtrlC defaults to true.
  • For pure-output tools that don't need input suppression, pass rawMode: false to mount().

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

Reviews (0)

No results found