# How Tabby Handles Unicode and Double-Width Characters in the Terminal

> Discover how Tabby terminal renders Unicode and double-width characters accurately. Learn about its use of xterm.js and wcwidth for proper cell allocation.

- Repository: [Eugene/tabby](https://github.com/Eugeny/tabby)
- Tags: internals
- Published: 2026-03-03

---

**Tabby delegates Unicode width calculations to xterm.js’s Unicode 11 addon, which uses the wcwidth library to correctly allocate one or two terminal cells per character according to the Unicode 11 standard.**

Tabby is a modern, open-source terminal emulator built on web technologies. To ensure accurate rendering of international text, emoji, and CJK (Chinese, Japanese, Korean) glyphs, Tabby implements a specialized system for handling Unicode and double-width characters. This architecture leverages battle-tested libraries rather than custom measurement logic to maintain proper terminal alignment across diverse character sets.

## Unicode Handling Architecture in Tabby

Tabby’s terminal emulation foundation rests on **xterm.js**, a widely adopted web terminal library. Rather than building proprietary Unicode measurement code, Tabby integrates **xterm.js’s Unicode 11 addon** to handle character width determination.

The addon implements the **Unicode 11 standard’s width tables**, ensuring that characters occupying two display cells—such as CJK ideographs, emojis, and certain mathematical symbols—receive the correct horizontal space allocation. This approach eliminates rendering misalignment issues common in terminals that assume mono-width for all glyphs.

## How the Unicode 11 Addon Works

Internally, the Unicode 11 addon relies on the **`wcwidth`** library to compute the column width of individual code points. The `wcwidth` dependency is pinned at version `^1.0.0` in Tabby’s `yarn.lock` file, ensuring consistent behavior across installations.

When active, xterm.js uses these width calculations to:

- Calculate precise cursor movement for wide characters
- Ensure line-wrapping respects actual visual widths rather than raw character counts
- Maintain proper alignment of the buffer, selection regions, and mouse interactions

This delegation allows Tabby to support the full range of Unicode characters without maintaining complex width tables in its own codebase.

## Implementation in XTermFrontend

The integration occurs in the `XTermFrontend` class located at [`tabby-terminal/src/frontends/xtermFrontend.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-terminal/src/frontends/xtermFrontend.ts). Tabby configures Unicode support through three specific steps:

1. **Import the Addon**

   At line 12, Tabby imports the Unicode handling module:

   ```typescript
   import { Unicode11Addon } from '@xterm/addon-unicode11'
   ```

2. **Load the Addon**

   Between lines 147-148, the addon is instantiated and registered with the terminal instance:

   ```typescript
   this.xterm.loadAddon(new Unicode11Addon())
   ```

3. **Activate Unicode 11**

   At line 157, Tabby explicitly enables the Unicode 11 width tables:

   ```typescript
   this.xterm.unicode.activeVersion = '11'
   ```

## Practical Code Example

Below is a simplified implementation demonstrating how Tabby initializes a terminal with full Unicode support:

```typescript
import { Terminal } from '@xterm/xterm';
import { Unicode11Addon } from '@xterm/addon-unicode11';

// Initialize terminal instance
const term = new Terminal({
  allowTransparency: true,
  allowProposedApi: true,
});

// Load Unicode 11 addon for double-width support
term.loadAddon(new Unicode11Addon());

// Activate Unicode 11 width tables
term.unicode.activeVersion = '11';

// Open terminal and write mixed-width content
term.open(document.getElementById('terminal')!);
term.write('Emoji: 😀 CJK: 你好 Double-width: 𝔘𝔫𝔦𝔠𝔬𝔡𝔢\r\n');

```

## Why This Architecture Matters

By delegating width calculations to xterm.js’s addon ecosystem, Tabby achieves several critical advantages:

- **Standards compliance**: Automatic adherence to Unicode 11 specifications without manual table updates
- **Reduced complexity**: No custom width-measurement code to maintain in the Tabby repository
- **Battle-tested reliability**: Leverages the same libraries used by millions of VS Code users and other xterm.js-based applications

This design ensures that whether displaying standard ASCII, combining diacritics, or full-width emoji, Tabby allocates exactly the correct number of terminal cells for every glyph.

## Summary

- Tabby uses **xterm.js’s Unicode 11 addon** to handle all Unicode width calculations
- The **`wcwidth`** library provides the underlying column-width computations
- Activation occurs in `XTermFrontend` via three steps: import at line 12, `loadAddon()` at lines 147-148, and setting `unicode.activeVersion = '11'` at line 157
- This architecture eliminates rendering misalignment for CJK characters, emoji, and other double-width glyphs
- All width logic is delegated to battle-tested external libraries, keeping Tabby’s codebase maintainable

## Frequently Asked Questions

### How does Tabby determine the width of Unicode characters?

Tabby delegates width determination to the **wcwidth** library through xterm.js’s Unicode 11 addon. When a character is rendered, the addon queries wcwidth to determine whether the code point occupies one or two terminal columns according to the Unicode 11 standard.

### What Unicode version does Tabby support for character widths?

Tabby explicitly activates **Unicode 11** by setting `this.xterm.unicode.activeVersion = '11'` in the `XTermFrontend` class. This version includes comprehensive width tables for modern emoji, CJK characters, and other double-width glyphs.

### Does Tabby require manual configuration to display CJK characters correctly?

No manual configuration is required. Tabby automatically loads the Unicode 11 addon during initialization in [`tabby-terminal/src/frontends/xtermFrontend.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-terminal/src/frontends/xtermFrontend.ts), ensuring that double-width characters render correctly immediately upon startup without user intervention.

### Where is the Unicode handling code located in Tabby's source?

The primary integration resides in [`tabby-terminal/src/frontends/xtermFrontend.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-terminal/src/frontends/xtermFrontend.ts), specifically at lines 12 (import), 147-148 (addon loading), and 157 (activation). The underlying width tables are provided by the `@xterm/addon-unicode11` dependency, which utilizes the `wcwidth` library pinned in `yarn.lock`.