or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-ink

React for CLI - build interactive command-line interfaces using React components and Flexbox layouts

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/ink@5.2.x

To install, run

npx @tessl/cli install tessl/npm-ink@5.2.0

0

# Ink

1

2

Ink is a React-like framework for building command-line interfaces that brings the familiar component-based development experience of React to terminal applications. It provides a comprehensive set of UI components powered by Facebook's Yoga layout engine to enable Flexbox-style layouts in the terminal, making it possible to create interactive CLI tools with real-time UI updates, focus management, and sophisticated terminal-based interfaces.

3

4

## Package Information

5

6

- **Package Name**: ink

7

- **Package Type**: npm

8

- **Language**: TypeScript

9

- **Installation**: `npm install ink react`

10

11

## Core Imports

12

13

```typescript

14

import { render, Box, Text, useInput, useApp } from "ink";

15

```

16

17

For type imports:

18

19

```typescript

20

import {

21

render,

22

Box,

23

Text,

24

useInput,

25

useApp,

26

type AppProps,

27

type StdinProps,

28

type StdoutProps,

29

type StderrProps

30

} from "ink";

31

```

32

33

For CommonJS:

34

35

```javascript

36

const { render, Box, Text, useInput, useApp } = require("ink");

37

```

38

39

## Basic Usage

40

41

```typescript

42

import React, { useState } from "react";

43

import { render, Box, Text, useInput, useApp } from "ink";

44

45

function Counter() {

46

const [count, setCount] = useState(0);

47

const { exit } = useApp();

48

49

useInput((input, key) => {

50

if (input === "q") {

51

exit();

52

}

53

54

if (key.upArrow) {

55

setCount(count + 1);

56

}

57

58

if (key.downArrow) {

59

setCount(count - 1);

60

}

61

});

62

63

return (

64

<Box>

65

<Text color="green">Counter: {count}</Text>

66

<Text dimColor> (Use ↑/↓ to change, 'q' to quit)</Text>

67

</Box>

68

);

69

}

70

71

// Render the app

72

render(<Counter />);

73

```

74

75

## Architecture

76

77

Ink is built around several key components:

78

79

- **React Reconciler**: Custom React renderer for terminal output instead of DOM

80

- **Yoga Layout Engine**: Facebook's Flexbox implementation for terminal layouts

81

- **Component System**: React-like components (Box, Text) with styling props

82

- **Hook System**: React hooks for input handling, focus management, and app lifecycle

83

- **Virtual DOM**: Custom DOM implementation optimized for terminal rendering

84

- **Event System**: Keyboard input parsing and event handling for interactive CLIs

85

86

## Capabilities

87

88

### Application Rendering

89

90

Core functionality for mounting and rendering React component trees to the terminal with full lifecycle management.

91

92

```typescript { .api }

93

function render(

94

node: ReactNode,

95

options?: NodeJS.WriteStream | RenderOptions

96

): Instance;

97

98

interface RenderOptions {

99

stdout?: NodeJS.WriteStream; // default: process.stdout

100

stdin?: NodeJS.ReadStream; // default: process.stdin

101

stderr?: NodeJS.WriteStream; // default: process.stderr

102

debug?: boolean; // default: false

103

exitOnCtrlC?: boolean; // default: true

104

patchConsole?: boolean; // default: true

105

}

106

107

interface Instance {

108

rerender: (node: ReactNode) => void;

109

unmount: () => void;

110

waitUntilExit: () => Promise<void>;

111

cleanup: () => void;

112

clear: () => void;

113

}

114

```

115

116

[Application Rendering](./rendering.md)

117

118

### Layout Components

119

120

Essential components for building terminal layouts using Flexbox-style positioning and styling.

121

122

```typescript { .api }

123

// Primary layout container component

124

function Box(props: BoxProps & { children?: ReactNode }): JSX.Element;

125

126

// Text display component with styling options

127

function Text(props: TextProps & { children?: ReactNode }): JSX.Element;

128

129

interface BoxProps {

130

// Flexbox layout properties

131

flexDirection?: "row" | "column" | "row-reverse" | "column-reverse";

132

flexWrap?: "nowrap" | "wrap" | "wrap-reverse";

133

flexGrow?: number;

134

flexShrink?: number;

135

justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";

136

alignItems?: "flex-start" | "center" | "flex-end" | "stretch";

137

// [Additional layout properties...]

138

}

139

140

interface TextProps {

141

color?: string;

142

backgroundColor?: string;

143

bold?: boolean;

144

italic?: boolean;

145

underline?: boolean;

146

strikethrough?: boolean;

147

wrap?: "wrap" | "truncate-end" | "truncate-start" | "truncate-middle";

148

}

149

```

