Plugins & Extensions
Zync has a decentralized extension system. Plugins run in sandboxed Web Workers or iframe panels and communicate with the app through a clean zync API — no native code required.
How It Works
Every plugin is a .zip archive containing at minimum:
manifest.json— declares the plugin's identity, version, and capabilities.main.js— your plugin logic, executed inside a Web Worker with access to thezyncglobal API.
Plugins come in two flavours:
- Background plugins — run in a Web Worker, no visible UI. Good for commands, status bar widgets, SSH automation.
- Panel plugins — register a full HTML/CSS/JS interface rendered in a sandboxed iframe inside Zync's tab bar. Good for dashboards, monitoring tools, custom file managers.
manifest.json
Every plugin must have a manifest.json at the root of its .zip. The id must follow reverse-DNS format and be globally unique.
{ "id": "com.yourname.plugin.my-plugin", "name": "My Plugin", "version": "1.0.0", "description": "A short description shown in the marketplace.", "author": "Your Name", "main": "main.js", "permissions": ["terminal", "statusBar", "ui", "panel", "ssh"]}For themes, add the theme-specific fields instead of main:
{ "id": "com.yourname.theme.my-theme", "name": "My Theme", "version": "1.0.0", "description": "A beautiful dark theme.", "author": "Your Name", "style": "theme.css", "mode": "dark", "preview_bg": "#0f111a", "preview_accent": "#6366f1"}The zync API
When your main.js runs, the global zync object is available. All async methods return Promises.
Lifecycle
zync.on('ready', function() { // Called once when the plugin is fully initialized. // Register commands and panels here. zync.logger.log('[my-plugin] ready');});Command Palette
Register commands that appear in Zync's command palette (Cmd+K / Ctrl+K).
zync.commands.register('my-plugin.ping', 'My Plugin: Ping Server', async function() { const output = await zync.ssh.exec('ping -c 4 8.8.8.8'); zync.ui.notify({ type: 'info', body: output });});Terminal
// Write text to the active terminalzync.terminal.send('ls -la');// Open a new terminal tab and run a commandzync.terminal.newTab({ command: 'htop' });SSH Exec
Run commands on the active SSH connection and get back the output as a string.
const uptime = await zync.ssh.exec('uptime -p');zync.ui.notify({ type: 'success', body: uptime });Status Bar
// Set a persistent status bar widgetzync.statusBar.set('my-plugin', '⚡ 12% CPU');// Update it on an intervalsetInterval(async () => { const stat = await zync.ssh.exec("top -bn1 | grep 'Cpu' | awk '{print $2}'"); zync.statusBar.set('my-plugin', stat.trim() + '% CPU');}, 5000);Notifications & Dialogs
// Toast notifications: success | error | info | warningzync.ui.notify({ type: 'success', body: 'Deployment complete!' });// Confirm dialog — returns Promise<boolean>const ok = await zync.ui.confirm({ title: 'Restart Nginx?', message: 'This will briefly interrupt traffic.', variant: 'danger',});if (ok) await zync.ssh.exec('sudo systemctl restart nginx');Panel Plugins (Full UI)
Call zync.panel.register to mount a full HTML interface as a tab inside Zync. The panel runs in a sandboxed iframe with a postMessage bridge back to the zync API.
zync.on('ready', function() { const html = `<!DOCTYPE html><html> <head> <style> body { font-family: sans-serif; background: #09090b; color: #fff; padding: 16px; } button { background: #6366f1; color: #fff; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; } </style> </head> <body> <h2>My Panel</h2> <button onclick="runCommand()">Run uptime</button> <pre id="out"></pre> <script> async function runCommand() { const result = await window.zync.ssh.exec('uptime'); document.getElementById('out').textContent = result; } </script> </body></html>`; zync.panel.register('my-plugin.panel', 'My Panel', html);});For complex panels, compile a full React or Vue app to a single HTML string (e.g. with Webpack html-webpack-plugin + inline-source). See the open-source pm2-monitor plugin in the zync-extensions repo for a complete example.
Packaging Your Plugin
Zip the plugin directory so that manifest.json is at the root of the archive (not inside a subfolder):
# From inside your plugin directory:$zip -r my-plugin.zip manifest.json main.js # Or if you have extra assets:$zip -r my-plugin.zip manifest.json main.js assets/The zip must be hosted at a publicly accessible URL so Zync can download and install it.
Publishing to the Official Marketplace
The official marketplace is the zync-extensions GitHub repository. To list your plugin:
- Fork github.com/gajendraxdev/zync-extensions.
- Add your plugin files under
plugins/your-plugin-id/. - Upload the
.zipto a permanent public URL (GitHub Releases on your own repo works well). - Add your entry to
marketplace.json:
{ "id": "com.yourname.plugin.my-plugin", "name": "My Plugin", "version": "1.0.0", "description": "What it does in one sentence.", "author": "Your Name", "type": "plugin", "downloadUrl": "https://github.com/yourname/my-plugin/releases/latest/download/my-plugin.zip"}- Open a Pull Request. Once merged your plugin appears in the in-app marketplace for all users.
Self-Hosted Registry
You don't have to use the official repository. Anyone can host their own plugin registry — a plain JSON file served over HTTPS — and users can point Zync at it from Settings. This is useful for private company plugins, beta channels, or curated plugin sets.
1. Create your marketplace.json
Your registry file must be a JSON array (or an object with a plugins key). Host it anywhere that returns the raw JSON over HTTPS — a GitHub repo, a CDN, or your own server.
[ { "id": "com.yourcompany.plugin.deploy", "name": "One-Click Deploy", "version": "2.1.0", "description": "Deploy to staging with a single command.", "author": "Acme Corp", "type": "plugin", "downloadUrl": "https://cdn.yourcompany.com/plugins/deploy-2.1.0.zip" }]2. Host it at a public URL
The simplest approach is a public GitHub repository — your raw URL will look like:
https://raw.githubusercontent.com/yourname/your-repo/main/marketplace.json3. Add the registry URL in Zync
In Zync, open Settings → Extensions and paste your registry URL. Zync will fetch it alongside the official marketplace and merge the results. Users on your team only need to add the URL once.
Format requirements
Zync accepts two formats for the registry file:
- Flat array —
[ { ...plugin }, ... ] - Object with keys —
{ "plugins": [...], "themes": [...] }
Each entry must have at minimum: id, name, version, and downloadUrl.