Open-source project
zulip/zulip-desktop avatar
zulip/zulip-desktop

zulip-desktop: the Electron client for Zulip on Mac, Windows and Linux

Zulip Desktop client for Mac, Windows and Linux.

992 stars550 forksTypeScriptApache-2.0

At a glance

What is it?
Zulip Desktop is the official Electron client for the Zulip chat platform, sharing most of its code with the Zulip web app and adding the things a browser tab cannot do: multiple organizations, desktop notifications with inline reply, tray integration, a spell checker and automatic updates.
Who is it for?
Adopt zulip-desktop when your organisation runs Zulip and people keep it open all day on more than one Zulip organization, since the multi-account sign-in, inline reply in the notification and the dock or tray presence are the features a browser tab cannot offer. Do not adopt it when your users live in the web app anyway, because the desktop client adds an Electron runtime and a packaging pipeline without adding much to a single-organization workflow.
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 23 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

Editorial analysis

The parts a browser tab cannot do

Zulip Desktop is the desktop client for Zulip, available for Mac, Linux and Windows. The README describes it in one line and then lists five features, and the list is the argument for the app existing at all.

Sign in to multiple organizations. A browser handles one account at a time in one profile, while the desktop client can hold several Zulip organizations at once, which matters for people who work across a company workspace and a volunteer or community workspace.

Desktop notifications with inline reply. The notification itself carries a reply field, so answering a message does not require switching to the window. That is a productivity claim rather than a technical one, but it is the feature that changes behaviour.

Tray and dock integration, so the app lives in the system tray on Linux and Windows and in the dock on Mac rather than only in the task switcher. A multi-language spell checker, and automatic updates.

Everything else the app does, it does because it shares most of its code with the Zulip web app. The README says this directly, and it is the single most important fact for anyone deciding whether to file a bug, extend the app, or adopt it at all.

An Electron app whose UI is the web app

The repository layout explains the architecture. There is an app directory holding the application code, public for static assets, docs with images including light and dark screenshots of the client, packaging for the per-platform build configuration, patches, tests, tools, and build.

The build configuration is electron.vite.config.ts, so the bundler is electron-vite rather than plain Vite, and the application entry point in package.json is ./out/main/index.js. The package is marked private and of type module, so it is an ES module project, and the version in the file matches the latest release tag at 5.13.2.

Two configuration files deserve attention. xo.config.ts sits at the root alongside a XO code style badge in the README, so JavaScript and TypeScript style is enforced by XO rather than left to review. i18next.config.ts shows that translations run through i18next, and the presence of .htmlhintrc and .stylelintrc means the HTML and CSS in the app directory are linted too, not only the scripts.

TypeScript is the primary language, with tsconfig.json, typings.d.ts and a watch-ts script that runs tsc -w for continuous type checking during development.

A small dependency footprint and a pinned toolchain

The dependency list in package.json is unusually short for an application of this size, and that is the clearest sign of the shared-code strategy.

There is exactly one runtime dependency, gatemaker, and the rest are development dependencies. Among those are @electron/remote for remote access to the main process, @sentry/core and @sentry/electron for crash and error reporting, and type packages for the APIs the app uses, including auto-launch, backoff, i18n, minimalistic-assert, node, p-fifo, semver and a tagify binding.

The reason the runtime list is so short is that the bulk of the application, the web app code, is not vendored into this repository as a package dependency in the ordinary sense. It is brought in through the build, which is also why the repository contains a pnpm-workspace.yaml, a patches directory and a tools directory, and why the CI workflow is named node.js.yml.

Toolchain versions are pinned rather than ranged. The packageManager field names pnpm at version 12.4.2 with its integrity hash, the engines field requires Node >=18, and there is an .npmrc at the root. For a team that wants reproducible builds, that is the configuration to trust.

Running the client from source

The scripts section of package.json defines the developer workflow, and each one is a single command.

The dev script installs Electron and starts the development server, the preview script installs Electron and previews a built bundle, and the build script installs Electron and builds the app. The watch-ts script runs the TypeScript compiler in watch mode, and a postinstall hook runs electron-builder install-app-deps so that native dependencies match the Electron runtime.

The build and packaging steps are separate. A build is made with electron-vite, and packaging on top of it is done by electron-builder:

bash
node --run build && electron-builder

There is also a directory-only packaging variant, a macOS App Store target, and an end-to-end test command that builds the app and then runs tape over the test files in the tests directory. The lint and format scripts are separate from the test script, which chains a TypeScript check with the HTML, CSS and JavaScript linters and a Prettier check.

The two identity files are xo.config.ts for JavaScript and TypeScript style and i18next.config.ts for translations. Contributors are pointed to the Zulip community server, the contribution guidelines in CONTRIBUTING.md and the development guide in development.md.

