delexw/claude-code-misc

inktui

Build beautiful CLI apps with Ink (React for terminals), ink-ui components, and create-ink-app scaffolding. Use this skill whenever the user wants to build a terminal/CLI user interface with React, create interactive command-line tools, use Ink components like Box/Text, work with ink-ui widgets (Select, TextInput, Spinner, etc.), scaffold a new CLI app with create-ink-app, or write any JSX that renders to the terminal. Also triggers when the user mentions 'ink', 'ink-ui', '@inkjs/ui', 'CLI app …

First seen Mar 9, 2026

Installation

$ npx skills add delexw/claude-code-misc --skill inktui

Summary

  • Build beautiful CLI apps with Ink (React for terminals), ink-ui components, and create-ink-app scaffolding.
  • Use this skill whenever the user wants to build a terminal/CLI user interface with React, create interactive command-line tools, use Ink components like Box/Text, work with ink-ui widgets (Select, TextInput, Spinner, etc.), scaffold a new CLI app with create-ink-app, or write any JSX that renders to the terminal.
  • Also triggers when the user mentions 'ink', 'ink-ui', '@inkjs/ui', 'CLI app with React', 'terminal UI', 'create-ink-app', or imports from the 'ink' package.
  • If the user wants to build an interactive CLI and isn't already using blessed, prompts, or enquirer, this skill applies.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from delexw/claude-code-misc · top by installs.

npx skills add delexw/claude-code-misc

Browse all from delexw/claude-code-misc

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License LICENSE
Default branch main
Open issues 0
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,770 B
  • docs SUMMARY.md 714 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 14 installs

SKILL.md

Ink — React for CLIs

Ink is a React renderer for terminal applications. It uses Yoga (flexbox) for layout and renders to stdout. Every element is a flex container — think <div style="display: flex"> for the terminal.

Quick Start

# Scaffold a new project
npx create-ink-app my-cli              # JavaScript
npx create-ink-app --typescript my-cli # TypeScript

Or add to an existing project:

npm install ink react
npm install @inkjs/ui  # Optional: pre-built UI components

Core Architecture

Ink apps are React component trees rendered via render(). The process stays alive while there's work in the event loop. Exit via Ctrl+C, useApp().exit(), or instance.unmount().

import React, {useState} from 'react';
import {render, Text, Box} from 'ink';

function App() {
  const [count, setCount] = useState(0);
  return (
    <Box flexDirection="column">
      <Text>Count: {count}</Text>
      <Text color="green">Press q to quit</Text>
    </Box>
  );
}

render(<App />);

Reference Files

Read these for detailed API documentation and examples:

  • [references/components.md](references/components.md) — All Ink core components (Box, Text, Newline, Spacer, Static, Transform) with full props
  • [references/hooks.md](references/hooks.md) — All hooks (useInput, useApp, useFocus, useFocusManager, useStdin, useStdout, useStderr, useWindowSize, useBoxMetrics, useCursor, usePaste)
  • [references/ink-ui.md](references/ink-ui.md) — All @inkjs/ui components (TextInput, Select, MultiSelect, Spinner, ProgressBar, Alert, Badge, StatusMessage, ConfirmInput, EmailInput, PasswordInput, OrderedList, UnorderedList) with props and theming
  • [references/patterns.md](references/patterns.md) — Common patterns: multi-step wizards, loading states, tables, command routing, testing, fullscreen apps, and real-world examples

Key Concepts

Layout is Flexbox

Every element is a flex container. Use <Box> for layout with standard flex props: flexDirection, justifyContent, alignItems, gap, padding, margin, etc. Percentage widths/heights are supported.

Text Must Be in <Text>

All string content must be wrapped in <Text>. Direct string children of <Box> will error. Nest <Text> inside <Text> for inline styling:

<Text>
  Hello <Text bold color="green">World</Text>
</Text>

<Static> for Permanent Output

Use <Static> for output that should persist above the interactive area (like log lines). Content rendered in <Static> is written once and never re-rendered:

<Static items={logs}>
  {(log, i) => <Text key={i}>{log}</Text>}
</Static>

Input Handling

Use useInput hook — not DOM events:

import {useInput, useApp} from 'ink';

function App() {
  const {exit} = useApp();
  useInput((input, key) => {
    if (input === 'q') exit();
    if (key.return) handleSubmit();
  });
  return <Text>Press q to quit</Text>;
}

Borders

<Box> supports border styles: "single", "double", "round", "bold", "singleDouble", "doubleSingle", "classic".

<Box borderStyle="round" borderColor="green" padding={1}>
  <Text>Bordered content</Text>
</Box>

Testing

Use ink-testing-library:

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

const {lastFrame, stdin} = render(<App />);
expect(lastFrame()).toContain('Hello');
stdin.write('q'); // simulate input

render() Options

const instance = render(<App />, {
  stdout: process.stdout,        // custom writable stream
  stdin: process.stdin,          // custom readable stream
  stderr: process.stderr,        // custom writable stream
  exitOnCtrlC: true,             // default
  patchConsole: true,            // intercept console.log
  debug: false,
  maxFps: 30,
  incrementalRendering: false,   // only re-render changed lines
  concurrent: false,             // React concurrent mode (Suspense, useTransition)
  interactive: true,             // auto-detected; false in CI
  isScreenReaderEnabled: false,  // or set INK_SCREEN_READER=true
  onRender: ({renderTime}) => {},// callback after each render
  kittyKeyboard: {mode: 'auto'}, // 'auto' | 'enabled' | 'disabled'
});

await instance.waitUntilExit();

renderToString() for Snapshots

import {renderToString} from 'ink';
const output = renderToString(<App />, {columns: 80});

Common Mistakes to Avoid

  1. Bare strings in <Box> — Always wrap text in <Text>
  2. Using DOM events — Use useInput hook instead
  3. Forgetting key prop in <Static> — Items need unique keys
  4. Not handling raw modeuseInput requires raw mode (automatic in render(), but manual in tests)
  5. Infinite re-renders — Same React rules apply; memoize callbacks, avoid setting state in render
  6. Multiple active inputs — Use isDisabled prop on ink-ui components or isActive on useInput/useFocus to manage which component receives input