К основному содержанию
скилл CX Codex

ink · assistant-ui — скилл для Claude Code: терминальный чат на Ink

Скилл для сборки чат-интерфейсов прямо в терминале: связывает рантайм assistant-ui с рендерером Ink и выводит ответы как ANSI-разметку.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add assistant-ui/skills --skill ink -a claude-code
Открыть на GitHub

Что делает ink

Скилл описывает, как собрать терминальное приложение на @assistant-ui/react-ink и @assistant-ui/react-ink-markdown. Рантайм, инструменты, состояние и транспорт AI SDK общие с веб-версией, но DOM, CSS и скопированных элементов тут нет. Экран собирается из Box и Text плюс примитивов, знающих о рантайме.

Стартовать можно с нуля: npx assistant-ui@latest create --ink my-app разворачивает пример with-react-ink. Для существующего Node-проекта рантайм, терминальный рендерер и транспорт ставятся одной командой. Дальше AssistantRuntimeProvider оборачивает useChatRuntime, а поток сообщений собирается из ThreadPrimitive, ComposerPrimitive и LoadingPrimitive.

Главная засада — адрес бэкенда. Терминальный процесс не умеет относительный /api/chat, поэтому AssistantChatTransport нужен полный URL, доступный из процесса, а API-роут живёт в отдельном бэкенд-проекте. Ввод устроен как контролируемый редактор строки: стрелки, Backspace и Ctrl D работают по одной графеме, так что эмодзи и CJK не рвутся. Meta-биндинги требуют терминала с Escape-последовательностями, а Shift Enter — поддержки CSI u.

Какие задачи решает

  • собрать чат-интерфейс в терминале без браузера
  • подключить рантайм assistant-ui к рендереру Ink
  • вывести ответы ассистента как ANSI-разметку
  • сделать редактирование строки безопасным для эмодзи и CJK
  • настроить историю треда, вложения и уведомления в терминале

Примеры запросов агенту

  • Собери терминальный чат на Ink: оберни useChatRuntime в AssistantRuntimeProvider и выведи поток через ThreadPrimitive
  • Добавь в композер multiLine и submitOnEnter, чтобы Enter отправлял, а Shift Enter переносил строку
  • Подключи MarkdownText из @assistant-ui/react-ink-markdown для вывода ответов ассистента

Как установить ink

1Через Skills CLI (Vercel)

npx skills add assistant-ui/skills --skill ink -a claude-code

2Вручную: положить файлы

~/.claude/skills/ink/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/ink/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора13

thread-list Скилл для assistant-ui: добавляет боковую панель с несколькими диалогами, переключением, переименованием, архивацией и удалением. CX Codex +1 6 200установок update Обновляет существующее приложение на assistant-ui до актуальных версий AI SDK v7 и assistant-ui 0.15.x, применяя нужные миграции. Пригодится, когда после апдейта посыпались ошибки типов или пропали хуки. CX Codex +1 5 900установок cloud Подключает AssistantCloud к приложению на assistant-ui: история тредов между сессиями, обратная связь по сообщениям и загрузка файлов. CX Codex +1 5 000установок react-mcp Скилл для работы с @assistant-ui/react-mcp: подключает MCP-серверы, выбранные пользователем, прямо в браузере и регистрирует их инструменты в чате. CX Codex +1 4 000установок observability Подключает Langfuse, LangSmith или Helicone к бэкенд-роутам assistant-ui на AI SDK и рисует собранные спаны через экспериментальный @assistant-ui/react-o11y. CX Codex +1 4 000установок copilots Скилл для assistant-ui: учит агента читать состояние страницы, кликать по компонентам и менять их состояние через хуки React. CX Codex +1 3 900установок generative-ui Скилл для assistant-ui: модель собирает интерфейс из готовых компонентов во время ответа, а не заполняет заранее написанный вами. CX Codex +1 1 000установок react-native Скилл для сборки чат-интерфейсов assistant-ui в Expo и чистом React Native: нативные примитивы, рантайм AI SDK и транспорт к бэкенду. CX Codex +1 909установок

