# nchat puts Telegram, WhatsApp and Signal behind one ncurses key map

> nchat is a C++ terminal client that binds Telegram, WhatsApp and Signal into one ncurses interface with a shared key map and a local message cache. It installs by Brew tap, yay, a curl script, or a make.sh build that pulls tdlib in.

**d99kris/nchat** — Terminal-based messaging client for Linux and macOS with Telegram, WhatsApp and Signal support

- Repository: https://github.com/d99kris/nchat
- Stars: 1,999 · Forks: 135
- Language: C++
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/d99kris-nchat

## One window, three protocols, one key map

nchat is a terminal-based multi-protocol messaging client for Linux and macOS with support for Telegram, WhatsApp and Signal. The interesting engineering is not that it renders chat in a terminal, it is that three protocols with different session models, media handling and authentication flows are presented through one interface.

The feature list is a normal messenger feature list, which is the point: markdown formatted messages, reply, delete, edit and forward, mentions in groups, reactions, read and edited indicators, user status including online, away and typing, jumping to the next unread chat, archiving, pinning and deleting chats, search within a chat, and list dialogs for chats, contacts, emojis and files. Media can be viewed and saved, and there are desktop notifications for new messages.

Two features are quietly important. The message history cache with text export means the client keeps history locally, and the toggle between textized and graphical emojis deals with the fact that a terminal's font decides whether an emoji is legible. Themes and key bindings are customisable through the project wiki.

The repository carries an MIT LICENSE at the root alongside LICENSE.AGPL-3.0 and LICENSE.GPL-3.0, which is the licensing arrangement you would expect for a client that links protocol libraries under copyleft: your own code stays MIT while the vendored components keep their terms.

## Installing where a package exists, and where one does not

Four routes are documented, and they differ in what you get.

On macOS the Brew tap builds the stable release:

```bash
brew tap d99kris/nchat
brew install nchat
```

Protocols can be dropped at install time, for example brew install nchat --without-telegram or --without-whatsapp, which is useful if you do not want to build a stack you will not use.

Arch has three separate targets: yay -S nchat-git for the latest git, yay -S nchat for the stable release, and yay -S nchat-bin for a pre-built binary.

The pre-built binary route is a curl pipe, for Linux with glibc 2.28 or later or musl on x86_64 and arm64, and for macOS arm64. The README calls that support experimental:

```bash
curl -fsSL https://raw.githubusercontent.com/d99kris/nchat/master/utils/install.sh | bash
```

Removal is the matching uninstall.sh from the same directory. It installs into your home directory under .local, both bin and share, and NCHAT_PREFIX overrides the location if you want /usr/local instead.

Piping a shell script from a repository URL is worth weighing. It executes whatever is on the branch at that moment, and the uninstall path has the same property, so read utils/install.sh before running it if that matters to you.

## Building from source means you are building tdlib too

The README warns about this up front: nchat consists of a large code base, mainly the Telegram library tdlib, so expect a relatively long first build. The source tree has CMakeLists.txt, src/, lib/, make.sh, and separate etc/, themes/, utils/, tests/ and dev/ directories.

Get the source first:

```bash
git clone https://github.com/d99kris/nchat && cd nchat
```

On macOS, Alpine, Arch, Fedora, Gentoo, Raspbian, Ubuntu or Void, the make.sh script handles it in two calls:

```bash
./make.sh deps
./make.sh build && ./make.sh install
```

That path installs to a system prefix such as /usr/local, and NCHAT_PREFIX overrides it again, with the README noting that a user-writable prefix installs without sudo or doas.

Doing it by hand means installing the dependency set yourself, and the lists differ enough to be worth reading rather than guessing. On Debian-based systems it is ccache, cmake, build-essential, gperf, help2man, libreadline-dev, libssl-dev, libncurses-dev, libncursesw5-dev, ncurses-doc, zlib1g-dev, libsqlite3-dev, libmagic-dev and golang. macOS uses brew for the same idea. Two optional pieces get called out: wl-clipboard on Wayland systems for clipboard functionality, and libpng-dev if you want to paste images straight from the clipboard.

ccache appears in every list, which tells you the project expects repeat local builds.

## The key map is the product, and it is long

What makes a terminal client usable is the key map, and the README documents it exhaustively. Global navigation uses Tab and Shift-Tab to move between chats, Ctrl-f to jump to the unread chat, Ctrl-n to go to a chat, Ctrl-q to quit, and Ctrl-l and Ctrl-p to toggle the contact list and top bar.

