Getting started
Make your first ForgeCast plugin, run it, and try it on make-believe chat. About ten minutes.
You need the ForgeCast desktop app (signed in, see how) and a text editor. VS Code with the Lua extension by sumneko is the easiest, because ForgeCast sets it up for you; anything that edits text works.
Turn on Developer mode
Open Settings → Developer and switch Developer mode on. It is a plain switch, open to everyone. It adds the plugin tools (New plugin, the Console, the Test environment and the SDK & reference tab) and makes a plugin reload itself when you save its files.
Make a plugin
Go to Plugins and choose New plugin. Give it a name and pick a starting point:
| Template | What it starts with |
|---|---|
| Blank | Logs every chat message. The smallest useful plugin. |
| Block users | Middleware that hides chat from a list, with a box on the Dashboard to manage the list. |
| Random chatter | Draws a random viewer from recent chat, for giveaways. |
| Super Chat notifier | A notification and a sound for Super Chats, new members and gifts. |
| Window demo | Opens a window of its own with a message counter and the latest chat. |
Choose Blank. ForgeCast creates a folder in your plugins folder (Plugins → Plugins folder opens it) with plugin.json, main.lua and the editor files.
Open it in your editor
Open the plugin's folder in VS Code. When it offers to install the Lua extension, say yes. The folder contains a .forgecast/ folder with forgecast.d.lua: that is the whole API, described for the language server, so you get completion, the documentation of each function as you type, and warnings for mistakes. You never need to edit anything in .forgecast/.
Not using VS Code?
The same file works in any editor with Lua language server support. Or write the code in a plain editor and keep the reference open next to it.
Write something
Replace the contents of main.lua with this:
-- Runs once, when the plugin is turned on.
log.info("hello from", plugin.name)
-- Runs for every new chat message.
chats.on(Event.NewChat, function(chat)
if chat.text:lower():find("hello", 1, true) then
ui.notify({ title = chat.author.name .. " says hello", message = chat.text })
end
end)and in plugin.json, add the notification permission next to the chat one:
"permissions": ["chat.read", "ui.notify"]Turn it on
Back in the app, the plugin is on the Plugins screen with a switch. Turn it on. ForgeCast lists what the plugin asked for and you tick what it may do (anything marked Be careful starts unticked). Choose Allow and turn on.
If you made a mistake, the plugin shows an error instead of running, with the file and line. Fix it, save, and it tries again.
Try it
Open the Test environment tab and send a chat line that says hello everyone. A notification appears in ForgeCast. Open the Console tab: the line hello from Blank is there, and so is anything else the plugin prints.
You can also follow a real stream (on the Dashboard, or by link in Developer mode) and your plugin sees its chat.
The life of a plugin
main.luaruns once, when the plugin is turned on (and again each time it is reloaded). Everything after that happens in the functions you hand to ForgeCast:chats.on(…, function),timer.every(…, function), a button'son_click.- Saving a file reloads the plugin while Developer mode is on. It starts from scratch, so anything it wants to keep must go through
storage. - If
main.luafails, the plugin stops and shows why. If a handler fails later (an error inside achats.onfunction, say), the error goes to the console and the plugin carries on; one broken handler never stops the others. - A plugin can only do what its
permissionslist says and what you approved. Calling something it isn't allowed to do gives an error that names the permission to add.
Make it a bit more
Here is the same plugin with a counter on the Dashboard. It needs ui.dashboard in the permissions too:
local count = 0
local box = dashboard.section({ id = "hellos", title = "Hellos so far" })
local function draw()
box:render(ui.column({
ui.heading(tostring(count)),
ui.button("Reset", function() count = 0 draw() end),
}))
end
chats.on(Event.NewChat, function(chat)
if chat.text:lower():find("hello", 1, true) then
count = count + 1
draw()
end
end)
draw()dashboard.section makes a box on the Dashboard; box:render(…) replaces what is inside it. That is the whole idea of interfaces in ForgeCast: you describe what to show, and call render again whenever it changes. Build an interface has everything you can put in it.
Next
- Copy a finished plugin from the examples and change it.
- Read Chat and streams for everything chat-related.
- Keep Testing and debugging open while you work.