Другие версии ink

Похожие

tui-design hyperb1iss Скилл для проектирования TUI: раскладка панелей, цвета, навигация с клавиатуры и асинхронные состояния. Пригодится, если вы пишете терминальный дашборд или пикер. CX Codex +1 1 300установок opentui msmps Помогает агенту собирать терминальные интерфейсы на OpenTUI: от выбора Core, React или Solid до ввода с клавиатуры, анимаций и тестов. CX Codex +1 64 500установок terminal-ui pproenca Скилл с 42 правилами для терминальных интерфейсов на TypeScript: рендеринг, ввод с клавиатуры, промпты. Пригодится, когда пишете CLI на Ink или Clack. CX Codex +1 836установок ratatui-tui blacktop Помогает агенту писать терминальные интерфейсы на ratatui: шаблоны проектов, виджеты, раскладка, асинхронные события. Пригодится, если делаете TUI на Rust. CX Codex +1 722установок hunk-review modem-dev Управляет запущенной TUI-сессией Hunk через CLI: переходит по дифам, оставляет инлайн-комментарии и обновляет просматриваемые ветки. CX Codex +1 1 800установок terminal-control anomalyco Управляет интерактивными терминальными программами через termctrl: читает экран, отправляет ввод и ждёт нужный текст. Нужен для TUI, REPL и живых CLI-сессий. CX Codex +1 505установок

Рядом в теме «Фронтенд и UI»

Всё по теме «Фронтенд и UI» →

Вопросы о ink

Как установить ink в Claude?

Выполните npx skills add assistant-ui/skills --skill ink -a claude-code. Скилл появится в ~/.claude/skills/ink/SKILL.md.

Что делает ink?

Помогает строить терминальные чат-интерфейсы на @assistant-ui/react-ink: подсказывает, как смонтировать рантайм, собрать тред из примитивов и отрисовать markdown в ANSI.

Что нужно для работы терминального чата?

API-роут должен крутиться в отдельном бэкенд-проекте, а AssistantChatTransport получает полный URL вместо относительного /api/chat. Meta-биндинги работают только в терминале с Escape-последовательностями.

Исходный текст

SKILL.md · MIT
---
name: ink
description: "Builds terminal chat UIs with @assistant-ui/react-ink and ANSI markdown with @assistant-ui/react-ink-markdown. Use when scaffolding `create --ink`, mounting `AssistantRuntimeProvider` around `useChatRuntime`, composing `ThreadPrimitive`, `ComposerPrimitive`, `MessagePrimitive`, `LoadingPrimitive`, `TextInput`, thread history, attachments, notifications, and terminal keyboard navigation, or when a chat needs grapheme safe editing, multiline display columns, an absolute backend URL, local file storage, or a custom `RemoteThreadListAdapter`. Route terminal markdown, tool output, message rendering, and Ink focus problems here. For browser application setup, web elements, and the standard web runtime, use [setup](../setup/SKILL.md)."
license: MIT
---

# assistant-ui Ink