Message actions hang off a selected message rather than the current text, which is a design decision that avoids a single key meaning two things. With a message selected, Ctrl-r downloads the attached file, Ctrl-v opens or views it, Ctrl-w opens a link, Ctrl-x replies to that message, Ctrl-z edits it, Alt-c copies it to the clipboard, Alt-q jumps to the quoted message, Alt-r forwards it, Alt-s toggles a reaction, and Alt-w opens it in an external viewer. Ctrl-d deletes the selected message.

Text input has its own set, so Ctrl-a and Ctrl-e move to start and end of line, Ctrl-u and Ctrl-k delete either side of the cursor, Alt-Left and Alt-Right move by word, Alt-Backsp and Alt-Delete delete a word, and Alt-c, Alt-v and Alt-x are copy, paste and cut for the input buffer when nothing is selected.

Two integrations stand out. Alt-e opens an external editor to compose, and Alt-$ runs an external spell check, which is how a terminal client borrows a real writing workflow rather than reimplementing one.

The command line is small in comparison: -d or --confdir for a directory other than ~/.config/nchat, -e and -ee for verbose and extra verbose logging, -k for a key code dump mode, -m for developer mode, -r to remove a protocol account, -s to set one up, -x to export the message cache to a directory, and -v and -h for version and help. -k in particular is what you want when writing custom key bindings.

## Account setup is a first-run flag, not a config file

There is no documented configuration file format, which is a real difference from most clients. The interface is configured through preferences inside the application, and account setup happens through the -s flag, which sets up a chat protocol account.

The pairing of -s and -r is the whole account lifecycle: create credentials, or remove them. That matters because a terminal client typically has no system keychain integration described here, so credentials live in the configuration directory that -d or --confdir points at, defaulting to ~/.config/nchat.

The message cache is the other persistent artefact. It backs history paging with PageUp and PageDn, survives restarts, and can be dumped out as text with -x, which is the escape hatch if you want your conversations in a format you can read with other tools.

What the README does not document is where credentials are stored, how they are protected, or whether the cache is encrypted at rest. For a messenger, that is the first question to answer from the documentation site before you adopt it, and it is a gap in the README rather than an answer.

## Platform support, release cadence, and what is missing

nchat is developed and tested on Linux and macOS, and the README names the current test targets as macOS Sequoia 15.5 and Ubuntu 24.04 LTS. Windows is not listed, and the pre-built binary section covers Linux on x86_64 and arm64 plus macOS arm64, so an Intel Mac is covered only by building.

Releases come frequently: v5.19.18 on 2026-09-26, v5.18.20 on 2026-08-15, v5.17.26 on 2026-07-18, with the last push on 2026-10-03 and the repository not archived. The version number in the five range suggests an actively developed application rather than a stable library API, so expect churn in key bindings and configuration between minor versions.

The functional gaps are visible from the key map rather than from a to-do list. There is no built-in voice or video call interface: Alt-t exists as an external telephone call command, which means the client hands off rather than carrying the call. Media handling is present for documents, photos and videos, and image pasting from the clipboard needs libpng-dev, so that path is optional by design.

 nchat earns its place when the protocols you use are already fixed and the terminal is where you live.

## Conclusion

nchat suits a Linux or macOS user who lives in the terminal and wants Telegram, WhatsApp and Signal in one window instead of three apps, and who is willing to read a long key map. It is the wrong choice on Windows, which the README does not list as a supported platform, or if you need voice and video calls, since the documented key map covers text, files and an external telephone command but no call UI. Verify first that your distribution has a package route, brew tap d99kris/nchat on macOS or yay -S nchat-bin on Arch, since building from source means compiling tdlib and takes a while.

## FAQ

### Which messaging protocols does nchat support?

Telegram, WhatsApp and Signal, in one terminal interface. The README also documents install-time flags such as --without-whatsapp and --without-telegram on Homebrew to leave a protocol out.

### How do I install nchat without building it from source?

On macOS use brew tap d99kris/nchat then brew install nchat. On Arch use yay -S nchat-bin for a pre-built binary. For Linux glibc 2.28 or musl and macOS arm64 there is a curl script at utils/install.sh that installs into ~/.local, overridable with NCHAT_PREFIX.

### Can I export nchat message history to text?

Yes. The -x or --export option exports the message cache to a specified directory, and history paging is bound to PageUp and PageDn inside the application.

## Sources

- [d99kris/nchat on GitHub](https://github.com/d99kris/nchat)
- [Issues](https://github.com/d99kris/nchat/issues)
- [License: MIT](https://github.com/d99kris/nchat/blob/master/LICENSE)
- [README](https://github.com/d99kris/nchat/blob/master/README.md)
- [Releases](https://github.com/d99kris/nchat/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/d99kris-nchat
