Plugin API
SailAPI is the first argument your plugin gets, and is also window.SailAPI. This page lists everything on it.
SailAPI.apiVersion is 2. Check it before using newer members, so your plugin can say "please update Sail" instead of breaking: if (!(SailAPI.apiVersion >= 2)) return;
Games#
| Member | Returns |
|---|---|
getGames() | Every game in the library, as summaries (below). |
getGame(id) | One game's summary, or null. |
getActiveGameId() | The id of the game whose page is open, or null. |
getCover(id, kind) | An image URL for the game: 'hero' (wide banner), 'portrait' (tall cover) or 'header' (small wide capsule). An empty string when there's none. |
openGame(id) | Opens the game's page. |
A game summary has only safe, public details:
{
index: 0, // its place in the library
id: "…",
name: "Geometry Dash",
steamAppId: "322170", // "" when it isn't a Steam game
playtime: 55080, // seconds
lastPlayed: 1792376058288, // ms since 1970, 0 if never
isFavorite: false,
isRunning: false,
achievements: { total: 558, unlocked: 52 }
}
Pages and downloads#
| Member | What it does |
|---|---|
showTab(name) | Switches to a page: 'library', 'mods', 'workshop', 'downloads', 'downloadmanager' or 'achievements'. |
getDownloadSummary() | { active, total }: downloads in progress and in the list. |
Account#
getAccount() describes the signed-in Sail account and the launcher profile in use. Nothing secret is included: no tokens and no file paths.
{
signedIn: true,
displayName: "Sailor",
username: "sailor",
email: "…",
memberSince: 1777248000000, // ms, 0 if unknown
avatar: "…", // an image URL Sail already shows, or ""
launcherProfile: "Default Profile",
launcherProfileCount: 3,
syncEnabled: true,
storage: { used: 0, quota: 0, plan: "…" } // or null
}
Add-ons#
getAddons({ type }) lists installed plugins that are switched on and have everything they need, optionally only one type (for example 'layout'). It's what Library Layouts uses to find layouts.
{
id, name, version, author, type,
folder, // where its files are
manifest, // its plugin.json
settings, // its current settings
openSettings // a function that opens its settings window, or null
}
Events#
Each returns a function that stops listening. Call it in your dispose().
| Member | Called when |
|---|---|
onLibraryChange(callback) | Games are added, removed or changed. |
onNavigate(callback) | The user goes to another page or game. |
onAccountChange(callback) | The user signs in or out, or the account details change. |
onAddonsChange(callback) | Plugins are installed, removed, switched on or off, or a layout's settings change. |
const stop = SailAPI.onLibraryChange(() => redraw());
return { dispose() { stop(); } };
Older members#
These still work, but can't be undone, so a plugin that uses them can't be switched off without restarting Sail.
| Member | What it does |
|---|---|
registerTheme(theme) | Adds a custom theme to Sail's theme list. |
addSidebarItem(name, icon, onClick) | Adds an entry under your folders in the sidebar. |
onGameLaunch(callback) | Calls back when a game is launched. |
Last updated 20 October 2026