**Always consult [assistant-ui.com/llms.txt](https://www.assistant-ui.com/llms.txt) for the latest API.**

`@assistant-ui/react-ink` connects the assistant-ui runtime to Ink's terminal renderer. It shares runtime, tools, state, and AI SDK transport with web apps, but it has no DOM, CSS, or copied elements. Compose your screen from Ink's `Box` and `Text` plus the runtime aware primitives. `@assistant-ui/react-ink-markdown` renders assistant text as ANSI styled terminal markdown.

## References

- [./references/primitives.md](./references/primitives.md) -- every terminal primitive namespace, its parts, scoped contexts, and the controlled `TextInput`
- [./references/hooks.md](./references/hooks.md) -- runtime, state, tool, notification, voice, and checklist hooks
- [./references/adapters.md](./references/adapters.md) -- file storage, attachment, and title adapters
- [./references/custom-backend.md](./references/custom-backend.md) -- local inference, local disk persistence, and backend thread ownership
- [./references/migration.md](./references/migration.md) -- what transfers from a web app and what must be rebuilt for Ink

## Start a terminal app

Scaffold the terminal example when starting fresh:

```sh
npx assistant-ui@latest create --ink my-app
cd my-app
```

`--ink` resolves to the `with-react-ink` CLI example. The example inventory also contains `with-react-ink-web`, but it is not the `--ink` scaffold target.

For an existing Node project, install the runtime, terminal renderer, and AI SDK transport together:

```sh
npm install @assistant-ui/react-ink @assistant-ui/react-ink-markdown ink react @assistant-ui/ai-sdk
```

The API route must run in a separate backend project. Unlike a browser app, a terminal process cannot use a relative `/api/chat` URL. Give `AssistantChatTransport` a complete URL that the process can reach.

```tsx
import { AssistantRuntimeProvider } from "@assistant-ui/react-ink";
import { AssistantChatTransport, useChatRuntime } from "@assistant-ui/ai-sdk";
import { Box } from "ink";
import { TerminalThread } from "./components/terminal-thread.js";

const CHAT_API_URL = "http://localhost:3000/api/chat";

export function App() {
  const runtime = useChatRuntime({
    transport: new AssistantChatTransport({ api: CHAT_API_URL }),
  });

  return (
    <AssistantRuntimeProvider runtime={runtime}>
      <Box flexDirection="column">
        <TerminalThread />
      </Box>
    </AssistantRuntimeProvider>
  );
}
```

`useChatRuntime` and `AssistantChatTransport` come from `@assistant-ui/ai-sdk`. Its backend uses the AI SDK v7 UI message stream. See the runtime's [AI SDK v7 guide](https://www.assistant-ui.com/docs/runtimes/ai-sdk/v7) for the route shape.

## Compose a terminal thread

`ThreadPrimitive.Messages` creates the current message scope before each child runs. Read `s.message` inside the message component, then use Ink primitives rather than web elements. Use `AuiIf` for runtime state gates and `LoadingPrimitive` for the active run.

```tsx
import { Box, Text } from "ink";
import {
  AuiIf,
  ComposerPrimitive,
  LoadingPrimitive,
  ThreadPrimitive,
  useAuiState,
} from "@assistant-ui/react-ink";
import { MarkdownText } from "@assistant-ui/react-ink-markdown";

function Message() {
  const message = useAuiState((s) => s.message);
  const text = message.content
    .filter((part) => part.type === "text")
    .map((part) => ("text" in part ? part.text : ""))
    .join("");

  if (message.role === "user") {
    return <Text color="green">You: {text}</Text>;
  }

  return (
    <Box flexDirection="column" marginBottom={1}>
      <Text color="blue">Assistant:</Text>
      <MarkdownText text={text} />
    </Box>
  );
}

export function TerminalThread() {
  return (
    <ThreadPrimitive.Root flexDirection="column">
      <AuiIf condition={(s) => s.thread.isEmpty}>
        <Text dimColor>Send a message to begin.</Text>
      </AuiIf>
      <ThreadPrimitive.Messages>{() => <Message />}</ThreadPrimitive.Messages>
      <LoadingPrimitive.Root gap={1}>
        <LoadingPrimitive.Spinner variant="bar" />
        <LoadingPrimitive.Text />
        <LoadingPrimitive.ElapsedTime />
      </LoadingPrimitive.Root>
      <Box borderStyle="round" borderColor="gray" paddingX={1}>
        <Text color="gray">{"> "}</Text>
        <ComposerPrimitive.Input submitOnEnter placeholder="Message..." autoFocus />
      </Box>
    </ThreadPrimitive.Root>
  );
}
```

The simple message example deliberately renders only text parts. Use `MessagePrimitive.Parts` when you need tool calls, attachments, data, sources, or reasoning. Its default terminal safe renderers handle those part types, and [primitives](./references/primitives.md) shows the component map.

## Terminal input behavior

`ComposerPrimitive.Input` is a composer bound `TextInput`. It is a controlled line editor, not Ink's nonexistent native input. `submitOnEnter` sends the current composer text. With `multiLine`, Enter inserts a newline unless `submitOnEnter` is enabled, in which case Shift Enter inserts a newline when the terminal distinguishes it. `Ctrl J` inserts a newline only in multiline mode and never submits a single line input.

- Left, Right, Backspace, Delete, and `Ctrl D` operate on one grapheme, so an emoji, ZWJ sequence, combining character, or CJK ideograph is never split.
- Home and End select the whole buffer in single line mode or the current line in multiline mode. `Ctrl A` and `Ctrl E` always select the current line boundary.
- Up and Down navigate multiline rows while preserving the terminal display column, calculated from grapheme widths rather than UTF 16 offsets.
- `Ctrl W`, `Alt B`, `Alt F`, and `Alt D` navigate or delete by `Intl.Segmenter` word boundaries. `Ctrl U` and `Ctrl K` kill to the current boundary. At multiline end of line, `Ctrl K` joins the next line.

Meta bindings need a terminal that emits Escape prefixed sequences. In macOS Terminal, enable “Use Option as Meta key” for the Alt bindings. Shift Enter requires CSI u support, including iTerm2 3.4 or newer, kitty, and foot. Other terminals treat it as Enter and use `submitOnEnter` behavior. See [primitives](./references/primitives.md) for `TextInput` outside a composer.

## Markdown in the terminal

Pass accumulated text to `MarkdownText` from `@assistant-ui/react-ink-markdown`. It produces terminal styled output rather than HTML or a React DOM tree. The package also exports `MarkdownTextPrimitive`, `useShikiHighlighter`, and theme types for a custom renderer, but start with `MarkdownText` unless you need to change its rendering pipeline.

```tsx
import { MarkdownText } from "@assistant-ui/react-ink-markdown";

export function AssistantReply({ text }: { text: string }) {
  return <MarkdownText text={text} />;
}
```

## Common Gotchas

**The terminal app sends requests to its own process instead of the backend**

- `AssistantChatTransport` needs an absolute `api` URL such as `http://localhost:3000/api/chat`. Host the AI SDK route separately from the Ink process.

**A web Thread or shadcn element renders nothing in the CLI**

- Browser elements require the DOM and CSS. Rebuild the surface with Ink `Box`, `Text`, and `@assistant-ui/react-ink` primitives.

**A primitive or state hook throws about missing runtime context**

- Mount it under `AssistantRuntimeProvider runtime={runtime}`. `ThreadPrimitive.Messages` and `MessagePrimitive.Parts` also create the item scopes their children read.

**Enter does not send or inserts a newline unexpectedly**

- `submitOnEnter` is false by default. Combine it with `multiLine` only when Enter should send and Shift Enter should insert a newline on capable terminals.

**Emoji deletion corrupts the visible input or vertical navigation lands in the wrong place**

- Use `ComposerPrimitive.Input` or exported `TextInput`. Their buffer uses grapheme segmentation and terminal display widths. Do not substitute character index arithmetic.

**Thread data disappears after restarting the CLI**

- `useLocalRuntime` is process memory. Use `createFileStorageAdapter` for one local process or a `RemoteThreadListAdapter` for backend owned metadata.

**Markdown was imported from the web package**

- Import `MarkdownText` from `@assistant-ui/react-ink-markdown`, which emits terminal formatting. Web markdown renderers target the DOM.

## Related Skills

- [setup](../setup/SKILL.md) -- CLI scaffolding, browser setup, and package installation
- [runtime](../runtime/SKILL.md) -- shared assistant-ui runtime, state, threads, and transport design
- [primitives](../primitives/SKILL.md) -- browser unstyled primitives when the target is not a terminal
- [tools](../tools/SKILL.md) -- toolkit definitions and tool call renderers that also work in Ink
- [markdown](../markdown/SKILL.md) -- browser markdown renderers and source display

© assistant-ui · MIT · assistant-ui/skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой