Packaging and Distribution
May 9, 2026 · View on GitHub
How to ship a plugin to users — local sideloading, marketplace submission, and version updates.
Distribution artifact: a zip
A distributable plugin is a single zip named <plugin_id>-<version>.zip containing the compiled dylib and any companion files Osaurus surfaces in the UI:
mYplugin-0.1.0.zip
├── MyPlugin.dylib # the compiled plugin
├── web/ # optional static web UI
│ ├── index.html
│ └── assets/
├── SKILL.md # optional skill bundle (or skills/ dir of them)
├── README.md # surfaces in the plugin detail page
└── CHANGELOG.md # surfaces in the plugin detail page
Build the zip with:
osaurus tools package <plugin_id> <version> [dylib_path]
osaurus tools package auto-detects .dylib files in the current directory, and includes web/, SKILL.md, README.md, CHANGELOG.md if present. Output: <plugin_id>-<version>.zip in the current directory.
Installed layout (created by Osaurus)
When a user runs osaurus tools install <zip> (or installs from the marketplace), Osaurus unpacks the zip into the user's tools directory and writes a receipt.json recording the install metadata, hashes, and signatures. The author never writes receipt.json — it's host-generated.
~/Library/Application Support/Osaurus/Tools/my-plugin/
├── 0.1.0/ # version directory (created on install)
│ ├── MyPlugin.dylib # from the zip
│ ├── receipt.json # generated by Osaurus, not the author
│ ├── web/ # from the zip
│ ├── SKILL.md # from the zip
│ ├── README.md # from the zip
│ ├── CHANGELOG.md # from the zip
│ └── .user_consent # created on first user grant (release builds only)
├── current → 0.1.0 # symlink Osaurus maintains
The current symlink lets multiple versions coexist and atomically switch on upgrade.
Build configuration
Swift
Your Package.swift must produce a dynamic library:
.library(name: "my-plugin", type: .dynamic, targets: ["MyPlugin"])
For release builds:
swift build -c release --product my-plugin
strip -x .build/release/libmy-plugin.dylib
Symbols you must export:
osaurus_plugin_entry_v2(host: *const osr_host_api) -> *const osr_plugin_api
The legacy osaurus_plugin_entry symbol still loads but is not recommended for new plugins (no host API access).
Rust
Cargo.toml:
[lib]
crate-type = ["cdylib"]
Build:
cargo build --release
strip target/release/libmy_plugin.dylib
Code signing
Required for release builds. Without a signature, Osaurus refuses to load the plugin.
codesign --sign "Developer ID Application: Your Name (TEAMID)" \
--options runtime \
--timestamp \
MyPlugin.dylib
Verify:
codesign -vv MyPlugin.dylib
For Apple notarization (required when distributing outside the Osaurus marketplace), submit a zip:
zip MyPlugin.zip MyPlugin.dylib
xcrun notarytool submit MyPlugin.zip \
--apple-id you@example.com \
--team-id TEAMID \
--password '@keychain:notary' \
--wait
receipt.json (host-generated, informational)
After install, Osaurus writes a receipt.json next to the dylib recording install metadata:
{
"plugin_id": "dev.example.MyPlugin",
"version": "0.1.0",
"installed_at": "2026-05-08T17:42:01Z",
"dylib_filename": "MyPlugin.dylib",
"dylib_sha256": "sha256-...",
"platform": "macOS",
"arch": "arm64",
"public_keys": {...},
"artifact": { "url": "...", "sha256": "...", "minisign": null, "size": 12345 }
}
osaurus tools verify reads each receipt and re-hashes the dylib to confirm the bundle hasn't been tampered with after install. As an author you don't write or ship receipt.json — Osaurus generates it from the artifact's metadata when the user installs your zip.
User consent
On first install in release builds, Osaurus shows the user a permission summary and creates .user_consent once they grant. Until that file exists the plugin fails to load with consent_required: prefixed errors. DEBUG builds (running osaurus tools dev) skip consent.
What's surfaced in the prompt:
- Plugin name, version, author
- Declared
requirementsper tool (e.g.network,filesystem) - Description from the manifest
- Link to your README
Plan your requirements and description fields with this prompt in mind — they're the user's first impression.
Local distribution (sideload)
After running osaurus tools package, install the zip you produced:
osaurus tools install ./my-plugin-0.1.0.zip
Osaurus unpacks the zip into the tools directory, generates a receipt.json, updates the current symlink, and triggers a reload. To trigger a reload manually after files change in place:
osaurus tools reload
For an even tighter dev loop, use osaurus tools dev — it builds, installs, and watches your sources for changes.
Marketplace submission
The Osaurus plugin registry is github.com/osaurus-ai/osaurus-tools.
Steps:
- Tag a release in your plugin repo (
git tag v0.1.0 && git push --tags) - The CI workflow
.github/workflows/release.yml(included in the scaffold) builds, signs, notarizes, and attaches the bundle to the GitHub Release - Open a PR against
osaurus-ai/osaurus-toolsadding your plugin's metadata toregistry.json - The Osaurus team reviews for security and DX, then merges
Once merged, your plugin appears in the in-app marketplace within ~24 hours.
Version updates
Semver guidance:
- Patch — bug fixes, no manifest changes, no new permissions
- Minor — new tools or routes, no removed/renamed capabilities, no new top-level permissions
- Major — breaking changes (renamed tools, removed routes, new required secrets)
When publishing a new version:
- Tag the new version (
git tag v0.2.0) - Bump
versionin your manifest'sget_manifest - Update
osaurus-plugin.json - Add a
CHANGELOG.mdentry (surfaced in the plugin detail page) - Open a PR against the registry to update the version pin
Existing users will be prompted to upgrade. Their .user_consent carries forward unless your requirements widened, in which case re-consent is required.
What you can include in a bundle
- The dylib (required)
web/static UI directoryskills/directory ofSKILL.mdfiles (auto-loaded into the agent)- README, CHANGELOG, LICENSE (auto-surfaced in the UI)
What you should NOT include:
- Any source code (ship a separate source repo)
- Secrets, API keys, .env files
- Files outside
web/that you'd be embarrassed to have a usercat
See also
- QUICKSTART.md — develop locally
- DEBUGGING.md — when installs fail
- TESTING.md — pre-flight checks before shipping