Marketplace / Docs / Publishing

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:

  1. A publisher account. Register from the CLI or the web:
    snippbot marketplace register
    
    Or visit /register.
  2. An authenticated CLI session. See the API Keys & CLI Auth guide for the full flow:
    snippbot marketplace login
    
  3. (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, mode 0600). 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:

  1. The CLI validates singularity.json against ManifestSchema. Validation errors abort the publish.
  2. The package is built into a .tar.gz archive using your .singularityignore exclusions; the build returns a SHA-256.
  3. If the package does not yet exist on the registry, the CLI creates it via POST /api/v1/packages using the manifest's name, display name, description, type, category, tags, license, and URLs.
  4. The version is uploaded via POST /api/v1/packages/{publisher}/{package_name}/versions as multipart/form-data with the archive and a JSON metadata blob containing version, changelog, README contents, and snippbot compatibility range.
  5. 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 init a 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 .singularityignore tight. 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 --json in CI. Most marketplace commands accept --json for machine-readable output; pipe it into your release notes generator.