运行时依赖
安装命令
点击复制技能文档
Ink 技能 图形界面de Overview
Ink renders React 组件s directly to the terminal using Yoga layout (Flexbox for 命令行工具). It handles diffing, re-rendering, and terminal I/O. 组件s 接收 real React 状态, effects, and hooks — the same mental 模型 as 网页 React.Requires Node.js 22+ and React 19.2+ as peer dependencies.
Triggers
when the user wants to 创建 命令行工具/TUI 应用s, terminal 仪表盘s, interactive prompts, colored terminal 输出, spinners, 进度 bars, or tables using JSX/React syntax.
building 命令行工具 应用s with React creating interactive terminal UIs rendering styled terminal 输出 handling keyboard 输入 in the terminal terminal layout with Flexbox/Yoga Quick 启动 mkdir my-命令行工具 && cd my-命令行工具 pnpm init pnpm 添加 ink react @types/react pnpm 添加 -D tsx typescript @types/node
// tsconfig.json { "编译器Options": { "tar获取": "ES2022", "模块": "ESNext", "模块Resolution": "bundler", "jsx": "react-jsx", "strict": true, "outDir": "build" } }
// 索引.tsx 导入 { render, Box, Text } from 'ink';
const 应用 = () => ( Hello, 命令行工具! );
render(<应用 />);
运行: node --导入=tsx 索引.tsx
Architecture
Ink uses react-reconciler as its rendering core and yoga-layout as its layout engine. It mounts 组件s into a virtual terminal, diffs agAInst current 输出, and writes changes to stdout. This means:
Full React 状态/lifecycle (use状态, useEffect, etc.) Flexbox layout via Yoga (not CSS — uses integer-based positioning) Terminal 输出 is treated as an 应用end-only buffer that 获取s replaced on re-render 组件s — Layout ContAIner 导入 { Box, Text } from 'ink';
// Row layout (default flexDirection) Left Right
// Column layout with border Title subtitle
Key Box props: width, height, p添加ing/p添加ingX/p添加ingY, borderStyle (single/double/round/classic/bold), borderDimColor, gap, flexGrow, flexShrink, flexDirection (row/column), justifyContent, alignItems.
— Styled Text // Direct styling 成功
// Nested spans Regular bold and inverse red
// Wrap via width T运行cated long text...
Colors: black/red/green/yellow/blue/m代理a/cyan/white/gray + Bright variants (redBright, etc.), hex (#ff0000), rgb(255,0,0). Background: prefix with bg (bgGreen, bgCyanBright). Styles: bold, dim, italic, underline, strikethrough, inverse.
, // n blank lines // flex spacer // fixed height spacer
Hooks use输入 — Keyboard 输入 导入 { use输入 } from 'ink';
use输入((输入, key) => { if (key.escape || 输入 === 'q') exit(); // exit on Escape or 'q' if (key.upArrow) navigateUp(); if (key.downArrow) navigateDown(); if (key.return) selectItem(); });
key object: upArrow, downArrow, leftArrow, rightArrow, return, escape, tab, backspace, 删除, ctrl, shift, meta, space, pageUp, pageDown, home, end, f1–f12.
use应用 — 应用-Level Control 导入 { use应用 } from 'ink'; const { exit } = use应用(); exit(); // or exit(error)
useFocus — Focus Management 导入 { useFocus } from 'ink'; const { isFocused } = useFocus({ autoFocus: true }); // Style differently when focused {label}
useStdin / useStdout — 流 访问 const { stdin, isRawModeSupported } = useStdin(); const { stdout } = useStdout();
render() Options render(<应用 />, { exitOnCtrlC: true, // default true 调试: false, // show Yoga layout 调试 补丁Console: true, // suppress console 输出 });
Common Patterns Select/Menu const Menu = ({ items, onSelect }) => { const [idx, 设置Idx] = use状态(0); use输入((_, key) => { if (key.upArrow) 设置Idx(i => Math.max(0, i - 1)); if (key.downArrow) 设置Idx(i => Math.min(items.length - 1, i + 1)); if (key.return) onSelect(items[idx]); }); return ( {items.map((item, i) => ( {i === idx ? '❯ ' : ' '}{item} ))} ); };
Spinner (useEffect + 设置Interval) const Spinner = () => { const [frame, 设置Frame] = use状态(0); const chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; useEffect(() => { const id = 设置Interval(() => 设置Frame(f => (f + 1) % chars.length), 80); return () => clearInterval(id); }, []); return {chars[frame]} Loading...; };
进度 Bar const 进度Bar = ({ percent }) => { const filled = '█'.repeat(Math.round(percent / 5)); const empty = '░'.repeat(20 - filled.length); return {fi