A plugin source and theme source for AList v4, addable from Admin → Plugins
→ Sources and Admin → Appearance → Theme Market. Not an official index —
a community-maintained list of third-party plugins and themes, validated by
CI against the schema alist-org/alist's backend parses.
- Add this source
- Index schema
- Repository layout
- Signing and trust
- Contributing
- Validation and CI
- License
Plugins — Admin → Plugins → Sources → Add source:
| Field | Value |
|---|---|
| Name | alist-registry (or anything you like) |
| Index URL | https://raw.githubusercontent.com/AlistGo/alist-registry/main/dist/plugins/index.json |
| Public key | see Signing and trust |
Themes — Admin → Appearance → Theme Market → Add source:
| Field | Value |
|---|---|
| Name | alist-registry |
| Index URL | https://raw.githubusercontent.com/AlistGo/alist-registry/main/dist/themes/index.json |
| Public key | optional — blank installs everything as untrusted |
Both files are generated by CI from plugins/ and themes/
(publish.yml) and committed back to main
on every merge.
Both index files mirror alist-org/alist's Go structs field-for-field; CI
enforces this on every pull request.
Mirrors internal/extension/index.go's IndexEntry — an array of these is
what GET .../plugins/sources fetches and extension.FetchIndex parses.
| Field | Type | Required | Notes |
|---|---|---|---|
id |
string | yes | reverse-domain, ^[a-zA-Z0-9][a-zA-Z0-9._-]*$, no .. — must match plugin.json's own id |
name |
string | yes | display name |
version |
string | yes | plain MAJOR.MINOR.PATCH |
kind |
string | yes | one ext.Kind value, e.g. StorageDriver |
core_api |
string | yes | semver constraint, e.g. ^0.1.0 |
sha256 |
string | yes | hex sha256 of the .tar.gz at url |
url |
string | yes | https:// download URL of the package |
sig |
string | no | base64 detached signature, informational only — the backend does not check it against the downloaded bytes at install time |
license |
string | yes | must be open-source; proprietary (or any closed license) is refused |
source_url |
string | yes | a missing source_url is treated as closed-source |
pricing |
string | yes | free or paid; paid is refused |
Signature verification happens inside the .tar.gz, not against this
index's sha256/sig fields. Every package is a directory containing
plugin.json, its binary, checksums.txt (a sha256 manifest of every other
file), and signature (an ed25519 signature over checksums.txt, produced
by alist plugin sign). extension.TieredVerifier.DetermineTier reads
checksums.txt/signature from inside the downloaded archive at install
time, never the index entry's sha256/sig. A package with no
checksums.txt/signature inside it installs as third-party (🔴)
regardless of what the index says about it. This repository's CI still
checks sha256 against the real downloaded bytes to catch a stale or wrong
entry, but that check belongs to this registry, not to the AList backend.
Mirrors internal/thememarket/thememarket.go's CatalogEntry — an array of
these is what a theme source's index URL serves.
| Field | Type | Required | Notes |
|---|---|---|---|
id |
string | yes | the catalog entry's own id, a distinct namespace from the downloaded descriptor's own "id" field |
name |
string | no | display name |
author |
string | no | |
version |
string | no | if present, use plain MAJOR.MINOR.PATCH so update/rollback comparisons are well-defined |
url |
string | yes | https:// URL of the theme's JSON descriptor |
sha256 |
string | yes | hex sha256 of the descriptor at url — enforced by the backend at install time (thememarket.DownloadTheme) |
preview |
string | no | https:// preview image URL |
has_js |
bool | no | whether the descriptor carries a non-blank js field |
mode |
string | no | light, dark, or omitted — descriptive, never enforced |
signature |
string | no | hex ed25519 signature over id|version|sha256|url (canonicalEntrySigningInput) — required and verified only if the source has a public key configured |
A theme source's public key is optional (thememarket.Source.PubKey): with
none configured, every theme from that source installs as untrusted. With
one configured, every entry it serves must carry a verifying signature or
installation is refused.
A theme descriptor itself only needs to parse as a JSON object with a
non-empty string "id" field (ValidateDescriptor). Token colors, CSS
sanitization, and JS gating are checked on the frontend at load time.
plugins/<plugin-id>/entry.json one file per plugin, id = directory name
themes/<theme-id>/entry.json one file per theme, id = directory name
themes/<theme-id>/theme.json (optional) the theme descriptor, if hosted here
dist/plugins/index.json generated: published plugin source index
dist/themes/index.json generated: published theme source catalog
scripts/ validator + index builder (Python, stdlib only)
dist/ is generated by CI and committed back to main on every merge — do
not hand-edit it.
This registry's ed25519 public key, for entries a maintainer has reviewed and signed personally:
44447605a7bc68e1a4acca29d1d4d3bfb21575fc83d432a18d731de50d5da158
The matching private key is not in this repository and not a CI secret; it
is held offline and used manually for packages a maintainer has rebuilt
from source and reviewed. Most entries in plugins/ are not signed by this
key and install as third-party (🔴), the same tier as any URL-installed
plugin. Ask for a review in your pull request if you want one — signing is
never automatic.
plugins/com.example.demoplugin is signed
with this key, to exercise the format and the verified-tier install path.
See CONTRIBUTING.md for how to submit a plugin or theme,
or open an issue from
.github/ISSUE_TEMPLATE/ first.
scripts/validate.py checks every entry.json:
required fields, https://-only URLs, a real sha256 match against the
downloaded package/descriptor, strict MAJOR.MINOR.PATCH versions, valid
plugin ids/kinds, and — given a git ref to diff against — that an update
never lowers a version.
python3 scripts/validate.py # full check, including downloads
python3 scripts/validate.py --no-hash # schema-only, no network accessscripts/build_index.py aggregates every entry
into dist/plugins/index.json / dist/themes/index.json. CI runs this on
every push to main after validation passes.
MIT.