Plugin Packaging And Market
Prepare a DynamicLake plugin for review, signed catalog distribution, and updates.
Overview
DynamicLake plugins are distributed as .dynamiclakeplugin packages. A package contains a manifest, one executable, optional helper files, and an optional icon.
DynamicLake Market lists reviewed plugins from a signed catalog. The app verifies the catalog signature, downloads the selected package, checks package hashes, validates the manifest, and installs the package into DynamicLake's managed plugin folder.
Package Layout
Use one package folder per plugin.
TimerStatus.dynamiclakeplugin
plugin.json
icon.png
timer-status.py
README.md
Keep the package focused. Put caches, generated logs, user data, and large assets outside the package.
Package Limits
DynamicLake enforces these limits during local install and Market install:
| Item | Limit | | --- | --- | | Archive | 7 MB max | | Extracted package folder | 20 MB max | | plugin.json | 128 KB max | | Icon | 1.5 MB max |
Icon guidance:
- Use a square PNG.
512 x 512is recommended.256 x 256is the practical minimum.- Do not bake in rounded corners. DynamicLake applies the corner radius in the app and on the Market website
Runtime JSON limits:
| Item | Limit | | --- | --- | | JSON message payload | 64 KB max | | Inline image data | 48 KB max decoded bytes |
Use sfSymbol or appIcon image components before inline image data. Inline images are for small status artwork, not screenshots or large previews.
Manifest Rules
plugin.json must live at the package root.
{
"schemaVersion": 1,
"identifier": "com.example.plugins.timer-status",
"name": "Timer Status",
"version": "1.0.0",
"developerName": "Example Studio",
"executable": "timer-status.py",
"arguments": [],
"icon": "icon.png",
"autoStart": true,
"settings": [
{
"id": "showTimer",
"type": "switch",
"title": "Show Timer",
"systemImage": "timer",
"tint": "cyan",
"default": true
}
]
}
Validation rules:
schemaVersionmust be1.identifiermust be 3-128 characters and may contain letters, numbers,.,_, and-.identifiermust not change between versions.namemust be 1-80 characters.versionmust be 1-40 characters.executablemust be a relative path inside the package.icon, when present, must be a relative path inside the package.settings, when present, may contain up to24rows.- Setting types can be
switch,slider,select, orbutton. - Setting ids must start with a letter and may contain letters, numbers,
_, and-. selectsettings may contain up to24unique options. Options can be strings or objects withtitleand optionalsystemImage.buttonsettings may open onlyhttporhttpsURLs.- Absolute paths, null bytes, and
..path segments are rejected.
Archive The Package
Zip the package folder itself, not only its contents.
ditto -c -k --keepParent TimerStatus.dynamiclakeplugin TimerStatus-1.0.0.zip
The archive should extract to:
TimerStatus.dynamiclakeplugin/
and not to loose files at the archive root.
Generate Hashes
Market catalog entries use SHA-256 hashes so DynamicLake can verify what it downloads and installs.
Generate the archive hash:
shasum -a 256 TimerStatus-1.0.0.zip
Generate a stable package hash from the extracted package contents. The exact catalog signing flow is managed by DynamicLake, but review needs the package that will be published to match the submitted archive.
Market Catalog Entry
Approved plugins are published in the signed catalog.
{
"identifier": "com.example.plugins.timer-status",
"name": "Timer Status",
"version": "1.0.0",
"developerName": "Ada Example & Lin Example",
"developers": [
{ "name": "Ada Example", "profileURL": "https://github.com/ada" },
{ "name": "Lin Example", "profileURL": "https://github.com/lin" }
],
"description": "Shows timer progress in DynamicLake",
"category": "Productivity",
"iconURL": "https://example.com/timer-status/icon.png",
"packageURL": "https://example.com/timer-status/TimerStatus-1.0.0.zip",
"packageSHA256": "64 lowercase hex characters for the extracted package",
"archiveSHA256": "64 lowercase hex characters for the downloaded zip",
"releaseNotesURL": "https://example.com/timer-status/releases/1.0.0",
"websiteURL": "https://example.com/timer-status",
"supportURL": "mailto:[email protected]",
"status": "available"
}
developers is optional and supports up to two creators. Keep developerName for compatibility with older DynamicLake versions; when two creators are present, set it to both names joined with & . Each creator profile is optional.
The catalog version controls updates. When the catalog version is newer than the installed version for the same identifier, DynamicLake shows an Update action.
Submit For Review
Submit plugins from DynamicLake Market:
https://market.dynamiclake.com
The submission form asks for:
- plugin name
- primary developer name and an optional second developer
- category
- summary
- optional package URL
- optional repository URL
- optional website, creator profile, and demo video
- review notes
After submission, DynamicLake creates a private review issue and sends a status email to the developer. Status emails can be:
- waiting for review
- in progress
- live
- rejected
When a submission is rejected, the review team should include a short public reply note so the developer knows what to fix.
Review Checklist
Before a plugin goes live:
- Confirm the archive is
7 MBor smaller. - Confirm the extracted package is
20 MBor smaller. - Confirm
plugin.jsonis128 KBor smaller. - Confirm the icon is a square PNG, preferably
512 x 512, and1.5 MBor smaller. - Confirm custom settings are useful, clearly titled, and do not request secrets through plain text.
- Check that the executable path is relative and points inside the package.
- Check that the plugin does not collect secrets or sensitive data without a clear reason.
- Check that network access, file access, and background behavior match the submission notes.
- Check the plugin creates useful DynamicLake surfaces and dismisses stale work cleanly.
Testing Plugin Changes
Run the package tests when changing the JSON wire protocol or public plugin schema types.
swift test
The tests cover:
- JSON command decoding and validation failures
- supported component fields, including images, timers, progress, status, text, and buttons
When adding a plugin schema feature, add at least one success case and one rejection case. For new JSON component fields, add both a valid decode test and a malformed payload test.
Local Install vs Market Install
Local install is for development and testing. DynamicLake still validates package structure and size, but local installs are not reviewed.
Market install is for users. DynamicLake uses the signed catalog, package URL, package hash, and archive hash before installing or updating a plugin.
For plugin message schema details, see JSONPluginAPI. For shared UI rules, see DesignGuidelines.