Plugin SDK Reference
Complete documentation for youwee-sdk (v2.2.0), the JavaScript/TypeScript authoring toolchain for building, signing, and distributing Youwee plugins.
1. Getting Started
SDK Overview
Youwee plugins are written in JavaScript/TypeScript and execute in a capability-based Deno sandbox. The SDK provides local development commands (using Bun), typescript typings, and access to app-mediated APIs for writing notification hooks, storage uploading, or post-processing tools. Note that Youwee executes packaged .ywp files, not raw workspaces.
Key Concepts
Plugin Workspace: The source directory containing your configurations, locales, and code. This is where you write and test code.
Packaged Plugin (.ywp): A signed archive produced from the workspace. Contains bundled code, checksums, and signature files. Only signed .ywp packages can be imported by users.
Important Rule: Workspaces are strictly for development. End-user distribution must use the signed .ywp format.
Development Lifecycle
Create a workspace folder containing plugin.json, package.json, and src/plugin.ts.
Install dependencies (bun install) with "youwee-sdk": "^2.2.0" in your package.json.
Configure your plugin metadata and triggers in plugin.json.
Write your hook functions in src/plugin.ts using the definePlugin(...) contract.
Add localized resources in locales/ (e.g. en.json, vi.json).
Run local typecheck (bun run typecheck) and runtime tests (bun run test:deno).
Build the bundled code: bunx youwee-sdk build (creates dist/plugin.cjs).
Generate signing keypair: bunx youwee-sdk keygen ./plugin.youwee-plugin-key.json.
Pack and sign: bunx youwee-sdk pack --private-key ./plugin.youwee-plugin-key.json (creates release/<slug>.ywp).
Import the signed .ywp file into Youwee settings or attach the workspace for live debugging.
Recommended Workspace Layout
my-plugin/
plugin.json # Plugin identity, permissions & settings config
package.json # NPM package properties & SDK dependency range
tsconfig.json # Editor and compiler configurations
README.md # Default documentation shown inside Youwee UI
README.vi.md # Localized Vietnamese documentation
CHANGELOG.md # Version history
src/
plugin.ts # Entrypoint where definePlugin() hooks reside
locales/
en.json # English translation keys
vi.json # Vietnamese translation keys
dist/
plugin.cjs # Generated production runtime bundle
release/
my-plugin.ywp # Signed packaged output imported into YouweeGitHub Actions in Workspace
Workspace scaffolds generated by Youwee include preconfigured GitHub actions:
CI Workflow (.github/workflows/ci.yml)
ci.yml: Runs type checking, code bundling, and contract tests against the Deno sandbox model.
name: CI
on: [push, pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- run: bun install
- run: bun run typecheck
- run: bun run build
- run: bun run test:denoRelease Workflow (.github/workflows/release.yml)
release.yml: Automates release packing, generates sha256 checksums, signs with the YOUWEE_PLUGIN_SIGNING_KEY repository secret, and uploads the final .ywp package to GitHub releases.
YOUWEE_PLUGIN_SIGNING_KEYname: Release Package
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- run: bun install
- run: bun run build
- run: echo "${{ secrets.YOUWEE_PLUGIN_SIGNING_KEY }}" > ./plugin-key.json
- run: bunx youwee-sdk pack --private-key ./plugin-key.json2. Manifest & Permissions
Every plugin must declare a plugin.json file. It defines identity, compatibility ranges, permissions, triggers, and configuration UI schemas.
{
"id": "local.gg-drive",
"slug": "gg-drive",
"name": "GG Drive",
"version": "0.1.0",
"runtime": {
"language": "javascript",
"supportedProviders": ["deno"],
"preferredProvider": "deno",
"entrypoint": "src/plugin.ts"
},
"compatibility": {
"appVersion": ">=0.15.0 <0.16.0",
"sdkVersion": ">=2.2.0 <3.0.0"
},
"triggers": [
"download.completed"
],
"permissions": {
"network": true,
"fs": [
"fs.payload-file.read",
"fs.user-selected.write"
],
"tools": [
"tool.ffmpeg.run"
]
},
"configFields": [
{
"key": "driveFolderId",
"inputType": "text",
"label": "Folder ID",
"required": true
}
],
"i18n": {
"defaultLocale": "en",
"supportedLocales": ["en", "vi"],
"directory": "locales"
}
}Identity Fields
id (immutable reverse-DNS name), slug (URL-safe string for paths), name (UI display name), and version.
Runtime Settings
language must be "javascript", supportedProviders must contain "deno", and entrypoint points to the workspace source code.
Lifecycle Triggers
List of triggers in plugin.json must use raw runtime strings (do not use triggers.downloadCompleted properties):
- download.queued: Fired when download is added to the download queue.
- download.beforeStart: Fired just before the downloader initializes connection.
- download.completed: Fired when the download succeeds and outputs a file.
- download.failed: Fired when the download job terminates with an error.
Capability Permissions
Youwee plugins run in a secure sandbox. Direct Deno filesystem and process spawning APIs are disabled. Instead, you declare capability permission scopes in plugin.json:
network: true - Grants outbound network fetch requests and YouTube API searches.
fs: Granular filesystem capabilities like fs.payload-file.read (access downloaded file), fs.payload-directory.read/write (neighboring files), fs.temp.read/write (scratchspace), and fs.user-selected.read/write (user config inputs).
tools: tool.ffmpeg.run and tool.ytdlp.run - Grants permission to run application-bundled yt-dlp and FFmpeg binaries.
YouTube Keyword Search API
When network: true is approved, plugins can request Youwee to perform keyword searches on YouTube using the app's managed connection. Excellent for finding matching videos, captions, or checking metadata:
const results = await ctx.youwee.youtube.searchVideos({
query: "hd drone flight 4k",
limit: 10,
filters: {
uploadDate: "thisWeek", // today, thisWeek, thisMonth, thisYear
duration: "short", // short (<4m), medium (4-20m), long (>20m)
sort: "viewCount", // relevance, viewCount
features: ["hd", "creativeCommons"] // live, fourK, hd, subtitles, creativeCommons, etc.
}
});
// Loading next page using continuation tokens
if (results.continuation) {
const nextPage = await ctx.youwee.youtube.searchVideos({
query: "hd drone flight 4k",
continuation: results.continuation,
limit: 10
});
}Configuration Fields (configFields)
Declare custom fields in configFields to let Youwee auto-render settings inputs. Supported input types: text, textarea, password (securely masked), number, boolean, file, directory, select, and multi-select. Saved variables are injected into runtime context.
3. Coding & Execution Context
Plugin Module Contract
The plugin module entrypoint must export a default object defined with definePlugin(...) that conforms to PluginDefinition.
import { definePlugin, triggers, type PluginDefinition } from "youwee-sdk";
const plugin = definePlugin({
meta: {
name: "My Post Processor",
version: "1.0.0",
description: "Converts output audio or triggers hooks after download."
},
hooks: {
[triggers.downloadCompleted]: async (ctx) => {
ctx.log.info(ctx.i18n.t("process.start", { file: ctx.file.name }));
// Perform app bridge mediated filesystem and tool tasks
const text = await ctx.youwee.fs.readText(ctx.file.path);
ctx.log.info("Read file contents successfully");
return ctx.ok("Job done successfully", { processedLines: text.split("\n").length });
}
}
} satisfies PluginDefinition);
export default plugin;Execution Context (ctx)
Each hook function receives a ctx argument containing payload metadata, configuration helpers, and secure app bridges.
ctx.triggerThe string identifier of the event triggering this execution.
ctx.downloadMetadata about the job (e.g. jobId, kind).
ctx.fileInformation about the file (e.g. path, name, size).
ctx.mediaInformation about the source media (e.g. url, title).
ctx.configAccess settings (get(key), require(key), has(key), all()).
ctx.logSafe logging methods (info, warn, error). Logs are shown in Youwee UI.
ctx.i18nLocalized translation helper (t(key, params), has(key), raw(key)).
ctx.youweeMeditated bridge APIs for filesystem, tools, and YouTube searches.
App Bridge APIs (ctx.youwee)
The ctx.youwee namespace exposes capability-based APIs that act as safe proxies to read/write files, call CLI tools, or perform keyword queries using the main application process's active sessions.
Filesystem Access (ctx.youwee.fs)
Read and write strings, binary data, or base64 files, manage directories, and create temporary files within sandboxed boundaries.
// UTF-8 Text read/write
const text = await ctx.youwee.fs.readText(ctx.file.path);
await ctx.youwee.fs.writeText(outputPath, text);
// Binary read/write (e.g. metadata, cover images)
const bytes = await ctx.youwee.fs.readBytes(ctx.file.path);
await ctx.youwee.fs.writeBytes(outputPath, bytes);
// Base64-encoded binary helper
const base64 = await ctx.youwee.fs.readBase64(ctx.file.path);
await ctx.youwee.fs.writeBase64(outputPath, base64);
// Directory & Temp operations
const files = await ctx.youwee.fs.readDir(approvedDirPath);
await ctx.youwee.fs.ensureDir(newDirPath);
const tempPath = await ctx.youwee.fs.tempDir("plugin-task-");
// Secure Cleanup
await ctx.youwee.fs.removeFile(tempPath + "/file.tmp");CLI Tools Runner (ctx.youwee.tools)
Spawn bundled instances of FFmpeg or yt-dlp to perform post-processing tasks, such as audio conversion, metadata embedding, or custom extraction.
// Run app-bundled FFmpeg command
const ffmpegResult = await ctx.youwee.tools.ffmpeg.run([
"-i", ctx.file.path,
"-vn",
"-acodec", "libmp3lame",
outputPath
]);
// Run app-bundled yt-dlp command
const ytdlpResult = await ctx.youwee.tools.ytdlp.run([
"--version"
]);
// Both return: { success: boolean, code: number, stdout: string, stderr: string }YouTube Keyword Search (ctx.youwee.youtube)
Run search queries on YouTube to retrieve video arrays and metadata without making raw external network requests.
const results = await ctx.youwee.youtube.searchVideos({
query: "lofi study beats",
limit: 15
});SDK Runtime Compatibility (ctx.youwee.sdk)
Inspect the active youwee-sdk runtime versions and assert if the host Youwee app version satisfies target compatibility ranges.
// Read SDK runtime version
const sdkVersion = ctx.youwee.sdk.version;
// Check compatibility range returns boolean
const isCompatible = ctx.youwee.sdk.checkAppVersion(">=0.15.0");
// Assert range throws a compatible error on failure
ctx.youwee.sdk.assertAppVersion(">=0.15.0");Results & Pipeline Mutations
Plugins return ctx.ok(message?, metadata?) for success, and ctx.fail(message?, metadata?) for failure. The return object can include mutations to pass file paths or metadata changes to subsequent plugins in the chain:
return {
success: true,
message: "Conversion complete",
mutations: {
activeFilepath: "/users/downloads/converted.mp3",
activeFilename: "converted.mp3",
extraFiles: ["/users/downloads/converted.vtt"]
}
};Internationalization (i18n)
To localize messages, declare i18n properties (defaultLocale, supportedLocales, directory) in plugin.json. Place JSON translation files in the locales folder (e.g. locales/en.json, locales/vi.json). Key translations are resolved dynamically from current app language.
Fallback Chain Order
- 1. Current active Youwee application locale
- 2. Application default fallback locale
- 3. Plugin's defaultLocale declared in manifest
- 4. Raw translation key string
{
"process.start": "Starting conversion of {{file}}"
}ctx.i18n.t("process.start", { file: ctx.file.name })4. Toolchain & Debugging
Build & Pack Commands
Use the Bun authoring toolchain to build and sign your plugin workspace:
Builds and bundles TypeScript files into a single bundle: dist/plugin.cjs.
Generates a secure Ed25519 signing keypair file.
Validates files, generates checksums and signatures, and outputs a signed .ywp package into release/.
Packaged Archive Structure
The packed .ywp file is a standard ZIP archive containing the following strict layout. Youwee inspects and verifies these files at import time:
manifest.json # Compiled static runtime manifest
build.json # SDK compiler & format metadata
checksums.json # SHA-256 integrity map for all files
signature.json # Ed25519 payload signature
dist/
plugin.cjs # Main compiled Javascript runtime
locales/
en.json # English translations
vi.json # Vietnamese translations
README.md # Default read documentation- manifest.json: Packed production manifest.
- build.json: SDK version metadata and build package formats.
- checksums.json: SHA-256 hashes of all bundled assets and files.
- signature.json: Ed25519 signatures validating the integrity of checksums.json.
- dist/plugin.cjs: Bundled JavaScript production runtime.
- locales/: Bundled localization files.
- README.md / CHANGELOG.md: Documentation rendered in Youwee UI.
Debugging & Live Workspaces
For quick iteration without building .ywp packages continually, use Youwee's Attach Workspace development flow:
- In Youwee, go to Settings > Plugins.
- Choose Attach Workspace and select your plugin workspace folder.
- Enable the attached plugin and assign it to a test workflow.
- Edit your src/plugin.ts or plugin.json files. Youwee reload is instant — trigger the workflow again to see updates.
Troubleshooting FAQ
Q:Deno throws permission errors (--allow-write or --allow-run)
A:Direct OS filesystem APIs and Deno command calls are blocked. Re-write your logic to use ctx.youwee.fs.* methods and ctx.youwee.tools.* methods instead.
Q:Plugin imports successfully but does not trigger
A:Verify the plugin is enabled in Settings > Plugins, appropriate triggers are requested in plugin.json, and the plugin has been assigned to active workflows.
Q:The manifest says my triggers are invalid
A:Ensure you are using raw trigger strings (e.g. "download.completed") instead of code properties (e.g. "triggers.downloadCompleted") in plugin.json.
Q:Environment variable fields are empty
A:Configuring user settings via permissions.env is obsolete. Use configFields in plugin.json to auto-render fields in the settings UI.
