ink-component-generator

Generate Ink (React for CLI) components for terminal UIs with hooks, state management, and layout components.

509 stars

Best use case

ink-component-generator is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Generate Ink (React for CLI) components for terminal UIs with hooks, state management, and layout components.

Teams using ink-component-generator should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/ink-component-generator/SKILL.md --create-dirs "https://raw.githubusercontent.com/a5c-ai/babysitter/main/library/specializations/cli-mcp-development/skills/ink-component-generator/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/ink-component-generator/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How ink-component-generator Compares

Feature / Agentink-component-generatorStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Generate Ink (React for CLI) components for terminal UIs with hooks, state management, and layout components.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Ink Component Generator

Generate Ink (React) components for terminal UIs.

## Capabilities

- Generate Ink React components
- Create custom hooks for CLI state
- Set up layout components (Box, Text)
- Implement input handling
- Create loading and progress components
- Set up testing with ink-testing-library

## Usage

Invoke this skill when you need to:
- Build terminal UIs with React patterns
- Create interactive CLI components
- Implement stateful terminal interfaces
- Set up Ink project structure

## Inputs

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| projectName | string | Yes | Project name |
| components | array | Yes | Component definitions |
| includeHooks | boolean | No | Generate custom hooks |

### Component Structure

```json
{
  "components": [
    {
      "name": "SelectList",
      "type": "interactive",
      "props": ["items", "onSelect"],
      "state": ["selectedIndex"]
    }
  ]
}
```

## Generated Patterns

### Select List Component

```tsx
import React, { useState, useCallback } from 'react';
import { Box, Text, useInput, useApp } from 'ink';

interface SelectListProps {
  items: string[];
  onSelect: (item: string, index: number) => void;
}

export const SelectList: React.FC<SelectListProps> = ({ items, onSelect }) => {
  const [selectedIndex, setSelectedIndex] = useState(0);
  const { exit } = useApp();

  useInput((input, key) => {
    if (key.upArrow) {
      setSelectedIndex((prev) => (prev > 0 ? prev - 1 : items.length - 1));
    } else if (key.downArrow) {
      setSelectedIndex((prev) => (prev < items.length - 1 ? prev + 1 : 0));
    } else if (key.return) {
      onSelect(items[selectedIndex], selectedIndex);
    } else if (input === 'q' || key.escape) {
      exit();
    }
  });

  return (
    <Box flexDirection="column">
      {items.map((item, index) => (
        <Box key={item}>
          <Text color={index === selectedIndex ? 'green' : undefined}>
            {index === selectedIndex ? '> ' : '  '}
            {item}
          </Text>
        </Box>
      ))}
      <Box marginTop={1}>
        <Text dimColor>Use arrow keys to navigate, Enter to select, q to quit</Text>
      </Box>
    </Box>
  );
};
```

### Text Input Component

```tsx
import React, { useState } from 'react';
import { Box, Text, useInput } from 'ink';

interface TextInputProps {
  placeholder?: string;
  onSubmit: (value: string) => void;
  mask?: string;
}

export const TextInput: React.FC<TextInputProps> = ({
  placeholder = '',
  onSubmit,
  mask,
}) => {
  const [value, setValue] = useState('');
  const [cursor, setCursor] = useState(0);

  useInput((input, key) => {
    if (key.return) {
      onSubmit(value);
      return;
    }
    if (key.backspace || key.delete) {
      setValue((prev) => prev.slice(0, -1));
      setCursor((prev) => Math.max(0, prev - 1));
      return;
    }
    if (!key.ctrl && !key.meta && input) {
      setValue((prev) => prev + input);
      setCursor((prev) => prev + 1);
    }
  });

  const displayValue = mask ? mask.repeat(value.length) : value;

  return (
    <Box>
      <Text>
        {displayValue || <Text dimColor>{placeholder}</Text>}
        <Text backgroundColor="white"> </Text>
      </Text>
    </Box>
  );
};
```

### Spinner Component

```tsx
import React, { useState, useEffect } from 'react';
import { Text } from 'ink';

const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];

interface SpinnerProps {
  label?: string;
}

export const Spinner: React.FC<SpinnerProps> = ({ label }) => {
  const [frame, setFrame] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setFrame((prev) => (prev + 1) % frames.length);
    }, 80);
    return () => clearInterval(timer);
  }, []);

  return (
    <Text>
      <Text color="green">{frames[frame]}</Text>
      {label && <Text> {label}</Text>}
    </Text>
  );
};
```

### Custom Hook - useAsync

```tsx
import { useState, useEffect, useCallback } from 'react';

interface AsyncState<T> {
  data: T | null;
  loading: boolean;
  error: Error | null;
}

export function useAsync<T>(
  asyncFn: () => Promise<T>,
  deps: any[] = []
): AsyncState<T> & { refetch: () => void } {
  const [state, setState] = useState<AsyncState<T>>({
    data: null,
    loading: true,
    error: null,
  });

  const execute = useCallback(async () => {
    setState({ data: null, loading: true, error: null });
    try {
      const data = await asyncFn();
      setState({ data, loading: false, error: null });
    } catch (error) {
      setState({ data: null, loading: false, error: error as Error });
    }
  }, deps);

  useEffect(() => {
    execute();
  }, [execute]);

  return { ...state, refetch: execute };
}
```

## Dependencies

```json
{
  "dependencies": {
    "ink": "^4.0.0",
    "react": "^18.0.0"
  },
  "devDependencies": {
    "@types/react": "^18.0.0",
    "ink-testing-library": "^3.0.0"
  }
}
```

## Target Processes

- tui-application-framework
- interactive-form-implementation
- dashboard-monitoring-tui

Related Skills

styled-components

509
from a5c-ai/babysitter

Styled Components theming, variants, SSR support, and patterns.

react-server-components

509
from a5c-ai/babysitter

React Server Components patterns including streaming, data fetching, client/server component composition, and performance optimization.

component-inventory

509
from a5c-ai/babysitter

Audit and inventory existing UI components in a codebase

color-palette-generator

509
from a5c-ai/babysitter

Generate accessible color palettes with WCAG compliance

tracing-schema-generator

509
from a5c-ai/babysitter

Generate distributed tracing schemas for OpenTelemetry with Jaeger/Zipkin integration

metrics-schema-generator

509
from a5c-ai/babysitter

Generate metrics schemas for Prometheus, OpenTelemetry, and Grafana dashboards

log-schema-generator

509
from a5c-ai/babysitter

Generate structured logging schemas with correlation ID patterns and ELK/Splunk integration

load-test-generator

509
from a5c-ai/babysitter

Generate load test scripts for k6, Locust, and Gatling from OpenAPI specs

graphql-schema-generator

509
from a5c-ai/babysitter

Generate GraphQL schemas from data models with resolver stubs and federation support

docs-site-generator

509
from a5c-ai/babysitter

Generate documentation sites using Docusaurus, MkDocs, or VuePress

dependency-graph-generator

509
from a5c-ai/babysitter

Generate module dependency graphs with circular dependency detection and coupling metrics

dashboard-generator

509
from a5c-ai/babysitter

Generate monitoring dashboards for Grafana and DataDog with alert integration