plugin.toml

Every plugin has a plugin.toml at the top of its folder. notesy reads it strictly: an unknown field, a bad value or a missing one is a problem, and notesy lists every problem at once on the Plugins page rather than stopping at the first.

tomlid = "ana.tasks"
name = "Tasks"
version = "1.2.0"
author = "Ana"
license = "MIT"
description = "Your note's tasks, beside it."
repository = "https://example.com/ana/tasks"
main = "main.rn"
permissions = ["notes.read", "ui"]

#The plugin

Field Required What it is
id yes author.name: lowercase letters, digits and -, each part 1 to 40 characters. The folder it's installed in has the same name. Ids starting notesy. are notesy's.
name yes What the Plugins page calls it.
version yes A semantic version, like 1.2.0.
author yes Who made it.
license yes An SPDX expression, like MIT or MIT OR Apache-2.0.
description no One or two sentences, shown under its name.
repository no Where its source is.
main no Its script, relative to its folder (main.rn). Without one it runs nothing and needs no approval.
notesy no The plugin API it's written for, like "1.0" (a semver requirement). A notesy whose API doesn't match won't load it, and says why. This notesy's API is 1.0.0.
permissions no What it asks to do (below).

A plugin has to do something: run a script, or add at least one of the things below (themes, icons, syntax, colors, languages).

#Permissions

Listed in permissions, shown to the user before a plugin with a script runs, and checked on every call. The ones in bold are shown in red. How and when notesy asks, and what an update or turning one off does: Permissions.

Id What it lets a plugin do
notes.read Read your notes and their properties
notes.write Create, change, rename and delete notes
files.read Read the other files in your vault, like images and PDFs
files.write Add, change and delete the other files in your vault
editor Read and change the note you're editing, and where the caret is
commands Add commands to the palette, with shortcuts, and run notesy's
ui Add panels, tabs, status bar items, settings pages, right-click menu items, hover card parts and dialogs
clipboard.read Read what you copy
clipboard.write Put things on your clipboard
notify Show notices
links.open Open web pages in your browser
accounts Sign you in to your accounts on the sites it names
plugins.share Share what it chooses with the plugins that ask to hear it

Three more are never listed by hand: naming hosts in [net] asks for net (connect to the internet, only to those sites), naming languages in [contributes] blocks asks for markdown (draw its own kinds of block in your notes), and naming plugins in [plugins] hears asks for plugins.hear (hear what they share).

The prompt warns, too, when a plugin can read what's yours and has a way to send it off: the network, opening links (a page's address can carry what it read), or sharing with other plugins.

#[net]

toml[net]
hosts = ["api.example.com", "*.example.org", "localhost:8080"]

The only sites the plugin may reach, through notesy's fetch (notesy::net). *.host means subdomains of it (not the host itself); a port can follow a colon. Plain http is allowed only to this computer and the local network, and those have to be named as such.

#[plugins]

The plugins whose shares it hears (notesy::events): naming one asks for plugins.hear. Needs main; a plugin can't hear itself (its parts talk on channels of their own), and hears at most 32.

toml[plugins]
hears = ["ana.sync"]

When the user approves it, notesy shows what it hears from whom, with a caution in red when a plugin it hears can read what's yours and this one can reach the internet or open links. When a plugin it hears is later allowed more, this one stops until they approve it again, seeing what changed.

#[[accounts]]

Services the plugin's script signs the user in to (notesy::accounts). Needs main and the accounts permission; a plugin asking for accounts has to name at least one.

toml[[accounts]]
id = "github"
name = "GitHub"
authorize_url = "https://github.com/login/oauth/authorize"
token_url = "https://github.com/login/oauth/access_token"
client_id = "Iv1.0123456789abcdef"
scopes = ["read:user"]
params = { allow_signup = "false" }
hosts = ["api.github.com"]

id (what the script calls it), name (the service, as the user knows it; the approval shows it), authorize_url (its sign-in page), token_url (where the code is traded for tokens), client_id (the app the plugin registered with the service), and any of scopes and params (more parameters for the sign-in page) and hosts (more sites its token goes to, where the service's API is). Both addresses, and every one of its hosts, have to be on hosts in [net]. Its token goes with a request only to its sign-in page's host, its token address's host and its hosts: never to another site the plugin names.

#[[previews]]

Screens of its own for notesy preview, each shown by its script (notesy::preview). Needs main.

toml[[previews]]
name = "board"
summary = "The task board, with a week of sample tasks"

name (lowercase letters, digits, -, _, + and ., starting with a letter: notesy preview ana.tasks/board shows it) and summary (a line for notesy preview --list).

#[contributes]

Files notesy reads itself.

toml[contributes]
themes = ["themes/dusk.toml"]
icons = "icons"
blocks = ["chart"]
Field What it is
themes Theme files in the plugin's folder; they show in Appearance as <id>/<file name>.
icons A folder of icons (an icon pack), shown in Appearance.
blocks Fenced-code languages its script draws as pictures (```chart), with notesy::blocks. Needs main; mermaid and typst are notesy's own.

#[[settings]]

Settings notesy draws a page for (under the plugin, in Settings) and keeps in its store. A script reads them with notesy::settings.

toml[[settings]]
key = "goal"
type = "number"
label = "Daily goal"
description = "Words to write each day."
default = 500
min = 100
max = 5000
step = 50
unit = " words"
style = "slider"

Every setting has key, type, label, and may have description, default, group (settings with the same group share a heading) and visible_if (the key of a switch: shown only while it's on).

type Extra fields What the user gets
switch an on/off switch
number min, max, step, integer, unit, style (stepper, slider or field) a number
text placeholder, multiline, max_length, secret a text field; a secret one goes to the system keychain and is never shown again
choice options, style (dropdown, or segmented for at most five) one of the options
multichoice options, min_selected, max_selected any of the options
list placeholder, max_items, suggest a list of strings; with suggest = true, its script suggests as a new one's typed (notesy::settings)
color alpha a color
note a note in the vault
folder a folder in the vault

An option is a table: { value = "week", label = "This week", description = "…" }.

#[[syntax]]

Text in notes between two marks, drawn a way of its own. Needs no approval.

toml[[syntax]]
name = "mention"
open = "@["
close = "]"
color = "accent"
background = "accent_soft"
bold = true

name (lowercase letters, digits, -, _), open, close, and any of color, background (a theme color's key, one of the plugin's own [[colors]], or #rrggbb), bold, italic, underline, strike, mono. At most 16.

#[[colors]]

Colors every theme gets, which the plugin's syntax and status items (and theme files) can use as <id>/<name>. The theme studio lists them under the plugin.

toml[[colors]]
name = "due"
label = "Due dates"
dark = "#f0a35e"
light = "#b45309"
follows = "warning"

name, label, and dark and light (#rrggbb or #rrggbbaa), or follows: a theme color it takes where it has no color of its own. At most 32.

#[[languages]]

Code languages for fenced blocks, highlighted by notesy from the words and marks listed. Needs no approval.

toml[[languages]]
names = ["ledger"]
keywords = ["account", "commodity"]
types = ["USD", "EUR"]
constants = ["true", "false"]
line_comments = [";"]
block_comment = ["/*", "*/"]
strings = ["\""]
ignore_case = false
calls = true

names (what a fence may say), then either like (one of notesy's own languages these are other names for) or the lists: keywords, types, constants, line_comments, block_comment, strings, ignore_case, calls (a word right before ( is a function). At most 8 languages and 2,000 words.

#[math]

Macros every formula can use, as if written at its start. Needs no approval.

toml[math.macros]
R = '\mathbb{R}'
abs = '\left|#1\right|'

Each key is a macro's name (letters only, without the \); its value is what it stands for, with #1 to #9 for its arguments. At most 64, each at most 512 characters. A note's own math-macros property (a list of \name = body) wins over a plugin's of the same name. A script can define more as it runs, with notesy::tex.

#[[icons]]

Icons of the plugin's own, for its views, panels, tabs, status items and commands to name: from images in its folder, or drawn by its script. Needs no approval.

toml[[icons]]
name = "chart"
file = "icons/chart.svg"

[[icons]]
name = "logo"
file = "icons/logo.png"
tint = false

[[icons]]
name = "count"    # no file: its script draws it

name (lowercase letters, digits, - and _), file (an SVG or a PNG in its folder, at most 256 KB; without one, its script draws it with icons::set, and it needs main), and tint: painted in the theme's colors like notesy's own icons (the default), or false to keep the image's own. At most 64. The plugin names one by name alone (icon: "chart"); anything else names it <plugin id>.chart. An icon pack can draw it differently, as with every icon; an <image> in its SVG may be inline data, never a file on this computer.

#What a script adds

Commands, side panels, tabs, sidebar sections and status bar items aren't named here: a plugin's script adds them as it runs, and can take them away again (notesy::commands, notesy::panels and notesy::views, notesy::sections, notesy::status). Whatever it added goes when it stops.

Every page