Skip to content

SilveryReact for modern terminal apps

Powerful apps. Polished UIs. Proudly terminal.

silvery-agent — ~/silvery
╭─ User ─────────────────────────────────────────────────────╮
 add a blinking cursor after the tagline                    
╰────────────────────────────────────────────────────────────╯

 Read .vitepress/theme/custom.css
   found .VPHero .tagline selector at line 148

 Edit .vitepress/theme/custom.css
  + tagline::after blink animation (1Hz steps(1))
   applied · 12 insertions · 0 deletions

╭─ Assistant ────────────────────────────────────────────────╮
 Blink lands at end of tagline.                             
 One cursor per page · matches the design doc.              
╰────────────────────────────────────────────────────────────╯

╭─ Input ────────────────────────────────────────────────────╮
                                                          
╰────────────────────────────────────────────────────────────╯

Why Silvery?

Silvery grew out of building a complex terminal app — a multi-pane workspace with thousands of nodes. Components needed to know their size during render. Updates needed to be fast. Scroll containers, mouse events, focus scopes, and Playwright-style testing needed to just work. What started as a renderer grew into a layout engine, then 45+ components, theming, testing infrastructure, and eventually a framework.

Along the way, three principles emerged. Take the best from the web, stay true to the terminal, and raise the bar for developer ergonomics, architecture composability, and performance.

The Silvery Way · Silvery vs Ink · About

Quick Start

console
$ npm install silvery react
console
$ bun add silvery react
console
$ pnpm add silvery react
console
$ yarn add silvery react
tsx
import { useState } from "react"
import { render, Box, Text, useInput } from "silvery"

function Counter() {
  const [count, setCount] = useState(0)
  useInput((input) => {
    if (input === "j") setCount((c) => c + 1)
  })
  return (
    <Box borderStyle="round" padding={1}>
      <Text>Count: {count}</Text>
    </Box>
  )
}

await render(<Counter />).run()

→ Continue with the Getting Started guide

Build Any Terminal App

Try the interactive examples:

console
$ npx @silvery/examples
console
$ bunx @silvery/examples
console
$ pnpm dlx @silvery/examples
console
$ vp @silvery/examples

Packages

PackageDescription
silveryComponents, hooks, renderer — the one package you need
@silvery/ink / @silvery/chalkInk compatibility — 99% of Ink 7.0 tests, 100% of Chalk tests
@silvery/testPlaywright-style testing — locators, press(), buffer assertions
@silvery/createComposable app builder — pipe() providers (under active development)
@silvery/theme84 color schemes, semantic tokens ($primary, $muted), auto-detect
@silvery/commanderBeautiful CLIs for free — help renders through Silvery itself
@silvery/headlessPure state machines — portable, embeddable, no React
@silvery/ansiTerminal primitives — styling, SGR, truecolor, detection

Ecosystem

Standalone projects Silvery builds on — each stands on its own:

  • Flexily — pure JS flexbox layout engine (Yoga-compatible, 2.5× faster, zero WASM)
  • Termless — headless terminal testing, like Playwright for terminal apps
  • terminfo.dev — terminal feature compatibility database (161 features, 19 terminals)
  • Loggily — structured logging + tracing + metrics in one library

Coming

  • Pretext — rich text layout with word-wrap, hyphenation, and proportional fonts (via Flexily integration)
  • Renderers — Canvas 2D, Web DOM (experimental today, production later)
  • Frameworks — Svelte, Solid.js, Vue adapters
  • @silvery/create — structured state management with commands, keybindings, effects-as-data