---
title: Packaging and Publishing
description: What an install package contains, the checks at install time and after install, signatures and trust levels, and the ways to distribute that exist today.
section: dev
order: 80
updated: 2026-11-05
translation_of: zh
source_sha: ee3864be798b
---
# Packaging and Publishing
## How you can distribute today
- **Install on your own machine**: click "Install" in Gem Studio. Notochord builds the draft into an install package locally and runs it through the same install flow as a gem from the store: the same checks, and the same setup on the gem's page afterwards. The only difference is that this package has no signature and is treated as "Developer mode (unsigned)".
- **Distribute to others**: there is currently no way to export a draft as an install package or submit it to the store. The store in the app currently lists open-source gems that we maintain ourselves.
## What is in an install package
A zip with these at its root:
| File | Description |
| --- | --- |
| `notochord.json` | The manifest. Besides the fields in the [manifest reference](/en/dev/manifest.md), it carries two items generated at packaging time: `agents[]` (generated from the header of each file under `agents/`) and `integrity` (the SHA-256 and size of every other file in the package). |
| `SIGNATURE.json` | The signature over the manifest. Drafts installed from Gem Studio do not have this file. |
| Other files | Tools (`tools/`), agents (`agents/.md`: header + system prompt), SOPs (`workflows/`), pages (`pages/`), collection migration modules (the files that `data.collections..migrations` points to), and so on. `db/` holds the schema and migrations of the `rawSqlite` database (`db/schema.sql`, `db/migrations/`); a gem that has them opens this database at startup, and if the schema or a migration is wrong, the gem cannot start. The next two folders need no declaration in the manifest; being there is enough: `skill/` (`SKILL.md` and the text files under `references/`, see [skill](/en/dev/manifest.md#skill)) and `docs/` (store description pages, Markdown only, see [docs](/en/dev/manifest.md#docs); when Gem Studio packages, it removes the files there that are not `.md`). |
## What is checked at install
Install and upgrade both check in the order below. If any item fails, the package is not installed:
1. **Unpacking**. The package may not contain absolute paths, `..`, symbolic links, or files whose names differ only in case; no more than 10000 files; the unpacked content may not exceed the total size declared in the manifest.
2. **Signature** (see the next section). Done before anything in the manifest is read.
3. **Manifest format**. A field in the manifest that is not recognized is rejected, not ignored. A gem id may not start with `draft-test.`; that prefix is reserved for Gem Studio tests.
4. **Version**. It may not be lower than the installed version. The same version is a reinstall: the installed files are replaced with the files in the package, and the gem's data and settings are kept.
5. **Integrity**. The files listed in `integrity` must correspond one to one with the files actually in the package: one extra, one missing, or a size or SHA-256 mismatch all fail. A package without a signature must also have `integrity` (Gem Studio computes it automatically when packaging).
6. **Whether the declarations are valid**. The form of permissions, whether the tools an agent references exist, whether `id`s in `resources` are duplicated, the call target and triggers of each SOP, the file types in `skill/` and `docs/`, and the [`data`](/en/dev/manifest.md#data) section: violations give `E_PERM_INVALID`, with a message starting with `data:` (unrecognized keys or a wrong `type` in the `data` section are already rejected at step 3); a collection's migration module must be a file in the package.
When installing from the store or Gem Studio, the gem is installed only if all of these checks pass; there is no confirmation step for the user. After install, open the gem's page: everything that needs configuration (accounts, mailboxes, knowledge bases) is still off, waiting for the user to set it up.
**Upgrade migrates data.** After all checks pass, the new version is activated. If the new version raised a collection's `version`, the [migration](/en/dev/storage.md#versions-and-migrations) runs first during activation. If the migration fails, or the change to `data` does not satisfy the [rules for changing fields](/en/dev/manifest.md#rules-for-changing-fields), the whole upgrade is rolled back: the data is restored as it was, the old version keeps running, and `E_ACTIVATION_FAILED` is reported.
Common errors:
| Error | Cause |
| --- | --- |
| `E_PATH_TRAVERSAL` | The package has a path or file type that is not allowed, or too many files |
| `E_SIG_INVALID` | `SIGNATURE.json` is malformed, or the signature does not match the manifest (the manifest was altered) |
| `E_UNKNOWN_KEY` | The signing key is not one this machine trusts |
| `E_PUBLISHER_MISMATCH` | `publisherId` in `SIGNATURE.json` differs from `author.publisherId` in the manifest |
| `E_PERM_INVALID` | The manifest format is wrong (the error points out which field), or some declaration is invalid |
| `E_VERSION_OLDER` | The package's version is lower than the installed one |
| `E_HASH_MISMATCH`, `E_SIZE_MISMATCH` | Files in the package do not match `integrity` |
| `E_WORKFLOW_INVALID`, `E_INPUT_INVALID` | Something is wrong with a SOP or its trigger; see [Events and Triggers](/en/dev/events.md#troubleshooting) |
| `E_ACTIVATION_FAILED` | All checks passed, but this version failed to activate after an upgrade or same-version reinstall, most likely because of `data`: the migration failed, or the change does not satisfy the [rules for changing fields](/en/dev/manifest.md#rules-for-changing-fields). The cause (such as `E_DATA_SCHEMA: …`) is in the error. On upgrade, it has already rolled back to the old version. On a first install, the original error is reported. |
## Signatures and trust levels
The signature is made over `notochord.json`: Ed25519, with the JSON canonicalized per RFC 8785 before signing. Changing anything in the manifest (permissions, a tool description, the hash of one file in `integrity`) invalidates the signature; the other files in the package are each pinned by `integrity`. Together, for a signed package, neither the manifest nor any file it references can be changed without being detected.
At install, a package is handled at one of three levels (the app does not currently show which one):
| Level | Meaning |
| --- | --- |
| Official signature | The signature verifies with Notochord's official public key. The official public key is built into the app and is not read from disk or the network. |
| Signed by a trusted developer | The signature comes from a developer key this machine trusts, and `publisherId` in `SIGNATURE.json` matches `author.publisherId` in the manifest. **The app does not yet have a way to add developer keys, so this level cannot be used for now.** |
| Developer mode (unsigned) | The signature is not verified. Installing a draft from Gem Studio is this level. Checks other than the signature run as usual. |
- A package downloaded from the store must pass signature verification, or it is not installed.
- **Files are also checked after install.** At activation, on every tool call, when a SOP starts and resumes, and before a skill file is read, Notochord compares the files in this gem's directory with the `integrity` from install time: one extra, one missing, or one changed (system-generated `.DS_Store`, `Thumbs.db`, and `desktop.ini` do not count, and are also left out of the manifest when packaging) and this gem stops running (`E_FILES_CHANGED` is reported). The user clicks "Download again" on the gem's page to repair it; data and settings are kept. After install, `notochord.json` on disk is no longer read; the manifest as it was at install time is authoritative. During development, do not edit the files of an installed gem directly; change them in Gem Studio and reinstall.