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

ink-terminal

v0.1.0-alpha.1

Published

High-performance React terminal renderer with double-buffering, Yoga layout, and streaming markdown — extracted from Claude Code

Readme

ink-terminal

高性能 React 终端渲染引擎,内含 27 项渲染优化技术。

Claude Code 内部渲染引擎提取而来。提供完整的 React 终端 UI 框架,包含双缓冲、硬件滚动、损伤追踪差分、原子输出 —— 对应用层完全透明。

English Documentation


核心特性

  • 60fps 节流渲染lodash.throttle + queueMicrotask,高频状态更新自动合并
  • 双缓冲 — frontFrame/backFrame 交换,每帧零内存分配
  • Blit 快速路径 — 未变化的子树通过 TypedArray.set() 批量复制 (memcpy 级别)
  • 打包 Int32Array 屏幕缓冲区 — 每个 cell 2 words,CharPool/StylePool 池化
  • 损伤追踪差分 — 只扫描变化的屏幕区域,而非整个缓冲区
  • DECSTBM 硬件滚动 — 终端侧行移位,只绘制新增行
  • BSU/ESU 原子输出 — DEC 2026 同步更新,消除画面撕裂
  • 增量 Markdown — O(delta) 解析 + Token LRU 缓存 (配合 StreamingMarkdown 使用)
  • 虚拟滚动 — 1000+ 消息只渲染可视区域
  • 纯 TypeScript Yoga 布局 — Flexbox 布局,零 native/WASM 依赖
  • 完整事件系统 — 键盘、鼠标点击、焦点、粘贴、窗口大小变化
  • React 19 + 自定义 Reconciler — 终端中使用完整 React 组件模型

架构

ink-terminal/
├── core/          # 第 1 层: 屏幕缓冲区, Diff, 终端 I/O (无 React 依赖)
├── react/         # 第 2 层: React reconciler, 组件, Hooks
├── events/        # 事件系统 (输入, 点击, 焦点, 键盘, 粘贴, 窗口变化)
├── termio/        # 终端 I/O 原语 (ANSI, CSI, DEC, ESC, OSC, SGR)
├── layout/        # Flexbox 布局引擎 (纯 TS Yoga 实现)
├── providers/     # 插件/回调接口,用于应用层集成
└── internal/      # 内置工具 (intl, stringWidth, sliceAnsi)

三层架构

| 层级 | 目录 | 需要 React | 用途 | |------|------|-----------|------| | Core | core/ | 否 | 屏幕缓冲区、差分引擎、终端能力检测 | | React | react/ | 是 | Reconciler、组件、Hooks、Ink 主类 | | 应用层 | (你的项目) | 是 | 主题、Markdown、消息列表、REPL |

安装

bun add ink-terminal react react-reconciler

快速开始

最小示例 (5 行核心代码)

import { render, Box, Text } from 'ink-terminal'

const App = () => (
  <Box flexDirection="column" padding={1}>
    <Text bold color="green">Hello Terminal!</Text>
    <Text>60fps 双缓冲渲染管线。</Text>
  </Box>
)

await render(<App />)

流式 Agent 输出

import { render, Box, Text, ScrollBox } from 'ink-terminal'
import { useState, useEffect } from 'react'

function AgentUI() {
  const [text, setText] = useState('')

  useEffect(() => {
    ;(async () => {
      for await (const chunk of myAgent.stream('hello')) {
        setText(t => t + chunk) // 自动 60fps 节流 + 双缓冲 + blit
      }
    })()
  }, [])

  return (
    <Box flexDirection="column">
      <ScrollBox overflow="scroll" stickyScroll>
        <Text>{text}</Text>
      </ScrollBox>
    </Box>
  )
}

await render(<AgentUI />)

仅这 5 行核心代码,你的输出就已获得:

  • 60fps 节流渲染(不会因 token 频率过高而卡死终端)
  • 双缓冲 + blit(只重绘变化的 cells)
  • 损伤追踪(只 diff 变化区域)
  • BSU/ESU 原子输出(无撕裂)

交互式应用

import {
  render, Box, Text, ScrollBox,
  AlternateScreen, useInput, useApp
} from 'ink-terminal'

function App({ messages }) {
  const { exit } = useApp()
  useInput((input, key) => {
    if (key.escape) exit()
  })

  return (
    <AlternateScreen>
      <Box flexDirection="column" height="100%">
        <Box borderStyle="single" paddingX={1}>
          <Text bold>My Agent</Text>
        </Box>
        <ScrollBox overflow="scroll" stickyScroll flexGrow={1}>
          {messages.map(m => (
            <Box key={m.id} paddingX={1}>
              <Text>{m.content}</Text>
            </Box>
          ))}
        </ScrollBox>
      </Box>
    </AlternateScreen>
  )
}

