Open-source project
signalapp/Signal-Desktop avatar
signalapp/Signal-Desktop

Signal Desktop, a linked client that cannot register an account

A private messenger for Windows, macOS, and Linux.

16,687 stars3,178 forksTypeScriptAGPL-3.0

At a glance

What is it?
Signal Desktop is Signal's Electron client for Windows, macOS and Linux, and it attaches to an account that already exists on an Android or iOS phone. It publishes no installable package, its working tree runs ahead of every published tag, and its AGPL-3.0-only licence is the first thing a forking team has to settle.
Who is it for?
Signal Desktop fits a team that already runs Signal on an Android or iOS handset and needs PDF handling, screen sharing or call diagnostics on a workstation, and that can accept an upgrade path tracked by hand at a download or a git tag. It does not fit anyone looking for a standalone desktop messenger or a registry dependency, because package.json is marked private and the client has no registration path of its own.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 3 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 November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • signalapp/Signal-Desktop16,687 ★ · +144
Star history
Repository2026-09-212026-11-14
signalapp/Signal-Desktop16.5k16.7k

144 Stars in the last 54 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Signal Desktop cannot register an account, so a phone is a hard prerequisite

Signal Desktop cannot register an account. Its README opens with the whole of its stated scope: it links with Signal on Android or iOS and lets you message from Windows, macOS and Linux computers. Everything the desktop app does is downstream of that link.

The missing half lives in sibling repositories. The README links Signal-Android and Signal-iOS. Registering an account is the phone app's job, and this repository never takes it over.

The consequence for an engineer is concrete. A team that wants Signal on a workstation only, with no handset in the loop, cannot configure its way there. No standalone mode exists to enable, no offline account to create, and the root listing ships nothing that would substitute for a phone. Everything you read further down this article is a feature of a second device, not of an independent client.

package.json is marked private, so there is no package to install

Installing Signal Desktop is a download, not a dependency. Two links are offered, the production build at signal.org/download and a beta build reached through a support article. Neither is a package manager target, and package.json says why.

json
"private": true,
"name": "signal-desktop",
"productName": "Signal",
"desktopName": "signal.desktop",
"main": "bundles/main.js",
"browserslist": "last 1 chrome versions"

The private flag means the workspace is never published to a registry, so an install of signal-desktop from npm or pnpm resolves to nothing. Whatever you want to pin, vendor or audit has to be pinned at a release artefact from signal.org or at a git tag.

That moves the upgrade question onto your desk. A team tracking a dependency reads a lockfile and sees what changed between versions. A team tracking this client tracks a downloaded binary or a commit. The browserslist entry tightens the same point at the front end: only the most recent Chromium is targeted, so there is no downlevelled fallback for an older embedded browser.

One more script deserves attention before a fork. The notarize entry in package.json reads:

json
"notarize": "echo 'No longer necessary'"

The script only prints that notarisation is no longer necessary; it does not say where that step now happens. A team that intends to redistribute rather than download has to answer that question outside the repository.

main is 8.32.0-alpha.1 while the newest tag is v8.30.0-beta.1

The releases tab and the working tree disagree about where the project is. The three most recent releases are v8.34.0-beta.1 published on 2026-10-28, v8.33.0 published on 2026-10-28 and v8.33.0-beta.1 published on 2026-10-20. The last push to main was on 2026-11-02. package.json in that same tree declares version 8.36.0-alpha.1.

Cloning main therefore hands you a build sitting between the shipped beta and the next release. No CHANGELOG file appears among the root entries, and the README carries no summary of what a release contains.

A .changeset/ directory sits at the root, while the README itself points only to the issue tracker, with an instruction to search existing issues before filing a duplicate. Plan a pin around a published tag rather than around main.

generate runs build:protobuf before build:rolldown:prod

Building this client is a two-phase pipeline, and the ordering is the interesting part. Phase zero is serial, phase one runs in parallel, and the database schema sits inside phase one.

json
"generate:phase-0": "run-s build:protobuf build:emoji-data build:rolldown:prod",
"generate:phase-1": "run-p --aggregate-output --print-label build:icu-types build:compact-locales build:styles:prod get-expire-time build:policy-files build:db-schema"

A protos directory at the repository root holds the wire definitions that build:protobuf consumes, and DATABASE_SCHEMA.md documents the local store that build:db-schema emits. Both are generated outputs, so a fork that changes what a message carries has to change the proto definitions and the schema, then re-run the pipeline. Editing generated files instead of their inputs buys you a build that is overwritten on the next pass.

None of this appears in the README. It points contributors at CONTRIBUTING.md and leaves the build order to package.json, so an engineer planning a fork learns the sequence from a script field and the data shape from a separate markdown file before writing a line of code.

Strings leave through Smartling and return through get-strings

Localisation is a vendor round trip, not a pull request. The root listing includes .smartling.yml and .smartling-source-example.sh, and the get-strings pipeline fans out from them.

json
"get-strings": "node scripts/get-strings.mjs && node scripts/gen-nsis-script.mjs && node scripts/gen-locales-config.mjs && run-p get-strings:locales get-strings:countries get-strings:emoji mark-unusued-strings-deleted && run-p build:compact-locales",
"get-strings:locales": "node scripts/build-localized-display-names.mjs locales scripts/locale-data/locale-display-names.csv build/locale-display-names.json"

The second line shows the shape of the work. Display names and country names are read from CSV files under scripts/locale-data and written into build as JSON, emoji data comes from scripts/get-emoji-locales.mjs, and the same command generates the NSIS installer script, which is how a Windows package ends up carrying the locale configuration.

One naming detail matters before you go looking: the script is spelled mark-unusued-strings-deleted in package.json, and searching the tree for the corrected spelling finds nothing.

background.html and seven sibling documents no README section explains

The renderer surface is split across separate documents. The root listing holds background.html next to loading.html, about.html, pdf.html, screenShare.html, call_diagnostic.html, debug_log.html and permissions_popup.html, with preload.wrapper.ts and a config directory beside them and bundles/main.js as the main entry.

Electron is named in the scripts themselves, since the start entry is electron . and the postinstall hook calls electron:install-app-deps. In that model the main process in bundles/main.js owns the windows and each HTML document is its own renderer with its own context. The file names indicate the intent: a permission prompt and a screen sharing surface exist as separate documents, and debug_log.html is a destination a user can be sent to when something breaks.

The cost lands on every change. A change to window behaviour has to be checked in each document rather than in one place, and no README section covers any of them, so you cannot learn from the documentation which documents are active in the build you installed. For a team writing support documentation, the repository hands over file names and no behaviour at all.

AGPL-3.0-only and export classification 5D002.C.1 set the cost of a fork

Two legal facts in the repository decide what you may do with it. The licence field reads AGPL-3.0-only, and the README closes with a link to the GNU AGPLv3 at gnu.org/licenses/agpl-3.0.html under Copyright 2013-2024 Signal Messenger, LLC.

The cryptography notice is the less usual one. It states that the Bureau of Industry and Security classifies the software as Export Commodity Control Number 5D002.C.1, covering information security software that uses or performs cryptographic functions with asymmetric algorithms, and that this form of distribution is eligible for export under the License Exception ENC Technology Software Unrestricted exception, citing Section 740.13 of the export regulations, for both object code and source code.

What that rules out is easy to state. The repository offers no alternative grant and names no commercial licence, so a team shipping a modified build inside a closed-source product has to settle the AGPL obligations before writing code rather than after. The README also directs users to check their own country's rules on the import, possession, use and re-export of encryption software before using it. That is a genuine gate for a reader outside the United States, and the repository offers nothing further to resolve it.

pdf.html and screenShare.html are the reason the desktop build exists

The README gives one justification for this project: it lets you message from your computers. Everything past that sentence appears only in the file listing. pdf.html is a document for PDF content, screenShare.html is a document for sharing a screen, and call_diagnostic.html and debug_log.html are diagnostics surfaces. Nothing in the documentation explains how any of them is reached from the interface, so a reader cannot confirm from the README that a given document exists in the build they installed.

That asymmetry is the decision. If the requirement is text messaging from a workstation and nothing more, the mobile clients the README already links are the primary device, they need no second installation, and adding this one buys a linked-device dependency plus an upgrade you track by hand. If the requirement includes handing over a PDF, sharing a window or reading a call log on a large display, those three documents are the reason the repository exists, and the README points testers at the beta channel to exercise changes before they reach the production build.

Editorial conclusion

Signal Desktop fits a team that already runs Signal on an Android or iOS handset and needs PDF handling, screen sharing or call diagnostics on a workstation, and that can accept an upgrade path tracked by hand at a download or a git tag. It does not fit anyone looking for a standalone desktop messenger or a registry dependency, because package.json is marked private and the client has no registration path of its own. Before adopting, confirm that the account it must link to is one your organisation can hold, and check the release issue tracker for which of pdf.html, screenShare.html and call_diagnostic.html are present in the build you plan to run.

Frequently asked questions

Is there a desktop version of Signal?

Yes. Signal Desktop messages from Windows, macOS and Linux computers by linking with Signal on Android or iOS. It is a linked second device rather than a standalone client, and it cannot register an account itself.

Can I use Signal Desktop without a phone?

No. The README states that Signal Desktop links with Signal on Android or iOS, so the account it attaches to is created in one of those apps. No standalone or offline mode is documented.

How do I install Signal Desktop?

Download the production build from signal.org/download, or install the beta build through the beta article linked from the README. There is no package manager path, because package.json is marked private, so nothing can be added as a dependency.

How do I install Signal Desktop on Linux?

The README gives no apt, dnf or other per-distribution command. It covers Windows, macOS and Linux through the single download link at signal.org/download, and no repository, package or signing key file appears at the root of the project.

What is the latest version of Signal Desktop?

The newest listed releases are v8.34.0-beta.1 and v8.33.0, both published on 2026-10-28. The working tree on main declares 8.36.0-alpha.1 in package.json, so a source build sits ahead of every published tag.

Official sources

  1. License: AGPL-3.0
  2. Project website
  3. README
  4. Releases
  5. signalapp/Signal-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/signalapp-signal-desktop.svg)](https://hysenlabs.com/projects/signalapp-signal-desktop)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/signalapp-signal-desktop.svg)](https://hysenlabs.com/projects/signalapp-signal-desktop)

Was this useful?