Browse API 1 documentation
Choose an extension type
Decide between a visible Sprig, composer utility, or headless Root.
Start with what the user should see. Grove has one package format, but its presentation determines how people open and use the extension.
| What you are building | Choose | Typical result |
|---|---|---|
| A dashboard, browser, game, or other persistent custom interface beside a conversation | Visible Sprig using channelPane, optionally window |
The extension renders its own HTML UI. |
| A bot console or dashboard that owns several joined channels on one network | Network tab Sprig using exclusive tab + server scope |
Mango runs one visible instance for that IRC session. |
| A picker or generator that briefly opens from the message composer | Composer Sprig using composer |
It returns text to the draft with grove.composer.complete(...). |
| Slash commands, native cards, badges, filters, member actions, or an upload provider | Headless Root using headless |
It has no web UI of its own and contributes native behavior to Mango. |
A settings page is optional configuration UI, not a fourth extension type. Any Sprig or Root may declare settings when it needs preferences or credentials.
Choose the surface first
Visible Sprig
Use a visible Sprig when the extension itself is something the user looks at or interacts with for more than one quick action.
"presentation": {
"surfaces": ["channelPane", "window"],
"defaultSurface": "channelPane"
}
Starting the Sprig from a conversation binds it to that conversation. window changes where the same content appears; it does not widen what IRC data the extension may access.
Good fits include a channel activity dashboard, a poll editor, a shared-game interface, or a tool that needs its own navigation.
Network tab Sprig
Use a server-scoped tab when one visible runtime coordinates several joined channels on the same IRC connection:
"presentation": {
"surfaces": ["tab"],
"defaultSurface": "tab",
"scope": "server"
}
tab is exclusive. Mango runs one instance per package and network, and reopening it selects the existing tab. Request channel.read to receive live messages plus the joined-channel roster, and network.send only when the extension must explicitly reply into those confirmed joined channels.
Composer Sprig
Use a composer Sprig for a focused choose-or-generate flow that ends by inserting text into Mango’s draft.
"presentation": {
"surfaces": ["composer"],
"defaultSurface": "composer"
}
composer must be the only surface. It opens only after an explicit user action, receives no IRC message stream or implicit send target, and cannot autostart. Finish with grove.composer.complete(text) so the user can review and send the result.
Good fits include GIF and emoji pickers, canned-response browsers, link builders, and local text transforms.
Headless Root
Use a Root when Mango should provide the visible UI, or when the extension reacts without presenting a pane.
"presentation": {
"surfaces": ["headless"]
}
A Root can register slash commands and native cards, publish status badges, add member-menu actions, filter messages, or provide an upload destination. Request only the capabilities used by those integrations.
Good fits include weather commands, message formatters, encryption filters, moderation helpers, and upload providers.
Then choose the scope
Surface and scope are separate decisions. A surface answers where is it visible? Scope answers which Mango or IRC context is it bound to?
| Required context | Scope | Notes |
|---|---|---|
| One channel or direct message | Omit presentation.scope |
Mango binds the instance to the conversation from which it starts. |
| One IRC connection | "scope": "server" |
One instance for that network session. Appropriate for a network tab, connection-wide commands, or filters. |
| The Mango application, without IRC message access | "scope": "application" |
Shared configuration and passive integrations such as an upload provider available across networks. |
For example, a connection-wide Root declares:
"presentation": {
"surfaces": ["headless"],
"scope": "server"
}
Application scope is intentionally not ambient access to every network. It has no IRC message, command, filter, presence, or implicit send route. Use it when a host integration should be configured once and does not need to observe IRC traffic.
Match capabilities to the feature
Capabilities describe the native operations the extension needs; hostPermissions separately lists external HTTPS or WSS origins it may contact.
| Feature | Typical capability |
|---|---|
| Read the bound conversation | channel.read or query.read |
| Read all live joined channels from server scope | channel.read |
| Send to the bound conversation | channel.send or query.send |
| Create and select a new private conversation while sending | query.send and query.open |
| Send to an explicit confirmed joined channel from server scope | network.send |
| Register slash commands and native cards | commands.register |
| Open a service profile from a native member action | ui.member-actions and ui.web-pane, plus matching hostPermissions |
| Publish native status badges | statusbar |
| Filter displayed or outgoing messages | messages.filter.inbound or messages.filter.outbound |
| Contribute an upload destination | uploads.provide |
| Upload one file produced by a composer utility through Mango | uploads.use |
| Open a system OAuth Authorization Code and PKCE flow | oauth.authorize |
| Call a non-CORS HTTPS API through bounded native transport | network.request plus matching hostPermissions |
| Persist ordinary web data | storage |
| Store credentials in Keychain | storage.secure |
See Capabilities before finalizing the manifest. A capability must be both declared and accepted by the user, and Mango checks the grant again for every bridge call.
Still unsure?
Choose the smallest shape that completes the user action:
- If the user needs to browse or manipulate a custom interface, start with a visible Sprig.
- If the interface exists only to produce draft text, use a composer Sprig.
- If native cards, commands, filters, badges, or uploads are enough, use a headless Root.
- Add a settings page only when configuration is necessary.
Continue with the Starter recipes to see each shape as a complete two-file package.