Shared Ink/React design system for gi4nks CLI tools.
Provides standardized themes, unicode symbols, layout constants, and React components for building consistent Terminal User Interfaces (TUI) with Ink.
npm install @gi4nks/inkimport { THEMES } from '@gi4nks/ink';
import type { Theme, ThemeName } from '@gi4nks/ink';
const theme = THEMES['dark']; // Theme object
const name: ThemeName = 'ocean'; // 'dark' | 'sunset' | 'ocean' | 'forest' | 'mono'Every component accepts a theme: Theme prop — never hardcode colors.
import { symbols } from '@gi4nks/ink';
// symbols.cursor → '❯'
// symbols.selected → '●'
// symbols.checkmark → '✓'
// symbols.cross → '✗'
// symbols.ai → '✦'
// symbols.spinner → ['⠋','⠙','⠹', ...]
// symbols.separator → '│'import { SectionHeader, THEMES } from '@gi4nks/ink';
<SectionHeader title="STATUS" theme={THEMES.dark} />
// renders: ── STATUS ──
<SectionHeader title="ERRORS" theme={THEMES.dark} count={3} />
// renders: ── ERRORS (3) ──import { Spinner, THEMES } from '@gi4nks/ink';
<Spinner theme={THEMES.dark} label="Loading..." />import { KeyHint, THEMES } from '@gi4nks/ink';
<KeyHint
theme={THEMES.dark}
hints={[
{ key: '↑↓', description: 'navigate' },
{ key: 'Enter', description: 'confirm' },
{ key: 'q', description: 'quit' },
]}
position="5/120"
/>
// renders: ↑↓ navigate │ Enter confirm │ q quit 5/120Generic config view with built-in AI provider selector and theme switcher.
import { ConfigView, THEMES } from '@gi4nks/ink';
import type { AIConfig, ThemeName } from '@gi4nks/ink';
<ConfigView
appName="myapp"
title="Configuration"
fields={[
{ label: 'Max History', key: 'maxHistory', type: 'number' },
{ label: 'Auto Save', key: 'autoSave', type: 'boolean' },
{ label: 'Username', key: 'username', type: 'string' },
{ label: 'API Token', key: 'token', type: 'password' },
]}
values={{ maxHistory: 100, autoSave: true, username: 'gi4nks', token: '' }}
aiConfig={{ provider: 'Gemini', model: 'gemini-2.0-flash' }}
theme={THEMES.dark}
themeName="dark"
isActive={true}
onSave={(values, aiConfig, themeName) => { /* persist */ }}
onCancel={() => { /* close */ }}
/>import { AIProviderSelector, THEMES } from '@gi4nks/ink';
import type { AIConfig } from '@gi4nks/ink';
<AIProviderSelector
value={{ provider: 'Gemini', model: 'gemini-2.0-flash' }}
onChange={(config: AIConfig) => { /* update state */ }}
onSave={() => { /* close */ }}
onCancel={() => { /* close */ }}
theme={THEMES.dark}
isActive={true}
/>| Key | Name | Primary | Secondary | Accent | Success | Warning | Error |
|---|---|---|---|---|---|---|---|
dark |
Dark Classic | cyan | magenta | blue | green | yellow | red |
sunset |
Sunset | orange | magenta | yellow | green | red | red |
ocean |
Deep Ocean | blue | cyan | white | green | yellow | red |
forest |
Forest | green | yellow | white | cyan | yellow | red |
mono |
Monochrome | white | white | gray | white | white | white |
All themes also define dim (gray) and bg (hex background color).
| Provider | Icon | Color | Models |
|---|---|---|---|
| Gemini | ◆ |
blue | gemini-2.5-pro, gemini-2.0-flash, gemini-1.5-pro |
| OpenAI | ◎ |
green | gpt-4o, gpt-4o-mini, o3-mini |
| Anthropic | ◇ |
yellow | claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5 |
| Ollama | ○ |
cyan | dynamic (fetched from local instance) |
Releases are automated via semantic-release on every push to main. Use Conventional Commits:
| Commit prefix | Release type |
|---|---|
feat: |
minor |
fix:, perf: |
patch |
BREAKING CHANGE: in footer |
major |
chore:, docs:, refactor: |
no release |
npm run dev # build with watch mode (tsup --watch)
npm run build # production build → dist/ (CJS + ESM + .d.ts)
npm run lint # eslint
npm test # vitest