Open-source project
zulip/zulip-terminal avatar
zulip/zulip-terminal

zulip-terminal is the Zulip client for people who work in a terminal

Official Zulip terminal client.

873 stars367 forksPythonApache-2.0

At a glance

What is it?
zulip-terminal is Zulip's official text-mode client, built on urwid, and it trades the browser interface for keyboard-only navigation in a window that scales from 80x24 upwards. The project documents its gaps against the web client honestly, but its last tagged release was 0.7.0 in 2022 while the main branch has kept moving since.
Who is it for?
zulip-terminal suits a developer who lives in a terminal, wants Zulip reachable over ssh, and prefers a keyboard-only client to a browser tab that reloads and animates. It does not suit an administrator, who cannot perform owner operations, edit all settings, or use a mouse for every action, and it is a poor fit for anyone who needs an internationalised interface.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 68 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A text interface aimed at the 80x24 terminal

Zulip Terminal is the official terminal client for Zulip, a text-based user interface built on urwid. Its stated aims say a lot about who it is for. It wants to give a broadly similar experience to the Zulip web client, ultimately supporting all of its features. It wants every action reachable from the keyboard. It wants to explore interface designs that suit the constraints of a display and a keyboard. It wants to support a wide range of platforms and terminal emulators. And it wants to make best use of the rows and columns available, scaling from 80x24 upwards.

The project describes itself as already providing a fairly stable, moderately featureful everyday experience, and says the development focus is on the parts of ordinary usage that most often force a user to switch to another client for one particular feature.

That last point is the honest summary. This is not a terminal emulator of the web client. It is a client built around the assumption that you are typing, on a machine you may be connected to remotely, and that the things you do most often are reading a stream, replying, and moving between conversations.

pip3 install zulip-term, or a virtual environment named zt_venv

The recommended install is a dedicated Python virtual environment, or an automated option such as pipx. The stable release is published on PyPI as zulip-term.

bash
pip3 install zulip-term

The development version comes from the main branch of the repository instead.

bash
pip3 install git+https://github.com/zulip/zulip-terminal.git@main

The isolated environment version takes three steps, and the project says Python 3.6 or newer is required to run the client.

bash
python3 -m venv zt_venv
source zt_venv/bin/activate

The activation step has to be repeated in every new shell window, which the documentation points out explicitly. Sample Dockerfiles are also provided under docker/.

There is one warning that a reader should not skip. The documentation states that there is no automatic-update system, so you have to track the update locations that matter to you. For a client that talks to a chat server whose protocol changes over time, that means deciding for yourself whether to stay on a tagged release or follow the main branch.

Four keys that deliberately differ from the web client

The hot keys are listed in a separate document, and the README calls out the ones that differ from the web client. Navigation aside, the additions are z, t, # and f.

z zooms in and out, and it works between streams and topics or between all direct messages and specific conversations. t toggles the view of topics for a stream in the left panel, a key the web client later adopted for recent topics. # narrows to messages in which you are mentioned, since @ is already used for something else. f narrows to messages you have starred, described as following.

Those keys are not arbitrary. They exist because the client is designed for someone who is not using a mouse, and a keyboard-only interface has to compress navigation into a small set of memorable positions. Every one of them narrows the view rather than opening a screen, which is a different interaction model from the web client.

One behaviour is worth knowing before you file a bug. The terminal client does not mark additional messages as read when the end of a conversation is visible, and there is a dedicated FAQ entry on when messages are marked as having been read. The web client marks them as you scroll, and this difference surprises people moving between the two.

Emoji become text and images become footlinks

The README is explicit about the rendering trade-offs, and the reason given is terminal and font compatibility. Emoji and reactions are rendered as text only. Images, which the web client can preview inline, are instead stored as footlinks, which are footnotes for links that keep messages readable while retaining a list of links to cross-reference.

This is the single clearest example of the project's philosophy. A terminal cannot assume the font on the other end has the glyph, and it cannot assume the image is worth the rows. So the client trades fidelity for reliability, and it says so rather than pretending the limitation is a feature.

The same reasoning shows up in the aim to support a wide range of platforms and terminal emulators. Rendering nothing that might break is how you keep a client usable over ssh on a machine you do not control. The cost is that a channel that depends on images loses something on the terminal side that it has in the browser.

Four capabilities the project says it will not have soon

The feature status section lists the limitations it expects to resolve only over the long term. Four are named.

Operations performed by users with extra privileges, that is owners and admins, are not supported. Accessing and updating all settings is not supported. Using a mouse or pointer to achieve all actions is not supported. And an internationalised UI is not supported.

The last one is the most consequential for a team. A terminal client without translation is a client for people who read English.

For queries about anything else that is missing, the documentation points at three places: the FAQ document, the open issues, and the Zulip community server. That is an honest way to handle a client that will never be complete, but it also means the answer to a specific question often lives outside the README, and you should expect to read the FAQ rather than find a feature list.

The last tag is from 2022, the branch is from 2026

The release list is thin and old: 0.7.0 in May 2022, 0.6.0 in January 2021 and 0.5.2 in July 2020. The last push to the repository was on 2026-08-16, and the client is still described as the official one, with the same CI, linting and coverage badges as before.

So the project is being worked on and the release tags are not keeping up with it. That distinction matters more here than in most projects, because the documentation tells you to install the git main branch if you want the latest development version, and that branch is where the recent work lives. A user who installs from PyPI gets 0.7.0.

The tooling in the repository suggests a very old Python baseline that is still being honoured. The mypy configuration sets python_version to 3.7, and the linting dependencies are pinned to versions chosen because later releases drop Python 3.7 support, including black 23.3.0 and ruff 0.0.267. The testing dependencies carry the same reasoning in their comments. The licence is Apache-2.0, which is permissive for a client that organisations deploy on developer machines.

Against the web client, the difference is the input model

The alternative is the Zulip web client, and the documentation treats it as the thing to be similar to rather than a competitor. The difference in approach is the input model. The browser client assumes a pointer, a scroll wheel, images and inline previews, and it renders emoji. The terminal client assumes a keyboard and a fixed grid, which is why it needs its own key map, why it renders reactions as text, and why it uses footlinks for images.

For the same reason, the terminal client scales down to 80x24 and up, and it is reachable over ssh on a remote box, where a browser client would need a forwarding setup. If you spend your day in a terminal window and you mostly read and reply, the terminal client removes the browser from the loop entirely.

If you also need to administer an organisation, upload a file and expect an inline preview, the web client remains the place to be, and the README is honest that these gaps are long term rather than imminent.

Editorial conclusion

zulip-terminal suits a developer who lives in a terminal, wants Zulip reachable over ssh, and prefers a keyboard-only client to a browser tab that reloads and animates. It does not suit an administrator, who cannot perform owner operations, edit all settings, or use a mouse for every action, and it is a poor fit for anyone who needs an internationalised interface. Verify first that your Zulip server and account work with the client, install it into a dedicated virtual environment so a dependency change cannot break your shell tooling, and treat pip3 install git+https://github.com/zulip/zulip-terminal.git@main as the version you will actually be running.

Frequently asked questions

How do I install zulip-terminal?

The stable release is on PyPI as zulip-term, installed with pip3 install zulip-term. The documentation recommends a dedicated virtual environment, created with python3 -m venv zt_venv and activated with source zt_venv/bin/activate, or an automated option such as pipx.

Does zulip-terminal update itself?

No. The documentation states there is no automatic-update system, so you have to track the update locations relevant to you. Sample Dockerfiles are provided under the docker/ directory.

Which features does the Zulip terminal client not support?

The README lists the long term gaps as operations performed by owners and admins, accessing and updating all settings, using a mouse to achieve all actions, and an internationalised UI.

How do emoji and images appear in zulip-terminal?

Emoji and reactions are rendered as text only, for terminal and font compatibility. Images that the web client can preview are instead stored as footlinks, footnotes for links that keep messages readable.

What version of zulip-terminal is current?

The listed releases stop at 0.7.0 from 2022-05-21, while the last push to the repository was on 2026-08-16. Installing from git with pip3 install git+https://github.com/zulip/zulip-terminal.git@main is how you get the current code.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. zulip/zulip-terminal on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/zulip-zulip-terminal.svg)](https://hysenlabs.com/projects/zulip-zulip-terminal)