DEV Community

Alex Spinov
Alex Spinov

Posted on

Ink Has a Free React for CLIs — Here's How to Use It

Building interactive CLI tools with raw stdin/stdout is painful. Ink lets you build CLI apps using React components — useState, useEffect, flexbox layout — all in the terminal.

What Is Ink?

Ink provides the React experience for command-line apps. Build interactive CLIs using JSX components, hooks, and flexbox — just like building a web app, but for the terminal.

Quick Start

npm install ink react
Enter fullscreen mode Exit fullscreen mode
import React, { useState, useEffect } from 'react';
import { render, Text, Box } from 'ink';

function App() {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCounter(prev => prev + 1);
    }, 100);
    return () => clearInterval(timer);
  }, []);

  return (
    <Box flexDirection="column" padding={1}>
      <Text bold color="green">My CLI App</Text>
      <Text>Counter: {counter}</Text>
    </Box>
  );
}

render(<App />);
Enter fullscreen mode Exit fullscreen mode

Layout With Flexbox

<Box flexDirection="row" gap={2}>
  <Box width="50%" borderStyle="round" padding={1}>
    <Text>Left Panel</Text>
  </Box>
  <Box width="50%" borderStyle="round" padding={1}>
    <Text>Right Panel</Text>
  </Box>
</Box>
Enter fullscreen mode Exit fullscreen mode

Built-In Components

import { Text, Box, Newline, Spacer, Static, Transform } from 'ink';

// Styled text
<Text bold color="red" underline>Error!</Text>
<Text color="#ff6347" backgroundColor="black">Custom colors</Text>
<Text dimColor italic>Subtle hint</Text>

// Spacer (like flex-grow)
<Box>
  <Text>Left</Text>
  <Spacer />
  <Text>Right</Text>
</Box>
Enter fullscreen mode Exit fullscreen mode

User Input

import { useInput, useApp } from 'ink';

function Game() {
  const [x, setX] = useState(0);
  const { exit } = useApp();

  useInput((input, key) => {
    if (key.leftArrow) setX(x => x - 1);
    if (key.rightArrow) setX(x => x + 1);
    if (input === 'q') exit();
  });

  return <Text>{' '.repeat(x)}🏃</Text>;
}
Enter fullscreen mode Exit fullscreen mode

Real-World Examples

Ink powers many popular CLI tools:

  • Gatsby — development server output
  • Prisma — database management CLI
  • Shopify — Hydrogen CLI
  • Jest — test runner output (parts)

Community Components

  • ink-text-input — text input field
  • ink-select-input — selection list
  • ink-spinner — loading spinners
  • ink-table — data tables
  • ink-progress-bar — progress bars
  • ink-gradient — gradient text
  • ink-big-text — ASCII art text

Testing

import { render } from 'ink-testing-library';

test('renders greeting', () => {
  const { lastFrame } = render(<Greeting name="World" />);
  expect(lastFrame()).toContain('Hello, World');
});
Enter fullscreen mode Exit fullscreen mode

Get Started


Building developer tools? My Apify scrapers power data-driven CLIs. Custom solutions: spinov001@gmail.com

Top comments (0)