Filing bugs: the shared code decides where they go

The Reporting issues section is short and practical, and it encodes the most confusing thing about this project.

Issues in an individual organization's Zulip window should be reported in the Zulip server and web app project, at zulip/zulip. Other issues, meaning the desktop app and its settings, should be reported in zulip/zulip-desktop, this repository.

So the boundary is per surface rather than per repository. If what you are looking at is a chat window for your organization, it is web app code that happens to be running inside Electron, and the fix belongs upstream in the server and web app project. If what you are looking at is the desktop app itself, its settings, the tray behaviour or the notification handling, it belongs here.

That rule has a practical consequence for teams running their own Zulip server. A fix that changes how a message renders or how a keyboard shortcut behaves will land in the shared web app code and reach every surface, including the web version, not only the desktop client. That is the payoff of sharing code, and it is also why the release numbers here move in step with the web app rather than independently.

Packaging targets and the update path

Three packaging targets appear in the scripts, and each answers a different distribution question.

The plain dist script builds with electron-builder and produces an installer for the current platform. The pack script does the same but with the --dir flag, producing an unpacked directory, which is what you want for a local run or for checking the layout of the output. The mas script targets the Mac App Store specifically with --mac=mas, which is a different signing and sandboxing arrangement from a normal macOS build, and the presence of a separate target for it confirms that the app is distributed both as a direct download and through Apple's store.

The packaging directory and the patches directory at the repository root are where that work lives, and the fact that patches are maintained for this repository means the shared web app code is adjusted as it is consumed here.

Automatic updates are listed as a feature of the app. The mechanism is not described in the README, and neither is the update server, the channel policy, or how an update interacts with a self-hosted Zulip installation. If your organisation runs its own server, that is worth asking about before you rely on it.

Licence, releases and who maintains what

The licence is Apache-2.0, stated in the README and in the LICENSE file at the repository root. It is a permissive licence with an explicit patent grant, which is why the project can share its code with the web app and with organisations that run their own server without a negotiation.

On activity, the repository is not archived and the last push was on 2026-09-29. The recent releases are v5.13.2 on 2026-09-21, v5.13.1 on 2026-09-18 and v5.12.4 on 2026-06-26. Patch releases a few days apart are normal for a client that ships many small fixes, and the version in package.json tracks the release tag exactly, so the commit you build from is identifiable.

The project is maintained by Zulip rather than by a community group, with the issue tracker, the community chat server at chat.zulip.org and the zulip.com/apps homepage as the public faces of it. There is also a changelog.md at the repository root, which is where you look first when a new build behaves differently from the previous one.

The README is explicit that downloads should come from the installation guide at zulip.com/help/desktop-app-install-guide, which is the place to find the packages for Mac, Linux and Windows rather than building from source for everyday use.

Editorial conclusion

Adopt zulip-desktop when your organisation runs Zulip and people keep it open all day on more than one Zulip organization, since the multi-account sign-in, inline reply in the notification and the dock or tray presence are the features a browser tab cannot offer. Do not adopt it when your users live in the web app anyway, because the desktop client adds an Electron runtime and a packaging pipeline without adding much to a single-organization workflow. Verify first that the code your issue touches lives in the right repository, since this client shares most of its code with the Zulip server and web app project and the README routes organisation-window bugs there, then check the installation guide at zulip.com/help/desktop-app-install-guide for the per-platform packages and confirm your Node version satisfies the >=18 requirement before running the build scripts.

Frequently asked questions

Where do I download the Zulip desktop app?

The README points to the installation guide at zulip.com/help/desktop-app-install-guide for downloads, and the desktop client is available for Mac, Linux and Windows.

What does the Zulip desktop client add over the web app?

The README lists sign in to multiple organizations, desktop notifications with inline reply, tray and dock integration, a multi-language spell checker, and automatic updates.

Where should I report a bug in the Zulip desktop app?

Issues in an individual organization's Zulip window go to the Zulip server and web app project at zulip/zulip, because the desktop client shares most of its code with the web app. Issues in the desktop app and its settings go to zulip/zulip-desktop.

What do I need to build the Zulip desktop app from source?

Node >=18 and pnpm, with pnpm at 12.4.2 named as the package manager. The dev script installs Electron and runs electron-vite dev, and the dist script builds and packages with electron-builder.

What licence is the Zulip desktop client released under?

Apache-2.0, stated in the README and with the licence text in the LICENSE file at the repository root.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. zulip/zulip-desktop 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-desktop.svg)](https://hysenlabs.com/projects/zulip-zulip-desktop)

Was this useful?