Getting Started
Welcome to the Ghosty plugin development guide. This page walks you through everything you need to go from a blank project to a running plugin inside the Ghosty AI assistant.
What are Ghosty Plugins?
Ghosty plugins are self-contained web applications that run inside the Ghosty desktop and mobile clients. They can appear as dashboard widgets (small cards on the user's home screen) or as fullscreen views (dedicated pages with their own navigation).
Plugins are loaded in a secure sandbox and communicate with the host application through the GhostySDK -- a JavaScript API injected into the plugin's runtime at load time. The SDK provides access to storage, notifications, user context, and navigation without requiring direct access to the underlying operating system.
Prerequisites
Before you begin, make sure you have the following installed:
| Tool | Minimum Version | Purpose |
|---|---|---|
| Node.js | 18.0 | JavaScript runtime for build tools (if needed) |
| npm / pnpm / yarn | Latest | Package manager (optional) |
| Git | 2.30 | Version control (required for submission) |
Use any code editor with HTML, CSS, and JavaScript support. Popular choices include VS Code, WebStorm, Sublime Text, and Zed. No special extensions are required.
Create a new plugin project
Create a directory for your plugin and set up the required files manually:
mkdir my-first-plugin
cd my-first-pluginEvery plugin needs a small set of files. Create the following structure:
my-first-plugin/
plugin.yaml # Plugin manifest (name, permissions, views)
widget.html # Dashboard widget markup
fullscreen.html # Fullscreen view markup (optional)
styles.css # Shared styles
script.js # Plugin logic and SDK interaction
assets/
icon.png # 512x512 plugin iconplugin.yaml
Create the manifest file that declares your plugin's identity and views. See the Manifest Reference for full details.
name: my-first-plugin
version: 1.0.0
display_name: My First Plugin
description: A simple greeting plugin.
author: your-username
views:
widget:
entry: widget.html
default_size: smallwidget.html
Create the HTML file for your dashboard widget:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="widget-root"></div>
<script src="script.js"></script>
</body>
</html>styles.css
Add some basic styles:
body {
margin: 0;
font-family: system-ui, -apple-system, sans-serif;
}
.greeting {
padding: 16px;
text-align: center;
}script.js
Write the plugin logic that interacts with the GhostySDK:
document.addEventListener("DOMContentLoaded", () => {
const root = document.getElementById("widget-root");
const name = window.ghosty?.user?.displayName ?? "Developer";
root.innerHTML = `
<div class="greeting">
<h2>Hello, ${name}!</h2>
<p>Your first Ghosty plugin is running.</p>
</div>
`;
});Preview your plugin
Open the Playground to preview your plugin in real-time. Paste your files into the editor panels to see a live preview of how your widget and fullscreen views will look inside the Ghosty shell.
The Playground emulates the Ghosty host environment, injects the SDK, and renders your plugin exactly as users will see it.
The Playground updates the preview immediately as you edit. Use it to iterate on your layout, styles, and SDK interactions without any build step.
Project structure explained
plugin.yaml
The manifest file declares your plugin's identity, required permissions, and view configuration. See the Manifest Reference for full details.
widget.html
The HTML entry point for your dashboard widget. Widgets receive a bounded canvas with known dimensions and can respond to resize events.
fullscreen.html
Optional. If your plugin declares a fullscreen view in the manifest, this file serves as the entry point for rendering and navigation within that view.
script.js
Your plugin logic. Register lifecycle hooks (onInit, onVisible,
onHidden, onDestroy) via the GhostySDK. The Ghosty runtime calls these
hooks at the appropriate moments in your plugin's lifecycle.
styles.css
Shared styles for both widget and fullscreen views. Keep your CSS modular and scoped to avoid conflicts with the host application.
Your first plugin
Let's modify the starter files to display a greeting.
Open script.js and update the contents:
document.addEventListener("DOMContentLoaded", () => {
const root = document.getElementById("widget-root");
const name = window.ghosty?.user?.displayName ?? "Developer";
root.innerHTML = `
<div class="greeting">
<h2>Hello, ${name}!</h2>
<p>Your first Ghosty plugin is running.</p>
</div>
`;
});Paste this into the Playground and you should see a card on the simulated dashboard that greets the current user.
Package and submit
When your plugin is ready for review, package your files into a ZIP archive and upload them through the Submission Portal:
- Ensure all required files are present (
plugin.yaml, entry HTML files, styles, scripts, and assets). - Create a ZIP archive of your plugin directory.
- Open the Submission Portal and upload the ZIP file.
The submission portal uploads your plugin to the Ghosty review queue. Our AI review pipeline checks for security issues, performance regressions, and guideline violations. Most submissions receive a decision within 24 hours.
Make sure your plugin requests only the permissions it actually uses. Requesting unnecessary permissions is the most common reason for review rejection. See the Security Guidelines for more.
Next steps
Now that you have a working plugin, explore the rest of the documentation:
- Plugin Manifest -- learn every field in
plugin.yaml - Permissions -- understand the permission model
- GhostySDK Reference -- browse the full API surface
- Lifecycle Hooks -- control your plugin's initialization and teardown
- Widget API -- build responsive dashboard widgets
- Code Examples -- see complete working plugins