One object
{ name, mount }. No base class to extend and no lifecycle to learn. mount gets bus.on, scope.add and onShutdown, and that is the whole API.
Green Tea. plugins
A plugin is a name and a mount function. It adds providers and steps to the graph, and green-tea figures out where they run. Publish it to JSR or npm, list it here, and it gets a page of its own.
Needs @green-tea/core@26.9.0-beta.2 or newer. Each card shows which runtimes that plugin supports.
import type { Plugin } from '@green-tea/core';
export function greeting(text = 'hello'): Plugin {
return {
name: 'greeting',
mount({ scope }) {
scope.add({
kind: 'provider',
name: 'greeting',
needs: [],
provides: ['greeting'],
run: () => ({ greeting: text }),
});
},
};
}The idea
{ name, mount }. No base class to extend and no lifecycle to learn. mount gets bus.on, scope.add and onShutdown, and that is the whole API.
Plugins import @green-tea/core with import type and keep it out of dependencies, and review checks for it. So installing one does not pull in a second copy of core.
Say what your plugin needs and what it provides, and green-tea works out where it runs.
The listing
Three to start. The version and runtimes on each card come straight from the registry.
Loads JWT signing keys at boot and publishes a sign/verify registry into the graph.
Counts green-tea's lifecycle events and renders them in the Prometheus text format.
A per-request rate limiter with a branded 429 and a swept in-memory store.
Why here
How it works
Put it on JSR, or on npm as an ESM-only package.
matcha create plugin --package scaffolds one.
Open a pull request that adds one yaml file.
jsr: "@your-scope/green-tea-your-plugin"
repo: https://github.com/you/green-tea-your-plugin
description: "One sentence, 20 to 200 characters."Once it merges, it is out on the next Friday cut.
Every plugin here today is one of ours. The first community entries are the ones people will see first.