Linter for Zotero, an addon that normalises and cross-checks your reference metadata
Linter for Zotero. A plugin for Zotero to format item metadata. Shortcut to set title rich text; set journal abbreviations, university places, and item languages, etc; detect duplicate items.
At a glance
- What is it?
- Linter for Zotero is a Zotero plugin that treats your reference library as something to be cleaned rather than merely stored. It detects duplicates on import, warns when an item's type does not match its content, rewrites titles, dates, DOIs, page numbers and journal names into consistent forms, and pulls corrected metadata from CrossRef, Semantic Scholar, arXiv and doi.org.
- Who is it for?
- Adopt Linter for Zotero if you maintain a shared reference library where the same source exists in several forms, or if you are importing references from sources that fill fields inconsistently, and skip it if your library is small and clean, because a manual pass may be faster than learning the rule set.
- 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 1 day 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
What a linter does to a library
The stated goal is to keep your Zotero library clean and consistent with automatic validation, corrections and metadata updates. That word, linter, comes from code and it is the right analogy, because a linter reports and fixes problems that are individually trivial and collectively corrosive. In a reference library the trivial problems are a title in sentence case in one item and title case in the next, a journal name spelled out here and abbreviated there, a date stored as a string somewhere and as a date elsewhere, a DOI with a prefix in one place and without it in another. None of these break anything. All of them break a bibliography. The plugin is an addon for Zotero, written in TypeScript, and it is built on the Zotero Plugin Template, with the badge in the README naming that template and the Zotero versions it targets shown as 8 or 9. The licence is AGPL-3.0-or-later, and the package is versioned 4.0.1 with the add-on identity recorded as Linter for Zotero under the addon ID [email protected].
Duplicate detection and type validation, on import
Two features act at the moment data enters your library, which is the right place for them, because problems caught on import are problems you never had. Automatic duplicate detection on import means a source that reaches Zotero through a translator and then again through a manual entry is flagged rather than silently duplicated. Smarter item type validation with import failure warnings is the other half: the plugin checks that the item's declared type makes sense for the content it holds, and warns rather than producing a record that will misbehave in a bibliography template. For a working researcher this is the difference between a library that can be queried and one that cannot. The metadata import path is where most duplication actually happens, since a DOI, a PDF and a manual entry can each produce a record, and none of them know about the others until something like this checks.
Field optimisation, and what the corrections actually do
The field optimisation list is the longest feature and the most revealing, because it names the specific normalisations. The plugin does language detection, so the item's language field reflects the actual content rather than whatever the source said. It applies sentence case to titles, which is the convention most style guides want and which imported metadata rarely follows. It abbreviates journal names, it normalises university locations, and it normalises dates, DOIs, page ranges and volumes. The last of those, page ranges, is a real source of inconsistency: the same page range arrives as 100-110, as 100 to 110 spelled out, as 100-10, and as pp. 100-110, depending on the source. A DOI with a URL prefix and a DOI without one is the same class of problem, and the plugin's rules include a require-doi, a correct-doi-long and a tool-get-short-doi rule, the last inspired by the DOI Manager project under an MPL-2.0 licence. The plugin also offers rich text editing for titles, with superscript, subscript, italics and bold, which matters for titles that carry chemical formulae or species names.
The data sources behind the corrections
The plugin is only as good as the reference data it consults, and the acknowledgements section is unusually specific about where that data comes from. The data resources are the ISO 639-3 language code set with an associated mapping table down to the two-letter codes, the JabRef journal abbreviation list, and the List of National Higher Education Institutions published by the Ministry of Education of the People's Republic of China, which is what makes the university location normalisation meaningful outside the anglophone world. The API services are CrossRef for DOI metadata and bibliographic metadata, Semantic Scholar for bibliographic metadata, shortdoi.org for generating short DOIs, doi.org for resolving them, and abbreviso for inferring journal abbreviations where no abbreviation list has an entry. The plugin also credits the Zotero Field Specification, curated by zepinglee, and the Zotero French translation team, and it acknowledges coding assistance from ChatGPT and DeepSeek during development. The last two acknowledgements are worth noting for a project with this scope, because the field specification is what keeps the plugin's behaviour aligned with what Zotero itself expects.
One-click metadata updates, and where the data comes back from
The update path is the feature that saves the most time, because a single missing field on a hundred items is a hundred manual edits otherwise. The plugin provides one-click metadata updates via DOI, arXiv ID and more, which means you point it at an identifier and it fetches the record. The mechanics are worth spelling out because they explain the plugin's dependencies. The CrossRef API is what resolves a DOI to a bibliographic record, and Semantic Scholar also supplies bibliographic metadata. doi.org is the resolver that turns a DOI into the landing page or the record, shortdoi.org produces a shorter form of a DOI for citation, and abbreviso infers the abbreviated journal name when the abbreviation is not in a curated list. Each of these is a network call to a third party, which means the plugin is online-dependent in a way that a purely local normaliser would not be.
Installing the addon, and the plugin toolchain behind it
Installation is a download and a drag. You go to the release page, or to the Zotero Chinese plugin listing, and download the latest .xpi file, then in Zotero you click Tools, then Plugin, and drag the .xpi onto the Plugins Manager window. The package metadata shows how the project is built, and it uses the Zotero Plugin Template toolchain throughout, with a start script that runs the plugin serve command, a build script that runs the plugin build and then a TypeScript type check, and a release script. Tests are split in two: unit tests run under vitest, and end-to-end tests run with the plugin test command, both wired into a test script that runs the unit suite and then the e2e suite, with a separate coverage script. Dependency updates are handled with a pnpm-based minor update command, and husky is the prepare hook. The package manager is pinned to pnpm 12.3.4 with a workspace file and a lockfile, and there is a vitest config, a tsconfig, an eslint config and a separate autocorrect configuration for prose linting.
The development environment, and what a local run needs
The environment example file shows what a developer needs to point the plugin at a real Zotero. The first variable is the path of the Zotero binary, with a note that the path delimiter should be escaped for win32 and that on macOS the path is the one inside the Zotero.app bundle. The second is the path of the profile used for development, and the comment tells you to start the profile manager with the Zotero binary and the -p flag to create a profile for development. The third is the directory where the database is located, and the comment says that if this field is kept empty, Zotero will start with the default data. There is also a variable for custom commands to kill Zotero processes, with the note that the built-in per-platform commands are already in zotero-plugin and you only need to override it if those are unsuitable. The last is a GitHub token, needed for release-it to create a release and upload assets automatically.
What it will not do, and how to decide
The limits follow from the design. This is a normaliser and a cross-checker, not a bibliography engine, so it does not decide your citation style, and it does not know whether a journal prefers one abbreviation over another in a particular style guide, which is why the abbreviation source is a JabRef list and a heuristic rather than a rule that matches every style. It also does not resolve the case where two records are genuinely the same work at different stages, such as a preprint and the published article, and its duplicate detection therefore needs a human in the loop for the ambiguous cases. And because the metadata updates go through external APIs, the plugin needs network access, which in turn means the identifiers you point it at are sent to those services. On the balance of it, the plugin earns its place in a library that grew by import, and it earns less in a library that was entered by hand with care. The project tracks its work on a GitHub project board for the todo list, the repository is not archived, and the last push was on 2026-09-09, the same day as release v4.0.1.
Editorial conclusion
Adopt Linter for Zotero if you maintain a shared reference library where the same source exists in several forms, or if you are importing references from sources that fill fields inconsistently, and skip it if your library is small and clean, because a manual pass may be faster than learning the rule set. Verify three things before you apply it broadly: that the automatic corrections suit your citation style, since the plugin rewrites fields rather than only reporting on them; that the language detection and journal abbreviation tables match your field conventions, particularly for non-English sources; and that the duplicate detection does not fire on items you deliberately keep in parallel, since a merge decision in a shared library is hard to undo.
Frequently asked questions
What does the Linter for Zotero plugin do?
It is a Zotero addon that formats item metadata, with rich text editing for titles, automatic duplicate detection on import, smarter item type validation with import failure warnings, field optimisation covering language detection, sentence case titles, journal abbreviations, university locations and normalised dates, DOIs, pages and volumes, and one-click metadata updates via DOI, arXiv ID and more.
How do I install Linter for Zotero?
Download the latest .xpi file from the release page or from the Zotero Chinese plugin listing, then in Zotero click Tools, then Plugin, and drag the .xpi onto the Plugins Manager window.
Which data sources does Linter for Zotero use for corrections?
ISO 639-3 with a mapping table for language codes, the JabRef journal abbreviation list, and the List of National Higher Education Institutions for university locations. For lookups it uses the CrossRef API, the Semantic Scholar API, shortdoi.org, doi.org and abbreviso.
Which Zotero versions does Linter for Zotero support?
The badge in the project documentation indicates support for Zotero 8 or later up to Zotero 9, and the addon is built on the Zotero Plugin Template with a toolchain that provides serve, build, test and release commands.
Official sources
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.
[](https://hysenlabs.com/projects/northword-zotero-format-metadata)Was this useful?