Skip to content
ocx
install

Publish packages

Build a deterministic archive, attach metadata that declares its environment, and push both to any OCI registry.

This section has a page for each step and for each decision around it. Follow the journey to the pages you need, or start with the first package at the end of this page. Most packages start as an upstream binary release on GitHub or a vendor’s download page. The pages below take you from “I have a binary” to “consumers can install it”, grouped by task.

  • Bundle a release: what goes in the archive, whether to repack the upstream layout and which compression to pick.
  • Declare dependencies: when to depend on another package instead of bundling it, how to pin by digest and which edge visibility to use.
  • Declare the environment: which variables to declare and how to mark each as private, public or interface.
  • Add named launchers: when to ship launchers instead of exposing bin/, and how to pick names that do not collide.
  • Announce a package: claim the namespace once, then publish tags into the index on every release.
  • Announce from CI: the credential postures for a GitHub or GitLab job, and who reviews what.

Common questions you will hit while publishing, and the page that answers each:

You have a compiled binary, a Python script or any other executable, and you want consumers to run it after ocx package install. The path takes three steps, and Publish a package to a registry covers each one in detail.

First, lay out the working directory. The bundle contents live under build/, and the metadata sidecar sits next to it. The sidecar is not part of the archive. ocx package push uploads it as the OCI manifest config blob, and OCX restores it beside content/ at install time.

  • mytool/workdir (cwd for the commands below)
    • build/bundle contents, which become content/ after install
      • bin/
        • mytoolyour binary, Python script or shell wrapper
    • metadata.jsonOCI config sidecar, not part of the archive

Second, write metadata.json with one public env entry that prepends the package’s bin/ to PATH:

{
"$schema": "https://ocx.sh/schemas/metadata/v1.json",
"type": "bundle",
"version": 1,
"env": [
{
"key": "PATH",
"type": "path",
"value": "${installPath}/bin",
"visibility": "public"
}
]
}

Third, bundle build/ into a deterministic archive and push it to a registry you can authenticate against. The push attaches metadata.json as the manifest config blob.

Terminal window
ocx login ghcr.io
ocx package create build -p linux/amd64 -m metadata.json -o mytool-1.0.0.tar.xz
ocx package push -p linux/amd64 -m metadata.json \
-i ghcr.io/me/mytool:1.0.0 mytool-1.0.0.tar.xz

Consumers reach the package with ocx package install ghcr.io/me/mytool:1.0.0, and the binary lands on their PATH once they pass --select or run ocx package select later, which makes the package current.