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

@ismail-elkorchi/terminal-ui

v0.1.5

Published

Typed terminal UI framework for prompts, full-screen apps, accessible components, deterministic rendering, and testing.

Readme

@ismail-elkorchi/terminal-ui

Build typed prompts and full-screen terminal applications from the same component, layout, input, accessibility, and testing foundations.

terminal-ui is ESM-only, has no runtime dependencies, and supports Node >=24, current Deno and Bun, and memory-backed tests.

The 0.1.x line is a development release. Public declarations are marked stable, beta, or experimental in the generated API reference. Terminal graphics remain experimental pending physical-terminal compatibility evidence.

Install

Node:

npm install @ismail-elkorchi/terminal-ui

Bun:

bun add @ismail-elkorchi/terminal-ui

Deno:

deno add jsr:@ismail-elkorchi/terminal-ui

Use the root entrypoint for ordinary applications. Focused entrypoints such as /prompts, /testing, /theme, and /component keep specialized APIs discoverable without requiring private imports.

Run a Prompt

import { input, runPrompt } from '@ismail-elkorchi/terminal-ui/prompts';

const result = await runPrompt(input({
  label: 'Project name',
  required: true
}));

if (result.status === 'submitted') {
  console.log(result.value);
} else {
  console.error(`Prompt ${result.reason}`);
}

Cancellation, validation failure, timeout, non-TTY denial, and host failure are typed results rather than ordinary control-flow exceptions.

Build a TUI

Applications own state. Components render that state and emit typed messages; update() is the only place that changes it.

import {
  button,
  column,
  defineTui,
  runTui,
  text
} from '@ismail-elkorchi/terminal-ui';

interface State {
  readonly count: number;
}

type Message =
  | { readonly kind: 'increment' }
  | { readonly kind: 'quit' };

const app = defineTui<State, Message>({
  id: 'counter',
  init: () => ({ state: { count: 0 } }),
  update: (state, message) => {
    if (message.kind === 'quit') {
      return { state, exit: { reason: 'quit' } };
    }
    return { state: { count: state.count + 1 } };
  },
  view: (state) => column([
    text({ content: `Count: ${String(state.count)}` }),
    button({
      id: 'increment',
      label: 'Increment',
      onPress: (): Message => ({ kind: 'increment' })
    }),
    button({
      id: 'quit',
      label: 'Quit',
      onPress: (): Message => ({ kind: 'quit' })
    })
  ])
});

const exit = await runTui(app);
if (exit.status === 'interrupted') {
  console.error('The terminal session was interrupted.');
}

Save this as counter.ts and run it with node counter.ts, deno run counter.ts, or bun counter.ts. Use Tab and Shift+Tab to move focus and Enter to activate a button.

runTui() resolves for application completion, cancellation, and host interruption. Operational failures reject with TuiRunError, whose exit contains diagnostics and the final accessible snapshot.

Compose the Interface

  • Layout factories such as column(), row(), grid(), surface(), and viewport() own geometry.
  • Components own interaction and accessibility while application state remains controlled by the caller.
  • The behavior namespace provides pure reducers, retained collections, and indexes for editing, keyboard and pointer text selection, paste, navigation, scrolling, and large data.
  • Semantic themes adapt to terminal color capabilities; top-level component styles provide typed local anatomy and state overrides.
  • Effects and subscriptions perform asynchronous work outside the serialized state transition.

Start with Building terminal apps, then use the component catalog, layout guide, and theme guide as the application grows.

Test Without a Terminal

import { text } from '@ismail-elkorchi/terminal-ui';
import { renderElementSnapshot } from '@ismail-elkorchi/terminal-ui/testing';

const snapshot = renderElementSnapshot({
  element: text({ content: 'Ready' }),
  terminalSize: { columns: 20, rows: 2 }
});

if (!snapshot.plainTextFrame.includes('Ready')) {
  throw new Error('Expected rendered text.');
}

The testing entrypoint also provides controlled clocks, input and resize scripts, frames, diffs, accessibility snapshots, transcripts, and PTY-style harnesses.

Documentation

Runnable applications are in examples. Reusable component authors can continue with Component definitions.

terminal-ui owns terminal interaction. Argument parsing, command trees, configuration, application persistence, networking, and plug-in semantics remain application concerns.