仅使用 Core 层 (无 React)

import {
  createScreen, CharPool, StylePool, HyperlinkPool,
  diffEach, blitRegion
} from 'ink-terminal/core'

// 创建双缓冲
const pools = { style: new StylePool(), char: new CharPool(), hyperlink: new HyperlinkPool() }
const screen1 = createScreen(80, 24, pools.style, pools.char, pools.hyperlink)
const screen2 = createScreen(80, 24, pools.style, pools.char, pools.hyperlink)

// 写入 cells, 差分, 输出
diffEach(screen1, screen2, (x, y, removed, added) => {
  // 处理 cell 变化
})

配置

通过 configure() 注入应用特定的回调。所有回调都在冷路径(日志、生命周期)—— 热渲染路径零外部调用。

import { configure } from 'ink-terminal'

configure({
  logForDebugging: (msg) => console.debug(`[ink] ${msg}`),
  logError: (msg) => console.error(`[ink] ${msg}`),
  terminalName: 'my-app',
  onBeforeRender: () => { /* 刷新交互指标 */ },
  onScrollActivity: () => { /* 标记滚动活动 */ },
  onInteraction: () => { /* 更新交互时间戳 */ },
  onFirstInput: () => { /* 停止捕获早期输入 */ },
  isMouseClicksDisabled: () => false,
  isEnvTruthy: (v) => v === '1' || v === 'true',
})

组件一览

| 组件 | 说明 | |------|------| | Box | Flexbox 容器(方向、内边距、外边距、边框) | | Text | 带样式的终端文本(粗体、斜体、颜色、下划线) | | ScrollBox | 可滚动容器,支持硬件滚动 (DECSTBM) | | AlternateScreen | 全屏备用缓冲区模式 | | Button | 支持焦点的交互按钮 | | Link | 可点击超链接 (OSC 8) | | Newline | 换行符 | | Spacer | Flex 空间填充 | | NoSelect | 不可选择区域 | | RawAnsi | 原始 ANSI 转义码直通 | | Ansi | 解析后的 ANSI 文本 |

Hooks 一览

| Hook | 说明 | |------|------| | useInput(handler) | 键盘/鼠标输入处理 | | useApp() | 访问应用实例(退出等) | | useStdin() | 原始 stdin 访问 | | useAnimationFrame(cb) | 帧同步动画回调 | | useInterval(cb, ms) | 定时器 | | useSelection() | 文本选择状态 | | useTabStatus() | 终端标签页状态栏 | | useTerminalFocus() | 终端焦点/失焦事件 | | useTerminalTitle(title) | 设置终端标题 | | useTerminalViewport() | 获取终端尺寸 |

子路径导出

import { ... } from 'ink-terminal'          // 完整 API
import { ... } from 'ink-terminal/core'     // 屏幕缓冲区, diff (无 React)
import { ... } from 'ink-terminal/react'    // React 组件, hooks, reconciler
import { ... } from 'ink-terminal/events'   // 事件类
import { ... } from 'ink-terminal/termio'   // 终端转义序列
import { ... } from 'ink-terminal/layout'   // Yoga 布局引擎

渲染管线

React setState
    │
    ▼
scheduleRender (lodash.throttle 16ms, leading+trailing)
    │
    ▼
queueMicrotask (延迟到 useLayoutEffect 之后)
    │
    ▼
onRender()
    ├── Yoga 布局计算
    ├── DFS 树遍历 → 屏幕缓冲区
    │   ├── Blit 快速路径 (clean 节点 → TypedArray memcpy)
    │   └── Dirty 节点 → 重渲染到 cells
    ├── Diff (损伤追踪, 每 cell 2 个 int 比较)
    ├── 优化 patches (合并光标移动, 去重超链接)
    └── 写入终端 (BSU → ANSI 转义码 → ESU)

27 项优化技术总览

