Skip to content

Plugins

ALMa's features are core. Alerts, the Inbox and a paper's PDF work as part of the app; a plugin is only the optional adapter that connects one of them to an outside service. Nothing here is required to use ALMa.

Four ship with it:

Plugin What it adds Used by
Slack Posts alert digests to a channel or a DM, and captures papers you send from your phone Alerts, Inbox
Email Sends alert digests over SMTP Alerts
Open-access PDFs Finds a paper's PDF from arXiv, PubMed Central, OpenAlex, Unpaywall, Crossref, the publisher's page and Semantic Scholar Paper PDFs
Shadow libraries Tries the Sci-Hub and Anna's Archive mirrors you add, after every open-access source has failed Paper PDFs

They all live in one place: Settings → Plugins.

What is true of every plugin

It ships switched off. A fresh install has no plugin on, and nothing in a plugin runs until you turn it on yourself.

Switching it on is what reveals its setup. An off plugin shows one line saying what it would do and a switch. Turn the switch on and its fields appear, along with its Test connection button where it has one.

Switching it off keeps its configuration. Your token, addresses and recipients stay where they were, secrets included. An off plugin is excluded from new delivery choices, from automated alert sends, from Inbox capture sweeps, and from PDF fetches — and its status pills disappear from Home. Turn it back on and it picks up where it was. Switching off never deletes an Inbox paper or a line of alert history.

An off plugin reaches nothing. This is enforced in the manifest, not by each plugin remembering to check: while a plugin is off, it hands out no inbound channel, and sending an alert or running its connection test raises PluginDisabledError — the API answers 409 rather than quietly making the call. Only self-description, configuration and a local status read stay available, which is why listing plugins never opens a connection to anything.

Secrets never touch settings.json. Tokens, passwords and keys go to the secret store (data/secrets.json, gitignored, mode 0600) and come back masked. Leaving a masked value in place keeps the stored one; clearing the field deletes it.