Ink
GitHub Overview
vadimdemedes/ink
🌈 React for interactive command-line apps
Repository:https://github.com/vadimdemedes/ink
Homepage:https://term.ink
Stars30,219
Watchers112
Forks699
Created:June 12, 2017
Language:TypeScript
License:MIT License
Topics
clicommand-lineflexboxinteractivejavascriptreact
Star History
Data as of: 7/25/2025, 11:10 AM
Ink
Ink is a JavaScript library that enables developers to build terminal user interfaces using React components. Known as "React for CLI", it allows developers to leverage their existing React knowledge to create powerful terminal applications with familiar component-based architecture.
Features
React Component Model
- JSX Syntax: Write terminal UIs using familiar JSX syntax
- State Management: Use React hooks like
useState
anduseEffect
- Component Reusability: Reuse UI components across projects
- Virtual DOM: Efficient differential rendering for terminal updates
Rich Built-in Capabilities
- Flexbox Layout: Uses Facebook's Yoga layout engine for precise positioning
- Text Styling: Support for colors, bold, italic, underline, and strikethrough
- Focus Management: Tab/Shift+Tab navigation between interactive elements
- Input Handling: Process keyboard input events with ease
Developer Experience
- TypeScript Support: First-class TypeScript support for type safety
- Hot Reload: Fast feedback during development
- Debug Support: React DevTools-like debugging experience
- Testing: Easy component testing with familiar patterns
Basic Usage
Installation
npm install ink react
# or
yarn add ink react
Hello World
import React from 'react';
import {render, Text} from 'ink';
const App = () => <Text>Hello World</Text>;
render(<App />);
User Input Handling
import React, {useState} from 'react';
import {render, Text, useInput} from 'ink';
const Counter = () => {
const [counter, setCounter] = useState(0);
useInput((input, key) => {
if (input === 'q') {
process.exit();
}
if (key.upArrow) {
setCounter(counter + 1);
}
if (key.downArrow) {
setCounter(counter - 1);
}
});
return (
<>
<Text>Count: {counter}</Text>
<Text color="gray">Use up/down arrows, 'q' to quit</Text>
</>
);
};
render(<Counter />);
Layout Construction
import React from 'react';
import {render, Box, Text} from 'ink';
const App = () => (
<Box flexDirection="column" padding={1}>
<Box marginBottom={1}>
<Text color="green">Header</Text>
</Box>
<Box flexDirection="row">
<Box marginRight={2}>
<Text>Left Sidebar</Text>
</Box>
<Box flexGrow={1}>
<Text>Main Content</Text>
</Box>
</Box>
<Box marginTop={1}>
<Text color="gray">Footer</Text>
</Box>
</Box>
);
render(<App />);
Core Components
Text
Display and style text content
<Text color="red" bold underline>
Styled text
</Text>
Box
Flexbox-based layout container
<Box
flexDirection="row"
justifyContent="center"
alignItems="center"
padding={2}
border={{type: 'round'}}
>
<Text>Centered content</Text>
</Box>
Static
Content that permanently remains on screen
<Static items={logs}>
{log => <Text key={log.id}>{log.message}</Text>}
</Static>
Real-world Example
CLI Progress Display
import React, {useState, useEffect} from 'react';
import {render, Box, Text} from 'ink';
import Spinner from 'ink-spinner';
const ProgressApp = () => {
const [progress, setProgress] = useState(0);
const [isComplete, setIsComplete] = useState(false);
useEffect(() => {
const timer = setInterval(() => {
setProgress(prev => {
if (prev >= 100) {
setIsComplete(true);
clearInterval(timer);
return 100;
}
return prev + 10;
});
}, 500);
return () => clearInterval(timer);
}, []);
return (
<Box flexDirection="column">
<Box>
<Text color={isComplete ? 'green' : 'blue'}>
{isComplete ? '✓' : <Spinner type="dots" />}
</Text>
<Text> Processing... {progress}%</Text>
</Box>
<Box marginTop={1}>
<Text>
{'█'.repeat(Math.floor(progress / 5))}
{'░'.repeat(20 - Math.floor(progress / 5))}
</Text>
</Box>
</Box>
);
};
render(<ProgressApp />);
Ecosystem
Related Packages
- ink-spinner: Spinner components
- ink-select-input: Selection menus
- ink-text-input: Text input fields
- ink-table: Table display
- ink-gradient: Gradient effects
- ink-link: Clickable links
Notable Adopters
- Cloudflare Wrangler: Serverless development CLI
- Shopify CLI: Shopify development tools
- Prisma: Database management CLI
- Linear CLI: Project management CLI
Advantages
- Low Learning Curve: Immediate productivity for React developers
- Maintainability: Component-based architecture improves maintainability
- Testability: Easy unit testing with familiar patterns
- Performance: Efficient differential updates
- Active Community: Rich ecosystem of third-party components
Limitations
- React Dependency: Includes React bundle size
- Learning Curve: Requires React knowledge
- Mouse Support: Limited mouse interaction support
- Complex Layouts: Advanced terminal features may be restricted
Comparison with Other Libraries
Feature | Ink | Blessed | Terminal Kit |
---|---|---|---|
Approach | React-like | Widget-based | Function-based |
Learning Curve | Low (for React devs) | Medium | Medium |
Performance | High | High | Medium |
Ecosystem | Rich | Medium | Medium |
TypeScript | Excellent | Partial | Partial |
Summary
Ink is the most accessible TUI library for React developers. It allows developers to leverage their existing React knowledge to build maintainable terminal applications. It's particularly well-suited for developing CLI tools that require ongoing maintenance, such as team development tools and CI/CD utilities.