150

151

[Layout Components](./components.md)

152

153

### User Input Handling

154

155

Comprehensive input handling system for creating interactive CLI applications with keyboard navigation and focus management.

156

157

```typescript { .api }

158

// Handle keyboard input with parsed key information

159

function useInput(

160

inputHandler: (input: string, key: Key) => void,

161

options?: { isActive?: boolean }

162

): void;

163

164

// Focus management for component navigation

165

function useFocus(options?: {

166

isActive?: boolean;

167

autoFocus?: boolean;

168

id?: string;

169

}): { isFocused: boolean; focus: (id: string) => void };

170

171

interface Key {

172

upArrow: boolean;

173

downArrow: boolean;

174

leftArrow: boolean;

175

rightArrow: boolean;

176

return: boolean;

177

escape: boolean;

178

ctrl: boolean;

179

shift: boolean;

180

tab: boolean;

181

backspace: boolean;

182

delete: boolean;

183

meta: boolean;

184

}

185

```

186

187

[User Input Handling](./hooks.md)

188

189

## Common Types

190

191

```typescript { .api }

192

// DOM element reference type for measuring and manipulation

193

interface DOMElement {

194

nodeName: string;

195

attributes: Record<string, any>;

196

childNodes: DOMNode[];

197

yogaNode?: YogaNode;

198

parentNode?: DOMElement;

199

style: Styles;

200

}

201

202

// Context Props types for hooks (also available as individual exports)

203

interface AppProps {

204

readonly exit: (error?: Error) => void;

205

}

206

207

interface StdinProps {

208

readonly stdin: NodeJS.ReadStream;

209

readonly setRawMode: (value: boolean) => void;

210

readonly isRawModeSupported: boolean;

211

readonly internal_exitOnCtrlC: boolean;

212

readonly internal_eventEmitter: EventEmitter;

213

}

214

215

interface StdoutProps {

216

readonly stdout: NodeJS.WriteStream;

217

readonly write: (data: string) => void;

218

}

219

220

interface StderrProps {

221

readonly stderr: NodeJS.WriteStream;

222

readonly write: (data: string) => void;

223

}

224

225

// Comprehensive styling interface based on Yoga layout

226

interface Styles {

227

// Layout

228

position?: "absolute" | "relative";

229

display?: "flex" | "none";

230

overflow?: "visible" | "hidden";

231

232

// Flexbox

233

flexDirection?: "row" | "column" | "row-reverse" | "column-reverse";

234

flexWrap?: "nowrap" | "wrap" | "wrap-reverse";

235

flexGrow?: number;

236

flexShrink?: number;

237

flexBasis?: number | string;

238

justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";

239

alignItems?: "flex-start" | "center" | "flex-end" | "stretch";

240

alignSelf?: "flex-start" | "center" | "flex-end" | "auto";

241

242

// Dimensions

243

width?: number | string;

244

height?: number | string;

245

minWidth?: number | string;

246

minHeight?: number | string;

247

248

// Spacing

249

margin?: number;

250

marginX?: number;

251

marginY?: number;

252

marginTop?: number;

253

marginBottom?: number;

254

marginLeft?: number;

255

marginRight?: number;

256

padding?: number;

257

paddingX?: number;

258

paddingY?: number;

259

paddingTop?: number;

260

paddingBottom?: number;

261

paddingLeft?: number;

262

paddingRight?: number;

263

gap?: number;

264

columnGap?: number;

265

rowGap?: number;

266

267

// Borders

268

borderStyle?: string;

269

borderTop?: boolean;

270

borderBottom?: boolean;

271

borderLeft?: boolean;

272

borderRight?: boolean;

273

borderColor?: string;

274

borderTopColor?: string;

275

borderBottomColor?: string;

276

borderLeftColor?: string;

277

borderRightColor?: string;

278

279

// Text

280

textWrap?: "wrap" | "truncate-end" | "truncate-start" | "truncate-middle" | "end" | "middle";

281

}

282

```