npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@m4ike1/ion-tui

v0.1.1

Published

Terminal User Interface library with differential rendering for efficient text-based applications

Readme

@m4ike1/ion-tui

Terminal UI library with differential rendering for interactive CLI applications. Renders a tree of components to the terminal, updating only changed lines for flicker-free output.

Install

Part of the ion monorepo. From the repo root:

npm install

Import from the package entrypoint:

import { TuiMainScreen, Text, type TUI } from "@m4ike1/ion-tui";

Requires Node >= 22.19.

Quick start

import { type TUI, Text, Editor, ProcessTerminal, TuiMainScreen, matchesKey } from "@m4ike1/ion-tui";

const terminal = new ProcessTerminal();
const tui: TUI = new TuiMainScreen(terminal);

tui.addChild(new Text("Welcome to my app!"));

const editor = new Editor(tui, { borderColor: (s) => s, selectList: { /* ... */ } });
editor.onSubmit = (text) => {
  tui.addChild(new Text(`You said: ${text}`));
};
tui.addChild(editor);
tui.setFocus(editor);

// In raw mode Ctrl+C does not send SIGINT; handle exit explicitly.
tui.addInputListener((data) => {
  if (matchesKey(data, "ctrl+c")) {
    tui.stop();
    process.exit(0);
  }
  return undefined;
});

tui.start();

See test/chat-simple.ts for a complete example (run with npx tsx test/chat-simple.ts).

Choosing a renderer

TUI is the shared interface for component management, focus, overlays, input, lifecycle, and rendering. Pick a concrete renderer at construction:

  • TuiMainScreen(terminal, showHardwareCursor?, logDirectory?) renders into the main buffer and preserves terminal scrollback.
  • TuiAltScreen(terminal, showHardwareCursor?, logDirectory?, options?: TuiAltScreenOptions) renders a fixed-height viewport in the alternate buffer with application-owned scrolling. On stop() it restores the main buffer and prints the final document.

Use isViewportTUI(tui) to narrow to ViewportTUI before calling setLayoutRoot(). VStack, HStack, and ScrollView layout semantics apply to the alternate-screen viewport; on TuiMainScreen the terminal owns scrollback. See docs/explanation.md.

Components

| Component | Purpose | |---|---| | Container | Groups children (addChild, removeChild, clear) | | Box | Container with padding and background function | | Text / TruncatedText | Wrapped multi-line text / single truncated line | | Input | Single-line input with history, undo, kill ring | | Editor | Multi-line editor with autocomplete and paste handling | | Markdown | Markdown rendering with theme and LaTeX option | | Loader / CancellableLoader | Animated spinner / abortable spinner (signal, onAbort) | | SelectList | Keyboard-navigable option list with filtering | | SettingsList | Settings rows with value cycling and submenus | | ScrollView | Scrollable region for alt-screen layouts | | VStack / HStack | Constrained flex layout for alt-screen layouts | | VirtualList | Windowed per-message cache for large transcripts | | Image | Inline image (Kitty / iTerm2 protocols, text fallback) | | MouseRegion | Adds mouse handling without changing rendering | | Spacer | Vertical spacing |

Full constructor and option details: docs/reference.md.

Input

Detect keys with matchesKey() and the Key helper (Kitty keyboard protocol aware):

import { matchesKey, Key } from "@m4ike1/ion-tui";

if (matchesKey(data, Key.ctrl("c"))) process.exit(0);
else if (matchesKey(data, Key.enter)) submit();
else if (matchesKey(data, Key.escape)) cancel();

String identifiers ("enter", "ctrl+c", "shift+tab") also work. Default bindings for editor and alt-screen actions live in TUI_KEYBINDINGS and are customizable via KeybindingsManager and setKeybindings(). TuiAltScreen normalizes SGR mouse input into TuiMouseEvent; TuiMainScreen does not capture mouse input.

Custom components

Every line returned by render(width) must fit within width; the TUI errors otherwise. Use truncateToWidth(), wrapTextWithAnsi(), and visibleWidth() from the package. Cache rendered output and clear it in invalidate(). Components showing a text cursor implement Focusable and emit CURSOR_MARKER at the cursor position; containers with an embedded Input/Editor must propagate focused to the child for correct IME candidate-window placement. Full contract: docs/reference.md; recipes: docs/how-to.md.

Testing

There is no VirtualTerminal export in the public API. Tests in this package use the in-repo helper test/virtual-terminal.ts (backed by @xterm/headless) with TuiMainScreen / TuiAltScreen. Package tests run with node --test (see package.json); run the suite via ./test.sh from the repo root.

Debug

  • ION_TUI_WRITE_LOG=/tmp/tui-ansi.log captures the raw ANSI stream written to stdout.
  • ION_TUI_ESC_TIMEOUT overrides the lone-Escape reassembly timeout in milliseconds (higher on SSH transports by default).

Further docs

  • docs/reference.md — complete public API reference.
  • docs/how-to.md — task recipes (layouts, overlays, custom components, keybindings, testing).
  • docs/explanation.md — rendering model and architecture concepts.