# Ink Migration

Source: /tuil/docs/guides/ink-migration
Locale: en

Move an existing Ink application into a tuil runtime incrementally.



## 1. Keep the component tree [#1-keep-the-component-tree]

tuil uses Ink, so begin by wrapping the existing root without rewriting its
children:

```tsx
const app = createApp({ id: "existing-cli", component: ExistingApp });
render(<ExistingApp />, { app });
```

## 2. Replace global input [#2-replace-global-input]

Move overlay-specific handlers to `TerminalInputLayer`, application shortcuts
to `HotkeyManager`, and traversal to focusable semantic components. This
prevents multiple `useInput` hooks from competing.

## 3. Introduce ownership boundaries [#3-introduce-ownership-boundaries]

Move global singletons into services, teardown into lifecycle disposers, and
cross-feature messages into declared events.

## 4. Adopt components selectively [#4-adopt-components-selectively]

Registry components are source-owned, so install only the primitives or blocks
you need:

<CodeBlockTabs defaultValue="npm">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npx @mwillbanks/tuil add button field text-input dialog
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm dlx @mwillbanks/tuil add button field text-input dialog
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn dlx @mwillbanks/tuil add button field text-input dialog
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun x @mwillbanks/tuil add button field text-input dialog
    ```
  </CodeBlockTab>
</CodeBlockTabs>

## 5. Convert tests [#5-convert-tests]

Keep frame assertions for visual regressions, then add semantic queries for
behavior. Semantic assertions survive spacing, color, and viewport changes.
