Skip to main content

What plugins are for

A plugin extends Cordial: it reacts to what the client is doing and asks Cordial to do something about it. Discord status from the current game, a FastFlag preset, a desktop notification when a server changes, a texture pack. If all you need is to apply something once at startup, a plain file is usually enough. Code earns its place when it watches, decides and acts.
A plugin can never reach into Roblox. There is no API for running code in the game, reading or writing its memory, or injecting scripts, and there never will be. Those things are absent, not disabled, so no plugin can ask for them. Why: ADR-001, ADR-003.

How it works

A plugin is a folder with a plugin.json and, usually, one TypeScript module. Cordial runs the module under Deno with no Deno permissions, so it cannot open a file, a socket or a program. It talks to Cordial in newline-delimited JSON over standard input and output. Everything a plugin does is a request to Cordial, carried out only if the user granted the capability it needs, in that profile. The plugin never holds the resource: to set Discord status it sends the text, and Cordial owns the connection. Why: ADR-007.

A plugin in five minutes

1

Make the folder

Keep the folder name and the id identical. Grants and settings key off the id; the FastFlag layer is read back by folder name.
2

Write the manifest

plugin.json
capabilities is what you request. What the plugin gets is what the user approves.
3

Write the module

main.ts
4

Grant it and run

Open Settings → Plugins, switch on Use Plugins, and turn on log on the plugin’s row. A plugin with nothing granted is never started. Press Play and look for the line in Cordial’s output.
Never write to standard output except protocol lines. console.log goes to the wire, and one unparseable line ends the conversation: Cordial stops the plugin. Use console.error for debugging; it lands in Cordial’s own output.

Developing without packaging

Instead of copying into the plugins folder, use Settings → Plugins → Add a plugin folder… and pick the folder that holds plugin.json. It is listed as Development, and edits inside it reload as you save. Adding or removing the folder takes effect the next time you press Play. FastFlags written with flags.set wait for the next launch too, because Roblox reads most flags once at startup. Details: Installing plugins.

What a plugin can use

A plugin can also declare preferences (switches, numbers, choices, text) in plugin.json. Cordial draws the settings page and hands the answers to the plugin read-only. Not available, by design: drawing over the game, adding controls to Cordial’s window, and changing a FastFlag in a running game. Two declared events, client.ready and window.resized, are not sent by anything yet.

Sharing a plugin

Pack the folder’s contents, with plugin.json at the top, as a .tar.zst archive. Users install it from Settings → Plugins → Install from a file. A plugin that contains code installs switched off, and nothing is granted until the user says so. There is a signed index format and an installer for it, but no index is running, so for now plugins are shared as files.

Examples to read

The four built-in plugins are small and real: flag-inspector (the shortest), fps-flex (preferences and pushes), discord-presence and hide-gui. The plugin API reference covers every method, event and refusal.