Actions and Tags for Zotero: event-driven tagging and scripts inside the client
Customize your Zotero workflow.
At a glance
- What is it?
- A Zotero 7 plugin that pairs library events with tag operations or custom JavaScript. It is a good fit if you already think in tags and want them applied without clicking, and a poor fit if you need a stable scripting API across Zotero upgrades.
- Who is it for?
- Adopt it if you run Zotero 7, your workflow is already tag-centric, and you are comfortable pasting community scripts into a data field. Skip it if you need a supported scripting API, automated tests, or a rollback path, since package.json still carries the scaffold's placeholder test script and the README documents no undo.
- 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 38 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 September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Actions and Tags actually automates in a Zotero library
Zotero's own tag support is manual. You select items, open the tag selector, and type. The plugin's premise is that most tagging decisions follow from something that just happened: an item was created, a file was opened, a tab was closed, an annotation was made. Actions and Tags, abbreviated AT in the README and also known as Zotero Tag, lets you bind a tag operation to one of those events or to a keyboard shortcut you choose.
The intended audience is narrow but real. It is for researchers who already use tags as their primary organising layer rather than collections, and who want the library to maintain itself while they read. The README frames the goal as customising your Zotero workflow, and the plugin ships one worked example rather than a library of prebuilt recipes. If you have never used Zotero tags, the plugin will not teach you a tagging scheme; it only executes one.
Events, operations and the data field: the plugin's execution model
An action is a three-part record. The event decides when it fires, the operation decides what happens, and the data field carries the payload. The README lists eleven events, including createItem, openFile, closeTab, createAnnotation, createNote, appendAnnotation, appendNote, changeAnnotationColor, programStartup, mainWindowLoad and mainWindowUnload. Five operations are listed: addTag, removeTag, toggleTag, otherAction and customScript. For tag operations the data field holds tags separated by commas; for customScript it holds the script itself.
The design is deliberately thin. There is no visual rule builder, no condition language, and no dry-run mode. Composition happens through otherAction, which runs other custom actions, so a chain is assembled by pointing one action at another. Anything beyond tag manipulation means writing JavaScript against the Zotero client, which is why the README points to a community discussion category for action scripts instead of documenting an API. The plugin depends on zotero-plugin-toolkit and js-yaml according to package.json, and it targets Zotero 7.
The honest trade-off: this is a scripting surface with a settings UI bolted on, not a no-code automation tool. The example actions the README links to, such as copy item link, replace tag, or auto-generate a note when opening an item, are community contributions pasted by hand, and their correctness is the author's, not the plugin's.
Installing the .xpi and getting the unread example to fire
Installation is the standard Zotero add-on path. Download the .xpi from the latest release, then in Zotero open Tools, then Addons, click the gear icon, choose Install Add-on from file, and select the downloaded file. The README notes that Firefox users should right click the xpi and choose Save As, because Firefox will otherwise try to install it as a browser extension. Restart Zotero when prompted; the plugin then appears in the extensions list.
The quickest way to confirm the plugin works is the bundled unread example. Add a paper to your library, whether by creating it, importing it, or capturing it with the Zotero connector. The README describes the result as an item tagged with /unread, which you can find in the Tags tab of the right panel. Open the item to read it, then close it, and the matching closeTab action removes the tag again. The README describes this as a one minute start.
To build your own action, open the plugin's settings page and click the Actions and Tags tab, then the plus button. The README's walkthrough of the community copy item link script sets the operation to customScript, assigns a shortcut and a menu label, and pastes the script into the data field. Click Save. The action then appears when you right click an item, under trigger action, and it also responds to the shortcut. The README's example copies the item link to the clipboard.
Where the plugin breaks down: customScript has no safety net
The most important limitation is stated by omission. The README documents no sandbox, no permission model, no dry-run, and no rollback for customScript. A script that calls removeTag with the wrong data, or that loops over the wrong selection, changes your library immediately. Zotero's own sync and backup behaviour is the only recovery path, and the plugin's documentation does not describe one.
The event model has edges too. Events fire on the client, so anything you automate happens on the machine where Zotero is running, not on the sync server. A tag applied on your laptop appears on your desktop only after sync completes, and an action bound to openFile will fire every time you open the file, which is fine for a toggle operation and wrong for a counter. There is also no condition syntax: if you want a tag applied only to items in a particular collection, or only to PDFs, that logic has to live inside a custom script rather than in the action settings.
Finally, the project's test script in package.json is the scaffold default, which prints an error and exits. There is no automated test suite to lean on, so an upgrade that changes internal behaviour will not be caught for you.
How it differs from Zotero's built-in tools and from Zotero Style
Zotero's built-in automatic tagging is the closest alternative, and it is a different thing. That feature derives tags from a controlled vocabulary applied by the metadata source, so a tag like a subject heading arrives with the item and reflects someone else's classification. Actions and Tags does the opposite: it applies tags you define, in response to events in your own session. If your problem is that imported records lack subject terms, the built-in route is the right one and this plugin will not help. If your problem is that you keep forgetting to mark items as unread, or to strip a tag when you finish reading, this plugin addresses exactly that.
Zotero Style, another plugin from the same author, appears in the related searches alongside this one. The README's own plugin list is the place to check what each does, since the two are separate add-ons with separate settings pages. The general difference is that Actions and Tags is about changing data in response to events, while a reading-focused plugin is about how items are displayed and tracked.
Maintenance, licence and what an upgrade costs you
The repository is not archived, and the last push was on 2026-08-24, the same day as the v2.6.1 release. The release cadence visible in the notes is uneven: v2.5.2 landed on 2026-05-27, then v2.6.0 and v2.6.1 arrived within a day of each other in late August. That pattern suggests bursts of work rather than a steady drip, and it means you should read release notes before updating rather than assuming continuity.
The licence is AGPL-3.0-or-later, per package.json. For a Zotero add-on this matters mainly if you fork it or ship a modified build: the AGPL's network and distribution conditions attach to derivative works. Using the plugin inside your own Zotero client raises no obvious obligation, but if you are embedding it in something you distribute, read the licence text rather than an article about it. I am not giving legal advice here.
Upgrade cost is the practical concern. Because custom scripts are user-supplied and untested by the project, a Zotero or plugin update can change the objects those scripts touch, and nothing in the repository will warn you. Keep a copy of each script you paste somewhere outside Zotero, so a broken action can be reverted by deleting it from the actions list.
A developer path: building the plugin from source
The repository is a TypeScript project built on the zotero-plugin-template scaffold. The scripts in package.json are start, build, release, lint, test and update-deps. Development configuration comes from a .env file copied from .env.example, which defines ZOTERO_PLUGIN_ZOTERO_BIN_PATH, ZOTERO_PLUGIN_PROFILE_PATH, ZOTERO_PLUGIN_DATA_DIR and an optional ZOTERO_PLUGIN_KILL_COMMAND.
cp .env.example .env
npm install
npm startThe .env.example comments explain that ZOTERO_PLUGIN_ZOTERO_BIN_PATH points at the Zotero binary, with backslashes escaped on Windows and the path ending in Zotero.app/Contents/MacOS/zotero on macOS, and that ZOTERO_PLUGIN_PROFILE_PATH should point at a development profile created with the -p flag. Leaving ZOTERO_PLUGIN_DATA_DIR empty makes Zotero start with its default data directory. The start script runs zotero-plugin serve, which is the scaffold's development server; build runs tsc --noEmit first, so type errors stop the build. Note that npm test is the placeholder from the template and exits with an error, so it is not a signal about the code's health.
Editorial conclusion
Adopt it if you run Zotero 7, your workflow is already tag-centric, and you are comfortable pasting community scripts into a data field. Skip it if you need a supported scripting API, automated tests, or a rollback path, since package.json still carries the scaffold's placeholder test script and the README documents no undo. Before installing, confirm your Zotero major version and read the discussion thread for the script you intend to paste, because the plugin runs that code with your library's permissions and offers no sandbox.
Frequently asked questions
How do I use Zotero tags with Actions and Tags for Zotero?
The plugin applies tags through actions rather than by hand. You pick an event such as createItem or closeTab, set the operation to addTag, removeTag or toggleTag, and put the tags in the data field separated by commas. The bundled unread example adds the unread tag on creation and removes it when the item is closed.
What is the difference between collections and tags in Zotero, and where does this plugin fit?
A collection holds an item in one place, while tags are labels an item can carry in any number. Actions and Tags works only on the tag layer, adding and removing labels in response to events, and it does not move items between collections.
How do I add tags to multiple items in Zotero with Actions and Tags for Zotero?
The README does not describe a bulk selection mode. Actions fire per event, so tagging many items at once is done by selecting them and using an action's shortcut or its entry in the right click menu, or by writing a customScript that iterates over the selection.
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/windingwind-zotero-actions-tags)