185 lines
9.4 KiB
Markdown
185 lines
9.4 KiB
Markdown
# Community plugins
|
||
|
||
<p align="center">
|
||
<img src="https://assets.noctalia.dev/noctalia-logo.svg?v=2" alt="Noctalia Logo" style="width: 192px" />
|
||
</p>
|
||
|
||
---
|
||
|
||
This repo is the **community** plugin source for [Noctalia](https://github.com/noctalia-dev/noctalia). Every
|
||
plugin merged here is listed in the shell's plugin store and on
|
||
[noctalia.dev/plugins](https://noctalia.dev/plugins), and users can install it without adding a source of their own.
|
||
|
||
Plugins maintained by the core team live in
|
||
[official-plugins](https://github.com/noctalia-dev/official-plugins), which does not accept third-party plugins.
|
||
This one does. **PRs are welcome.**
|
||
|
||
> The plugin system is in **beta**. The manifest format and the plugin API may still change before v5 is stable.
|
||
> Expect to bump your plugin when they do.
|
||
|
||
## Layout
|
||
|
||
Each plugin is **one top-level directory**, named after the part of its id that follows the `/`, so `me/hello` lives
|
||
in `hello/`:
|
||
|
||
```
|
||
hello/
|
||
plugin.toml # manifest: id ("me/hello"), metadata, entries, settings
|
||
hello.luau # your entry scripts
|
||
README.md # rendered as the plugin's page on noctalia.dev
|
||
thumbnail.webp # the plugin's card image
|
||
translations/
|
||
en.json # every label_key / description_key the manifest references
|
||
```
|
||
|
||
`catalog.toml` at the repo root indexes every plugin. **It is generated by CI, so never edit it or include it in a
|
||
commit.**
|
||
|
||
A plugin id is `<author>/<plugin>`. The author part is yours (your GitHub handle is the obvious choice) and keeps your
|
||
id distinct from everyone else's, but the **directory name is first-come within this repo**. If `weather/` is already
|
||
taken, pick another name; the official repo is a separate source, so a name used there is not taken here. Both id
|
||
segments must be lowercase and match `[a-z0-9][a-z0-9._-]*`.
|
||
|
||
## What a plugin is allowed to be
|
||
|
||
Noctalia plugins are **trusted, unsandboxed Luau**. There is no permission broker and no capability sandbox:
|
||
installing a plugin is equivalent to running a script the user owns. It can read and write files, spawn processes, and
|
||
talk to the network as the user.
|
||
|
||
That is a deliberate design choice, and it puts the burden on review. So:
|
||
|
||
- **No obfuscated, minified, or generated code.** A reviewer must be able to read every line you ship.
|
||
- **No downloading and executing remote code.** Ship your logic in the repo, at a version people reviewed.
|
||
- **Declare what you shell out to.** External commands go in `dependencies` in `plugin.toml` and get a mention in your
|
||
README.
|
||
- **Account for every network call, filesystem write, and spawned process** in your PR description.
|
||
|
||
Anything that looks like it is hiding what it does will be rejected, regardless of intent.
|
||
|
||
## Writing a plugin
|
||
|
||
The [plugin development docs](https://docs.noctalia.dev/noctalia/plugins/development/) are the reference: the
|
||
[manifest](https://docs.noctalia.dev/noctalia/plugins/development/manifest/), the
|
||
[entry types](https://docs.noctalia.dev/noctalia/plugins/development/entries/) (`[[widget]]`, `[[panel]]`, `[[shortcut]]`,
|
||
`[[service]]`, `[[desktop_widget]]`, `[[launcher_provider]]`), the
|
||
[declarative UI](https://docs.noctalia.dev/noctalia/plugins/development/declarative-ui/) vocabulary, the
|
||
[runtime API](https://docs.noctalia.dev/noctalia/plugins/development/runtime-api/), and the
|
||
[workflow](https://docs.noctalia.dev/noctalia/plugins/development/workflow/) for developing and testing locally.
|
||
|
||
The fastest start is to read
|
||
[`noctalia/example`](https://github.com/noctalia-dev/official-plugins/tree/main/example) in the official repo. It
|
||
exercises a bar widget, a declarative widget, a service, a shortcut, a launcher provider, and a panel in one plugin.
|
||
|
||
To run your plugin while you work on it, add this checkout as a `path` source:
|
||
|
||
```sh
|
||
noctalia msg plugins source add dev path ~/dev/community-plugins
|
||
noctalia msg plugins enable me/hello
|
||
```
|
||
|
||
`.luau` edits hot-reload; manifest changes are picked up on the next config reload.
|
||
|
||
### Editor setup
|
||
|
||
`noctalia.d.luau` declares the whole plugin API, so luau-lsp gives you autocomplete and typo diagnostics. It lives in
|
||
official-plugins, which is its single source of truth; it is **not** vendored here, because a committed copy would be a
|
||
second one for everyone to trust and keep in sync. Fetch it into the repo root, where it is gitignored:
|
||
|
||
```sh
|
||
curl -O https://raw.githubusercontent.com/noctalia-dev/official-plugins/main/noctalia.d.luau
|
||
```
|
||
|
||
Re-run that whenever the plugin API changes; your local copy is a snapshot, not a subscription.
|
||
|
||
The committed `.vscode/settings.json` already points luau-lsp at it; for another editor, add it to luau-lsp's
|
||
`types.definitionFiles`. `.luaurc` sets `nonstrict` mode, matching the `--!nonstrict` directive every plugin file
|
||
starts with.
|
||
|
||
### Thumbnail
|
||
|
||
Every plugin ships a `thumbnail.webp`. It is the card image in the plugin store and on the website. Generate one with
|
||
the **[thumbnail generator](https://assets.noctalia.dev/plugins/thumbnail-generator.html)**: drop in a screenshot of
|
||
your plugin, set the title, category tag and accent color, then export the 960×540 WebP and commit it as
|
||
`<plugin>/thumbnail.webp`.
|
||
|
||
### README
|
||
|
||
`README.md` is the plugin's public page, so it must tell a user how to access every entry instead of only describing
|
||
the implementation. Follow [`README_TEMPLATE.md`](README_TEMPLATE.md), which mirrors the structure used by the
|
||
official plugins:
|
||
|
||
- Start with a title, a short explanation, a `Plugin` table, and practical `Usage` instructions.
|
||
- Copy the plugin id and every entry id exactly from `plugin.toml`.
|
||
- If the plugin declares a panel, include the exact command
|
||
`noctalia msg panel-toggle <author>/<plugin>:<panel-id>`.
|
||
- If it declares a launcher provider, document its `/<prefix>` and give an example query.
|
||
- Mention every manifest dependency under `Requirements`, using the exact dependency name.
|
||
- Document declared settings, including units or non-obvious effects.
|
||
- Use `IPC` and `Notes` when the plugin exposes extra events or has important filesystem, network, process, privacy,
|
||
hardware, or compositor behavior.
|
||
|
||
CI derives ids, panel commands, launcher prefixes, dependencies, and whether settings exist from `plugin.toml`. Its
|
||
error messages show the exact missing value, while maintainers review the usefulness and accuracy of the prose.
|
||
|
||
### Translations
|
||
|
||
Write `translations/en.json` only. Every `label_key` and `description_key` in your manifest must resolve to a key in
|
||
it, and CI checks this. Do not add machine-translated locales; other languages are handled separately.
|
||
|
||
To test the latest translated locales from [Noctalia Translate](https://i18n.noctalia.dev) in a working checkout, run:
|
||
|
||
```sh
|
||
./.tools/i18n-pull.sh
|
||
```
|
||
|
||
The command asks for confirmation and overwrites the locale files returned by the translation service. It does not
|
||
delete local locale files that are absent from the export. Review the resulting diff before committing anything.
|
||
|
||
### Tags
|
||
|
||
The `tags` in `plugin.toml` are used for catalog search. Tags must be lowercase and selected from this list:
|
||
|
||
- Surfaces: `bar`, `desktop`, `launcher`, `panel`, `service`, `shortcut`
|
||
- Purpose: `ai`, `animation`, `audio`, `clock`, `countdown`, `demo`, `development`, `emoticon`, `fun`, `gaming`,
|
||
`hardware`, `indicator`, `language`, `media`, `music`, `network`, `privacy`, `productivity`, `recording`, `system`,
|
||
`theming`, `time`, `utility`, `video`, `wallpaper`
|
||
- Compositors: `hyprland`, `labwc`, `mangowc`, `niri`, `sway`
|
||
- Distributions: `arch`, `debian`, `fedora`, `gentoo`, `nixos`, `opensuse`, `void`
|
||
|
||
If your plugin does not fit any existing tag, propose a new one in your pull request rather than inventing a tag in
|
||
the manifest.
|
||
|
||
## Submitting
|
||
|
||
Open a PR against `main`. CI validates your manifest, entry scripts, required files, and thumbnail on every push.
|
||
|
||
- **One plugin per PR.**
|
||
- The directory name matches the part of `id` after the `/` in `plugin.toml` **exactly**.
|
||
- `version` is semver and gets bumped on every change to the plugin.
|
||
- `plugin_api` is the oldest Noctalia plugin API level the plugin requires. Use the current documented level for a new
|
||
plugin, and increase it only when the plugin adopts a capability from a newer API level.
|
||
- `description` is concise catalog copy, limited to 120 characters. Put feature details in the plugin's README.
|
||
- `license` is set in `plugin.toml`. You keep the copyright on your plugin; if it is not MIT, put a `LICENSE` file in
|
||
your plugin directory. There is no repo-wide license covering contributed plugins.
|
||
- Screenshots or a short video for anything with a visual surface.
|
||
|
||
Maintainers read the code before merging. Expect review comments about clarity, and about anything the plugin does
|
||
that is not obvious from its description.
|
||
|
||
## Maintaining your plugin
|
||
|
||
The plugin directory is yours. Someone else's PR changing your plugin is not merged without your sign-off, unless it
|
||
fixes something that is broken or is a mechanical change applied across the whole repo. Maintainers will @-mention you
|
||
on PRs and issues that touch it.
|
||
|
||
If you stop maintaining a plugin, set `deprecated = true` in its `plugin.toml` rather than deleting the directory. The
|
||
store keeps working for people who already installed it, but it stops being offered to new users. Plugins that are
|
||
broken and unmaintained across a Noctalia release may be deprecated by maintainers.
|
||
|
||
## Help
|
||
|
||
- [Documentation](https://docs.noctalia.dev)
|
||
- [Discord](https://discord.noctalia.dev)
|
||
- Bugs in Noctalia itself (not in a plugin) belong in
|
||
[noctalia](https://github.com/noctalia-dev/noctalia/issues).
|