Publishing APM Primitives and Packages
Publishing means: getting a primitive or package into a tagged release of calab-ai/apm-registry so it shows up in the next portal-data.json snapshot.
CLI status (May 2026):
gh calab apm publish primitiveandgh calab apm publish packageare not yet shipped. No PR matchingfeat/apm-publish-commandsis open incalab-ai/gh-calabat the time of writing. The current production flow is the manual PR + semantic-release path documented below. This page will be updated to point at the CLI commands as soon as they merge.
The release pipeline at a glance
flowchart LR A[Author] --> B[PR to apm-registry] B --> C[CI: schema + manifest validation] C --> D[PR review + merge] D --> E[semantic-release tags<br/>primitives/ | packages/] E --> F[Catalog regenerate<br/>portal-data.json] F --> G[GitHub Release attaches<br/>portal-data.json artifact] G --> H[Marketplace + handbook<br/>pick up next sync]
There is no publishing endpoint outside the registry repo. Every release is a Git tag created by semantic-release running in CI on main.
Manual flow (today)
1. Branch from main
git clone https://github.com/calab-ai/apm-registry
cd apm-registry
git checkout -b feat/<your-primitive-or-package>2. Add the content
- For a primitive: drop a new directory under
primitives/<type>/<name>/withapm-primitive.jsonand the entrypoint file. See Authoring primitives. - For a package: drop a new directory under
packages/<name>/withapm-package.json. See Authoring packages.
3. Validate locally
pip install 'jsonschema==4.*'
python scripts/validate_primitive_manifests.py
# (and the equivalent for packages, once added)CI runs the same gates on every PR via .github/workflows/validate-primitive-manifests.yml.
4. Conventional Commit message
The release pipeline derives the new version from your commit message. Use Conventional Commits:
| Commit prefix | Bump | Use it when… |
|---|---|---|
feat(<scope>): … | minor | Adding a new primitive, adding a primitive to a package, additive metadata. |
fix(<scope>): … | patch | Fixing a typo, correcting frontmatter, non-behavioral cleanup. |
feat(<scope>)!: … or BREAKING CHANGE: footer | major | Removing a primitive, replacing one, or any consumer-breaking change. |
chore, docs, ci | none | Tooling and docs that don’t require a release. |
The <scope> should be the primitive or package name (e.g. feat(workspace-base): add summarise skill).
5. Open the PR
gh pr create --repo calab-ai/apm-registry \
--base main \
--title "feat(<scope>): <summary>" \
--body "<what + why + test evidence>"PR review is owned by the relevant CODEOWNERS group; default is @calab-ai/guild-delivery for content under primitives/ and packages/.
6. Merge → semantic-release tags
On merge to main, semantic-release (configured per docs/release-guidelines.md in the registry) will:
- Determine the next version from your commit messages.
- Push a tag of the appropriate shape:
- Primitive:
refs/tags/primitives/<type>/<name>/v<version> - Package:
refs/tags/packages/<name>/v<version> - Catalog snapshot:
refs/tags/catalog/v<version>
- Primitive:
- Create a GitHub Release with the changelog and attach the regenerated
portal-data.jsonartifact.
You can verify release creation against the latest GA release.
7. Catalog refresh
The catalog generator (catalog/generate.ps1) re-reads every primitive and package manifest and rewrites catalog/portal-data.json. The marketplace portal and the handbook’s APM Marketplace consume the new artifact on their next sync.
Future: gh calab apm publish
The intended developer surface — once the CLI commands ship — will collapse the steps above into:
# Publish a primitive (lints manifest, opens PR, drives release on merge)
gh calab apm publish primitive primitives/skills/my-new-skill
# Publish a package
gh calab apm publish package packages/my-new-packageDesign notes (subject to change until merged):
- Both subcommands accept either a directory path or a primitive/package id.
- Both run the same
validate_*_manifests.pychecksgh calab apm validateruns locally. - Output follows the standard JSON envelope from
docs/apm-cli-contract.md:data.published.kind∈{primitive, package}data.published.id,data.published.version,data.published.tag
- Exit codes follow the standard contract —
4for validation,5for tag conflict,7for auth.
When the publish PR opens in calab-ai/gh-calab, this page will link to it directly. Until then, file feature requests there.
Tag-conflict prevention
Each tag must be unique. If you bump version in your manifest but a tag of that shape already exists (e.g. someone else released the same number first), semantic-release will fail. Resolution:
- Pull the latest tags:
git fetch --tags origin. - Check
git tag -l "primitives/<type>/<name>/*"(orpackages/<name>/*). - Bump your manifest
versionpast the highest existing tag. - Amend or add a fix-up commit and re-push.
Related
- Authoring primitives
- Authoring packages
- Installing
- Registry: release-guidelines
- CLI contract:
gh-calabapm-cli-contract - Open CLI work: calab-ai/gh-calab pulls