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:

ToolMinimum VersionPurpose
Node.js18.0JavaScript runtime for build tools (if needed)
npm / pnpm / yarnLatestPackage manager (optional)
Git2.30Version control (required for submission)
Recommended editor

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-plugin

Every 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 icon

plugin.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: small

widget.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.

Instant feedback

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:

  1. Ensure all required files are present (plugin.yaml, entry HTML files, styles, scripts, and assets).
  2. Create a ZIP archive of your plugin directory.
  3. 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.

Review requirements

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: