# What UI Library Does Dexter Use for Its CLI? A Deep Dive into Ink

> Discover what UI library Dexter uses for its CLI. Dexter leverages Ink, a React-based library for interactive terminal components. Learn more about this powerful tool.

- Repository: [Virat Singh/dexter](https://github.com/virattt/dexter)
- Tags: deep-dive
- Published: 2026-02-16

---

**Dexter uses Ink, a React-based UI library that renders interactive components directly in the terminal.**

The Dexter CLI—an open-source financial AI agent built by `virattt/dexter`—leverages **Ink** to create a modern, component-driven user interface within the command line. This UI library allows Dexter to compose rich, dynamic interfaces using familiar React patterns while maintaining the portability and speed of a terminal application.

## Why Dexter Chose Ink as Its Terminal UI Library

Ink provides a **declarative, component-based abstraction** over low-level terminal control sequences. Instead of manually writing ANSI escape codes to manipulate cursor position or color output, developers can use standard React components and hooks.

For Dexter, this architectural choice delivers several advantages:

- **Familiar Development Model**: The codebase uses standard React patterns—components, props, and hooks—making it accessible to frontend developers.
- **Real-Time Interactivity**: Ink's hook system (`useInput`, `useApp`) enables Dexter to capture keyboard events and manage application lifecycle without blocking the main thread.
- **Composable Layouts**: Primitive components like `Box` and `Text` allow Dexter to build complex, responsive terminal layouts that adapt to varying screen sizes.

## Key Ink Components and Hooks in Dexter's Codebase

Dexter's implementation demonstrates Ink's core primitives across several key files. The following sections break down how specific Ink APIs power different aspects of the CLI.

### Rendering the Application with `render`

Every Ink application begins with the `render` function, which mounts the React component tree to the terminal output stream.

In [`src/index.tsx`](https://github.com/virattt/dexter/blob/main/src/index.tsx), Dexter initializes its main application view:

```tsx
import { render } from 'ink';
import { App } from './components/AgentEventView';

render(<App />);

```

This entry point demonstrates Ink's fundamental paradigm: you write standard JSX components, and Ink handles the translation to terminal-specific rendering instructions.

### Layout Primitives: `Box` and `Text`

Ink provides layout primitives that mirror CSS Flexbox behavior. Dexter uses `Box` (a flex container) and `Text` (styled string output) throughout its component hierarchy.

In [`src/components/Intro.tsx`](https://github.com/virattt/dexter/blob/main/src/components/Intro.tsx), Dexter composes its welcome screen:

```tsx
import { Box, Text } from 'ink';

export const Intro = () => (
  <Box flexDirection="column" padding={1}>
    <Text color="cyan">Welcome to Dexter</Text>
    <Text>Ask any financial question and let the AI agent do the work.</Text>
  </Box>
);

```

The `Box` component accepts props like `flexDirection`, `padding`, and `justifyContent`, enabling Dexter to create structured, visually separated sections without manual coordinate calculations.

### Handling User Input with `useInput`

Interactive CLI applications require real-time keyboard handling. Ink's `useInput` hook captures keystrokes and special keys (arrows, return, escape) through a callback interface.

Dexter implements user query input in [`src/components/Input.tsx`](https://github.com/virattt/dexter/blob/main/src/components/Input.tsx):

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

export const Input = () => {
  const [query, setQuery] = useState('');
  
  useInput((input, key) => {
    if (key.return) submit(query);
    else setQuery(q => q + input);
  });

  return <Text>{query}</Text>;
};

```

Additionally, [`src/cli.tsx`](https://github.com/virattt/dexter/blob/main/src/cli.tsx) utilizes `useApp` alongside `useInput` to manage application exit logic and global keyboard shortcuts, demonstrating how Ink hooks compose to handle complex interaction patterns.

## How Ink Powers Dexter's Interactive Financial Agent

Beyond static layouts, Dexter leverages Ink for dynamic, real-time content updates. The [`src/components/AgentEventView.tsx`](https://github.com/virattt/dexter/blob/main/src/components/AgentEventView.tsx) file renders the AI agent's "thinking" process, tool calls, and progress indicators.

Ink's reconciliation engine efficiently updates only changed terminal cells, allowing Dexter to display streaming AI responses and animated spinners without flickering or full-screen redraws. This capability is crucial for a financial agent CLI, where users expect immediate visual feedback during long-running analysis tasks.

## Summary

- **Ink** is the React-based UI library that powers Dexter's terminal interface, providing a declarative component model for CLI applications.
- **Key files** implementing Ink include [`src/index.tsx`](https://github.com/virattt/dexter/blob/main/src/index.tsx) (render entry), [`src/components/Intro.tsx`](https://github.com/virattt/dexter/blob/main/src/components/Intro.tsx) (layout primitives), [`src/components/Input.tsx`](https://github.com/virattt/dexter/blob/main/src/components/Input.tsx) (input handling), and [`src/cli.tsx`](https://github.com/virattt/dexter/blob/main/src/cli.tsx) (application lifecycle).
- **Core APIs** used are `render`, `Box`, `Text`, `useInput`, and `useApp`, enabling Dexter to create responsive, interactive financial analysis interfaces within the terminal.

## Frequently Asked Questions

### What is Ink and how does it work?

Ink is a React renderer for terminal applications. It allows developers to write JSX components that Ink translates into terminal control sequences, enabling interactive, component-based UIs in command-line environments without manual ANSI escape code manipulation.

### Why did Dexter choose Ink over other CLI libraries?

Dexter selected Ink because it provides a familiar React development model using hooks and components, while offering efficient terminal rendering. This allows the project to maintain complex interactive features—like real-time AI streaming and keyboard navigation—using standard TypeScript patterns rather than imperative terminal libraries.

### Can I use Ink for my own TypeScript CLI projects?

Yes, Ink supports TypeScript natively and works with standard React patterns. You can install it via npm (`npm install ink react`), write components in TSX files, and bundle them with tools like tsx or esbuild. The library provides type definitions for all components and hooks, making it suitable for strongly-typed CLI development.

### How does Dexter handle real-time updates in the terminal?

Dexter uses Ink's reconciliation engine to efficiently update terminal output. When the AI agent streams responses or updates its thinking state, Dexter updates React component props or state, and Ink calculates the minimal set of terminal cells to redraw. This prevents flickering and allows smooth rendering of dynamic content like progress indicators and streaming text in [`src/components/AgentEventView.tsx`](https://github.com/virattt/dexter/blob/main/src/components/AgentEventView.tsx).