An open API service indexing awesome lists of open source software.

https://github.com/simon-he95/vue-tui

Vue 3 terminal UI toolkit for browser DOM and CLI stdout: components, ANSI rendering, markdown transcripts, log views, and agent consoles.
https://github.com/simon-he95/vue-tui

agent-console ansi cli-ui dom-renderer log-viewer markdown stdout-renderer terminal terminal-components terminal-ui tui ui virtual-list vue vue-terminal vue-tui vue3

Last synced: about 5 hours ago
JSON representation

Vue 3 terminal UI toolkit for browser DOM and CLI stdout: components, ANSI rendering, markdown transcripts, log views, and agent consoles.

Awesome Lists containing this project

README

          





Vue TUI

# @simon_he/vue-tui

[![npm version](https://img.shields.io/npm/v/@simon_he/vue-tui?style=flat-square)](https://www.npmjs.com/package/@simon_he/vue-tui)
[![npm downloads](https://img.shields.io/npm/dm/@simon_he/vue-tui?style=flat-square)](https://www.npmjs.com/package/@simon_he/vue-tui)
[![CI](https://github.com/Simon-He95/vue-tui/actions/workflows/ci.yml/badge.svg)](https://github.com/Simon-He95/vue-tui/actions/workflows/ci.yml)
[![Runtime compatibility](https://github.com/Simon-He95/vue-tui/actions/workflows/runtime-compat.yml/badge.svg)](https://github.com/Simon-He95/vue-tui/actions/workflows/runtime-compat.yml)
[![Security](https://github.com/Simon-He95/vue-tui/actions/workflows/security.yml/badge.svg)](https://github.com/Simon-He95/vue-tui/actions/workflows/security.yml)
![TypeScript types](https://img.shields.io/npm/types/@simon_he/vue-tui?style=flat-square)
![Node version](https://img.shields.io/node/v/@simon_he/vue-tui?style=flat-square)
[![MIT License](https://img.shields.io/github/license/Simon-He95/vue-tui?style=flat-square)](./license)

[Docs](https://vue-tui.pages.dev/) | [npm](https://www.npmjs.com/package/@simon_he/vue-tui) | [GitHub](https://github.com/Simon-He95/vue-tui) | [Issues](https://github.com/Simon-He95/vue-tui/issues)

Vue TUI is a Vue 3 terminal UI toolkit for building terminal-style interfaces that render to browser DOM, real CLI stdout, and headless tests.

Use it to build browser terminal dashboards, Vue-powered CLI apps, streaming markdown transcripts, log viewers, virtual lists, and AI agent consoles with one shared component model.

## Why Vue TUI?

- **Vue component model for terminal UIs**: build with `TerminalProvider`, `TBox`, `TInput`, `TList`, `TTable`, and more.
- **Browser + CLI renderers**: render the same UI model to browser DOM or real stdout.
- **High-throughput surfaces**: virtual lists, append-only logs, streaming markdown, and agent transcripts.
- **Clear host boundaries**: browser-safe root entrypoint, CLI-only APIs under `/cli`, sanitized links, and explicit host permissions.

## Agent UI Showcase

A real agent console built on `@simon_he/vue-tui` can stream agent output, markdown content, tool-call status, and input chrome in one terminal surface.

[![Agent console rendering built with vue-tui](./docs/public/agent-console-rendering-poster.png)](./docs/public/agent-console-rendering.mp4)

[Watch the rendering demo](./docs/public/agent-console-rendering.mp4)

## Install

```bash
pnpm add @simon_he/vue-tui vue
```

Vue is a peer dependency. The current package supports Vue `>=3.3.0 <4`.

## Runtime Support

The published package supports Node.js `>=16.17` for CLI/runtime consumers.

Development, release validation, and documentation builds are run on Node.js 20 in CI because the repository toolchain uses modern build/test tooling.

## Entry Points

| Import | Stability | Use it for |
| ------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `@simon_he/vue-tui` | Public | Browser-safe terminal core, DOM renderer, stable Vue components, and input host plugin factory |
| `@simon_he/vue-tui/core` | Public | Terminal core, buffer-facing types, ANSI/theme/path/hyperlink helpers |
| `@simon_he/vue-tui/renderer/dom` | Public | DOM renderer factory and renderer capabilities |
| `@simon_he/vue-tui/vue` | Advanced | Extended Vue components, composables, router helpers, and Vue runtime internals |
| `@simon_he/vue-tui/runtime` | Advanced | Runtime wiring, selection helpers, and clipboard abstraction |
| `@simon_he/vue-tui/observability` | Advanced | Frame perf store, profiler hooks, and trace helpers |
| `@simon_he/vue-tui/cli` | Public | Node-only headless Vue app runtime, stdin driver, stdout renderer, path provider, recording, and terminal clipboard helpers |
| `@simon_he/vue-tui/markdown` | Public | `TMarkdownText`, `TVirtualMarkdown`, markdown parser and layout helpers, streaming markdown block sources |
| `@simon_he/vue-tui/mermaid` | Public | Optional `beautiful-mermaid` bridge: adaptive `TMermaid`(图片 → ANSI → 源码)、`TMermaidText`(ANSI)、`TMermaidImage`(图形协议图片) |
| `@simon_he/vue-tui/experimental` | Experimental | `T3DViewport`, `TVideo`, charts, `TVirtualList`, `TTranscriptView`, `TLogView`, TLog companions, and append-only log tooling |
| `@simon_he/vue-tui/experimental/video/node` | Experimental | Node-only lazy FFmpeg frame source plus optional yt-dlp resolver for supported video pages |
| `@simon_he/vue-tui/experimental/3d/bun` | Experimental | Bun-only raw WGSL/WebGPU Pull renderers, including the vue-tui terminal badge scene |
| `@simon_he/vue-tui/agent` | Experimental | Agent/console transcript, tool-call header, log, markdown, virtual list, render plane, and overlay component aggregation |
| `@simon_he/vue-tui/agent/mermaid` | Experimental | Agent namespace optional `beautiful-mermaid` bridge: adaptive `TMermaid`、`TMermaidText`、`TMermaidImage` |

The stable surface is terminal core, DOM rendering, CLI runtime, basic Vue components, markdown APIs, and the optional Mermaid bridge. High-throughput log, virtualization, and agent/console aggregation APIs stay under `/experimental` or `/agent` until their public surface settles; keep those imports isolated in application code. Use `/agent/mermaid` when agent code wants the optional Mermaid wrapper without changing the `/agent` main entrypoint.

Experimental chart components are imported from the `/experimental` entrypoint:

```ts
import {
TCandlestickChart,
TContributionGraph,
TLineChart,
TPieChart,
} from "@simon_he/vue-tui/experimental";
```

`T3DViewport` is renderer-agnostic and Pull-based. The bundled WGSL renderer is isolated in the Bun-only entrypoint so browser-safe imports do not load native GPU code:

```ts
import { T3DViewport } from "@simon_he/vue-tui/experimental";
import { createTerminalBadge3DRenderer } from "@simon_he/vue-tui/experimental/3d/bun";

const renderer = createTerminalBadge3DRenderer();
```

Install the optional `bun-webgpu` peer, then run the complete direction-E terminal badge example with `bun run run:3d:terminal`. Drag to orbit and use a two-finger trackpad gesture or mouse wheel to zoom. CLI hover steering requires `createStdinDriver({ enableMouseMotion: true })`.

#### `experimental/3d/bun` platform requirements

| Requirement | Detail |
| --------------------------- | ---------------------------------------------------- |
| Runtime | **Bun only** — Node.js and browser are not supported |
| `bun-webgpu` peer | Must be installed manually: `bun add bun-webgpu` |
| macOS x64 / arm64 | ✅ Prebuilt binary available |
| Linux x64 | ✅ Prebuilt binary available |
| Windows x64 | ✅ Prebuilt binary available |
| Linux arm64 / musl (Alpine) | ❌ No prebuilt binary — must build from source |

> `T3DViewport` itself (from `/experimental`) has zero native dependencies and works everywhere. Only `experimental/3d/bun` requires Bun and the optional peer. `bun-webgpu` is an experimental library; see [bun-webgpu](https://github.com/kommander/bun-webgpu) for current status.

#### Terminal graphics protocol requirements

`TVideo` and `T3DViewport` automatically negotiate their output format based on the detected terminal:

| Terminal capability | Output quality |
| ----------------------------------- | ---------------------------------------------- |
| kitty or iTerm2 protocol | Pixel-accurate frames (PNG) |
| No graphics protocol (any terminal) | `gray8` ASCII art — functional, lower fidelity |

`TAgentTerminalGraphic` (mermaid diagrams, KaTeX math, images) requires kitty, iTerm2, or sixel to render visually; without a protocol it shows the `fallback` text prop. Always provide a meaningful `fallback` value so non-graphical terminals still convey the content.

> sixel terminals get graphics for `TAgentTerminalGraphic` but ASCII art for `TVideo` / `T3DViewport` — only kitty and iTerm2 support pixel-accurate video and 3D frames. See [docs/platform-contracts.md](./docs/platform-contracts.md) for the full degradation table.

Do not deep import from `@simon_he/vue-tui/dist/...`; only the entry points above are part of the supported package contract.

### Migration: Node Host Adapter Moved To `/cli`

Node-specific input host defaults are no longer exported from the browser-safe root entrypoint.

Before:

```ts
import { createDefaultTInputHostAdapter, defaultTInputHostPlugin } from "@simon_he/vue-tui";
```

After:

```ts
import { createTInputHostPlugin } from "@simon_he/vue-tui";
import { createDefaultTInputHostAdapter, defaultTInputHostPlugin } from "@simon_he/vue-tui/cli";
```

### Migration: Root Entry Was Narrowed

The root entrypoint now keeps only stable browser-safe APIs. Extended Vue components and Vue router/composable helpers move to `@simon_he/vue-tui/vue`.

| Before root import | New import |
| ------------------ | ----------------------- |
| `TAnchor` | `@simon_he/vue-tui/vue` |
| `TFlow` | `@simon_he/vue-tui/vue` |
| `TInputBox` | `@simon_he/vue-tui/vue` |
| `TPathPicker` | `@simon_he/vue-tui/vue` |
| `TJsonEditor` | `@simon_he/vue-tui/vue` |
| `TRenderPlane` | `@simon_he/vue-tui/vue` |
| `TRenderLayer` | `@simon_he/vue-tui/vue` |
| `TTransition` | `@simon_he/vue-tui/vue` |
| router/composables | `@simon_he/vue-tui/vue` |
| Node host defaults | `@simon_he/vue-tui/cli` |

Before:

```ts
import { TAnchor, TFlow } from "@simon_he/vue-tui";
```

After:

```ts
import { TAnchor, TFlow } from "@simon_he/vue-tui/vue";
```

### Hyperlinks

DOM renderer link rendering is opt-in through `domRendererOptions.links`. Once enabled, DOM anchors allow safe absolute and relative targets such as `https:`, `http:`, `mailto:`, `/path`, `./path`, `../path`, `#hash`, and `?q=1`. Link callbacks preserve native browser behavior unless they return `false`.

CLI/stdout rendering uses OSC8 hyperlinks and keeps a stricter boundary: only safe absolute `https:`, `http:`, and `mailto:` hrefs are emitted by default. `file:` links stay opt-in for terminal-specific providers and lower-level `Style.href` writers.

`TLink` is the public component-level link primitive. It renders DOM-safe `Style.href` metadata for absolute `https:` / `http:` / `mailto:` and relative targets, supports focus, click, keyboard activation, and host-controlled attempted opens through `TerminalProvider.linkOpener` or `createTerminalApp({ linkOpener })`. `TLinkifyText` detects safe URLs in plain text and writes the same href metadata without owning activation. Browser `TerminalProvider` defaults to `window.open`; CLI/headless apps must opt in. `TLink` intentionally rejects `file:` URLs; use lower-level `Style.href` writers plus terminal-specific opt-in when exposing file links.

## Browser Usage

```vue

import { ref } from "vue";
import { TerminalProvider, TBox, TInput, TLink, TLinkifyText, TText } from "@simon_he/vue-tui";

const input = ref("");








```

`TerminalProvider` wires the terminal buffer, DOM renderer, event manager, scheduler, runtime, layout context, and input plugins for browser Vue apps.

## CLI Usage

For a real terminal, mount a headless Vue app and attach stdout/stdin:

```ts
import {
createStdinDriver,
createStdoutRenderer,
createTerminalApp,
installTerminalCleanup,
type TerminalCleanupHandle,
} from "@simon_he/vue-tui/cli";
import App from "./App.vue";

const app = createTerminalApp({
cols: process.stdout.columns || 80,
rows: process.stdout.rows || 24,
component: App as any,
defaultStyle: { fg: "whiteBright" },
});

app.mount();

const renderer = createStdoutRenderer(app.terminal, {
output: process.stdout,
hideCursor: true,
colorMode: "auto",
allowFileUrls: true,
});

app.scheduler.flush();

let driver: ReturnType | null = null;
let terminalCleanup: TerminalCleanupHandle | null = null;
let disposed = false;

const cleanup = () => {
if (disposed) return;
disposed = true;
terminalCleanup?.uninstall();
driver?.dispose();
renderer.dispose();
app.dispose();
};

const exit = () => {
cleanup();
process.exit(0);
};

terminalCleanup = installTerminalCleanup(cleanup, {
signalPolicy: "reraise",
cleanupOnUnhandledRejection: false,
});
driver = createStdinDriver({
dispatch(event) {
const prevented = app.events.dispatch(event);
app.scheduler.flush();
return prevented;
},
enableMouse: true,
onExit: exit,
});
```

Signal cleanup restores terminal state first. `installTerminalCleanup()` returns a cleanup handle: call `handle.uninstall()` to remove process listeners without disposing the app, or `handle.cleanup()` to run cleanup manually. By default, signal handling uses `signalPolicy: "reraise"`: the helper cleans up, removes its own listeners, and re-sends the original signal when no other listener owns that signal. If the host process has other listeners for the same signal, those listeners keep ownership of termination. Set `signalPolicy: "cleanup-only"` only when the host explicitly owns termination, or `signalPolicy: "exit"` when vue-tui should exit with the conventional signal exit code after cleanup.

Unhandled promise rejections stay host-owned by default. Setting `cleanupOnUnhandledRejection: true` cleans up and rethrows by default. Set `rethrowUnhandledRejection: false` only when the host explicitly wants to suppress the rejection.

## Core Concepts

- `createTerminal({ cols, rows })` owns the cell buffer, cursor, planes, scrollback, and commit events.
- `createDomRenderer(terminal, container)` renders terminal cells to DOM with row caching and fast paths for plain and styled rows.
- `createStdoutRenderer(terminal, options)` emits ANSI output for real terminal UIs from `/cli`.
- `TerminalProvider` is the browser-facing Vue runtime provider.
- `createTerminalApp()` is the headless runtime for CLI apps and deterministic tests.
- `TRenderPlane` separates transcript, chrome, input, and overlay surfaces so small updates do not repaint large panes.

## Components

| Area | Import | Components / APIs |
| -------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Stable layout | `@simon_he/vue-tui` | `TBox`, `TView` |
| Stable text | `@simon_he/vue-tui` | `TText`, `TLink`, `TLinkifyText` |
| Stable input | `@simon_he/vue-tui` | `TInput`, `TList`, `TSelect` |
| Stable overlay | `@simon_he/vue-tui` | `TDialog` |
| Vue extended | `@simon_he/vue-tui/vue` | `TAnchor`, `TFlex`, `TFlexItem`, `TFlow`, `TRenderPlane`, `TRenderLayer`, `TTransition`, `TInputBox`, `TPathPicker`, `TJsonEditor`, `TMultilineModal`, `TDebugOverlay`, composables, router APIs |
| Markdown | `@simon_he/vue-tui/markdown` | `TMarkdownText`, `TVirtualMarkdown` |
| Mermaid | `@simon_he/vue-tui/mermaid` | `TMermaid`(adaptive,图片→ANSI→源码)、`TMermaidText`、`TMermaidImage`、`beautifulMermaidRenderer` |
| Experimental | `@simon_he/vue-tui/experimental` | `TVideo`, `TContributionGraph`, `TLineChart`, `TCandlestickChart`, `TPieChart`, `TVirtualList`, `TTranscriptView`, `TLogView`, `TLogSearchBar`, `TLogLinksPanel`, `TLogScrollbar`, `TLogMinimap` |
| Video adapter | `@simon_he/vue-tui/experimental/video/node` | `createFfmpegVideoFrameSource`, `createYtDlpVideoFrameSource` |
| Agent console | `@simon_he/vue-tui/agent` | `TAgentTranscript`, `TToolCallView`, `TToolLogView`, `TVirtualMarkdown`, `TVirtualList`, `TRenderPlane` |
| Agent Mermaid | `@simon_he/vue-tui/agent/mermaid` | `TMermaid`(adaptive,图片→ANSI→源码)、`TMermaidText`、`TMermaidImage`、`beautifulMermaidRenderer` |
| Runtime | `@simon_he/vue-tui/runtime` | runtime, event, and selection APIs |
| CLI | `@simon_he/vue-tui/cli` | `createTerminalApp`, `createStdoutRenderer`, `createStdinDriver`, Node host adapters |

For streaming Mermaid source, pass `streaming` with `final`. When `streaming=true` and `final=false`, transient renderer errors do not replace the last successfully rendered diagram; if no diagram has rendered yet, `incompleteText` is shown until the source becomes renderable or `final=true` surfaces the final error.

This table is a category overview. The generated API reference for root, `/vue`, and `/experimental` components lives in [docs/generated/components-api.md](./docs/generated/components-api.md) for humans and [docs/generated/api-manifest.json](./docs/generated/api-manifest.json) for CI, release checks, and README/docs drift checks; the manifest also tracks package entrypoint exports.

## Documentation

| Page | Purpose |
| ------------------------------------------------------------------ | -------------------------------------------------------------------- |
| [Docs home](./docs/index.md) | Product overview and reading path |
| [Vue Terminal UI](./docs/guide/vue-terminal-ui.md) | English landing page for terminal-style Vue interfaces |
| [Vue CLI UI](./docs/guide/vue-cli-ui.md) | CLI app model with Vue component composition |
| [CLI stdout renderer](./docs/guide/cli-stdout-renderer.md) | Stdout renderer, stdin driver, cleanup, and terminal output |
| [Terminal log viewer](./docs/guide/terminal-log-viewer.md) | Append-only logs, retained windows, wrapping, links, and search |
| [Markdown transcripts](./docs/guide/markdown-transcript.md) | Static and streaming markdown transcript rendering |
| [Examples index](./docs/examples.md) | Browser, terminal, and smoke example commands |
| [Core API](./docs/api.md) | Terminal, renderer, events, runtime, planes, and scheduler contracts |
| [Terminal UI best practices](./docs/terminal-ui-best-practices.md) | Cell layout, input focus, render invalidation, transcripts, tests |
| [Performance](./docs/performance.md) | Practical performance guidance |
| [Benchmarks](./docs/benchmarks.md) | Release benchmark budgets, sample results, and comparison boundaries |
| [OpenTUI Solid comparison](./docs/compare-opentui-solid.md) | Same-scenario comparison protocol and public claim boundaries |
| [High-throughput rendering](./docs/high-throughput-rendering.md) | Scheduler, dirty rows, mailbox, log, and renderer architecture |
| [Component acceptance](./docs/components-acceptance.md) | Release readiness checks for component API and behavior |
| [Agent Console](./docs/agent-console.md) | Streaming transcript example stack |
| [Release candidate](./docs/release-candidate.md) | 1.0 RC validation, package export checks, and migration notes |
| [Security policy](./SECURITY.md) | Vulnerability reporting and terminal permission boundaries |

Run the docs locally:

```bash
pnpm run docs:dev
pnpm run docs:build
```

## Examples

```bash
pnpm -C examples/basic dev
pnpm run build:examples
pnpm run build:examples:terminal
pnpm run run:basic:terminal
pnpm run run:agent-console:terminal
pnpm run example:tlog-view-lab
pnpm run example:agent-console
pnpm run example:agent-console:smoke
pnpm run example:agent-console:terminal:smoke
```

The smoke commands are deterministic and avoid real LLM APIs, real TTY dependencies, and timing-only pass/fail gates.

## Performance Notes

- Use `TVirtualList` instead of rendering thousands of row components.
- Use `TLogView` with `createAppendOnlyLogStore({ maxLines })` for retained streaming logs.
- Provide stable line keys for custom `TLogView` sources; mutable rows should change keys or call the explicit invalidation APIs.
- Split high-volume content and frequently changing chrome into different `TRenderPlane`s.
- Style objects are treated as immutable. Reuse stable style objects on hot paths, but pass a new object when a style changes.

Useful checks:

```bash
pnpm run bench:dom-renderer
pnpm run bench:scroll-mailbox
pnpm run bench:phase2
```

## Issues And Feedback

- Report bugs: [new bug report](https://github.com/Simon-He95/vue-tui/issues/new?template=bug_report.yml)
- Request features: [new feature request](https://github.com/Simon-He95/vue-tui/issues/new?template=feature_request.yml)
- Report documentation issues: [new docs issue](https://github.com/Simon-He95/vue-tui/issues/new?template=docs.yml)
- Report vulnerabilities privately: [Security policy](./SECURITY.md)
- Browse existing issues: [GitHub issues](https://github.com/Simon-He95/vue-tui/issues)

For renderer, scheduler, or terminal behavior bugs, include the renderer target (`DOM`, `stdout`, or headless), the relevant command, and a minimal reproduction when possible.

## Development

Use Node.js 20 for repository development, release validation, and documentation builds. This is a toolchain requirement, not the runtime requirement for the published package.

```bash
pnpm install
pnpm run format:check
pnpm run lint
pnpm run typecheck
pnpm run test
pnpm run build
```

Release validation:

```bash
pnpm run release:dry-run
```

`release:dry-run` runs checks, tests, docs build, benchmarks, examples smoke, and packed package install smoke.
`release:ci` aliases `release:dry-run` for validation-only CI usage. The GitHub Release workflow is preferred because it publishes the already-verified tarball with npm provenance. If workflow token/provenance is unavailable, `release:local:dry-run` and `release:local` publish the locally verified tarball with the `rc` dist-tag. `release` and `release:workflow-only` intentionally fail to avoid accidental direct publishing.

## Package Notes

- The published package ships `dist` only.
- Root, core, runtime, DOM renderer, observability, Vue, CLI, markdown, experimental, and agent entrypoints are available as ESM, CJS, and type declarations after build.
- The Mermaid bridge entrypoints ship ESM, CJS, and type declarations.
- The root browser/core API does not require a Node runtime, but CLI usage expects a Node-like stdout/stdin environment.
- Terminal emoji and East Asian width behavior still depends on the user terminal and font.

## License

[MIT](./license)