Skip to main content

Publishing and packaging guide

The complete flow from packaging a .qplugin to listing it in the store. For API details, see the plugin store API reference.

What a .qplugin is

A .qplugin is just a zip archive, with one hard rule: manifest.json must be at the root of the archive.
❌ Wrong example (zipping the whole dist folder):

Minimal manifest.json template

⚠️ Must-read for Windows users: backslash \ problems

This is the most common packaging failure on Windows, and the error looks like this:

Cause

Some Windows tools (the old “Send to > Compressed (zipped) folder”, Compress-Archive in PowerShell 5.1, etc.) use \ as the zip entry path separator. The zip specification requires /. The store and the launcher reject packages containing \ — this is a security check against zip-slip path traversal attacks and will not be relaxed.

Fix

  • ✅ Use the one-click PowerShell script below (it replaces separators with / automatically)
  • ✅ Compress with the 7-Zip GUI
  • ✅ Use Compress-Archive from PowerShell 7+
  • ❌ Avoid the legacy Windows 10 right-click “Send to → Compressed (zipped) folder” and PowerShell 5.1
Supports picking a folder via a dialog and forces forward slashes automatically. Save it as pack.ps1, then right-click “Run with PowerShell” or run .\pack.ps1 -FolderPath D:\path\to\dist from the command line:
The script packages the contents of the folder you select. Select the directory containing your build output (such as dist) and make sure manifest.json is at the root of that directory.

Method 2: other common approaches

7-Zip (GUI)

  • Open the dist folder and select all content files (do not select the outer folder)
  • Right-click → 7-Zip → Add to archive
  • The resulting zip uses / in its internal paths by nature

PowerShell 7+

Validate package paths from the command line

Before uploading, check whether any zip entries still use backslashes:
The output should contain no \.

Upload and publish

The CLI uses the RFC 8628 device flow, so everything happens on the command line:
Flow: device flow login (prints the authorization code and verification URL, confirmed in the browser) → POST /developer/keys to upload the developer public key and obtain a certificate → the private key signs the package body (signature.json + signature.cert.json packed into the .qplugin) → find or create the plugin record → POST /plugins/:id/versions multipart upload. See the qomicex CLI tool reference for details.

Option 2: manual upload on the web

  • Log in to the plugin store → upgrade to developer
  • Developer center → create a plugin (fill in slug, name, category)
  • You must sign with the CLI before uploading (the store enforces signature verification):
  • Plugin management page → “Upload new version” → select the signed .qplugin (rename the zip extension to .qplugin)
  • Packages that are purely L3 with no dangerous permissions are published automatically; the rest go to manual review, and the result appears in the version list
  • Store uploads enforce signature verification: a missing signature.json or a failed verification → 422 signature_invalid, and the upload is rejected
  • Signing = Ed25519 three-level trust chain (the store root key issues the developer public key certificate → the developer private key signs the package body); signedHash is the SHA-256 of the canonical manifest plus the file listing
  • Key generation: openssl genpkey -algorithm Ed25519 -out dev-key.pem or node scripts/plugin-keygen.mjs generate
Quick reference for common upload errors: