Skip to main content

FAQ

Frequently asked questions about unblessed.

General​

What is unblessed?​

unblessed is a modern, TypeScript-first terminal UI library for building interactive command-line applications. It's built on top of the original blessed library but reimagined for modern development with cross-platform support (Node.js and browsers).

Is unblessed compatible with blessed?​

Yes! The @unblessed/blessed package provides 100% backward compatibility with blessed. You can drop it in as a replacement and your existing code should work without changes. See the Migration Guide.

Why choose unblessed over blessed?​

  • ✅ TypeScript: Full type safety and IDE autocomplete
  • ✅ Browser Support: Run terminal UIs in browsers with XTerm.js
  • ✅ Modern Build: ESM + CJS, tree-shakeable, actively maintained
  • ✅ Better DX: Improved error messages, comprehensive tests, great docs
  • ✅ Platform Agnostic: Runtime dependency injection allows portability

Why is it called "unblessed"?​

The name reflects that while it's based on blessed, it's been "unblessed" of the legacy patterns and reimagined for modern JavaScript/TypeScript development. It's a fork that has evolved into its own identity.

Installation & Setup​

What Node.js version do I need?​

unblessed requires Node.js >= 22.0.0. This is due to modern JavaScript features used throughout the codebase.

Which package should I install?​

It depends on your use case:

  • @unblessed/node - For new Node.js projects (recommended)
  • @unblessed/browser - For browser-based terminal UIs
  • @unblessed/blessed - For migrating from blessed
  • @unblessed/core - Only if building custom runtime adapters

Do I need to install types separately?​

No! All packages include TypeScript definitions. There's no need for separate @types/* packages.

Can I use unblessed with JavaScript (not TypeScript)?​

Absolutely! unblessed works perfectly with plain JavaScript. TypeScript definitions are included for those who want them, but they're completely optional.

Development​

Do I need to initialize the runtime?​

No! The runtime auto-initializes when you import from @unblessed/node or @unblessed/browser. Just import and use:

import { Screen, Box } from "@unblessed/node";
// Runtime is ready - no setup needed
const screen = new Screen();

Why is my terminal messed up after my app crashes?​

When an app crashes, the terminal might stay in alternate buffer mode or have the cursor hidden. Add cleanup handlers:

screen.key(["C-c"], () => {
screen.destroy();
process.exit(0);
});

process.on("uncaughtException", (err) => {
screen.destroy();
console.error(err);
process.exit(1);
});

How do I debug rendering issues?​

Enable debug mode:

const screen = new Screen({
debug: true,
log: "./debug.log",
});

This logs all rendering operations to help diagnose issues.

Can I use unblessed with tsx or ts-node?​

Yes! unblessed works with all TypeScript runners:

# tsx (recommended)
tsx app.ts

# ts-node
ts-node app.ts

# esbuild
node --loader esbuild-register app.ts

Browser Support​

Can I really run terminal UIs in browsers?​

Yes! The @unblessed/browser package uses XTerm.js to create a terminal emulator in the browser. Your unblessed widgets render inside it just like in a real terminal.

What doesn't work in browsers?​

  • Real file system: Virtual FS with bundled data only
  • Child processes: Terminal widget won't work
  • Native TTY: Always reports as TTY in browsers

See Browser Platform Guide for details.

Do I need Vite to use unblessed in browsers?​

No, but Vite is recommended. unblessed works with any modern bundler (Webpack, Rollup, esbuild). See the Browser Guide for bundler configuration.

Widgets & Features​

How do I create a widget?​

Use the parent option to attach widgets:

const box = new Box({
parent: screen, // Required
content: "Hello",
border: { type: "line" },
});

Why isn't my widget showing?​

Common issues:

  1. Forgot to call screen.render():

    screen.render(); // Must call this!
  2. Widget is off-screen: Check positioning

    // ❌ Bad - might be off screen
    box.top = 1000;

    // ✅ Good
    box.top = "center";
  3. No parent: Widget must be attached

    // ✅ Always specify parent
    const box = new Box({ parent: screen });

How do I handle keyboard input?​

Global keys:

screen.key(["C-c", "q"], () => process.exit(0));

Widget-specific keys:

list.key("enter", () => {
const selected = list.selected;
// Handle selection
});

How do I handle mouse events?​

Enable mouse on the widget:

const box = new Box({
parent: screen,
mouse: true, // Enable mouse
clickable: true,
});

box.on("click", (data) => {
console.log("Clicked at", data.x, data.y);
});

How do I style widgets?​

Use the style object:

const box = new Box({
style: {
fg: "white",
bg: "blue",
border: { fg: "cyan" },
focus: { border: { fg: "green" } },
hover: { bg: "gray" },
},
});

Or use inline tags:

const box = new Box({
content: "{red-fg}Error:{/red-fg} Something went wrong",
tags: true, // Enable tag parsing
});

What colors are supported?​

  • Named colors: 'red', 'blue', 'green', etc.
  • Hex colors: '#ff0000', '#00ff00'
  • 256-color: 196 (color index)
  • Default: 'default' or -1

Testing​

How do I test terminal UIs?​

Use the @unblessed/vrt package for visual regression testing:

import { compareWithGolden } from "@unblessed/vrt";

it("renders correctly", () => {
const screen = new Screen();
const box = new Box({ parent: screen, content: "Test" });
screen.render();

const recording = createRecording(screen);
const result = compareWithGolden("golden.vrt.json", recording);

expect(result.pass).toBe(true);
screen.destroy();
});

See the Testing Guide for details.

Can I use Jest with unblessed?​

Yes! unblessed works with Jest, Vitest, and other test frameworks. For Jest, you may need to configure ESM support:

// jest.config.js
export default {
extensionsToTreatAsEsm: [".ts"],
transform: {
"^.+\\.ts$": ["ts-jest", { useESM: true }],
},
};

Performance​

Is unblessed fast?​

Yes! Performance benchmarks on modern hardware:

  • Empty screen render: ~6.5ms
  • Complex screen (100 boxes): ~11ms
  • Large list (1K items): ~187ms

Use smartCSR: true for optimal performance.

How do I optimize rendering?​

  1. Enable smart CSR:

    const screen = new Screen({ smartCSR: true });
  2. Batch updates:

    // ❌ Bad - renders 3 times
    box1.setContent("One");
    screen.render();
    box2.setContent("Two");
    screen.render();
    box3.setContent("Three");
    screen.render();

    // ✅ Good - renders once
    box1.setContent("One");
    box2.setContent("Two");
    box3.setContent("Three");
    screen.render();
  3. Use alwaysScroll: false when not needed

See Performance Guide for more tips.

Troubleshooting​

My colors aren't showing correctly​

Check your terminal's color support:

echo $TERM
# Should be something like "xterm-256color"

Set it if needed:

export TERM=xterm-256color

Mouse events aren't working​

  1. Check terminal support: Not all terminals support mouse
  2. Enable mouse on widget:
    const box = new Box({ mouse: true });
  3. Check terminal multiplexers: tmux/screen need configuration

Unicode characters aren't rendering​

Enable full unicode support:

const screen = new Screen({
fullUnicode: true,
});

Application hangs on exit​

Make sure to call screen.destroy():

screen.key(["C-c"], () => {
screen.destroy(); // Important!
process.exit(0);
});

Contributing​

How can I contribute?​

We welcome contributions! Ways to help:

Check the repository for contribution guidelines.

I found a bug, what should I include?​

Please include:

  • unblessed version (npm list @unblessed/node)
  • Node.js version (node --version)
  • Terminal emulator and OS
  • Minimal code to reproduce
  • Expected vs actual behavior
  • Screenshots if relevant

Can I use unblessed in commercial projects?​

Yes! unblessed is MIT licensed - use it freely in commercial and open-source projects.

Project Status​

Is unblessed production-ready?​

unblessed is currently in alpha. The API is stable and backward-compatible with blessed, but:

  • ✅ Core functionality is solid (2,112 tests passing)
  • ✅ Safe for non-critical applications
  • ⚠️ API may have minor changes before 1.0
  • ⚠️ Some edge cases may not be covered

We welcome alpha testers to help us reach 1.0!

What's the roadmap?​

Current priorities:

  1. Alpha: API stabilization, bug fixes, documentation
  2. Beta: Performance optimization, more examples
  3. 1.0: Production-ready release

See GitHub Milestones for details.

How often is unblessed updated?​

We follow semantic versioning with automated releases:

  • Patch releases (bug fixes): As needed
  • Minor releases (features): Monthly
  • Major releases (breaking changes): Rare, planned ahead

Getting Help​

Where can I get help?​

  • 📖 Documentation: Start here - most questions are answered in the docs
  • 💬 GitHub Discussions: Ask questions, share ideas
  • 🐛 GitHub Issues: Report bugs, request features
  • 📧 Direct Contact: For security issues only

The docs don't answer my question​

We're always improving! Please:

  1. Ask in GitHub Discussions
  2. Suggest doc improvements via issues
  3. Submit a PR to improve documentation

Still Have Questions?​

If your question isn't answered here: