Observed since 20 Oct, 19:01 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
A linter launcher for projects that have multiple source languages.
zulint is a lightweight linting framework designed for complex applications using a mix of third-party linters and custom rules.
This project requires Python 3.10 or newer. Our CI tests run on Python 3.10–3.13 and the upcoming Python 3.14 pre-release.
Modern full-stack web applications generally involve code written in several programming languages, each of which have their own standard linter tools. For example, Zulip uses Python (mypy/pyflake/pycodestyle), JavaScript (eslint), CSS (stylelint), puppet (puppet-lint), shell (shellcheck), and several more. For many codebases, this results in linting being an unpleasantly slow experience, resulting in even more unpleasant secondary problems like developers merging code that doesn't pass lint, not enforcing linter rules, and debates about whether a useful linter is "worth the time".
Zulint is the linter framework we built for Zulip to create a reliable, lightning-fast linter experience to solve these problems. It has the following features:
git to only checks files in source control (not
automatically generated, untracked, or .gitignore files).pre-commit hook, only
checking files that have changed (and only starting linters which
check files that have changed).Message objects
in views code to be done via our access_message_by_id functions
(which do security checks to ensure the user the request is being
done on behalf of has access to the message), and that is enforced
in part by custom regular expression lint rules. This system is
optimized Python: Zulip has a few hundred custom linter rules of
this type.This codebase has been in production use in Zulip for several years, but only in 2019 was generalized for use by other projects. Its API to be beta and may change (with notice in the release notes) if we discover a better API, and patches to further extend it for more use cases are encouraged.
Once a project is setup with zulint, you'll have a top-level linter script with at least the following options:
$ ./example-lint --help
usage: example-lint [-h] [--modified] [--verbose-timing] [--skip SKIP]
[--only ONLY] [--list] [--list-groups] [--groups GROUPS]
[--verbose] [--fix]
[targets [targets ...]]
positional arguments:
targets Specify directories to check
optional arguments:
-h, --help show this help message and exit
--modified, -m Only check modified files
--verbose-timing, -vt
Print verbose timing output
--skip SKIP Specify linters to skip, eg: --skip=mypy,gitlint
--only ONLY Specify linters to run, eg: --only=mypy,gitlint
--list, -l List all the registered linters
--list-groups, -lg List all the registered linter groups
--groups GROUPS, -g GROUPS
Only run linter for languages in the group(s), e.g.:
--groups=backend,frontend
--verbose, -v Print verbose output where available
--fix Automatically fix problems where supported
When registering an external linter with linter_config.external_linter, you
can now pass a cwd argument to run the linter in a different working
directory. This is helpful in monorepos where individual projects maintain
their own configuration files.
See https://github.com/adambirds/xkcd-password-gen/blob/master/tools/pre-commit for an example pre-commit hook.
Run the following commands in a terminal to install zulint.
git clone git@github.com:adambirds/adamlint.git
python3 -m venv venv
source venv/bin/activate
python3 setup.py install
pypistats · 87 observations shown. Missing days are unknown. Source category: overall: without mirrors.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-19 – 2026-10-19 | 19 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-18 – 2026-10-18 | 120 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-17 – 2026-10-17 | 220 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-16 – 2026-10-16 | 2 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-15 – 2026-10-15 | 45 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-14 – 2026-10-14 | 29 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-13 – 2026-10-13 | 18 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-12 – 2026-10-12 | 9 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-11 – 2026-10-11 | 3 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-10 – 2026-10-10 | 14 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-09 – 2026-10-09 | 14 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-08 – 2026-10-08 | 9 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-07 – 2026-10-07 | 2 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-06 – 2026-10-06 | 18 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-05 – 2026-10-05 | 5 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-04 – 2026-10-04 | 28 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-03 – 2026-10-03 | 16 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-02 – 2026-10-02 | 3 | 2026-10-20T21:32:28.3077218Z |
| 2026-10-01 – 2026-10-01 | 3 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-30 – 2026-09-30 | 10 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-29 – 2026-09-29 | 4 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-28 – 2026-09-28 | 12 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-27 – 2026-09-27 | 12 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-26 – 2026-09-26 | 28 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-25 – 2026-09-25 | 1 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-24 – 2026-09-24 | 3 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-23 – 2026-09-23 | 4 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-22 – 2026-09-22 | 6 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-21 – 2026-09-21 | 5 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-20 – 2026-09-20 | 23 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-19 – 2026-09-19 | 27 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-18 – 2026-09-18 | 1 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-17 – 2026-09-17 | 4 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-16 – 2026-09-16 | 59 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-15 – 2026-09-15 | 70 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-14 – 2026-09-14 | 52 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-13 – 2026-09-13 | 7 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-12 – 2026-09-12 | 24 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-11 – 2026-09-11 | 25 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-10 – 2026-09-10 | 7 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-09 – 2026-09-09 | 3 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-08 – 2026-09-08 | 78 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-07 – 2026-09-07 | 92 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-06 – 2026-09-06 | 54 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-05 – 2026-09-05 | 16 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-04 – 2026-09-04 | 6 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-02 – 2026-09-02 | 1 | 2026-10-20T21:32:28.3077218Z |
| 2026-09-01 – 2026-09-01 | 1 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-31 – 2026-08-31 | 5 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-30 – 2026-08-30 | 4 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-29 – 2026-08-29 | 33 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-28 – 2026-08-28 | 14 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-27 – 2026-08-27 | 17 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-26 – 2026-08-26 | 28 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-25 – 2026-08-25 | 14 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-24 – 2026-08-24 | 10 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-23 – 2026-08-23 | 3 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-22 – 2026-08-22 | 21 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-21 – 2026-08-21 | 19 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-20 – 2026-08-20 | 15 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-19 – 2026-08-19 | 107 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-18 – 2026-08-18 | 61 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-17 – 2026-08-17 | 27 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-16 – 2026-08-16 | 50 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-15 – 2026-08-15 | 155 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-14 – 2026-08-14 | 5 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-13 – 2026-08-13 | 3 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-12 – 2026-08-12 | 5 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-11 – 2026-08-11 | 6 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-10 – 2026-08-10 | 12 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-09 – 2026-08-09 | 39 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-08 – 2026-08-08 | 14 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-07 – 2026-08-07 | 15 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-06 – 2026-08-06 | 4 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-05 – 2026-08-05 | 5 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-03 – 2026-08-03 | 9 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-02 – 2026-08-02 | 1 | 2026-10-20T21:32:28.3077218Z |
| 2026-08-01 – 2026-08-01 | 8 | 2026-10-20T21:32:28.3077218Z |
| 2026-07-31 – 2026-07-31 | 1 | 2026-10-20T21:32:28.3077218Z |
| 2026-07-30 – 2026-07-30 | 7 | 2026-10-20T21:32:28.3077218Z |
| 2026-07-29 – 2026-07-29 | 11 | 2026-10-20T21:32:28.3077218Z |
| 2026-07-28 – 2026-07-28 | 11 | 2026-10-20T21:32:28.3077218Z |
| 2026-07-27 – 2026-07-27 | 13 | 2026-10-20T21:32:28.3077218Z |
| 2026-07-25 – 2026-07-25 | 5 | 2026-10-20T21:32:28.3077218Z |
| 2026-07-24 – 2026-07-24 | 11 | 2026-10-20T21:32:28.3077218Z |
| 2026-07-23 – 2026-07-23 | 2 | 2026-10-20T21:32:28.3077218Z |
| 2026-07-22 – 2026-07-22 | 11 | 2026-10-20T21:32:28.3077218Z |
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 1.1.0 | 30 Aug 2025 | 3 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 19:01 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:24be04b2b29a77ca50f076ab049b88cabde261a7b21faa6dcec11880dbc509f6