Package: zulip-term
Recent changes|Configuration|Hot Keys|FAQs|Development|TutorialAboutZulip Terminal is the official terminal client for Zulip, providing atext-based user interface (TUI).Specific aims include:Providing a broadly similar user experience to the Zulip web client, ultimately supporting all of its featuresEnabling all actions to be achieved through the keyboard (seeHot keys)Exploring alternative user interface designs suited to the display and input constraintsSupporting a wide range of platforms and terminal emulatorsMaking best use of available rows/columns to scale from 80x24 upwards (seeSmall terminal notes)Learn how to use Zulip Terminal with ourTutorial.Feature statusWe consider the client to already provide a fairly stable moderately-featureful everyday-user experience.The terminal client currently has a number of intentional differences to the Zulip web client:Additional and occasionallydifferentHot keysto better support keyboard-only navigation; other than directional movement these also include:z- zoom in/out, between streams & topics, or all private messages & specific conversationst- toggle view of topics for a stream in left panel (later adopted for recent topics in web client)#- narrow to messages in which you're mentioned (@is already used)f- narrow to messages you've starred (arefollowing)Not marking additional messages read when the end of a conversation is visible (FAQ entry)Emoji and reactions are rendered as text only, for maximum terminal/font compatibilityFootlinks - footnotes for links (URLs) - make messages readable, while retaining a list of links to cross-referenceContent previewable in the web client, such as images, are also stored as footlinksThe current development focus is on improving aspects of everyday usage which are more commonly used - to reduce the need for users to temporarily switch to another client for a particular feature.Current limitations which we expect to only resolve over the long term include support for:All operations performed by users with extra privileges (owners/admins)Accessing and updating all settingsUsing a mouse/pointer to achieve all actionsAn internationalized UIFor queries on missing feature support please take a look at theFrequently Asked Questions (FAQs),
our openIssues, or sign up onhttps://chat.zulip.organd chat with users and developers in the#zulip-terminalstream!Supported platformsLinuxOSXWSL (On Windows)Supported Server VersionsThe minimum server version that Zulip Terminal supports is2.1.0. It may still work with earlier versions.Supported Python VersionsVersion 0.6.0 was the last release with support for Python 3.5.Later releases and the main development branch are currently tested (on Ubuntu) with:CPython 3.6-3.10PyPy 3.6-3.9Since our automated testing does not cover interactive testing of the UI, there
may be issues with some Python versions, though generally we have not found
this to be the case.Please note that generally we limit each release to between a lower and upper
Python version, so it is possible that for example if you have a newer version
of Python installed, then some releases (ormain) may not install correctly.
In some cases this can give rise to the symptoms in issue #1145.InstallationWe recommend installing in a dedicated python virtual environment (see below) or using an automated option such aspipxStable- Numbered stable releases are available on PyPI as the packagezulip-termTo install, run a command like:pip3 install zulip-termLatest- The latest development version can be installed from the main git repositoryTo install, run a command like:pip3 install git+https://github.com/zulip/zulip-terminal.git@mainWe also provide some sample Dockerfiles to build docker images indocker/.Installing into an isolated Python virtual environmentWith the python 3.6+ required for running, the following should work on most systems:python3 -m venv zt_venv(creates a virtual environment namedzt_venvin the current directory)source zt_venv/bin/activate(activates the virtual environment; this assumes a bash-like shell)Run one of the install commands above,If you open a different terminal window (or log-off/restart your computer), you'll need to runstep 2of the above list again before runningzulip-term, since that activates that virtual environment. You can read more about virtual environments in thePython 3 library venv documentation.Keeping your install up to dateStable releases are made available on PyPI and GitHub; to ensure you keep up to date with them we suggest checking those sites for updates.
Stable releases are also announced in the #announcestream on the Zulip Community server (https://chat.zulip.org), where you are welcome to make an account; future releases are expected to be announced in #announce>terminal releases.If running from themaingit branch, note that this does not automatically update, and you must do so manually.
This also applies to other source or development installs, including eg.https://aur.archlinux.org/packages/python-zulip-term-git/Running for the first timeUpon first runningzulip-termit looks for azuliprcfile, by default in your home directory, which contains the details to log into a Zulip server.If it doesn't find this file, you have two options:zulip-termwill prompt you for your server, email and password, and create azuliprcfile for you in that locationNOTE:If you use Google, Github or another external authentication to access your Zulip organization then you likely won't have a password set and currently need to create one to use zulip-terminal. If your organization is on Zulip cloud, you can visithttps://zulip.com/accounts/go?next=/accounts/password/resetto create a new password for your account. For self-hosted servers please go to your<Organization URL>/accounts/password/reset/(eg:https://chat.zulip.org/accounts/password/reset/) to create a new password for your account.Each time you runzulip-term, you can specify the path to an alternativezuliprcfile using the-cor--config-fileoptions, eg.$ zulip-term -c /path/to/zuliprcYour personal zuliprc file can be obtained from Zulip servers in your account settings in the web application, which gives you all the permissions you have there. Bot zuliprc files can be downloaded from a similar area for each bot, and will have more limited permissions.NOTE:If your server uses self-signed certificates or an insecure connection, you will need to add extra options to thezuliprcfile manually - see the documentation for theZulip python module.We suggest runningzulip-termusing the-eor--exploreoption (in explore mode) when you are trying Zulip Terminal for the first time, where we intentionally do not mark messages as read. Try following along with ourTutorialto get the hang of things.ConfigurationThezuliprcfile contains information to connect to your chat server in the[api]section, but also optional configuration forzulip-termin the[zterm]section:[api]
email=example@example.com
key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
site=https://realm.zulipchat.com

[zterm]
# Alternative themes are listed in the FAQ
theme=zt_dark
# Autohide defaults to 'no_autohide', but can be set to 'autohide' to hide the left & right panels except when focused.
autohide=autohide
# Footlinks default to 'enabled', but can be set to 'disabled' to hide footlinks.
# disabled won't show any footlinks.
# enabled will show the first 3 per message.
footlinks=disabled
# If you need more flexibility, use maximum-footlinks.
# Maximum footlinks to be shown, defaults to 3, but can be set to any value 0 or greater.
# This option cannot be used with the footlinks option; use one or the other.
maximum-footlinks=3
# Notify defaults to 'disabled', but can be set to 'enabled' to display notifications (see next section).
notify=enabled
# Color depth defaults to 256 colors, but can be set to 1 (for monochrome), 16, or 24bit.
color-depth=256NOTE:Most of these configuration settings may be specified on the command line whenzulip-termis started;zulip-term -horzulip-term --helpwill give the full list of options.NotificationsNote that notifications are not currently supported on WSL; see#767.LinuxThe following command installsnotify-sendon Debian based systems, similar
commands can be found for other linux systems as well.sudo apt-get install libnotify-binOSXNo additional package is required to enable notifications in OS X. However to have a notification sound, set the following variable (based on your type of shell). The sound value (here Ping) can be any one of the.aifffiles found at/System/Library/Soundsor~/Library/Sounds.Bashecho 'export ZT_NOTIFICATION_SOUND=Ping' >> ~/.bash_profile
source ~/.bash_profileZSHecho 'export ZT_NOTIFICATION_SOUND=Ping' >> ~/.zshenv
source ~/.zshenvCopy to clipboardZulip Terminal allows users to copy certain texts to the clipboard via a Python module,Pyperclip. This module makes use of various system packages which may or may not come with the OS.
The "Copy to clipboard" feature is currently only available for copying Stream email, from theStream information popup.LinuxOn Linux, this module makes use ofxcliporxselcommands, which should already come with the OS. If none of these commands are installed on your system, then install any ONE using:sudo apt-get install xclip [Recommended]ORsudo apt-get install xselOSX and WSLNo additional package is required to enable copying to clipboard.Contributor GuidelinesZulip Terminal is being built by the awesomeZulipcommunity.To be a part of it and to contribute to the code, feel free to work on anyissueor propose your idea on#zulip-terminal.For commit structure and style, please review theCommit Stylesection below.If you are new togit(or not!), you may benefit from theZulip git guide.
When contributing, it's important to note that we use arebase-oriented workflow.A simpletutorialis available for implementing thetypingindicator.
Follow it to understand how to implement a new feature for zulip-terminal.You can of course browse the source on GitHub & in the source tree you download, and check thesource file overviewfor ideas of how files are currently arranged.UrwidZulip Terminal usesurwidto render the UI components in terminal. Urwid is an awesome library through which you can render a decent terminal UI just using python.Urwid's Tutorialis a great place to start for new contributors.Setting up a development environmentVarious options are available; we are exploring the benefits of each and would appreciate feedback on which you use or feel works best.Note that the tools used in each case are typically the same, but are called in different ways.With any option, you first need to clone the zulip/zulip-terminal repository locally (the following will place the repository in the current directory):$ git clone git@github.com:zulip/zulip-terminal.gitThe following commands should be run in the repository directory, which can be achieved withcd zulip-terminal.PipenvInstall pipenv (see therecommended installation notes; pipenv can be installed in a virtual environment, if you wish)$ pip3 install --user pipenvInitialize the pipenv virtual environment for zulip-term (using the default python 3; use eg.--python 3.6to be more specific)$ pipenv --threeInstall zulip-term, with the development requirements$ pipenv install --dev
$ pipenv run pip3 install -e '.[dev]'PipManually create & activate a virtual environment; any method should work, such as that used in the above simple installationpython3 -m venv zt_venv(creates a venv namedzt_venvin the current directory)source zt_venv/bin/activate(activates the venv; this assumes a bash-like shell)Install zulip-term, with the development requirements$ pip3 install -e '.[dev]'make/pipThis is the newest and simplest approach, if you havemakeinstalled:make(sets up an installed virtual environment inzt_venvin the current directory)source zt_venv/bin/activate(activates the venv; this assumes a bash-like shell)Development tasksOnce you have a development environment set up, you might find the following useful, depending upon your type of environment:TaskMake & PipPipenvRun normallyzulip-termpipenv run zulip-termRun in debug modezulip-term -dpipenv run zulip-term -dRun with profilingzulip-term --profilepipenv run zulip-term --profileRun all linters./tools/lint-allpipenv run ./tools/lint-allRun all testspytestpipenv run pytestBuild test coverage reportpytest --cov-report html:cov_html --cov=./pipenv run pytest --cov-report html:cov_html --cov=./If using make with pip, runningmakewill ensure the development environment is up to date with the specified dependencies, useful after fetching from git and rebasing.Passing linters and automated testsThe linters and automated tests (pytest) are run in CI (GitHub Actions) when
you submit a pull request (PR), and we expect them to pass before code is
merged.NOTE:Mergeable PRs with multiple commits are expected to pass linting
and tests ateach commit, not simply overallRunning these tools locally can speed your development and avoid the need
to repeatedly push your code to GitHub simply to run these checks.If you have troubles understanding why the linters or pytest are failing,
please do push your code to a branch/PR and we can discuss the problems in
the PR or on chat.zulip.org.All linters and tests can be run using the commands in the table above.
Individual linters may also be run via scripts intools/.In addition, if using amake-based system:make lintandmake testrun all of each group of tasksmake checkruns all checks, which is useful before pushing a PR (or an update)Correcting some linting errors requires manual intervention, such as frommypyfor type-checking.
However, other linting errors may be fixed automatically, as detailed below -this can save a lot of time manually adjusting your code to pass the
linters!Auto-formatting codeThe project usesblackandisortfor code-style and import sorting respectively.These tools can be run as linters locally , but can alsoautomaticallyformat your code for you.If you're using amake-based setup, runningmake fixwill run both (and a
few other tools) and reformat the current state of your code - so you'll want
to commit first just in case, then--amendthat commit if you're happy with
the changes.You can also use the tools individually on a file or directory, eg.black zulipterminalorisort tests/model/test_model.pyCommit StyleWe aim to follow a standard commit style to keep thegit logconsistent and easy to read.Much like working with code, it's great to refer to the git log, for the style we're actively using.Our overall style for commit structure and messages broadly follows the generalZulip version control guidelines, so we recommend reading that first.Our commit titles have slight variations from the general Zulip style, with each:starting with one or more areas in lower case, followed by a colon and spacearea being slash-separated modified files without extensions, or the type of the changeending with a concise description starting with a capital and ending with a full-stop (period)having a maximum overall length of 72 (fitting github web interface without abbreviation)Some example commit titles:file3/file1/file2: Improve behavior of something.- a general commit updating filesfile1.txt,file2.pyandfile3.mdrefactor: file1/file2: Extract some common function.- a pure refactor which doesn't change the functional behaviorbugfix: file1: Avoid some noticeable bug.- an ideally small commit to fix a bugtests: file1: Improve test for something.- only improve tests forfile1, likely intest_file1.pyrequirements: Upgrade some-dependency from 9.2 to 9.3.- upgrade a dependency from version 9.2 to version 9.3Generally with changes to code we request you update linting and tests to pass on a per-commit basis (not just per pull request).
If you update tests, you can add eg.Tests updated.in your commit text.Ideally we prefer that behavioral changes are accompanied by test improvements or additions, and an accompanyingTests added.or similar is then useful.To aid in satisfying some of these rules you can useGitLint, as described in the following section.However, please check your commits manually versus these style rules, since GitLint cannot check everything - including language or grammar!GitLintIf you plan to submit git commits in pull-requests (PRs), then we highly suggest installing thegitlintcommit-message hook by runninggitlint install-hook(orpipenv run gitlint install-hookwith pipenv setups). While the content still depends upon your writing skills, this ensures a more consistent formatting structure between commits, including by different authors.If the hook is installed as described above, then after completing the text for a commit, it will be checked by gitlint against the style we have set up, and will offer advice if there are any issues it notices. If gitlint finds any, it will ask if you wish to commit with the message as it is (yfor 'yes'), stop the commit process (nfor 'no'), or edit the commit message (efor 'edit').Other gitlint options are available; for example it is possible to apply it to a range of commits with the--commitsoption, eg.gitlint --commits HEAD~2..HEADwould apply it to the last few commits.Tips for working with tests (pytest)Tests for zulip-terminal are written usingpytest. You can read the tests in the/testsfolder to learn about writing tests for a new class/function. If you are new to pytest, reading its documentation is definitely recommended.We currently have thousands of tests which get checked upon runningpytest. While it is dependent on your system capability, this should typically take less than one minute to run. However, during debugging you may still wish to limit the scope of your tests, to improve the turnaround time:If lots of tests are failing in a very verbose way, you might try the-xoption (eg.pytest -x) to stop tests after the first failure; due to parametrization of tests and test fixtures, many apparent errors/failures can be resolved with just one fix! (try eg.pytest --maxfail 3for a less-strict version of this)To avoid running all the successful tests each time, along with the failures, you can run with--lf(eg.pytest --lf), short for--last-failed(similar useful options may be--failed-firstand--new-first, which may work well with-x)Since pytest 3.10 there is--sw(--stepwise), which works through known failures in the same way as--lfand-xcan be used, which can be combined with--stepwise-skipto control which test is the current focusIf you know the names of tests which are failing and/or in a specific location, you might limit tests to a particular location (eg.pytest tests/model) or use a selected keyword (eg.pytest -k __handle)When only a subset of tests are running it becomes more practical and useful to use the-voption (--verbose); instead of showing a.(orF,E,x, etc) for each test result, it gives the name (with parameters) of each test being run (eg.pytest -v -k __handle). This option also shows more detail in tests and can be given multiple times (eg.pytest -vv).For additional help with pytest options seepytest -h, or check out thefull pytest documentation.Debugging TipsOutput usingprintThe stdout (standard output) for zulip-terminal is redirected to./debug.logif debugging is enabled at run-time using-dor--debug.This means that if you want to check the value of a variable, or perhaps indicate reaching a certain point in the code, you can simply useprint(), eg.print(f"Just about to do something with{variable}")and when running with a debugging option, the string will be printed to./debug.log.With a bash-like terminal, you can run something liketail -f debug.login another terminal, to see the output fromprintas it happens.Interactive debugging using pudb & telnetIf you want to debug zulip-terminal while it is running, or in a specific state, you can insertfrompudb.remoteimportset_traceset_trace()in the part of the code you want to debug. This will start a telnet connection for you. You can find the IP address and
port of the telnet connection in./debug.log. Then simply run$ telnet 127.0.0.1 6899in another terminal, where127.0.0.1is the IP address and6899is port you find in./debug.log.There's no effect in Zulip Terminal after making local changes!This likely means that you have installed both normal and development versions of zulip-terminal.To ensure you run the development version:If using pipenv, callpipenv run zulip-termfrom the cloned/downloadedzulip-terminaldirectory;If using pip (pip3), ensure you have activated the correct virtual environment (venv); depending on how your shell is configured, the name of the venv may appear in the command prompt. Note that not including the-ein the pip3 command will also cause this problem.