/install ink-tui
Ink Skill Guide
Overview
Ink renders React components directly to the terminal using Yoga layout (Flexbox for CLI). It handles diffing, re-rendering, and terminal I/O. Components receive real React state, effects, and hooks — the same mental model as web React.Requires Node.js 22+ and React 19.2+ as peer dependencies.
Triggers
when the user wants to create CLI/TUI apps, terminal dashboards, interactive prompts, colored terminal output, spinners, progress bars, or tables using JSX/React syntax.
- building CLI apps with React
- creating interactive terminal UIs
- rendering styled terminal output
- handling keyboard input in the terminal
- terminal layout with Flexbox/Yoga
Quick Start
mkdir my-cli && cd my-cli
pnpm init
pnpm add ink react @types/react
pnpm add -D tsx typescript @types/node
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"outDir": "build"
}
}
// index.tsx
import { render, Box, Text } from 'ink';
const App = () => (
\x3CBox flexDirection="column">
\x3CText color="green" bold>Hello, CLI!\x3C/Text>
\x3C/Box>
);
render(\x3CApp />);
Run: node --import=tsx index.tsx
Architecture
Ink uses react-reconciler as its rendering core and yoga-layout as its layout engine. It mounts components into a virtual terminal, diffs against current output, and writes changes to stdout. This means:
- Full React state/lifecycle (useState, useEffect, etc.)
- Flexbox layout via Yoga (not CSS — uses integer-based positioning)
- Terminal output is treated as an append-only buffer that gets replaced on re-render
Components
\x3CBox> — Layout Container
import { Box, Text } from 'ink';
// Row layout (default flexDirection)
\x3CBox gap={2}>
\x3CText>Left\x3C/Text>
\x3CText>Right\x3C/Text>
\x3C/Box>
// Column layout with border
\x3CBox flexDirection="column" borderStyle="round" padding={1} width={40}>
\x3CText bold>Title\x3C/Text>
\x3CText dim>subtitle\x3C/Text>
\x3C/Box>
Key Box props: width, height, padding/paddingX/paddingY, borderStyle (single/double/round/classic/bold), borderDimColor, gap, flexGrow, flexShrink, flexDirection (row/column), justifyContent, alignItems.
\x3CText> — Styled Text
// Direct styling
\x3CText color="green" bold underline>Success\x3C/Text>
// Nested spans
\x3CText>
Regular \x3CText bold>bold\x3C/Text> and \x3CText color="red" inverse>inverse red\x3C/Text>
\x3C/Text>
// Wrap via width
\x3CText width={40} wrap="truncate">Truncated long text...\x3C/Text>
Colors: black/red/green/yellow/blue/magenta/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.
\x3CNewline>, \x3CSpacer>
\x3CNewline count={2} /> // n blank lines
\x3CSpacer /> // flex spacer
\x3CSpacer height={3} /> // fixed height spacer
Hooks
useInput — Keyboard Input
import { useInput } from 'ink';
useInput((input, key) => {
if (key.escape || input === '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, delete, ctrl, shift, meta, space, pageUp, pageDown, home, end, f1–f12.
useApp — App-Level Control
import { useApp } from 'ink';
const { exit } = useApp();
exit(); // or exit(error)
useFocus — Focus Management
import { useFocus } from 'ink';
const { isFocused } = useFocus({ autoFocus: true });
// Style differently when focused
\x3CText color={isFocused ? 'blue' : 'dim'}>{label}\x3C/Text>
useStdin / useStdout — Stream Access
const { stdin, isRawModeSupported } = useStdin();
const { stdout } = useStdout();
render() Options
render(\x3CApp />, {
exitOnCtrlC: true, // default true
debug: false, // show Yoga layout debug
patchConsole: true, // suppress console output
});
Common Patterns
Select/Menu
const Menu = ({ items, onSelect }) => {
const [idx, setIdx] = useState(0);
useInput((_, key) => {
if (key.upArrow) setIdx(i => Math.max(0, i - 1));
if (key.downArrow) setIdx(i => Math.min(items.length - 1, i + 1));
if (key.return) onSelect(items[idx]);
});
return (
\x3CBox flexDirection="column">
{items.map((item, i) => (
\x3CText key={i} color={i === idx ? 'green' : undefined}>
{i === idx ? '❯ ' : ' '}{item}
\x3C/Text>
))}
\x3C/Box>
);
};
Spinner (useEffect + setInterval)
const Spinner = () => {
const [frame, setFrame] = useState(0);
const chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
useEffect(() => {
const id = setInterval(() => setFrame(f => (f + 1) % chars.length), 80);
return () => clearInterval(id);
}, []);
return \x3CText>{chars[frame]} Loading...\x3C/Text>;
};
Progress Bar
const ProgressBar = ({ percent }) => {
const filled = '█'.repeat(Math.round(percent / 5));
const empty = '░'.repeat(20 - filled.length);
return \x3CText>{filled}{empty} {percent}%\x3C/Text>;
};
Input Field (useInput + useState)
const Input = ({ onSubmit }) => {
const [value, setValue] = useState('');
useInput((input, key) => {
if (key.return) { onSubmit(value); setValue(''); }
else if (key.backspace) setValue(v => v.slice(0, -1));
else if (input.length === 1 && !key.ctrl) setValue(v => v + input);
});
return \x3CText>❯ {value}\x3CText dim>█\x3C/Text>\x3C/Text>;
};
Resources
This skill includes:
- components.md — Full component and prop reference
- hooks.md — Hook API details and custom hook patterns
- examples.md — Complete runnable examples (counter, table, loading, CLI arguments)
Key Constraints
- Node.js >= 22 required (ESM only)
- React >= 19.2 is a peer dependency
- Only works in real terminal (no browser)
- Layout via Yoga Flexbox — units are characters/rows, not pixels
- No scrolling — the terminal viewport is the canvas
- Colors depend on terminal support (most modern terminals support 256-color)
- Interactive mode requires raw stdin (Ink enables it automatically)
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install ink-tui - 安装完成后,直接呼叫该 Skill 的名称或使用
/ink-tui触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
Ink — React for interactive command-line apps. 是什么?
Ink — React for interactive command-line apps. Build rich terminal UIs with React components. 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 61 次。
如何安装 Ink — React for interactive command-line apps.?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install ink-tui」即可一键安装,无需额外配置。
Ink — React for interactive command-line apps. 是免费的吗?
是的,Ink — React for interactive command-line apps. 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。
Ink — React for interactive command-line apps. 支持哪些平台?
Ink — React for interactive command-line apps. 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 Ink — React for interactive command-line apps.?
由 OpenLark(@openlark)开发并维护,当前版本 v1.0.0。