| # | 层级 | 优化 | 核心原理 | |---|------|------|----------| | 1 | React | 60fps 节流渲染 | lodash throttle + queueMicrotask | | 2 | React | 双缓冲 | frontFrame/backFrame 交换 | | 3 | 树遍历 | Blit 快速路径 | clean 节点 TypedArray memcpy | | 4 | 树遍历 | 脏标记传播 | shallowEqual 守卫 + 祖先链 | | 5 | 缓冲区 | 打包 Int32Array | 每 cell 2 words | | 6 | 缓冲区 | CharPool ASCII 快速路径 | Int32Array 直接索引 | | 7 | 缓冲区 | StylePool 转换缓存 | 预序列化 ANSI diff | | 8 | Diff | 损伤矩形追踪 | 只 diff 变化区域 | | 9 | Diff | findNextDiff | 2 个 int 比较/cell, JIT 内联 | | 10 | Diff | visibleCellAtIndex | 跳过不可见空格 | | 11 | 终端 | DECSTBM 硬件滚动 | CSI 滚动区域 | | 12 | 终端 | BSU/ESU 原子写入 | DEC 2026 | | 13 | 终端 | Patch 优化器 | 合并光标移动/去重超链接 | | 14 | 输出 | charCache 跨帧持久化 | 16384 上限 | | 15 | Markdown | 流式增量解析 | stable/unstable 分割 | | 16 | Markdown | Token LRU 缓存 | 500 条, hash 键控 | | 17 | 虚拟滚动 | scrollTop 量化 | 40 行 bin | | 18 | 虚拟滚动 | Slide cap | 每 commit 最多挂载 25 项 | | 19 | 虚拟滚动 | useDeferredValue 时间切片 | React 并发特性 | | 20 | 虚拟滚动 | Resize 高度缩放 | 非清除 | | 21 | 滚动 | 自适应消耗 | xterm.js <=5 即时, >5 步进 | | 22 | 滚动 | 比例消耗 | 原生终端, 3/4 剩余量 | | 23 | 内存 | 池定期重置 | 每 5 分钟 CharPool+HyperlinkPool | | 24 | 渲染器 | Output 复用 | charCache 跨帧持久化 | | 25 | 渲染器 | 毒化检测 | prevScreen/absoluteRemoved | | 26 | 监控 | 分阶段帧计时 | renderer/diff/optimize/write/yoga | | 27 | 监控 | FPS P99 追踪 | 最坏 1% 帧 |

与原版 Ink 对比

| 特性 | 原版 Ink | ink-terminal | |------|---------|--------------| | 屏幕缓冲区 | 每帧字符串拼接 | 打包 Int32Array + CharPool/StylePool | | Diff 算法 | 逐行字符串比较 | 逐 Cell 整数比较 + 损伤追踪 | | 滚动 | 全量重绘 | DECSTBM 硬件滚动 + blit+shift | | 原子输出 | 无 | BSU/ESU (DEC 2026) | | 字符宽度 | 基础 | Unicode Grapheme Segmenter + bidi | | 布局引擎 | Yoga WASM | 纯 TS Yoga (零安装成本) | | 虚拟滚动 | 无 | 内置 (量化/slide cap/deferred) | | 帧性能 | 无监控 | 分阶段计时 + FPS P99 | | 组件数量 | ~10 | 50+ | | 事件系统 | 基础 keyboard | keyboard + click + focus + paste + resize |

Agent 集成指南

集成深度选择

| 需求 | 推荐方式 | 代码量 | 获得的优化 | |------|----------|--------|-----------| | 只显示流式文本 | setText(t => t + chunk) | 5 行 | 60fps + 双缓冲 + blit + BSU/ESU | | 显示工具调用和结果 | Message 协议 + 事件分发 | 50 行 | 上述 + 工具渲染 + 进度显示 | | 完整交互式终端 | REPL 级别消息循环 | 200 行 | 上述 + 虚拟滚动 + 输入处理 |

数据流

Agent 事件 → React setState → 自动渲染管线
    │                              │
    ▼                              ▼
text_delta → setText(t + d)    Ink 60fps 节流 → Yoga → Screen → Diff → Terminal
tool_use   → setTools([...])   (对 agent 完全透明)
message    → setMessages([...])

详细的集成文档见 docs/ink-terminal-agent-integration-guide.md

项目统计

  • 113 个 TypeScript 文件22,430 行代码
  • 27 项渲染优化技术
  • 0 个 TypeScript 错误 (tsc --noEmit)
  • 纯 TypeScript Yoga 布局引擎 (~2,578 行,无 WASM/native addon)
  • 18 个 npm 依赖,2 个 peer 依赖 (react, react-reconciler)

参考文档

| 文档 | 说明 | |------|------| | docs/terminal-rendering-guide.md | 渲染优化技术详解 (8 章节, 40+ 行号引用) | | docs/terminal-rendering-exploration-report.md | 完整探索过程记录 | | docs/ink-terminal-extraction-plan.md | 提取方案设计 (三层架构, 72 文件清单) | | docs/ink-terminal-agent-integration-guide.md | Agent 适配指南 (3 种集成模式) | | docs/ink-terminal-rust-integration.md | Rust 项目集成方案 (3 种方案对比) |

许可证

本项目包含从 Anthropic 的 Claude Code 提取的代码。许可条款请参阅原始项目。