Publishing Packages
Scaffold, sign, and publish packages to the Singularity Marketplace from the web or the CLI.
Jump to section
How to scaffold, sign, and publish packages to the Singularity Marketplace from both the web and the command line.
Overview
Singularity packages are versioned, signed bundles that extend Snippbot with new agents, tools, workflows, MCP servers, hooks, and more. Publishing happens through two surfaces:
- The web form at
/publish— a guided UI for first-time publishers and metadata-only updates. - The CLI (
snippbot marketplace publish) — the canonical path for repeatable, scripted, and signed publishing from source.
Both surfaces hit the same registry API. The CLI is what you use from CI; the web form is what you use to verify metadata, screenshots, and pricing before a release.
Package Types
When you scaffold a package you pick a type that tells Snippbot how to install and run it. The supported values come from the ArtifactType enum in packages/core/src/snippbot_core/marketplace/manifest.py:
| Type | Description |
|---|---|
agent_profile |
A reusable agent personality — system prompt, defaults, tool list. Default for init. |
agent |
A full agent implementation with its own runtime entrypoint. |
tool |
A single agent-invokable tool. See the Tool Authoring Guide. |
mcp_server |
An MCP server that exposes tools and resources over the Model Context Protocol. |
workflow |
A scripted multi-step workflow callable by agents. |
hook |
A lifecycle hook that runs in response to events (e.g. pre-tool-use, post-message). |
scheduled_job |
A periodic task driven by Snippbot's scheduler. |
shared_asset |
Static assets (knowledge packs, prompts, datasets) consumed by other packages. |
sandbox_preset |
A reusable sandbox profile (Seatbelt / bwrap / firejail rules). |
channel |
A messaging channel adapter (Slack, Discord, etc.). |
Pick the type that matches what you're shipping — it determines validation rules, permission declarations, and how Snippbot loads the artifact at runtime.
Prerequisites
Before your first publish, you need:
- A publisher account. Register from the CLI or the web:
Or visitsnippbot marketplace register/register. - An authenticated CLI session. See the API Keys & CLI Auth guide for the full flow:
snippbot marketplace login - (Recommended) An Ed25519 signing key. Required if you want a "signed" badge on your package and want clients to verify integrity. Covered in Signing Your Package.
Scaffolding a New Package
You have two ways to scaffold:
Option A — Download a starter template
Browse the Starter Templates page and download a ZIP for any package type. Each template ships with a pre-configured singularity.json, a README.md, and worked example stubs (e.g. a real PROFILE.md for agent_profile, a runnable entrypoint for tool, etc.). Best for first-time publishers.
Option B — `marketplace init` from the CLI
Use marketplace init to drop a minimal starter singularity.json manifest and .singularityignore into a directory:
snippbot marketplace init . --type tool
The command creates:
singularity.json— manifest with placeholder name, version, type, description, license, and files glob..singularityignore— gitignore-style exclusion list (defaults to ignoring.git/,.vscode/,.idea/,dist/,build/,.env, OS files).
If --type is omitted, the default is agent_profile. Edit singularity.json to fill in your real name, version, display name, description, category, tags, and any type-specific fields before publishing.
Signing Your Package
Signed packages get a verified badge in the marketplace and let installers cryptographically verify the artifact hasn't been tampered with. Signing is optional but strongly recommended.
Generate a key pair
snippbot marketplace keygen
This writes two files to the current directory (or --output <dir>):
singularity_signing_key— your Ed25519 private key (PEM, mode0600). Never commit or share this.singularity_signing_key.pub— your Ed25519 public key (PEM). Safe to commit.
Upload the public key to your publisher profile
snippbot marketplace upload-key ./singularity_signing_key.pub
This sends the public key to POST /api/v1/publishers/{your-name}/signing-key. The registry stores its fingerprint and uses it to verify signatures on future publishes.
Sign your package before publishing
snippbot marketplace sign .
This computes the SHA-256 of the built tarball and writes a .signature JSON file in your package directory containing the algorithm (Ed25519), signature, artifact hash, and timestamp. Use --key <path> to point at a private key in a non-default location (default lookup order: ~/.snippbot/singularity_signing_key, then <package_dir>/singularity_signing_key).
Publishing via the CLI
Once your manifest is valid and (optionally) signed, publish with:
snippbot marketplace publish .
What happens:
- The CLI validates
singularity.jsonagainstManifestSchema. Validation errors abort the publish. - The package is built into a
.tar.gzarchive using your.singularityignoreexclusions; the build returns a SHA-256. - If the package does not yet exist on the registry, the CLI creates it via
POST /api/v1/packagesusing the manifest's name, display name, description, type, category, tags, license, and URLs. - The version is uploaded via
POST /api/v1/packages/{publisher}/{package_name}/versionsasmultipart/form-datawith the archive and a JSON metadata blob containing version, changelog, README contents, and snippbot compatibility range. - On success the CLI prints the marketplace URL for your new version.
If a README.md, readme.md, or Readme.md exists in the package root, its contents are uploaded as the version's rendered README.
Publishing via the Web
Visit /publish for a guided form (PublishForm React component). The web form covers:
- New package metadata: name, display name, description, type, category, tags, license, repository/homepage URLs.
- A pricing toggle (free vs paid; paid requires Stripe-connected payouts).
- Cover image and screenshot uploads.
For a brand-new release the web flow expects you to upload a pre-built archive or to publish via the CLI and use the form only to update metadata. Use whichever surface fits your workflow.
Versioning and Update Policies
Singularity packages use semver-style version strings (major.minor.patch). Each call to marketplace publish registers a new version against the existing package — you cannot overwrite a published version.
Installers can pin their update behavior per package:
snippbot marketplace update-policy @publisher/package-name auto
snippbot marketplace update-policy @publisher/package-name prompt
snippbot marketplace update-policy @publisher/package-name pin --pinned-version 1.2.3
The three policies:
auto— automatically apply new patch and minor releases.prompt— ask before applying any update.pin— stay on the named version until manually changed.
Policies are stored locally in ~/.snippbot/marketplace_preferences.json and affect the snippbot marketplace update command's behavior.
Rolling Back a Release
If a release breaks installs, you can roll back an installed package to its previous version:
snippbot marketplace rollback @publisher/package-name
This rolls back the locally installed copy. To unpublish or yank a registry version, contact support — the registry does not currently expose a self-service unpublish endpoint.
CLI Reference
The full list of marketplace CLI commands with every flag is at the Snippbot CLI reference.
The publishing-related commands at a glance:
snippbot marketplace init [DIR] --type <type>— scaffold a new package.snippbot marketplace keygen [--output DIR]— generate an Ed25519 signing key pair.snippbot marketplace upload-key <public_key>— register your public key with your publisher profile.snippbot marketplace sign [DIR] [--key PATH]— sign a package's archive.snippbot marketplace publish [DIR]— build, upload, and register a new version.snippbot marketplace update-policy <pkg> <auto|prompt|pin> [--pinned-version VER]— configure update behavior locally.snippbot marketplace rollback <pkg>— revert a locally installed package to its previous version.
Tips and Best Practices
- Validate before you publish. The CLI runs schema validation, but you should also
snippbot marketplace inita sibling directory and diff fields when adopting a new package type — types differ in which fields are required. - Bump the version on every publish. The registry rejects duplicate versions; semver-bump even for metadata-only changes so installers can react.
- Include a
README.md. It becomes the version's rendered page on the marketplace. A README that's empty or missing leaves the package's listing looking like an empty placeholder. - Sign for distribution. Unsigned packages still work, but signed packages get a verified badge and let cautious users opt into "signed-only" installs.
- Keep
.singularityignoretight. The default excludes.git/, build artifacts, and OS files — but add anything secret (private keys, dev databases) explicitly so a stray file can't sneak into a published archive. - Use
--jsonin CI. Most marketplace commands accept--jsonfor machine-readable output; pipe it into your release notes generator.