52946b9159
* docs: document the plugin marketplace Add a public Plugin Marketplace page covering both audiences: operators using the in-app catalog (Browse/Installed tabs, one-click install, Update to vX, the Sources dialog for team/corporate registries, plugin icons, feature-flag gating, sideloading still works) and plugin authors publishing into it (one-repo-per-plugin GitHub Release assets, the optional manifest icon field, submitting a plugins.yaml PR to the official catalog, GitHub-stars-only ranking, and hosting your own index.json source). Also cross-link the new page from plugins.md (replacing the now-false "No plugin marketplace" security note), plugins-authoring.md, and plugins-manifest.md (new icon field row); register it in meta.json and coverage.json. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: correct plugin-registry CI validation claims The registry index-build workflow does not validate plugins.yaml against schema.json, nor does build-index.mjs compare the entry id to the manifest id — bad entries are skipped-and-logged, and CI only fails when a non-empty list resolves to zero built entries. Reword the submission steps (in both the marketplace docs page and plugin-registry/README.md) to describe what the workflow actually does: it resolves each entry against the GitHub API and requires a correctly named <id>-<version>.tar.gz release asset, with maintainer approval as the real gate. Also clarify that plugins.yaml `categories` are free-form curation tags, not the manifest's category enum. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: split plugin-registry Pages deploy into its own job The single build-and-deploy job bound the `github-pages` environment at the job level, so GitHub evaluated that environment's protection rules on every PR run — failing the check even though the deploy steps were gated to non-PR events. This broke every PR touching plugin-registry/**, which is exactly what a plugin-submission PR does. Split into a PR-safe `build` job (no environment) and a non-PR-gated `deploy` job that owns the `github-pages` environment and runs only `deploy-pages`. Behavior on push/schedule/workflow_call is unchanged; PRs now run build+tests without tripping the environment gate. The star refresh calls this workflow by file path, so the job rename is safe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: describe index-build asset resolution accurately build-index.mjs picks the <id>-<version>.tar.gz release asset when present but falls back to the release's first .tar.gz otherwise, and only errors when a release has no .tar.gz at all — it does not hard-fail a misnamed asset. Reword the submission steps to present the exact asset name as an authoring instruction (so the index resolves the right asset) rather than a builder-enforced gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Revert "ci: split plugin-registry Pages deploy into its own job" This reverts commit2c5f649146. * Reapply "ci: split plugin-registry Pages deploy into its own job" This reverts commit3795cdb98a. --------- Co-authored-by: Kandev Agent <agent@kandev.dev> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
91 lines
4.5 KiB
Markdown
91 lines
4.5 KiB
Markdown
# Kandev plugin registry
|
|
|
|
This directory is the **official Kandev marketplace source** — the curated,
|
|
PR-edited list of plugins that show up when a user opens **Settings > Plugins >
|
|
Browse** inside Kandev.
|
|
|
|
It is deliberately minimal. It records *which repositories* are in the official
|
|
catalog; it does **not** store plugin metadata (display name, description,
|
|
author, version, tarball URL, checksum, stars). All of that is read from each
|
|
plugin's own GitHub release when the catalog index is built, so the listing can
|
|
never drift from what actually ships.
|
|
|
|
## Files
|
|
|
|
| File | Purpose |
|
|
| --- | --- |
|
|
| `plugins.yaml` | The curated pointer list — one entry per plugin repo. Human-edited via PR. |
|
|
| `schema.json` | JSON Schema (draft 2020-12) that `plugins.yaml` MUST validate against. Enforced in CI. |
|
|
| `build-index.mjs` | Build script (zero-dependency Node) that resolves each entry to a full catalog record and emits `index.json`. |
|
|
| `build-index.test.mjs` | `node --test` coverage for the build script's parser and enrichment. |
|
|
|
|
The generated `index.json` is published to GitHub Pages by the
|
|
[`plugin-registry-index`](../.github/workflows/plugin-registry-index.yml)
|
|
workflow and served as the fetch contract Kandev consumes.
|
|
|
|
## One repository per plugin
|
|
|
|
Each plugin lives in its **own** public GitHub repository, named
|
|
`kdlbs/kandev-plugin-<name>` for first-party plugins (third parties may use any
|
|
`owner/name`). Every plugin repo publishes its package as a GitHub **Release**
|
|
asset in the standard Kandev package format:
|
|
|
|
- `<id>-<version>.tar.gz` — the plugin package, and
|
|
- `checksums.txt` — the integrity manifest the install pipeline verifies.
|
|
|
|
The `kdlbs/kandev-plugin-template` starter repo is the recommended way to
|
|
bootstrap a new plugin with the right layout and a release workflow.
|
|
|
|
The catalog ranks plugins by **GitHub stars** (with a "recently updated"
|
|
alternative from each repo's last release). Kandev collects **no download or
|
|
usage telemetry** — there is no "most installed" metric, by design.
|
|
|
|
## Submitting a plugin to the official catalog
|
|
|
|
1. **Publish your plugin.** Push it to a public GitHub repository and cut a
|
|
GitHub **Release** whose assets include `<id>-<version>.tar.gz` and
|
|
`checksums.txt`. The release must pass the standard package integrity gate.
|
|
2. **Fork this repo** (`kdlbs/kandev`).
|
|
3. **Add one entry** to `plugin-registry/plugins.yaml` pointing at your public
|
|
repo:
|
|
|
|
```yaml
|
|
- id: my-plugin # MUST equal the `id` in your plugin manifest
|
|
repo: your-org/your-plugin-repo
|
|
categories: [productivity]
|
|
```
|
|
|
|
The `id` **MUST match the `id` in your plugin manifest** and be unique across
|
|
the file. `repo` is `owner/name`. `featured` is a maintainer-only pin and
|
|
should be left out of submissions.
|
|
4. **Open a pull request.** The index-build workflow runs on your PR (build +
|
|
tests, no Pages deploy) and resolves your entry against the GitHub API — your
|
|
repo must have a latest release that publishes a `.tar.gz` package and its
|
|
`checksums.txt`; an entry whose repo has no release or no package is skipped.
|
|
Name the package `<id>-<version>.tar.gz` and keep your entry `id` equal to
|
|
your manifest `id` so the index resolves the right asset. `plugins.yaml` must
|
|
also follow the `schema.json` pointer-list contract.
|
|
5. **A maintainer reviews and merges** — maintainer approval is what gates the
|
|
official catalog. Once merged, the index-build workflow picks up your entry
|
|
and your plugin appears in the in-app catalog on the next build.
|
|
|
|
## Teams and corporates: host your own source instead
|
|
|
|
You do **not** have to PR into this registry to share plugins internally. Kandev
|
|
supports **additional marketplace sources**: any URL that serves an `index.json`
|
|
document of the same shape can be added under **Settings > Plugins** as an extra
|
|
source, and its plugins are merged into the catalog alongside the official ones.
|
|
|
|
This is the recommended path for a team or corporate registry — host your own
|
|
`index.json` (for example by copying this directory's `plugins.yaml` +
|
|
`build-index.mjs` + workflow into your own repo and pointing Kandev at your Pages
|
|
URL). Adding a source is an explicit act of trust in that source's maintainer,
|
|
much like `brew tap`-ing a third-party tap. When the same `id` appears in more
|
|
than one source, the official source wins and later duplicates are hidden.
|
|
|
|
## Sideloading is always available
|
|
|
|
Appearing in this registry is only about **discovery**. Anyone can still install
|
|
an unlisted plugin by URL or by uploading a `.tar.gz` directly — the marketplace
|
|
never removes those escape hatches.
|